]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/pcmcia/pxa2xx_base.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / pcmcia / pxa2xx_base.c
index ae07b4db8a6ec00def420e5af77bbcede2b90730..2c540542b5af7fb183a57f8ea66b230649c16c2e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
+#include <mach/smemc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -116,37 +117,49 @@ static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
 
 static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
 {
-       MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+       uint32_t val;
+
+       val = ((pxa2xx_mcxx_setup(speed, clock)
                & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
                | ((pxa2xx_mcxx_asst(speed, clock)
                & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
                | ((pxa2xx_mcxx_hold(speed, clock)
                & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+       __raw_writel(val, MCMEM(sock));
+
        return 0;
 }
 
 static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
 {
-       MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+       uint32_t val;
+
+       val = ((pxa2xx_mcxx_setup(speed, clock)
                & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
                | ((pxa2xx_mcxx_asst(speed, clock)
                & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
                | ((pxa2xx_mcxx_hold(speed, clock)
                & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+       __raw_writel(val, MCIO(sock));
+
        return 0;
 }
 
 static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
 {
-       MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+       uint32_t val;
+
+       val = ((pxa2xx_mcxx_setup(speed, clock)
                & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
                | ((pxa2xx_mcxx_asst(speed, clock)
                & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
                | ((pxa2xx_mcxx_hold(speed, clock)
                & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+       __raw_writel(val, MCATT(sock));
+
        return 0;
 }
 
@@ -166,8 +179,8 @@ static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int cl
 
 static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
 {
-       unsigned int clk = get_memclk_frequency_10khz();
-       return pxa2xx_pcmcia_set_mcxx(skt, clk);
+       unsigned long clk = clk_get_rate(skt->clk);
+       return pxa2xx_pcmcia_set_mcxx(skt, clk / 10000);
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -202,22 +215,21 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
 }
 #endif
 
-static void pxa2xx_configure_sockets(struct device *dev)
+void pxa2xx_configure_sockets(struct device *dev)
 {
        struct pcmcia_low_level *ops = dev->platform_data;
-
        /*
         * We have at least one socket, so set MECR:CIT
         * (Card Is There)
         */
-       MECR |= MECR_CIT;
+       uint32_t mecr = MECR_CIT;
 
        /* Set MECR:NOS (Number Of Sockets) */
        if ((ops->first + ops->nr) > 1 ||
            machine_is_viper() || machine_is_arcom_zeus())
-               MECR |= MECR_NOS;
-       else
-               MECR &= ~MECR_NOS;
+               mecr |= MECR_NOS;
+
+       __raw_writel(mecr, MECR);
 }
 
 static const char *skt_names[] = {
@@ -270,24 +282,41 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
        struct pcmcia_low_level *ops;
        struct skt_dev_info *sinfo;
        struct soc_pcmcia_socket *skt;
+       struct clk *clk;
 
        ops = (struct pcmcia_low_level *)dev->dev.platform_data;
-       if (!ops)
+       if (!ops) {
+               ret = -ENODEV;
+               goto err0;
+       }
+
+       if (cpu_is_pxa320() && ops->nr > 1) {
+               dev_err(&dev->dev, "pxa320 supports only one pcmcia slot");
+               ret = -EINVAL;
+               goto err0;
+       }
+
+       clk = clk_get(&dev->dev, NULL);
+       if (!clk)
                return -ENODEV;
 
        pxa2xx_drv_pcmcia_ops(ops);
 
        sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
-       if (!sinfo)
+       if (!sinfo) {
+               clk_put(clk);
                return -ENOMEM;
+       }
 
        sinfo->nskt = ops->nr;
+       sinfo->clk = clk;
 
        /* Initialize processor specific parameters */
        for (i = 0; i < ops->nr; i++) {
                skt = &sinfo->skt[i];
 
                skt->nr = ops->first + i;
+               skt->clk = clk;
                skt->ops = ops;
                skt->socket.owner = ops->owner;
                skt->socket.dev.parent = &dev->dev;
@@ -295,18 +324,26 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
 
                ret = pxa2xx_drv_pcmcia_add_one(skt);
                if (ret)
-                       break;
+                       goto err1;
        }
 
        if (ret) {
                while (--i >= 0)
                        soc_pcmcia_remove_one(&sinfo->skt[i]);
                kfree(sinfo);
+               clk_put(clk);
        } else {
                pxa2xx_configure_sockets(&dev->dev);
                dev_set_drvdata(&dev->dev, sinfo);
        }
 
+       return 0;
+
+err1:
+       while (--i >= 0)
+               soc_pcmcia_remove_one(&sinfo->skt[i]);
+       kfree(sinfo);
+err0:
        return ret;
 }
 
@@ -320,6 +357,7 @@ static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
        for (i = 0; i < sinfo->nskt; i++)
                soc_pcmcia_remove_one(&sinfo->skt[i]);
 
+       clk_put(sinfo->clk);
        kfree(sinfo);
        return 0;
 }