1f7be8ec1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*======================================================================
31da177e4SLinus Torvalds
41da177e4SLinus Torvalds Device driver for the PCMCIA control functionality of PXA2xx
51da177e4SLinus Torvalds microprocessors.
61da177e4SLinus Torvalds
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds (c) Ian Molton (spyro@f2s.com) 2003
91da177e4SLinus Torvalds (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds derived from sa11xx_base.c
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds Portions created by John G. Dorsey are
141da177e4SLinus Torvalds Copyright (C) 1999 John G. Dorsey.
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds ======================================================================*/
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds #include <linux/module.h>
195a0e3ad6STejun Heo #include <linux/slab.h>
201da177e4SLinus Torvalds #include <linux/init.h>
211da177e4SLinus Torvalds #include <linux/cpufreq.h>
221da177e4SLinus Torvalds #include <linux/ioport.h>
231da177e4SLinus Torvalds #include <linux/kernel.h>
241da177e4SLinus Torvalds #include <linux/spinlock.h>
25d052d1beSRussell King #include <linux/platform_device.h>
2608d3df8cSArnd Bergmann #include <linux/soc/pxa/cpu.h>
276a946f1bSArnd Bergmann #include <linux/soc/pxa/smemc.h>
281da177e4SLinus Torvalds
291da177e4SLinus Torvalds #include <asm/io.h>
301da177e4SLinus Torvalds #include <asm/irq.h>
3120f18ff3SMarc Zyngier #include <asm/mach-types.h>
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds #include <pcmcia/ss.h>
341da177e4SLinus Torvalds #include <pcmcia/cistpl.h>
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds #include "soc_common.h"
371da177e4SLinus Torvalds #include "pxa2xx_base.h"
381da177e4SLinus Torvalds
39b393c696SEric Miao /*
40b393c696SEric Miao * Personal Computer Memory Card International Association (PCMCIA) sockets
41b393c696SEric Miao */
42b393c696SEric Miao
43b393c696SEric Miao #define PCMCIAPrtSp 0x04000000 /* PCMCIA Partition Space [byte] */
44b393c696SEric Miao #define PCMCIASp (4*PCMCIAPrtSp) /* PCMCIA Space [byte] */
45b393c696SEric Miao #define PCMCIAIOSp PCMCIAPrtSp /* PCMCIA I/O Space [byte] */
46b393c696SEric Miao #define PCMCIAAttrSp PCMCIAPrtSp /* PCMCIA Attribute Space [byte] */
47b393c696SEric Miao #define PCMCIAMemSp PCMCIAPrtSp /* PCMCIA Memory Space [byte] */
48b393c696SEric Miao
49b393c696SEric Miao #define PCMCIA0Sp PCMCIASp /* PCMCIA 0 Space [byte] */
50b393c696SEric Miao #define PCMCIA0IOSp PCMCIAIOSp /* PCMCIA 0 I/O Space [byte] */
51b393c696SEric Miao #define PCMCIA0AttrSp PCMCIAAttrSp /* PCMCIA 0 Attribute Space [byte] */
52b393c696SEric Miao #define PCMCIA0MemSp PCMCIAMemSp /* PCMCIA 0 Memory Space [byte] */
53b393c696SEric Miao
54b393c696SEric Miao #define PCMCIA1Sp PCMCIASp /* PCMCIA 1 Space [byte] */
55b393c696SEric Miao #define PCMCIA1IOSp PCMCIAIOSp /* PCMCIA 1 I/O Space [byte] */
56b393c696SEric Miao #define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */
57b393c696SEric Miao #define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */
58b393c696SEric Miao
59b393c696SEric Miao #define _PCMCIA(Nb) /* PCMCIA [0..1] */ \
60b393c696SEric Miao (0x20000000 + (Nb) * PCMCIASp)
61b393c696SEric Miao #define _PCMCIAIO(Nb) _PCMCIA(Nb) /* PCMCIA I/O [0..1] */
62b393c696SEric Miao #define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \
63b393c696SEric Miao (_PCMCIA(Nb) + 2 * PCMCIAPrtSp)
64b393c696SEric Miao #define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \
65b393c696SEric Miao (_PCMCIA(Nb) + 3 * PCMCIAPrtSp)
66b393c696SEric Miao
67b393c696SEric Miao #define _PCMCIA0 _PCMCIA(0) /* PCMCIA 0 */
68b393c696SEric Miao #define _PCMCIA0IO _PCMCIAIO(0) /* PCMCIA 0 I/O */
69b393c696SEric Miao #define _PCMCIA0Attr _PCMCIAAttr(0) /* PCMCIA 0 Attribute */
70b393c696SEric Miao #define _PCMCIA0Mem _PCMCIAMem(0) /* PCMCIA 0 Memory */
71b393c696SEric Miao
72b393c696SEric Miao #define _PCMCIA1 _PCMCIA(1) /* PCMCIA 1 */
73b393c696SEric Miao #define _PCMCIA1IO _PCMCIAIO(1) /* PCMCIA 1 I/O */
74b393c696SEric Miao #define _PCMCIA1Attr _PCMCIAAttr(1) /* PCMCIA 1 Attribute */
75b393c696SEric Miao #define _PCMCIA1Mem _PCMCIAMem(1) /* PCMCIA 1 Memory */
76b393c696SEric Miao
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds #define MCXX_SETUP_MASK (0x7f)
791da177e4SLinus Torvalds #define MCXX_ASST_MASK (0x1f)
801da177e4SLinus Torvalds #define MCXX_HOLD_MASK (0x3f)
811da177e4SLinus Torvalds #define MCXX_SETUP_SHIFT (0)
821da177e4SLinus Torvalds #define MCXX_ASST_SHIFT (7)
831da177e4SLinus Torvalds #define MCXX_HOLD_SHIFT (14)
841da177e4SLinus Torvalds
pxa2xx_mcxx_hold(u_int pcmcia_cycle_ns,u_int mem_clk_10khz)851da177e4SLinus Torvalds static inline u_int pxa2xx_mcxx_hold(u_int pcmcia_cycle_ns,
861da177e4SLinus Torvalds u_int mem_clk_10khz)
871da177e4SLinus Torvalds {
881da177e4SLinus Torvalds u_int code = pcmcia_cycle_ns * mem_clk_10khz;
891da177e4SLinus Torvalds return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
901da177e4SLinus Torvalds }
911da177e4SLinus Torvalds
pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns,u_int mem_clk_10khz)921da177e4SLinus Torvalds static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns,
931da177e4SLinus Torvalds u_int mem_clk_10khz)
941da177e4SLinus Torvalds {
951da177e4SLinus Torvalds u_int code = pcmcia_cycle_ns * mem_clk_10khz;
9624d6572bSMilan Plzik return (code / 300000) + ((code % 300000) ? 1 : 0) + 1;
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds
pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns,u_int mem_clk_10khz)991da177e4SLinus Torvalds static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns,
1001da177e4SLinus Torvalds u_int mem_clk_10khz)
1011da177e4SLinus Torvalds {
1021da177e4SLinus Torvalds u_int code = pcmcia_cycle_ns * mem_clk_10khz;
1031da177e4SLinus Torvalds return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
1041da177e4SLinus Torvalds }
1051da177e4SLinus Torvalds
1061da177e4SLinus Torvalds /* This function returns the (approximate) command assertion period, in
1071da177e4SLinus Torvalds * nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
1081da177e4SLinus Torvalds */
pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,u_int pcmcia_mcxx_asst)1091da177e4SLinus Torvalds static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
1101da177e4SLinus Torvalds u_int pcmcia_mcxx_asst)
1111da177e4SLinus Torvalds {
1121da177e4SLinus Torvalds return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds
pxa2xx_pcmcia_mcmem(int sock,int speed,int clock)1156a946f1bSArnd Bergmann static uint32_t pxa2xx_pcmcia_mcmem(int sock, int speed, int clock)
1161da177e4SLinus Torvalds {
117ad68bb9fSMarek Vasut uint32_t val;
118ad68bb9fSMarek Vasut
119ad68bb9fSMarek Vasut val = ((pxa2xx_mcxx_setup(speed, clock)
1201da177e4SLinus Torvalds & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
1211da177e4SLinus Torvalds | ((pxa2xx_mcxx_asst(speed, clock)
1221da177e4SLinus Torvalds & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
1231da177e4SLinus Torvalds | ((pxa2xx_mcxx_hold(speed, clock)
1241da177e4SLinus Torvalds & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
1251da177e4SLinus Torvalds
1266a946f1bSArnd Bergmann return val;
1271da177e4SLinus Torvalds }
1281da177e4SLinus Torvalds
pxa2xx_pcmcia_mcio(int sock,int speed,int clock)1296a946f1bSArnd Bergmann static int pxa2xx_pcmcia_mcio(int sock, int speed, int clock)
1301da177e4SLinus Torvalds {
131ad68bb9fSMarek Vasut uint32_t val;
132ad68bb9fSMarek Vasut
133ad68bb9fSMarek Vasut val = ((pxa2xx_mcxx_setup(speed, clock)
1341da177e4SLinus Torvalds & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
1351da177e4SLinus Torvalds | ((pxa2xx_mcxx_asst(speed, clock)
1361da177e4SLinus Torvalds & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
1371da177e4SLinus Torvalds | ((pxa2xx_mcxx_hold(speed, clock)
1381da177e4SLinus Torvalds & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
1391da177e4SLinus Torvalds
140ad68bb9fSMarek Vasut
1416a946f1bSArnd Bergmann return val;
1421da177e4SLinus Torvalds }
1431da177e4SLinus Torvalds
pxa2xx_pcmcia_mcatt(int sock,int speed,int clock)1446a946f1bSArnd Bergmann static int pxa2xx_pcmcia_mcatt(int sock, int speed, int clock)
1451da177e4SLinus Torvalds {
146ad68bb9fSMarek Vasut uint32_t val;
147ad68bb9fSMarek Vasut
148ad68bb9fSMarek Vasut val = ((pxa2xx_mcxx_setup(speed, clock)
1491da177e4SLinus Torvalds & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
1501da177e4SLinus Torvalds | ((pxa2xx_mcxx_asst(speed, clock)
1511da177e4SLinus Torvalds & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
1521da177e4SLinus Torvalds | ((pxa2xx_mcxx_hold(speed, clock)
1531da177e4SLinus Torvalds & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
1541da177e4SLinus Torvalds
155ad68bb9fSMarek Vasut
1566a946f1bSArnd Bergmann return val;
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds
pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket * skt)1596a946f1bSArnd Bergmann static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
1601da177e4SLinus Torvalds {
1616a946f1bSArnd Bergmann unsigned long clk = clk_get_rate(skt->clk) / 10000;
1621da177e4SLinus Torvalds struct soc_pcmcia_timing timing;
1631da177e4SLinus Torvalds int sock = skt->nr;
1641da177e4SLinus Torvalds
1651da177e4SLinus Torvalds soc_common_pcmcia_get_timing(skt, &timing);
1661da177e4SLinus Torvalds
1676a946f1bSArnd Bergmann pxa_smemc_set_pcmcia_timing(sock,
1686a946f1bSArnd Bergmann pxa2xx_pcmcia_mcmem(sock, timing.mem, clk),
1696a946f1bSArnd Bergmann pxa2xx_pcmcia_mcatt(sock, timing.attr, clk),
1706a946f1bSArnd Bergmann pxa2xx_pcmcia_mcio(sock, timing.io, clk));
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds return 0;
1731da177e4SLinus Torvalds }
1741da177e4SLinus Torvalds
1751da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds static int
pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket * skt,unsigned long val,struct cpufreq_freqs * freqs)1781da177e4SLinus Torvalds pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
1791da177e4SLinus Torvalds unsigned long val,
1801da177e4SLinus Torvalds struct cpufreq_freqs *freqs)
1811da177e4SLinus Torvalds {
1821da177e4SLinus Torvalds switch (val) {
1831da177e4SLinus Torvalds case CPUFREQ_PRECHANGE:
1841da177e4SLinus Torvalds if (freqs->new > freqs->old) {
1851da177e4SLinus Torvalds debug(skt, 2, "new frequency %u.%uMHz > %u.%uMHz, "
1861da177e4SLinus Torvalds "pre-updating\n",
1871da177e4SLinus Torvalds freqs->new / 1000, (freqs->new / 100) % 10,
1881da177e4SLinus Torvalds freqs->old / 1000, (freqs->old / 100) % 10);
189d344a21aSMarek Vasut pxa2xx_pcmcia_set_timing(skt);
1901da177e4SLinus Torvalds }
1911da177e4SLinus Torvalds break;
1921da177e4SLinus Torvalds
1931da177e4SLinus Torvalds case CPUFREQ_POSTCHANGE:
1941da177e4SLinus Torvalds if (freqs->new < freqs->old) {
1951da177e4SLinus Torvalds debug(skt, 2, "new frequency %u.%uMHz < %u.%uMHz, "
1961da177e4SLinus Torvalds "post-updating\n",
1971da177e4SLinus Torvalds freqs->new / 1000, (freqs->new / 100) % 10,
1981da177e4SLinus Torvalds freqs->old / 1000, (freqs->old / 100) % 10);
199d344a21aSMarek Vasut pxa2xx_pcmcia_set_timing(skt);
2001da177e4SLinus Torvalds }
2011da177e4SLinus Torvalds break;
2021da177e4SLinus Torvalds }
2031da177e4SLinus Torvalds return 0;
2041da177e4SLinus Torvalds }
2051da177e4SLinus Torvalds #endif
2061da177e4SLinus Torvalds
pxa2xx_configure_sockets(struct device * dev,struct pcmcia_low_level * ops)207817ed574SRobert Jarzmik void pxa2xx_configure_sockets(struct device *dev, struct pcmcia_low_level *ops)
2081da177e4SLinus Torvalds {
209*d6df7df7SArnd Bergmann pxa_smemc_set_pcmcia_socket(1);
2101da177e4SLinus Torvalds }
211d5240dfdSRussell King EXPORT_SYMBOL(pxa2xx_configure_sockets);
2121da177e4SLinus Torvalds
213b393c696SEric Miao static const char *skt_names[] = {
214b393c696SEric Miao "PCMCIA socket 0",
215b393c696SEric Miao "PCMCIA socket 1",
216b393c696SEric Miao };
217b393c696SEric Miao
218b393c696SEric Miao #define SKT_DEV_INFO_SIZE(n) \
219b393c696SEric Miao (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
220b393c696SEric Miao
pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket * skt)221701a5dc0SRussell King - ARM Linux int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)
22220f18ff3SMarc Zyngier {
223b393c696SEric Miao skt->res_skt.start = _PCMCIA(skt->nr);
224b393c696SEric Miao skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1;
225b393c696SEric Miao skt->res_skt.name = skt_names[skt->nr];
226b393c696SEric Miao skt->res_skt.flags = IORESOURCE_MEM;
227b393c696SEric Miao
228b393c696SEric Miao skt->res_io.start = _PCMCIAIO(skt->nr);
229b393c696SEric Miao skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
230b393c696SEric Miao skt->res_io.name = "io";
231b393c696SEric Miao skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
232b393c696SEric Miao
233b393c696SEric Miao skt->res_mem.start = _PCMCIAMem(skt->nr);
234b393c696SEric Miao skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
235b393c696SEric Miao skt->res_mem.name = "memory";
236b393c696SEric Miao skt->res_mem.flags = IORESOURCE_MEM;
237b393c696SEric Miao
238b393c696SEric Miao skt->res_attr.start = _PCMCIAAttr(skt->nr);
239b393c696SEric Miao skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
240b393c696SEric Miao skt->res_attr.name = "attribute";
241b393c696SEric Miao skt->res_attr.flags = IORESOURCE_MEM;
242da4f0073SRussell King - ARM Linux
243da4f0073SRussell King - ARM Linux return soc_pcmcia_add_one(skt);
244b393c696SEric Miao }
245d0d26c33SRussell King EXPORT_SYMBOL(pxa2xx_drv_pcmcia_add_one);
246b393c696SEric Miao
pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level * ops)247701a5dc0SRussell King - ARM Linux void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
248701a5dc0SRussell King - ARM Linux {
249701a5dc0SRussell King - ARM Linux /* Provide our PXA2xx specific timing routines. */
250701a5dc0SRussell King - ARM Linux ops->set_timing = pxa2xx_pcmcia_set_timing;
251701a5dc0SRussell King - ARM Linux #ifdef CONFIG_CPU_FREQ
252701a5dc0SRussell King - ARM Linux ops->frequency_change = pxa2xx_pcmcia_frequency_change;
253701a5dc0SRussell King - ARM Linux #endif
254701a5dc0SRussell King - ARM Linux }
255d0d26c33SRussell King EXPORT_SYMBOL(pxa2xx_drv_pcmcia_ops);
256701a5dc0SRussell King - ARM Linux
pxa2xx_drv_pcmcia_probe(struct platform_device * dev)257d0d26c33SRussell King static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
258da4f0073SRussell King - ARM Linux {
259701a5dc0SRussell King - ARM Linux int i, ret = 0;
260da4f0073SRussell King - ARM Linux struct pcmcia_low_level *ops;
261da4f0073SRussell King - ARM Linux struct skt_dev_info *sinfo;
262da4f0073SRussell King - ARM Linux struct soc_pcmcia_socket *skt;
2632a125dd5SEric Miao struct clk *clk;
264da4f0073SRussell King - ARM Linux
265d0d26c33SRussell King ops = (struct pcmcia_low_level *)dev->dev.platform_data;
266a4257af5SMarek Vasut if (!ops) {
267a4257af5SMarek Vasut ret = -ENODEV;
268a4257af5SMarek Vasut goto err0;
269a4257af5SMarek Vasut }
270a4257af5SMarek Vasut
271a4257af5SMarek Vasut if (cpu_is_pxa320() && ops->nr > 1) {
272a4257af5SMarek Vasut dev_err(&dev->dev, "pxa320 supports only one pcmcia slot");
273a4257af5SMarek Vasut ret = -EINVAL;
274a4257af5SMarek Vasut goto err0;
275a4257af5SMarek Vasut }
276da4f0073SRussell King - ARM Linux
277ac92f151SRussell King clk = devm_clk_get(&dev->dev, NULL);
278e09a7164SWei Yongjun if (IS_ERR(clk))
2792a125dd5SEric Miao return -ENODEV;
2802a125dd5SEric Miao
281701a5dc0SRussell King - ARM Linux pxa2xx_drv_pcmcia_ops(ops);
28220f18ff3SMarc Zyngier
2838e2caf0dSRussell King sinfo = devm_kzalloc(&dev->dev, SKT_DEV_INFO_SIZE(ops->nr),
2848e2caf0dSRussell King GFP_KERNEL);
285ac92f151SRussell King if (!sinfo)
286da4f0073SRussell King - ARM Linux return -ENOMEM;
28720f18ff3SMarc Zyngier
288da4f0073SRussell King - ARM Linux sinfo->nskt = ops->nr;
289da4f0073SRussell King - ARM Linux
290da4f0073SRussell King - ARM Linux /* Initialize processor specific parameters */
291da4f0073SRussell King - ARM Linux for (i = 0; i < ops->nr; i++) {
292da4f0073SRussell King - ARM Linux skt = &sinfo->skt[i];
293da4f0073SRussell King - ARM Linux
294da4f0073SRussell King - ARM Linux skt->nr = ops->first + i;
2952a125dd5SEric Miao skt->clk = clk;
296e0d21178SRussell King soc_pcmcia_init_one(skt, ops, &dev->dev);
297da4f0073SRussell King - ARM Linux
298da4f0073SRussell King - ARM Linux ret = pxa2xx_drv_pcmcia_add_one(skt);
299da4f0073SRussell King - ARM Linux if (ret)
300a4257af5SMarek Vasut goto err1;
301da4f0073SRussell King - ARM Linux }
302da4f0073SRussell King - ARM Linux
303817ed574SRobert Jarzmik pxa2xx_configure_sockets(&dev->dev, ops);
304a7a5ac58SMarc Zyngier dev_set_drvdata(&dev->dev, sinfo);
30520f18ff3SMarc Zyngier
306a4257af5SMarek Vasut return 0;
307a4257af5SMarek Vasut
308a4257af5SMarek Vasut err1:
309a4257af5SMarek Vasut while (--i >= 0)
310a4257af5SMarek Vasut soc_pcmcia_remove_one(&sinfo->skt[i]);
3118e2caf0dSRussell King
312a4257af5SMarek Vasut err0:
3131da177e4SLinus Torvalds return ret;
3141da177e4SLinus Torvalds }
3159468613bSRussell King
pxa2xx_drv_pcmcia_remove(struct platform_device * dev)3169468613bSRussell King static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
3179468613bSRussell King {
318be85458eSRussell King - ARM Linux struct skt_dev_info *sinfo = platform_get_drvdata(dev);
319be85458eSRussell King - ARM Linux int i;
320be85458eSRussell King - ARM Linux
321be85458eSRussell King - ARM Linux for (i = 0; i < sinfo->nskt; i++)
322be85458eSRussell King - ARM Linux soc_pcmcia_remove_one(&sinfo->skt[i]);
323be85458eSRussell King - ARM Linux
324be85458eSRussell King - ARM Linux return 0;
3259468613bSRussell King }
3269468613bSRussell King
pxa2xx_drv_pcmcia_resume(struct device * dev)32785c61021SMike Rapoport static int pxa2xx_drv_pcmcia_resume(struct device *dev)
3289468613bSRussell King {
329817ed574SRobert Jarzmik struct pcmcia_low_level *ops = (struct pcmcia_low_level *)dev->platform_data;
330817ed574SRobert Jarzmik
331817ed574SRobert Jarzmik pxa2xx_configure_sockets(dev, ops);
332d7646f76SDominik Brodowski return 0;
3331da177e4SLinus Torvalds }
3341da177e4SLinus Torvalds
33547145210SAlexey Dobriyan static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = {
33685c61021SMike Rapoport .resume = pxa2xx_drv_pcmcia_resume,
33785c61021SMike Rapoport };
33885c61021SMike Rapoport
3399468613bSRussell King static struct platform_driver pxa2xx_pcmcia_driver = {
3401da177e4SLinus Torvalds .probe = pxa2xx_drv_pcmcia_probe,
3419468613bSRussell King .remove = pxa2xx_drv_pcmcia_remove,
3429468613bSRussell King .driver = {
3431da177e4SLinus Torvalds .name = "pxa2xx-pcmcia",
34485c61021SMike Rapoport .pm = &pxa2xx_drv_pcmcia_pm_ops,
3459468613bSRussell King },
3461da177e4SLinus Torvalds };
3471da177e4SLinus Torvalds
pxa2xx_pcmcia_init(void)3481da177e4SLinus Torvalds static int __init pxa2xx_pcmcia_init(void)
3491da177e4SLinus Torvalds {
3509468613bSRussell King return platform_driver_register(&pxa2xx_pcmcia_driver);
3511da177e4SLinus Torvalds }
3521da177e4SLinus Torvalds
pxa2xx_pcmcia_exit(void)3531da177e4SLinus Torvalds static void __exit pxa2xx_pcmcia_exit(void)
3541da177e4SLinus Torvalds {
3559468613bSRussell King platform_driver_unregister(&pxa2xx_pcmcia_driver);
3561da177e4SLinus Torvalds }
3571da177e4SLinus Torvalds
358f36598aeSRichard Purdie fs_initcall(pxa2xx_pcmcia_init);
3591da177e4SLinus Torvalds module_exit(pxa2xx_pcmcia_exit);
3601da177e4SLinus Torvalds
3611da177e4SLinus Torvalds MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>");
3621da177e4SLinus Torvalds MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA2xx core socket driver");
3631da177e4SLinus Torvalds MODULE_LICENSE("GPL");
36412c2c019SKay Sievers MODULE_ALIAS("platform:pxa2xx-pcmcia");
365