hi,

Here's an update to the AT91RM9200 CompactFlash driver.  It contains
changes that have been in the AT91 patches for a while now.
Can it please be included in pcmcia-2.6.git for the next merge window.

The changes include:
- Use the I/O memory address and IRQ passed via the platform_device
resources instead of constant global values.
- The pin setup should be handled in the platform setup code, and not in
the driver.
- The IRQ should not be used as a random'ness source.
- Return errors if ioremap() or request_mem_region() fails.
- The suspend/resume code should be using {enable/disable}_irq_wake()
instead of {enable/disable}_irq().


Signed-off-by: Andrew Victor <[EMAIL PROTECTED]>



diff -urN -x CVS linux-2.6.19-rc2.orig/drivers/pcmcia/at91_cf.c 
linux-2.6.19/drivers/pcmcia/at91_cf.c
--- linux-2.6.19-rc2.orig/drivers/pcmcia/at91_cf.c      Thu Oct 19 16:31:59 2006
+++ linux-2.6.19/drivers/pcmcia/at91_cf.c       Mon Oct 16 14:19:13 2006
@@ -32,10 +32,11 @@
  * A0..A10 work in each range; A23 indicates I/O space;  A25 is CFRNW;
  * some other bit in {A24,A22..A11} is nREG to flag memory access
  * (vs attributes).  So more than 2KB/region would just be waste.
+ * Note: These are offsets from the physical base address.
  */
-#define        CF_ATTR_PHYS    (AT91_CF_BASE)
-#define        CF_IO_PHYS      (AT91_CF_BASE  + (1 << 23))
-#define        CF_MEM_PHYS     (AT91_CF_BASE  + 0x017ff800)
+#define        CF_ATTR_PHYS    (0)
+#define        CF_IO_PHYS      (1 << 23)
+#define        CF_MEM_PHYS     (0x017ff800)
 
 /*--------------------------------------------------------------------------*/
 
@@ -48,6 +49,8 @@
 
        struct platform_device  *pdev;
        struct at91_cf_data     *board;
+       
+       unsigned long           phys_baseaddr;
 };
 
 #define        SZ_2K                   (2 * SZ_1K)
@@ -168,7 +171,7 @@
         * some cards only like that way to get at the odd byte, despite
         * CF 3.0 spec table 35 also giving the D8-D15 option.
         */
-       if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) {
+       if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) {
                csr |= AT91_SMC_DBW_8;
                pr_debug("%s: 8bit i/o bus\n", driver_name);
        } else {
@@ -194,11 +197,11 @@
 
        cf = container_of(s, struct at91_cf_socket, socket);
 
-       map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+       map->flags &= (MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT);
        if (map->flags & MAP_ATTRIB)
-               map->static_start = CF_ATTR_PHYS;
+               map->static_start = cf->phys_baseaddr + CF_ATTR_PHYS;
        else
-               map->static_start = CF_MEM_PHYS;
+               map->static_start = cf->phys_baseaddr + CF_MEM_PHYS;
 
        return 0;
 }
@@ -235,18 +238,13 @@
 
        cf->board = board;
        cf->pdev = pdev;
+       cf->phys_baseaddr = io->start;
        platform_set_drvdata(pdev, cf);
 
        /* CF takes over CS4, CS5, CS6 */
        csa = at91_sys_read(AT91_EBI_CSA);
        at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
 
-       /* force poweron defaults for these pins ... */
-       (void) at91_set_A_periph(AT91_PIN_PC9, 0);      /* A25/CFRNW */
-       (void) at91_set_A_periph(AT91_PIN_PC10, 0);     /* NCS4/CFCS */
-       (void) at91_set_A_periph(AT91_PIN_PC11, 0);     /* NCS5/CFCE1 */
-       (void) at91_set_A_periph(AT91_PIN_PC12, 0);     /* NCS6/CFCE2 */
-
        /* nWAIT is _not_ a default setting */
        (void) at91_set_A_periph(AT91_PIN_PC6, 1);      /*  nWAIT */
 
@@ -266,8 +264,7 @@
        );
 
        /* must be a GPIO; ergo must trigger on both edges */
-       status = request_irq(board->det_pin, at91_cf_irq,
-                       IRQF_SAMPLE_RANDOM, driver_name, cf);
+       status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
        if (status < 0)
                goto fail0;
        device_init_wakeup(&pdev->dev, 1);
@@ -288,14 +285,18 @@
                cf->socket.pci_irq = NR_IRQS + 1;
 
        /* pcmcia layer only remaps "real" memory not iospace */
-       cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K);
-       if (!cf->socket.io_offset)
+       cf->socket.io_offset = (unsigned long) ioremap(cf->phys_baseaddr + 
CF_IO_PHYS, SZ_2K);
+       if (!cf->socket.io_offset) {
+               status = -ENXIO;
                goto fail1;
+       }
 
        /* reserve CS4, CS5, and CS6 regions; but use just CS4 */
        if (!request_mem_region(io->start, io->end + 1 - io->start,
-                               driver_name))
-               goto fail1;
+                               driver_name)) {
+               status = -ENXIO;
+               goto fail1a;
+       }
 
        pr_info("%s: irqs det #%d, io #%d\n", driver_name,
                board->det_pin, board->irq_pin);
@@ -316,14 +317,15 @@
        return 0;
 
 fail2:
-       iounmap((void __iomem *) cf->socket.io_offset);
        release_mem_region(io->start, io->end + 1 - io->start);
+fail1a:
+       iounmap((void __iomem *) cf->socket.io_offset);
 fail1:
        if (board->irq_pin)
                free_irq(board->irq_pin, cf);
 fail0a:
-       free_irq(board->det_pin, cf);
        device_init_wakeup(&pdev->dev, 0);
+       free_irq(board->det_pin, cf);
 fail0:
        at91_sys_write(AT91_EBI_CSA, csa);
        kfree(cf);
@@ -340,8 +342,8 @@
        pcmcia_unregister_socket(&cf->socket);
        if (board->irq_pin)
                free_irq(board->irq_pin, cf);
-       free_irq(board->det_pin, cf);
        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);
 
@@ -360,26 +362,20 @@
        struct at91_cf_data     *board = cf->board;
 
        pcmcia_socket_dev_suspend(&pdev->dev, mesg);
-       if (device_may_wakeup(&pdev->dev))
+       if (device_may_wakeup(&pdev->dev)) {
                enable_irq_wake(board->det_pin);
-       else {
+               if (board->irq_pin)
+                       enable_irq_wake(board->irq_pin);
+       } else {
                disable_irq_wake(board->det_pin);
-               disable_irq(board->det_pin);
+               if (board->irq_pin)
+                       disable_irq_wake(board->irq_pin);
        }
-       if (board->irq_pin)
-               disable_irq(board->irq_pin);
        return 0;
 }
 
 static int at91_cf_resume(struct platform_device *pdev)
 {
-       struct at91_cf_socket   *cf = platform_get_drvdata(pdev);
-       struct at91_cf_data     *board = cf->board;
-
-       if (board->irq_pin)
-               enable_irq(board->irq_pin);
-       if (!device_may_wakeup(&pdev->dev))
-               enable_irq(board->det_pin);
        pcmcia_socket_dev_resume(&pdev->dev);
        return 0;
 }




_______________________________________________
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia

Reply via email to