Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80af9e6d authored by Joachim Eastwood's avatar Joachim Eastwood Committed by Dominik Brodowski
Browse files

pcmcia at91_cf: fix raw gpio number usage



This patches fixes two things:
* Use gpio_valid function to check gpio before usage
  This must be done after 63b4c296 which uses -EINVAL for unused pin's
* Use gpio_to_irq to convert gpio's to irq
  The driver assumed a 1:1 mapping between gpio and irq numbers. This is no
  longer true after d0fbda9a.

Tested on custom RM9200 board with 8gb CF card.

Signed-off-by: default avatarJoachim Eastwood <joachim.eastwood@jotron.com>
Acked-by: default avatarJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent f24fa8af
Loading
Loading
Loading
Loading
+26 −26
Original line number Original line Diff line number Diff line
@@ -16,13 +16,13 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/gpio.h>


#include <pcmcia/ss.h>
#include <pcmcia/ss.h>


#include <mach/hardware.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/sizes.h>
#include <asm/gpio.h>


#include <mach/board.h>
#include <mach/board.h>
#include <mach/at91rm9200_mc.h>
#include <mach/at91rm9200_mc.h>
@@ -69,7 +69,7 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf)
{
{
	struct at91_cf_socket *cf = _cf;
	struct at91_cf_socket *cf = _cf;


	if (irq == cf->board->det_pin) {
	if (irq == gpio_to_irq(cf->board->det_pin)) {
		unsigned present = at91_cf_present(cf);
		unsigned present = at91_cf_present(cf);


		/* kick pccard as needed */
		/* kick pccard as needed */
@@ -95,8 +95,8 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)


	/* NOTE: CF is always 3VCARD */
	/* NOTE: CF is always 3VCARD */
	if (at91_cf_present(cf)) {
	if (at91_cf_present(cf)) {
		int rdy	= cf->board->irq_pin;	/* RDY/nIRQ */
		int rdy	= gpio_is_valid(cf->board->irq_pin);	/* RDY/nIRQ */
		int vcc	= cf->board->vcc_pin;
		int vcc	= gpio_is_valid(cf->board->vcc_pin);


		*sp = SS_DETECT | SS_3VCARD;
		*sp = SS_DETECT | SS_3VCARD;
		if (!rdy || gpio_get_value(rdy))
		if (!rdy || gpio_get_value(rdy))
@@ -117,7 +117,7 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
	cf = container_of(sock, struct at91_cf_socket, socket);
	cf = container_of(sock, struct at91_cf_socket, socket);


	/* switch Vcc if needed and possible */
	/* switch Vcc if needed and possible */
	if (cf->board->vcc_pin) {
	if (gpio_is_valid(cf->board->vcc_pin)) {
		switch (s->Vcc) {
		switch (s->Vcc) {
			case 0:
			case 0:
				gpio_set_value(cf->board->vcc_pin, 0);
				gpio_set_value(cf->board->vcc_pin, 0);
@@ -221,7 +221,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
	struct resource		*io;
	struct resource		*io;
	int			status;
	int			status;


	if (!board || !board->det_pin || !board->rst_pin)
	if (!board || !gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
		return -ENODEV;
		return -ENODEV;


	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -241,7 +241,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
	status = gpio_request(board->det_pin, "cf_det");
	status = gpio_request(board->det_pin, "cf_det");
	if (status < 0)
	if (status < 0)
		goto fail0;
		goto fail0;
	status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
	status = request_irq(gpio_to_irq(board->det_pin), at91_cf_irq, 0, driver_name, cf);
	if (status < 0)
	if (status < 0)
		goto fail00;
		goto fail00;
	device_init_wakeup(&pdev->dev, 1);
	device_init_wakeup(&pdev->dev, 1);
@@ -250,7 +250,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
	if (status < 0)
	if (status < 0)
		goto fail0a;
		goto fail0a;


	if (board->vcc_pin) {
	if (gpio_is_valid(board->vcc_pin)) {
		status = gpio_request(board->vcc_pin, "cf_vcc");
		status = gpio_request(board->vcc_pin, "cf_vcc");
		if (status < 0)
		if (status < 0)
			goto fail0b;
			goto fail0b;
@@ -262,15 +262,15 @@ static int __init at91_cf_probe(struct platform_device *pdev)
	 * unless we report that we handle everything (sigh).
	 * unless we report that we handle everything (sigh).
	 * (Note:  DK board doesn't wire the IRQ pin...)
	 * (Note:  DK board doesn't wire the IRQ pin...)
	 */
	 */
	if (board->irq_pin) {
	if (gpio_is_valid(board->irq_pin)) {
		status = gpio_request(board->irq_pin, "cf_irq");
		status = gpio_request(board->irq_pin, "cf_irq");
		if (status < 0)
		if (status < 0)
			goto fail0c;
			goto fail0c;
		status = request_irq(board->irq_pin, at91_cf_irq,
		status = request_irq(gpio_to_irq(board->irq_pin), at91_cf_irq,
				IRQF_SHARED, driver_name, cf);
				IRQF_SHARED, driver_name, cf);
		if (status < 0)
		if (status < 0)
			goto fail0d;
			goto fail0d;
		cf->socket.pci_irq = board->irq_pin;
		cf->socket.pci_irq = gpio_to_irq(board->irq_pin);
	} else
	} else
		cf->socket.pci_irq = nr_irqs + 1;
		cf->socket.pci_irq = nr_irqs + 1;


@@ -289,7 +289,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
	}
	}


	pr_info("%s: irqs det #%d, io #%d\n", driver_name,
	pr_info("%s: irqs det #%d, io #%d\n", driver_name,
		board->det_pin, board->irq_pin);
		gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin));


	cf->socket.owner = THIS_MODULE;
	cf->socket.owner = THIS_MODULE;
	cf->socket.dev.parent = &pdev->dev;
	cf->socket.dev.parent = &pdev->dev;
@@ -311,19 +311,19 @@ fail2:
fail1:
fail1:
	if (cf->socket.io_offset)
	if (cf->socket.io_offset)
		iounmap((void __iomem *) cf->socket.io_offset);
		iounmap((void __iomem *) cf->socket.io_offset);
	if (board->irq_pin) {
	if (gpio_is_valid(board->irq_pin)) {
		free_irq(board->irq_pin, cf);
		free_irq(gpio_to_irq(board->irq_pin), cf);
fail0d:
fail0d:
		gpio_free(board->irq_pin);
		gpio_free(board->irq_pin);
	}
	}
fail0c:
fail0c:
	if (board->vcc_pin)
	if (gpio_is_valid(board->vcc_pin))
		gpio_free(board->vcc_pin);
		gpio_free(board->vcc_pin);
fail0b:
fail0b:
	gpio_free(board->rst_pin);
	gpio_free(board->rst_pin);
fail0a:
fail0a:
	device_init_wakeup(&pdev->dev, 0);
	device_init_wakeup(&pdev->dev, 0);
	free_irq(board->det_pin, cf);
	free_irq(gpio_to_irq(board->det_pin), cf);
fail00:
fail00:
	gpio_free(board->det_pin);
	gpio_free(board->det_pin);
fail0:
fail0:
@@ -340,15 +340,15 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
	pcmcia_unregister_socket(&cf->socket);
	pcmcia_unregister_socket(&cf->socket);
	release_mem_region(io->start, resource_size(io));
	release_mem_region(io->start, resource_size(io));
	iounmap((void __iomem *) cf->socket.io_offset);
	iounmap((void __iomem *) cf->socket.io_offset);
	if (board->irq_pin) {
	if (gpio_is_valid(board->irq_pin)) {
		free_irq(board->irq_pin, cf);
		free_irq(gpio_to_irq(board->irq_pin), cf);
		gpio_free(board->irq_pin);
		gpio_free(board->irq_pin);
	}
	}
	if (board->vcc_pin)
	if (gpio_is_valid(board->vcc_pin))
		gpio_free(board->vcc_pin);
		gpio_free(board->vcc_pin);
	gpio_free(board->rst_pin);
	gpio_free(board->rst_pin);
	device_init_wakeup(&pdev->dev, 0);
	device_init_wakeup(&pdev->dev, 0);
	free_irq(board->det_pin, cf);
	free_irq(gpio_to_irq(board->det_pin), cf);
	gpio_free(board->det_pin);
	gpio_free(board->det_pin);
	kfree(cf);
	kfree(cf);
	return 0;
	return 0;
@@ -362,9 +362,9 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
	struct at91_cf_data	*board = cf->board;
	struct at91_cf_data	*board = cf->board;


	if (device_may_wakeup(&pdev->dev)) {
	if (device_may_wakeup(&pdev->dev)) {
		enable_irq_wake(board->det_pin);
		enable_irq_wake(gpio_to_irq(board->det_pin));
		if (board->irq_pin)
		if (gpio_is_valid(board->irq_pin))
			enable_irq_wake(board->irq_pin);
			enable_irq_wake(gpio_to_irq(board->irq_pin));
	}
	}
	return 0;
	return 0;
}
}
@@ -375,9 +375,9 @@ static int at91_cf_resume(struct platform_device *pdev)
	struct at91_cf_data	*board = cf->board;
	struct at91_cf_data	*board = cf->board;


	if (device_may_wakeup(&pdev->dev)) {
	if (device_may_wakeup(&pdev->dev)) {
		disable_irq_wake(board->det_pin);
		disable_irq_wake(gpio_to_irq(board->det_pin));
		if (board->irq_pin)
		if (gpio_is_valid(board->irq_pin))
			disable_irq_wake(board->irq_pin);
			disable_irq_wake(gpio_to_irq(board->irq_pin));
	}
	}


	return 0;
	return 0;