diff options
Diffstat (limited to 'drivers/pcmcia/pxa2xx_base.c')
| -rw-r--r-- | drivers/pcmcia/pxa2xx_base.c | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 76e640bccde..cfec9dd18ff 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -17,6 +17,7 @@ ======================================================================*/ #include <linux/module.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/cpufreq.h> #include <linux/ioport.h> @@ -25,13 +26,12 @@ #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> #include <mach/pxa2xx-regs.h> #include <asm/mach-types.h> -#include <pcmcia/cs_types.h> #include <pcmcia/ss.h> #include <pcmcia/cistpl.h> @@ -116,37 +116,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 +178,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 @@ -177,7 +189,6 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, unsigned long val, struct cpufreq_freqs *freqs) { -#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock" switch (val) { case CPUFREQ_PRECHANGE: if (freqs->new > freqs->old) { @@ -185,7 +196,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, "pre-updating\n", freqs->new / 1000, (freqs->new / 100) % 10, freqs->old / 1000, (freqs->old / 100) % 10); - pxa2xx_pcmcia_set_mcxx(skt, freqs->new); + pxa2xx_pcmcia_set_timing(skt); } break; @@ -195,7 +206,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, "post-updating\n", freqs->new / 1000, (freqs->new / 100) % 10, freqs->old / 1000, (freqs->old / 100) % 10); - pxa2xx_pcmcia_set_mcxx(skt, freqs->new); + pxa2xx_pcmcia_set_timing(skt); } break; } @@ -203,23 +214,23 @@ 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); } +EXPORT_SYMBOL(pxa2xx_configure_sockets); static const char *skt_names[] = { "PCMCIA socket 0", @@ -271,43 +282,59 @@ 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 (IS_ERR(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->ops = ops; - skt->socket.owner = ops->owner; - skt->socket.dev.parent = &dev->dev; - skt->socket.pci_irq = NO_IRQ; + skt->clk = clk; + soc_pcmcia_init_one(skt, ops, &dev->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); - } else { - pxa2xx_configure_sockets(&dev->dev); - dev_set_drvdata(&dev->dev, sinfo); - } + pxa2xx_configure_sockets(&dev->dev); + dev_set_drvdata(&dev->dev, sinfo); + return 0; + +err1: + while (--i >= 0) + soc_pcmcia_remove_one(&sinfo->skt[i]); + clk_put(clk); + kfree(sinfo); +err0: return ret; } @@ -321,23 +348,18 @@ 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; } -static int pxa2xx_drv_pcmcia_suspend(struct device *dev) -{ - return pcmcia_socket_dev_suspend(dev); -} - static int pxa2xx_drv_pcmcia_resume(struct device *dev) { pxa2xx_configure_sockets(dev); - return pcmcia_socket_dev_resume(dev); + return 0; } static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = { - .suspend = pxa2xx_drv_pcmcia_suspend, .resume = pxa2xx_drv_pcmcia_resume, }; |
