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

Commit 4c1fc445 authored by David Brownell's avatar David Brownell Committed by Linus Torvalds
Browse files

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: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9ab9898e
Loading
Loading
Loading
Loading
+47 −15
Original line number Diff line number Diff line
@@ -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;
}