at91_cf: use generic gpio calls

Update the AT91 CF driver to use the generic GPIO calls instead of the
AT91-specific ones; and request exclusive use of those signals.

Minor tweaks to cleanup code paths: always in reverse order of how the
resources were allocated, with remove() matching the fault paths of
probe().

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
David Brownell 2008-02-04 22:27:42 -08:00 committed by Linus Torvalds
parent 9ab9898e32
commit 4c1fc445c2
1 changed files with 47 additions and 15 deletions

View File

@ -21,9 +21,9 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/sizes.h> #include <asm/sizes.h>
#include <asm/gpio.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h>
#include <asm/arch/at91rm9200_mc.h> #include <asm/arch/at91rm9200_mc.h>
@ -56,7 +56,7 @@ struct at91_cf_socket {
static inline int at91_cf_present(struct at91_cf_socket *cf) static inline int at91_cf_present(struct at91_cf_socket *cf)
{ {
return !at91_get_gpio_value(cf->board->det_pin); return !gpio_get_value(cf->board->det_pin);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -100,9 +100,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
int vcc = cf->board->vcc_pin; int vcc = cf->board->vcc_pin;
*sp = SS_DETECT | SS_3VCARD; *sp = SS_DETECT | SS_3VCARD;
if (!rdy || at91_get_gpio_value(rdy)) if (!rdy || gpio_get_value(rdy))
*sp |= SS_READY; *sp |= SS_READY;
if (!vcc || at91_get_gpio_value(vcc)) if (!vcc || gpio_get_value(vcc))
*sp |= SS_POWERON; *sp |= SS_POWERON;
} else } else
*sp = 0; *sp = 0;
@ -121,10 +121,10 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
if (cf->board->vcc_pin) { if (cf->board->vcc_pin) {
switch (s->Vcc) { switch (s->Vcc) {
case 0: case 0:
at91_set_gpio_value(cf->board->vcc_pin, 0); gpio_set_value(cf->board->vcc_pin, 0);
break; break;
case 33: case 33:
at91_set_gpio_value(cf->board->vcc_pin, 1); gpio_set_value(cf->board->vcc_pin, 1);
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -132,7 +132,7 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
} }
/* toggle reset if needed */ /* toggle reset if needed */
at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET); gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET);
pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
@ -239,11 +239,24 @@ static int __init at91_cf_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, cf); platform_set_drvdata(pdev, cf);
/* must be a GPIO; ergo must trigger on both edges */ /* must be a GPIO; ergo must trigger on both edges */
status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf); 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);
if (status < 0)
goto fail00;
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
status = gpio_request(board->rst_pin, "cf_rst");
if (status < 0)
goto fail0a;
if (board->vcc_pin) {
status = gpio_request(board->vcc_pin, "cf_vcc");
if (status < 0)
goto fail0b;
}
/* /*
* The card driver will request this irq later as needed. * The card driver will request this irq later as needed.
* but it causes lots of "irqNN: nobody cared" messages * but it causes lots of "irqNN: nobody cared" messages
@ -251,16 +264,20 @@ static int __init at91_cf_probe(struct platform_device *pdev)
* (Note: DK board doesn't wire the IRQ pin...) * (Note: DK board doesn't wire the IRQ pin...)
*/ */
if (board->irq_pin) { if (board->irq_pin) {
status = gpio_request(board->irq_pin, "cf_irq");
if (status < 0)
goto fail0c;
status = request_irq(board->irq_pin, at91_cf_irq, status = request_irq(board->irq_pin, at91_cf_irq,
IRQF_SHARED, driver_name, cf); IRQF_SHARED, driver_name, cf);
if (status < 0) if (status < 0)
goto fail0a; goto fail0d;
cf->socket.pci_irq = board->irq_pin; cf->socket.pci_irq = board->irq_pin;
} else } else
cf->socket.pci_irq = NR_IRQS + 1; cf->socket.pci_irq = NR_IRQS + 1;
/* pcmcia layer only remaps "real" memory not iospace */ /* pcmcia layer only remaps "real" memory not iospace */
cf->socket.io_offset = (unsigned long) ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K); cf->socket.io_offset = (unsigned long)
ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
if (!cf->socket.io_offset) { if (!cf->socket.io_offset) {
status = -ENXIO; status = -ENXIO;
goto fail1; goto fail1;
@ -296,11 +313,21 @@ 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 (board->irq_pin) {
free_irq(board->irq_pin, cf); free_irq(board->irq_pin, cf);
fail0d:
gpio_free(board->irq_pin);
}
fail0c:
if (board->vcc_pin)
gpio_free(board->vcc_pin);
fail0b:
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(board->det_pin, cf);
fail00:
gpio_free(board->det_pin);
fail0: fail0:
kfree(cf); kfree(cf);
return status; return status;
@ -313,13 +340,18 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
struct resource *io = cf->socket.io[0].res; struct resource *io = cf->socket.io[0].res;
pcmcia_unregister_socket(&cf->socket); pcmcia_unregister_socket(&cf->socket);
if (board->irq_pin) release_mem_region(io->start, io->end + 1 - io->start);
iounmap((void __iomem *) cf->socket.io_offset);
if (board->irq_pin) {
free_irq(board->irq_pin, cf); free_irq(board->irq_pin, cf);
gpio_free(board->irq_pin);
}
if (board->vcc_pin)
gpio_free(board->vcc_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(board->det_pin, cf);
iounmap((void __iomem *) cf->socket.io_offset); gpio_free(board->det_pin);
release_mem_region(io->start, io->end + 1 - io->start);
kfree(cf); kfree(cf);
return 0; return 0;
} }