Merge branch 'for-2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[safe/jmp/linux-2.6] / drivers / pcmcia / pxa2xx_base.c
index 0e35acb..df4532e 100644 (file)
@@ -17,6 +17,7 @@
   ======================================================================*/
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
@@ -214,7 +215,8 @@ static void pxa2xx_configure_sockets(struct device *dev)
        MECR |= MECR_CIT;
 
        /* Set MECR:NOS (Number Of Sockets) */
-       if ((ops->first + ops->nr) > 1 || machine_is_viper())
+       if ((ops->first + ops->nr) > 1 ||
+           machine_is_viper() || machine_is_arcom_zeus())
                MECR |= MECR_NOS;
        else
                MECR &= ~MECR_NOS;
@@ -228,17 +230,54 @@ static const char *skt_names[] = {
 #define SKT_DEV_INFO_SIZE(n) \
        (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
 
-int __pxa2xx_drv_pcmcia_probe(struct device *dev)
+int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)
 {
-       int i, ret;
+       skt->res_skt.start = _PCMCIA(skt->nr);
+       skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1;
+       skt->res_skt.name = skt_names[skt->nr];
+       skt->res_skt.flags = IORESOURCE_MEM;
+
+       skt->res_io.start = _PCMCIAIO(skt->nr);
+       skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
+       skt->res_io.name = "io";
+       skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+       skt->res_mem.start = _PCMCIAMem(skt->nr);
+       skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
+       skt->res_mem.name = "memory";
+       skt->res_mem.flags = IORESOURCE_MEM;
+
+       skt->res_attr.start = _PCMCIAAttr(skt->nr);
+       skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
+       skt->res_attr.name = "attribute";
+       skt->res_attr.flags = IORESOURCE_MEM;
+
+       return soc_pcmcia_add_one(skt);
+}
+EXPORT_SYMBOL(pxa2xx_drv_pcmcia_add_one);
+
+void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
+{
+       /* Provide our PXA2xx specific timing routines. */
+       ops->set_timing  = pxa2xx_pcmcia_set_timing;
+#ifdef CONFIG_CPU_FREQ
+       ops->frequency_change = pxa2xx_pcmcia_frequency_change;
+#endif
+}
+EXPORT_SYMBOL(pxa2xx_drv_pcmcia_ops);
+
+static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
+{
+       int i, ret = 0;
        struct pcmcia_low_level *ops;
        struct skt_dev_info *sinfo;
        struct soc_pcmcia_socket *skt;
 
-       if (!dev || !dev->platform_data)
+       ops = (struct pcmcia_low_level *)dev->dev.platform_data;
+       if (!ops)
                return -ENODEV;
 
-       ops = (struct pcmcia_low_level *)dev->platform_data;
+       pxa2xx_drv_pcmcia_ops(ops);
 
        sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
        if (!sinfo)
@@ -250,69 +289,50 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev)
        for (i = 0; i < ops->nr; i++) {
                skt = &sinfo->skt[i];
 
-               skt->nr         = ops->first + i;
-               skt->irq        = NO_IRQ;
-
-               skt->res_skt.start      = _PCMCIA(skt->nr);
-               skt->res_skt.end        = _PCMCIA(skt->nr) + PCMCIASp - 1;
-               skt->res_skt.name       = skt_names[skt->nr];
-               skt->res_skt.flags      = IORESOURCE_MEM;
+               skt->nr = ops->first + i;
+               skt->ops = ops;
+               skt->socket.owner = ops->owner;
+               skt->socket.dev.parent = &dev->dev;
+               skt->socket.pci_irq = NO_IRQ;
 
-               skt->res_io.start       = _PCMCIAIO(skt->nr);
-               skt->res_io.end         = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
-               skt->res_io.name        = "io";
-               skt->res_io.flags       = IORESOURCE_MEM | IORESOURCE_BUSY;
-
-               skt->res_mem.start      = _PCMCIAMem(skt->nr);
-               skt->res_mem.end        = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
-               skt->res_mem.name       = "memory";
-               skt->res_mem.flags      = IORESOURCE_MEM;
-
-               skt->res_attr.start     = _PCMCIAAttr(skt->nr);
-               skt->res_attr.end       = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
-               skt->res_attr.name      = "attribute";
-               skt->res_attr.flags     = IORESOURCE_MEM;
+               ret = pxa2xx_drv_pcmcia_add_one(skt);
+               if (ret)
+                       break;
        }
 
-       /* Provide our PXA2xx specific timing routines. */
-       ops->set_timing  = pxa2xx_pcmcia_set_timing;
-#ifdef CONFIG_CPU_FREQ
-       ops->frequency_change = pxa2xx_pcmcia_frequency_change;
-#endif
-
-       ret = soc_common_drv_pcmcia_probe(dev, ops, sinfo);
-
-       if (!ret)
-               pxa2xx_configure_sockets(dev);
+       if (ret) {
+               while (--i >= 0)
+                       soc_pcmcia_remove_one(&sinfo->skt[i]);
+               kfree(sinfo);
+       } else {
+               pxa2xx_configure_sockets(&dev->dev);
+               dev_set_drvdata(&dev->dev, sinfo);
+       }
 
        return ret;
 }
-EXPORT_SYMBOL(__pxa2xx_drv_pcmcia_probe);
-
-
-static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
-{
-       return __pxa2xx_drv_pcmcia_probe(&dev->dev);
-}
 
 static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
 {
-       return soc_common_drv_pcmcia_remove(&dev->dev);
-}
+       struct skt_dev_info *sinfo = platform_get_drvdata(dev);
+       int i;
 
-static int pxa2xx_drv_pcmcia_suspend(struct device *dev)
-{
-       return pcmcia_socket_dev_suspend(dev);
+       platform_set_drvdata(dev, NULL);
+
+       for (i = 0; i < sinfo->nskt; i++)
+               soc_pcmcia_remove_one(&sinfo->skt[i]);
+
+       kfree(sinfo);
+       return 0;
 }
 
 static int pxa2xx_drv_pcmcia_resume(struct device *dev)
 {
        pxa2xx_configure_sockets(dev);
-       return pcmcia_socket_dev_resume(dev);
+       return 0;
 }
 
-static struct dev_pm_ops  pxa2xx_drv_pcmcia_pm_ops = {
-       .suspend        = pxa2xx_drv_pcmcia_suspend,
+static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = {
        .resume         = pxa2xx_drv_pcmcia_resume,
 };