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/io.h>
#include <asm/sizes.h>
#include <asm/gpio.h>
#include <asm/arch/board.h>
#include <asm/arch/gpio.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)
{
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;
*sp = SS_DETECT | SS_3VCARD;
if (!rdy || at91_get_gpio_value(rdy))
if (!rdy || gpio_get_value(rdy))
*sp |= SS_READY;
if (!vcc || at91_get_gpio_value(vcc))
if (!vcc || gpio_get_value(vcc))
*sp |= SS_POWERON;
} else
*sp = 0;
@ -121,10 +121,10 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
if (cf->board->vcc_pin) {
switch (s->Vcc) {
case 0:
at91_set_gpio_value(cf->board->vcc_pin, 0);
gpio_set_value(cf->board->vcc_pin, 0);
break;
case 33:
at91_set_gpio_value(cf->board->vcc_pin, 1);
gpio_set_value(cf->board->vcc_pin, 1);
break;
default:
return -EINVAL;
@ -132,7 +132,7 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
}
/* 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",
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);
/* 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)
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);
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.
* 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...)
*/
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,
IRQF_SHARED, driver_name, cf);
if (status < 0)
goto fail0a;
goto fail0d;
cf->socket.pci_irq = board->irq_pin;
} else
cf->socket.pci_irq = NR_IRQS + 1;
/* 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) {
status = -ENXIO;
goto fail1;
@ -296,11 +313,21 @@ fail2:
fail1:
if (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);
fail0d:
gpio_free(board->irq_pin);
}
fail0c:
if (board->vcc_pin)
gpio_free(board->vcc_pin);
fail0b:
gpio_free(board->rst_pin);
fail0a:
device_init_wakeup(&pdev->dev, 0);
free_irq(board->det_pin, cf);
fail00:
gpio_free(board->det_pin);
fail0:
kfree(cf);
return status;
@ -313,13 +340,18 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
struct resource *io = cf->socket.io[0].res;
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);
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);
free_irq(board->det_pin, cf);
iounmap((void __iomem *) cf->socket.io_offset);
release_mem_region(io->start, io->end + 1 - io->start);
gpio_free(board->det_pin);
kfree(cf);
return 0;
}