aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-02-27 19:19:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-02-27 19:19:22 -0500
commitf1dd6ad599732fc89f36fdd65a2c2cf3c63a8711 (patch)
tree5092207128e47cba99dc0fe373fff6a36f4cb4b8 /drivers/pcmcia
parent8d37a371b6869920e6c40c495c68eabba1ef3909 (diff)
parente10b234b3c4e255d3300a486c4ac15b43253ac6d (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (141 commits) MIPS: Alchemy: defconfig updates MIPS: Alchemy: Fix Au1100 ethernet build failure MIPS: Alchemy: Repair db1500/bosporus builds MIPS: ARC: Cleanup unused definitions from sgialib.h MIPS: Cobalt: convert legacy port addresses to GT-64111 bus addresses MIPS: Alchemy: use 36bit addresses for PCMCIA resources. MIPS: Cobalt: Fix theoretical port aliasing issue MIPS: Use ALIGN(x, bytes) instead of __ALIGN_MASK(x, bytes - 1) MIPS: Crazy spinlock speed test. MIPS: Optimize spinlocks. MIPS: Alchemy: devboard PM needs to save CPLD registers. MIPS: PowerTV: Eliminate duplicate opcode definition macros MIPS: Lemote 2F: Move printks out of port_access_lock. MIPS: PNX833x: Convert IRQ controller locks to raw spinlocks. MIPS: Octeon: Replace spinlock with raw_spinlocks in dma-octeon.c. MIPS: Octeon: Replace rwlocks in irq_chip handlers with raw_spinlocks. MIPS: Octeon: Convert octeon_irq_msi_lock to raw spinlock. MIPS: Loongson: Remove pointless sample_lock from oprofile code. MIPS: SNI: Convert sni_rm200_i8259A_lock to raw spinlock. MIPS: i8259: Convert IRQ controller lock to raw spinlock. ...
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/Kconfig21
-rw-r--r--drivers/pcmcia/Makefile12
-rw-r--r--drivers/pcmcia/au1000_db1x00.c305
-rw-r--r--drivers/pcmcia/au1000_generic.c10
-rw-r--r--drivers/pcmcia/au1000_generic.h18
-rw-r--r--drivers/pcmcia/au1000_pb1x00.c119
-rw-r--r--drivers/pcmcia/au1000_xxs1500.c188
-rw-r--r--drivers/pcmcia/db1xxx_ss.c623
-rw-r--r--drivers/pcmcia/xxs1500_ss.c350
9 files changed, 1003 insertions, 643 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index e8f35dac2d51..0a6601c76809 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -173,6 +173,27 @@ config PCMCIA_AU1X00
173 tristate "Au1x00 pcmcia support" 173 tristate "Au1x00 pcmcia support"
174 depends on SOC_AU1X00 && PCMCIA 174 depends on SOC_AU1X00 && PCMCIA
175 175
176config PCMCIA_ALCHEMY_DEVBOARD
177 tristate "Alchemy Db/Pb1xxx PCMCIA socket services"
178 depends on SOC_AU1X00 && PCMCIA
179 select 64BIT_PHYS_ADDR
180 help
181 Enable this driver of you want PCMCIA support on your Alchemy
182 Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200 board.
183 NOT suitable for the PB1000!
184
185 This driver is also available as a module called db1xxx_ss.ko
186
187config PCMCIA_XXS1500
188 tristate "MyCable XXS1500 PCMCIA socket support"
189 depends on PCMCIA && MIPS_XXS1500
190 select 64BIT_PHYS_ADDR
191 help
192 Support for the PCMCIA/CF socket interface on MyCable XXS1500
193 systems.
194
195 This driver is also available as a module called xxs1500_ss.ko
196
176config PCMCIA_BCM63XX 197config PCMCIA_BCM63XX
177 tristate "bcm63xx pcmcia support" 198 tristate "bcm63xx pcmcia support"
178 depends on BCM63XX && PCMCIA 199 depends on BCM63XX && PCMCIA
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 3c83f68c803a..381b031d9d75 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -35,18 +35,10 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o
35obj-$(CONFIG_BFIN_CFPCMCIA) += bfin_cf_pcmcia.o 35obj-$(CONFIG_BFIN_CFPCMCIA) += bfin_cf_pcmcia.o
36obj-$(CONFIG_AT91_CF) += at91_cf.o 36obj-$(CONFIG_AT91_CF) += at91_cf.o
37obj-$(CONFIG_ELECTRA_CF) += electra_cf.o 37obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
38obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
38 39
39au1x00_ss-y += au1000_generic.o 40au1x00_ss-y += au1000_generic.o
40au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o 41au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o
41au1x00_ss-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o
42au1x00_ss-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o
43au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o
44au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o
45au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o
46au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o
47au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o
48au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o
49au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o
50 42
51sa1111_cs-y += sa1111_generic.o 43sa1111_cs-y += sa1111_generic.o
52sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o 44sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
@@ -76,3 +68,5 @@ pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o
76pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o 68pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o
77 69
78obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) 70obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y)
71
72obj-$(CONFIG_PCMCIA_XXS1500) += xxs1500_ss.o
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c
deleted file mode 100644
index c78d77fd7e3b..000000000000
--- a/drivers/pcmcia/au1000_db1x00.c
+++ /dev/null
@@ -1,305 +0,0 @@
1/*
2 *
3 * Alchemy Semi Db1x00 boards specific pcmcia routines.
4 *
5 * Copyright 2002 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * Copyright 2004 Pete Popov, updated the driver to 2.6.
10 * Followed the sa11xx API and largely copied many of the hardware
11 * independent functions.
12 *
13 * ########################################################################
14 *
15 * This program is free software; you can distribute it and/or modify it
16 * under the terms of the GNU General Public License (Version 2) as
17 * published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
27 *
28 * ########################################################################
29 *
30 *
31 */
32
33#include <linux/module.h>
34#include <linux/kernel.h>
35#include <linux/errno.h>
36#include <linux/interrupt.h>
37#include <linux/device.h>
38#include <linux/init.h>
39
40#include <asm/irq.h>
41#include <asm/signal.h>
42#include <asm/mach-au1x00/au1000.h>
43
44#if defined(CONFIG_MIPS_DB1200)
45 #include <db1200.h>
46#elif defined(CONFIG_MIPS_PB1200)
47 #include <pb1200.h>
48#else
49 #include <asm/mach-db1x00/db1x00.h>
50 static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
51#endif
52
53#include "au1000_generic.h"
54
55#if 0
56#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
57#else
58#define debug(x,args...)
59#endif
60
61
62struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS];
63extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int);
64
65static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt)
66{
67#ifdef CONFIG_MIPS_DB1550
68 skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3;
69#elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
70 skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT;
71#else
72 skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2;
73#endif
74 return 0;
75}
76
77static void db1x00_pcmcia_shutdown(struct au1000_pcmcia_socket *skt)
78{
79 bcsr->pcmcia = 0; /* turn off power */
80 au_sync_delay(2);
81}
82
83static void
84db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state *state)
85{
86 u32 inserted;
87 unsigned char vs;
88
89 state->ready = 0;
90 state->vs_Xv = 0;
91 state->vs_3v = 0;
92 state->detect = 0;
93
94 switch (skt->nr) {
95 case 0:
96 vs = bcsr->status & 0x3;
97#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
98 inserted = BOARD_CARD_INSERTED(0);
99#else
100 inserted = !(bcsr->status & (1<<4));
101#endif
102 break;
103 case 1:
104 vs = (bcsr->status & 0xC)>>2;
105#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
106 inserted = BOARD_CARD_INSERTED(1);
107#else
108 inserted = !(bcsr->status & (1<<5));
109#endif
110 break;
111 default:/* should never happen */
112 return;
113 }
114
115 if (inserted)
116 debug("db1x00 socket %d: inserted %d, vs %d pcmcia %x\n",
117 skt->nr, inserted, vs, bcsr->pcmcia);
118
119 if (inserted) {
120 switch (vs) {
121 case 0:
122 case 2:
123 state->vs_3v=1;
124 break;
125 case 3: /* 5V */
126 break;
127 default:
128 /* return without setting 'detect' */
129 printk(KERN_ERR "db1x00 bad VS (%d)\n",
130 vs);
131 }
132 state->detect = 1;
133 state->ready = 1;
134 }
135 else {
136 /* if the card was previously inserted and then ejected,
137 * we should turn off power to it
138 */
139 if ((skt->nr == 0) && (bcsr->pcmcia & BCSR_PCMCIA_PC0RST)) {
140 bcsr->pcmcia &= ~(BCSR_PCMCIA_PC0RST |
141 BCSR_PCMCIA_PC0DRVEN |
142 BCSR_PCMCIA_PC0VPP |
143 BCSR_PCMCIA_PC0VCC);
144 au_sync_delay(10);
145 }
146 else if ((skt->nr == 1) && bcsr->pcmcia & BCSR_PCMCIA_PC1RST) {
147 bcsr->pcmcia &= ~(BCSR_PCMCIA_PC1RST |
148 BCSR_PCMCIA_PC1DRVEN |
149 BCSR_PCMCIA_PC1VPP |
150 BCSR_PCMCIA_PC1VCC);
151 au_sync_delay(10);
152 }
153 }
154
155 state->bvd1=1;
156 state->bvd2=1;
157 state->wrprot=0;
158}
159
160static int
161db1x00_pcmcia_configure_socket(struct au1000_pcmcia_socket *skt, struct socket_state_t *state)
162{
163 u16 pwr;
164 int sock = skt->nr;
165
166 debug("config_skt %d Vcc %dV Vpp %dV, reset %d\n",
167 sock, state->Vcc, state->Vpp,
168 state->flags & SS_RESET);
169
170 /* pcmcia reg was set to zero at init time. Be careful when
171 * initializing a socket not to wipe out the settings of the
172 * other socket.
173 */
174 pwr = bcsr->pcmcia;
175 pwr &= ~(0xf << sock*8); /* clear voltage settings */
176
177 state->Vpp = 0;
178 switch(state->Vcc){
179 case 0: /* Vcc 0 */
180 pwr |= SET_VCC_VPP(0,0,sock);
181 break;
182 case 50: /* Vcc 5V */
183 switch(state->Vpp) {
184 case 0:
185 pwr |= SET_VCC_VPP(2,0,sock);
186 break;
187 case 50:
188 pwr |= SET_VCC_VPP(2,1,sock);
189 break;
190 case 12:
191 pwr |= SET_VCC_VPP(2,2,sock);
192 break;
193 case 33:
194 default:
195 pwr |= SET_VCC_VPP(0,0,sock);
196 printk("%s: bad Vcc/Vpp (%d:%d)\n",
197 __func__,
198 state->Vcc,
199 state->Vpp);
200 break;
201 }
202 break;
203 case 33: /* Vcc 3.3V */
204 switch(state->Vpp) {
205 case 0:
206 pwr |= SET_VCC_VPP(1,0,sock);
207 break;
208 case 12:
209 pwr |= SET_VCC_VPP(1,2,sock);
210 break;
211 case 33:
212 pwr |= SET_VCC_VPP(1,1,sock);
213 break;
214 case 50:
215 default:
216 pwr |= SET_VCC_VPP(0,0,sock);
217 printk("%s: bad Vcc/Vpp (%d:%d)\n",
218 __func__,
219 state->Vcc,
220 state->Vpp);
221 break;
222 }
223 break;
224 default: /* what's this ? */
225 pwr |= SET_VCC_VPP(0,0,sock);
226 printk(KERN_ERR "%s: bad Vcc %d\n",
227 __func__, state->Vcc);
228 break;
229 }
230
231 bcsr->pcmcia = pwr;
232 au_sync_delay(300);
233
234 if (sock == 0) {
235 if (!(state->flags & SS_RESET)) {
236 pwr |= BCSR_PCMCIA_PC0DRVEN;
237 bcsr->pcmcia = pwr;
238 au_sync_delay(300);
239 pwr |= BCSR_PCMCIA_PC0RST;
240 bcsr->pcmcia = pwr;
241 au_sync_delay(100);
242 }
243 else {
244 pwr &= ~(BCSR_PCMCIA_PC0RST | BCSR_PCMCIA_PC0DRVEN);
245 bcsr->pcmcia = pwr;
246 au_sync_delay(100);
247 }
248 }
249 else {
250 if (!(state->flags & SS_RESET)) {
251 pwr |= BCSR_PCMCIA_PC1DRVEN;
252 bcsr->pcmcia = pwr;
253 au_sync_delay(300);
254 pwr |= BCSR_PCMCIA_PC1RST;
255 bcsr->pcmcia = pwr;
256 au_sync_delay(100);
257 }
258 else {
259 pwr &= ~(BCSR_PCMCIA_PC1RST | BCSR_PCMCIA_PC1DRVEN);
260 bcsr->pcmcia = pwr;
261 au_sync_delay(100);
262 }
263 }
264 return 0;
265}
266
267/*
268 * Enable card status IRQs on (re-)initialisation. This can
269 * be called at initialisation, power management event, or
270 * pcmcia event.
271 */
272void db1x00_socket_init(struct au1000_pcmcia_socket *skt)
273{
274 /* nothing to do for now */
275}
276
277/*
278 * Disable card status IRQs and PCMCIA bus on suspend.
279 */
280void db1x00_socket_suspend(struct au1000_pcmcia_socket *skt)
281{
282 /* nothing to do for now */
283}
284
285struct pcmcia_low_level db1x00_pcmcia_ops = {
286 .owner = THIS_MODULE,
287
288 .hw_init = db1x00_pcmcia_hw_init,
289 .hw_shutdown = db1x00_pcmcia_shutdown,
290
291 .socket_state = db1x00_pcmcia_socket_state,
292 .configure_socket = db1x00_pcmcia_configure_socket,
293
294 .socket_init = db1x00_socket_init,
295 .socket_suspend = db1x00_socket_suspend
296};
297
298int au1x_board_init(struct device *dev)
299{
300 int ret = -ENODEV;
301 bcsr->pcmcia = 0; /* turn off power, if it's not already off */
302 au_sync_delay(2);
303 ret = au1x00_pcmcia_socket_probe(dev, &db1x00_pcmcia_ops, 0, 2);
304 return ret;
305}
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 02088704ac2c..171c8a654887 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -405,18 +405,16 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
405 skt->virt_io = (void *) 405 skt->virt_io = (void *)
406 (ioremap((phys_t)AU1X_SOCK0_IO, 0x1000) - 406 (ioremap((phys_t)AU1X_SOCK0_IO, 0x1000) -
407 (u32)mips_io_port_base); 407 (u32)mips_io_port_base);
408 skt->phys_attr = AU1X_SOCK0_PSEUDO_PHYS_ATTR; 408 skt->phys_attr = AU1X_SOCK0_PHYS_ATTR;
409 skt->phys_mem = AU1X_SOCK0_PSEUDO_PHYS_MEM; 409 skt->phys_mem = AU1X_SOCK0_PHYS_MEM;
410 } 410 }
411#ifndef CONFIG_MIPS_XXS1500
412 else { 411 else {
413 skt->virt_io = (void *) 412 skt->virt_io = (void *)
414 (ioremap((phys_t)AU1X_SOCK1_IO, 0x1000) - 413 (ioremap((phys_t)AU1X_SOCK1_IO, 0x1000) -
415 (u32)mips_io_port_base); 414 (u32)mips_io_port_base);
416 skt->phys_attr = AU1X_SOCK1_PSEUDO_PHYS_ATTR; 415 skt->phys_attr = AU1X_SOCK1_PHYS_ATTR;
417 skt->phys_mem = AU1X_SOCK1_PSEUDO_PHYS_MEM; 416 skt->phys_mem = AU1X_SOCK1_PHYS_MEM;
418 } 417 }
419#endif
420 pcmcia_base_vaddrs[i] = (u32 *)skt->virt_io; 418 pcmcia_base_vaddrs[i] = (u32 *)skt->virt_io;
421 ret = ops->hw_init(skt); 419 ret = ops->hw_init(skt);
422 420
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index 13a4fbc58711..a324d329dea6 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -36,30 +36,14 @@
36#define AU1X_SOCK0_IO 0xF00000000ULL 36#define AU1X_SOCK0_IO 0xF00000000ULL
37#define AU1X_SOCK0_PHYS_ATTR 0xF40000000ULL 37#define AU1X_SOCK0_PHYS_ATTR 0xF40000000ULL
38#define AU1X_SOCK0_PHYS_MEM 0xF80000000ULL 38#define AU1X_SOCK0_PHYS_MEM 0xF80000000ULL
39/* pseudo 32 bit phys addresses, which get fixed up to the
40 * real 36 bit address in fixup_bigphys_addr() */
41#define AU1X_SOCK0_PSEUDO_PHYS_ATTR 0xF4000000
42#define AU1X_SOCK0_PSEUDO_PHYS_MEM 0xF8000000
43 39
44/* pcmcia socket 1 needs external glue logic so the memory map 40/* pcmcia socket 1 needs external glue logic so the memory map
45 * differs from board to board. 41 * differs from board to board.
46 */ 42 */
47#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || \ 43#if defined(CONFIG_MIPS_PB1000)
48 defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || \
49 defined(CONFIG_MIPS_PB1200)
50#define AU1X_SOCK1_IO 0xF08000000ULL 44#define AU1X_SOCK1_IO 0xF08000000ULL
51#define AU1X_SOCK1_PHYS_ATTR 0xF48000000ULL 45#define AU1X_SOCK1_PHYS_ATTR 0xF48000000ULL
52#define AU1X_SOCK1_PHYS_MEM 0xF88000000ULL 46#define AU1X_SOCK1_PHYS_MEM 0xF88000000ULL
53#define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000
54#define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8800000
55#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || \
56 defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || \
57 defined(CONFIG_MIPS_DB1200)
58#define AU1X_SOCK1_IO 0xF04000000ULL
59#define AU1X_SOCK1_PHYS_ATTR 0xF44000000ULL
60#define AU1X_SOCK1_PHYS_MEM 0xF84000000ULL
61#define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4400000
62#define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8400000
63#endif 47#endif
64 48
65struct pcmcia_state { 49struct pcmcia_state {
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index b1984ed72d1d..5a979cb8f3e6 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * 2 *
3 * Alchemy Semi Pb1x00 boards specific pcmcia routines. 3 * Alchemy Semi Pb1000 boards specific pcmcia routines.
4 * 4 *
5 * Copyright 2002 MontaVista Software Inc. 5 * Copyright 2002 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc. 6 * Author: MontaVista Software, Inc.
@@ -46,20 +46,11 @@
46 46
47#define debug(fmt, arg...) do { } while (0) 47#define debug(fmt, arg...) do { } while (0)
48 48
49#ifdef CONFIG_MIPS_PB1000
50#include <asm/pb1000.h> 49#include <asm/pb1000.h>
51#define PCMCIA_IRQ AU1000_GPIO_15 50#define PCMCIA_IRQ AU1000_GPIO_15
52#elif defined (CONFIG_MIPS_PB1500)
53#include <asm/pb1500.h>
54#define PCMCIA_IRQ AU1500_GPIO_203
55#elif defined (CONFIG_MIPS_PB1100)
56#include <asm/pb1100.h>
57#define PCMCIA_IRQ AU1000_GPIO_11
58#endif
59 51
60static int pb1x00_pcmcia_init(struct pcmcia_init *init) 52static int pb1x00_pcmcia_init(struct pcmcia_init *init)
61{ 53{
62#ifdef CONFIG_MIPS_PB1000
63 u16 pcr; 54 u16 pcr;
64 pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST; 55 pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
65 56
@@ -74,21 +65,10 @@ static int pb1x00_pcmcia_init(struct pcmcia_init *init)
74 au_sync_delay(20); 65 au_sync_delay(20);
75 66
76 return PCMCIA_NUM_SOCKS; 67 return PCMCIA_NUM_SOCKS;
77
78#else /* fixme -- take care of the Pb1500 at some point */
79
80 u16 pcr;
81 pcr = au_readw(PCMCIA_BOARD_REG) & ~0xf; /* turn off power */
82 pcr &= ~(PC_DEASSERT_RST | PC_DRV_EN);
83 au_writew(pcr, PCMCIA_BOARD_REG);
84 au_sync_delay(500);
85 return PCMCIA_NUM_SOCKS;
86#endif
87} 68}
88 69
89static int pb1x00_pcmcia_shutdown(void) 70static int pb1x00_pcmcia_shutdown(void)
90{ 71{
91#ifdef CONFIG_MIPS_PB1000
92 u16 pcr; 72 u16 pcr;
93 pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST; 73 pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
94 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0); 74 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
@@ -96,14 +76,6 @@ static int pb1x00_pcmcia_shutdown(void)
96 au_writel(pcr, PB1000_PCR); 76 au_writel(pcr, PB1000_PCR);
97 au_sync_delay(20); 77 au_sync_delay(20);
98 return 0; 78 return 0;
99#else
100 u16 pcr;
101 pcr = au_readw(PCMCIA_BOARD_REG) & ~0xf; /* turn off power */
102 pcr &= ~(PC_DEASSERT_RST | PC_DRV_EN);
103 au_writew(pcr, PCMCIA_BOARD_REG);
104 au_sync_delay(2);
105 return 0;
106#endif
107} 79}
108 80
109static int 81static int
@@ -112,21 +84,11 @@ pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
112 u32 inserted0, inserted1; 84 u32 inserted0, inserted1;
113 u16 vs0, vs1; 85 u16 vs0, vs1;
114 86
115#ifdef CONFIG_MIPS_PB1000
116 vs0 = vs1 = (u16)au_readl(PB1000_ACR1); 87 vs0 = vs1 = (u16)au_readl(PB1000_ACR1);
117 inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2)); 88 inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2));
118 inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2)); 89 inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2));
119 vs0 = (vs0 >> 4) & 0x3; 90 vs0 = (vs0 >> 4) & 0x3;
120 vs1 = (vs1 >> 12) & 0x3; 91 vs1 = (vs1 >> 12) & 0x3;
121#else
122 vs0 = (au_readw(BOARD_STATUS_REG) >> 4) & 0x3;
123#ifdef CONFIG_MIPS_PB1500
124 inserted0 = !((au_readl(GPIO2_PINSTATE) >> 1) & 0x1); /* gpio 201 */
125#else /* Pb1100 */
126 inserted0 = !((au_readl(SYS_PINSTATERD) >> 9) & 0x1); /* gpio 9 */
127#endif
128 inserted1 = 0;
129#endif
130 92
131 state->ready = 0; 93 state->ready = 0;
132 state->vs_Xv = 0; 94 state->vs_Xv = 0;
@@ -203,7 +165,6 @@ pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
203 165
204 if(configure->sock > PCMCIA_MAX_SOCK) return -1; 166 if(configure->sock > PCMCIA_MAX_SOCK) return -1;
205 167
206#ifdef CONFIG_MIPS_PB1000
207 pcr = au_readl(PB1000_PCR); 168 pcr = au_readl(PB1000_PCR);
208 169
209 if (configure->sock == 0) { 170 if (configure->sock == 0) {
@@ -323,84 +284,6 @@ pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
323 au_writel(pcr, PB1000_PCR); 284 au_writel(pcr, PB1000_PCR);
324 au_sync_delay(300); 285 au_sync_delay(300);
325 286
326#else
327
328 pcr = au_readw(PCMCIA_BOARD_REG) & ~0xf;
329
330 debug("Vcc %dV Vpp %dV, pcr %x, reset %d\n",
331 configure->vcc, configure->vpp, pcr, configure->reset);
332
333
334 switch(configure->vcc){
335 case 0: /* Vcc 0 */
336 pcr |= SET_VCC_VPP(0,0);
337 break;
338 case 50: /* Vcc 5V */
339 switch(configure->vpp) {
340 case 0:
341 pcr |= SET_VCC_VPP(2,0);
342 break;
343 case 50:
344 pcr |= SET_VCC_VPP(2,1);
345 break;
346 case 12:
347 pcr |= SET_VCC_VPP(2,2);
348 break;
349 case 33:
350 default:
351 pcr |= SET_VCC_VPP(0,0);
352 printk("%s: bad Vcc/Vpp (%d:%d)\n",
353 __func__,
354 configure->vcc,
355 configure->vpp);
356 break;
357 }
358 break;
359 case 33: /* Vcc 3.3V */
360 switch(configure->vpp) {
361 case 0:
362 pcr |= SET_VCC_VPP(1,0);
363 break;
364 case 12:
365 pcr |= SET_VCC_VPP(1,2);
366 break;
367 case 33:
368 pcr |= SET_VCC_VPP(1,1);
369 break;
370 case 50:
371 default:
372 pcr |= SET_VCC_VPP(0,0);
373 printk("%s: bad Vcc/Vpp (%d:%d)\n",
374 __func__,
375 configure->vcc,
376 configure->vpp);
377 break;
378 }
379 break;
380 default: /* what's this ? */
381 pcr |= SET_VCC_VPP(0,0);
382 printk(KERN_ERR "%s: bad Vcc %d\n",
383 __func__, configure->vcc);
384 break;
385 }
386
387 au_writew(pcr, PCMCIA_BOARD_REG);
388 au_sync_delay(300);
389
390 if (!configure->reset) {
391 pcr |= PC_DRV_EN;
392 au_writew(pcr, PCMCIA_BOARD_REG);
393 au_sync_delay(100);
394 pcr |= PC_DEASSERT_RST;
395 au_writew(pcr, PCMCIA_BOARD_REG);
396 au_sync_delay(100);
397 }
398 else {
399 pcr &= ~(PC_DEASSERT_RST | PC_DRV_EN);
400 au_writew(pcr, PCMCIA_BOARD_REG);
401 au_sync_delay(100);
402 }
403#endif
404 return 0; 287 return 0;
405} 288}
406 289
diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c
deleted file mode 100644
index b43d47b50819..000000000000
--- a/drivers/pcmcia/au1000_xxs1500.c
+++ /dev/null
@@ -1,188 +0,0 @@
1/*
2 *
3 * MyCable board specific pcmcia routines.
4 *
5 * Copyright 2003 MontaVista Software Inc.
6 * Author: Pete Popov, MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * ########################################################################
10 *
11 * This program is free software; you can distribute it and/or modify it
12 * under the terms of the GNU General Public License (Version 2) as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 *
24 * ########################################################################
25 *
26 *
27 */
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/delay.h>
31#include <linux/ioport.h>
32#include <linux/kernel.h>
33#include <linux/timer.h>
34#include <linux/mm.h>
35#include <linux/proc_fs.h>
36#include <linux/types.h>
37
38#include <pcmcia/cs_types.h>
39#include <pcmcia/cs.h>
40#include <pcmcia/ss.h>
41#include <pcmcia/cistpl.h>
42#include <pcmcia/bus_ops.h>
43
44#include <asm/io.h>
45#include <asm/irq.h>
46#include <asm/system.h>
47
48#include <asm/au1000.h>
49#include <asm/au1000_pcmcia.h>
50
51#define PCMCIA_MAX_SOCK 0
52#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1)
53#define PCMCIA_IRQ AU1000_GPIO_4
54
55#if 0
56#define DEBUG(x, args...) printk(__func__ ": " x, ##args)
57#else
58#define DEBUG(x,args...)
59#endif
60
61static int xxs1500_pcmcia_init(struct pcmcia_init *init)
62{
63 return PCMCIA_NUM_SOCKS;
64}
65
66static int xxs1500_pcmcia_shutdown(void)
67{
68 /* turn off power */
69 au_writel(au_readl(GPIO2_PINSTATE) | (1<<14)|(1<<30),
70 GPIO2_OUTPUT);
71 au_sync_delay(100);
72
73 /* assert reset */
74 au_writel(au_readl(GPIO2_PINSTATE) | (1<<4)|(1<<20),
75 GPIO2_OUTPUT);
76 au_sync_delay(100);
77 return 0;
78}
79
80
81static int
82xxs1500_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
83{
84 u32 inserted; u32 vs;
85 unsigned long gpio, gpio2;
86
87 if(sock > PCMCIA_MAX_SOCK) return -1;
88
89 gpio = au_readl(SYS_PINSTATERD);
90 gpio2 = au_readl(GPIO2_PINSTATE);
91
92 vs = gpio2 & ((1<<8) | (1<<9));
93 inserted = (!(gpio & 0x1) && !(gpio & 0x2));
94
95 state->ready = 0;
96 state->vs_Xv = 0;
97 state->vs_3v = 0;
98 state->detect = 0;
99
100 if (inserted) {
101 switch (vs) {
102 case 0:
103 case 1:
104 case 2:
105 state->vs_3v=1;
106 break;
107 case 3: /* 5V */
108 default:
109 /* return without setting 'detect' */
110 printk(KERN_ERR "au1x00_cs: unsupported VS\n",
111 vs);
112 return;
113 }
114 state->detect = 1;
115 }
116
117 if (state->detect) {
118 state->ready = 1;
119 }
120
121 state->bvd1= gpio2 & (1<<10);
122 state->bvd2 = gpio2 & (1<<11);
123 state->wrprot=0;
124 return 1;
125}
126
127
128static int xxs1500_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
129{
130
131 if(info->sock > PCMCIA_MAX_SOCK) return -1;
132 info->irq = PCMCIA_IRQ;
133 return 0;
134}
135
136
137static int
138xxs1500_pcmcia_configure_socket(const struct pcmcia_configure *configure)
139{
140
141 if(configure->sock > PCMCIA_MAX_SOCK) return -1;
142
143 DEBUG("Vcc %dV Vpp %dV, reset %d\n",
144 configure->vcc, configure->vpp, configure->reset);
145
146 switch(configure->vcc){
147 case 33: /* Vcc 3.3V */
148 /* turn on power */
149 DEBUG("turn on power\n");
150 au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30),
151 GPIO2_OUTPUT);
152 au_sync_delay(100);
153 break;
154 case 50: /* Vcc 5V */
155 default: /* what's this ? */
156 printk(KERN_ERR "au1x00_cs: unsupported VCC\n");
157 case 0: /* Vcc 0 */
158 /* turn off power */
159 au_sync_delay(100);
160 au_writel(au_readl(GPIO2_PINSTATE) | (1<<14)|(1<<30),
161 GPIO2_OUTPUT);
162 break;
163 }
164
165 if (!configure->reset) {
166 DEBUG("deassert reset\n");
167 au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<4))|(1<<20),
168 GPIO2_OUTPUT);
169 au_sync_delay(100);
170 au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<5))|(1<<21),
171 GPIO2_OUTPUT);
172 }
173 else {
174 DEBUG("assert reset\n");
175 au_writel(au_readl(GPIO2_PINSTATE) | (1<<4)|(1<<20),
176 GPIO2_OUTPUT);
177 }
178 au_sync_delay(100);
179 return 0;
180}
181
182struct pcmcia_low_level xxs1500_pcmcia_ops = {
183 xxs1500_pcmcia_init,
184 xxs1500_pcmcia_shutdown,
185 xxs1500_pcmcia_socket_state,
186 xxs1500_pcmcia_get_irq_info,
187 xxs1500_pcmcia_configure_socket
188};
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
new file mode 100644
index 000000000000..3889cf07d6ce
--- /dev/null
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -0,0 +1,623 @@
1/*
2 * PCMCIA socket code for the Alchemy Db1xxx/Pb1xxx boards.
3 *
4 * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>
5 *
6 */
7
8/* This is a fairly generic PCMCIA socket driver suitable for the
9 * following Alchemy Development boards:
10 * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200.
11 *
12 * The Db1000 is used as a reference: Per-socket card-, carddetect- and
13 * statuschange IRQs connected to SoC GPIOs, control and status register
14 * bits arranged in per-socket groups in an external PLD. All boards
15 * listed here use this layout, including bit positions and meanings.
16 * Of course there are exceptions in later boards:
17 *
18 * - Pb1100/Pb1500: single socket only; voltage key bits VS are
19 * at STATUS[5:4] (instead of STATUS[1:0]).
20 * - Au1200-based: additional card-eject irqs, irqs not gpios!
21 */
22
23#include <linux/delay.h>
24#include <linux/gpio.h>
25#include <linux/interrupt.h>
26#include <linux/pm.h>
27#include <linux/platform_device.h>
28#include <linux/resource.h>
29#include <linux/spinlock.h>
30
31#include <pcmcia/cs_types.h>
32#include <pcmcia/ss.h>
33
34#include <asm/mach-au1x00/au1000.h>
35#include <asm/mach-db1x00/bcsr.h>
36
37#define MEM_MAP_SIZE 0x400000
38#define IO_MAP_SIZE 0x1000
39
40struct db1x_pcmcia_sock {
41 struct pcmcia_socket socket;
42 int nr; /* socket number */
43 void *virt_io;
44
45 /* the "pseudo" addresses of the PCMCIA space. */
46 phys_addr_t phys_io;
47 phys_addr_t phys_attr;
48 phys_addr_t phys_mem;
49
50 /* previous flags for set_socket() */
51 unsigned int old_flags;
52
53 /* interrupt sources: linux irq numbers! */
54 int insert_irq; /* default carddetect irq */
55 int stschg_irq; /* card-status-change irq */
56 int card_irq; /* card irq */
57 int eject_irq; /* db1200/pb1200 have these */
58
59#define BOARD_TYPE_DEFAULT 0 /* most boards */
60#define BOARD_TYPE_DB1200 1 /* IRQs aren't gpios */
61#define BOARD_TYPE_PB1100 2 /* VS bits slightly different */
62 int board_type;
63};
64
65#define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket)
66
67/* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */
68static int db1200_card_inserted(struct db1x_pcmcia_sock *sock)
69{
70 unsigned short sigstat;
71
72 sigstat = bcsr_read(BCSR_SIGSTAT);
73 return sigstat & 1 << (8 + 2 * sock->nr);
74}
75
76/* carddetect gpio: low-active */
77static int db1000_card_inserted(struct db1x_pcmcia_sock *sock)
78{
79 return !gpio_get_value(irq_to_gpio(sock->insert_irq));
80}
81
82static int db1x_card_inserted(struct db1x_pcmcia_sock *sock)
83{
84 switch (sock->board_type) {
85 case BOARD_TYPE_DB1200:
86 return db1200_card_inserted(sock);
87 default:
88 return db1000_card_inserted(sock);
89 }
90}
91
92/* STSCHG tends to bounce heavily when cards are inserted/ejected.
93 * To avoid this, the interrupt is normally disabled and only enabled
94 * after reset to a card has been de-asserted.
95 */
96static inline void set_stschg(struct db1x_pcmcia_sock *sock, int en)
97{
98 if (sock->stschg_irq != -1) {
99 if (en)
100 enable_irq(sock->stschg_irq);
101 else
102 disable_irq(sock->stschg_irq);
103 }
104}
105
106static irqreturn_t db1000_pcmcia_cdirq(int irq, void *data)
107{
108 struct db1x_pcmcia_sock *sock = data;
109
110 pcmcia_parse_events(&sock->socket, SS_DETECT);
111
112 return IRQ_HANDLED;
113}
114
115static irqreturn_t db1000_pcmcia_stschgirq(int irq, void *data)
116{
117 struct db1x_pcmcia_sock *sock = data;
118
119 pcmcia_parse_events(&sock->socket, SS_STSCHG);
120
121 return IRQ_HANDLED;
122}
123
124static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data)
125{
126 struct db1x_pcmcia_sock *sock = data;
127
128 /* Db/Pb1200 have separate per-socket insertion and ejection
129 * interrupts which stay asserted as long as the card is
130 * inserted/missing. The one which caused us to be called
131 * needs to be disabled and the other one enabled.
132 */
133 if (irq == sock->insert_irq) {
134 disable_irq_nosync(sock->insert_irq);
135 enable_irq(sock->eject_irq);
136 } else {
137 disable_irq_nosync(sock->eject_irq);
138 enable_irq(sock->insert_irq);
139 }
140
141 pcmcia_parse_events(&sock->socket, SS_DETECT);
142
143 return IRQ_HANDLED;
144}
145
146static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
147{
148 int ret;
149 unsigned long flags;
150
151 if (sock->stschg_irq != -1) {
152 ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq,
153 0, "pcmcia_stschg", sock);
154 if (ret)
155 return ret;
156 }
157
158 /* Db/Pb1200 have separate per-socket insertion and ejection
159 * interrupts, which should show edge behaviour but don't.
160 * So interrupts are disabled until both insertion and
161 * ejection handler have been registered and the currently
162 * active one disabled.
163 */
164 if (sock->board_type == BOARD_TYPE_DB1200) {
165 local_irq_save(flags);
166
167 ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,
168 IRQF_DISABLED, "pcmcia_insert", sock);
169 if (ret)
170 goto out1;
171
172 ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq,
173 IRQF_DISABLED, "pcmcia_eject", sock);
174 if (ret) {
175 free_irq(sock->insert_irq, sock);
176 local_irq_restore(flags);
177 goto out1;
178 }
179
180 /* disable the currently active one */
181 if (db1200_card_inserted(sock))
182 disable_irq_nosync(sock->insert_irq);
183 else
184 disable_irq_nosync(sock->eject_irq);
185
186 local_irq_restore(flags);
187 } else {
188 /* all other (older) Db1x00 boards use a GPIO to show
189 * card detection status: use both-edge triggers.
190 */
191 set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
192 ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,
193 0, "pcmcia_carddetect", sock);
194
195 if (ret)
196 goto out1;
197 }
198
199 return 0; /* all done */
200
201out1:
202 if (sock->stschg_irq != -1)
203 free_irq(sock->stschg_irq, sock);
204
205 return ret;
206}
207
208static void db1x_pcmcia_free_irqs(struct db1x_pcmcia_sock *sock)
209{
210 if (sock->stschg_irq != -1)
211 free_irq(sock->stschg_irq, sock);
212
213 free_irq(sock->insert_irq, sock);
214 if (sock->eject_irq != -1)
215 free_irq(sock->eject_irq, sock);
216}
217
218/*
219 * configure a PCMCIA socket on the Db1x00 series of boards (and
220 * compatibles).
221 *
222 * 2 external registers are involved:
223 * pcmcia_status (offset 0x04): bits [0:1/2:3]: read card voltage id
224 * pcmcia_control(offset 0x10):
225 * bits[0:1] set vcc for card
226 * bits[2:3] set vpp for card
227 * bit 4: enable data buffers
228 * bit 7: reset# for card
229 * add 8 for second socket.
230 */
231static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
232 struct socket_state_t *state)
233{
234 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
235 unsigned short cr_clr, cr_set;
236 unsigned int changed;
237 int v, p, ret;
238
239 /* card voltage setup */
240 cr_clr = (0xf << (sock->nr * 8)); /* clear voltage settings */
241 cr_set = 0;
242 v = p = ret = 0;
243
244 switch (state->Vcc) {
245 case 50:
246 ++v;
247 case 33:
248 ++v;
249 case 0:
250 break;
251 default:
252 printk(KERN_INFO "pcmcia%d unsupported Vcc %d\n",
253 sock->nr, state->Vcc);
254 }
255
256 switch (state->Vpp) {
257 case 12:
258 ++p;
259 case 33:
260 case 50:
261 ++p;
262 case 0:
263 break;
264 default:
265 printk(KERN_INFO "pcmcia%d unsupported Vpp %d\n",
266 sock->nr, state->Vpp);
267 }
268
269 /* sanity check: Vpp must be 0, 12, or Vcc */
270 if (((state->Vcc == 33) && (state->Vpp == 50)) ||
271 ((state->Vcc == 50) && (state->Vpp == 33))) {
272 printk(KERN_INFO "pcmcia%d bad Vcc/Vpp combo (%d %d)\n",
273 sock->nr, state->Vcc, state->Vpp);
274 v = p = 0;
275 ret = -EINVAL;
276 }
277
278 /* create new voltage code */
279 cr_set |= ((v << 2) | p) << (sock->nr * 8);
280
281 changed = state->flags ^ sock->old_flags;
282
283 if (changed & SS_RESET) {
284 if (state->flags & SS_RESET) {
285 set_stschg(sock, 0);
286 /* assert reset, disable io buffers */
287 cr_clr |= (1 << (7 + (sock->nr * 8)));
288 cr_clr |= (1 << (4 + (sock->nr * 8)));
289 } else {
290 /* de-assert reset, enable io buffers */
291 cr_set |= 1 << (7 + (sock->nr * 8));
292 cr_set |= 1 << (4 + (sock->nr * 8));
293 }
294 }
295
296 /* update PCMCIA configuration */
297 bcsr_mod(BCSR_PCMCIA, cr_clr, cr_set);
298
299 sock->old_flags = state->flags;
300
301 /* reset was taken away: give card time to initialize properly */
302 if ((changed & SS_RESET) && !(state->flags & SS_RESET)) {
303 msleep(500);
304 set_stschg(sock, 1);
305 }
306
307 return ret;
308}
309
310/* VCC bits at [3:2]/[11:10] */
311#define GET_VCC(cr, socknr) \
312 ((((cr) >> 2) >> ((socknr) * 8)) & 3)
313
314/* VS bits at [0:1]/[3:2] */
315#define GET_VS(sr, socknr) \
316 (((sr) >> (2 * (socknr))) & 3)
317
318/* reset bits at [7]/[15] */
319#define GET_RESET(cr, socknr) \
320 ((cr) & (1 << (7 + (8 * (socknr)))))
321
322static int db1x_pcmcia_get_status(struct pcmcia_socket *skt,
323 unsigned int *value)
324{
325 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
326 unsigned short cr, sr;
327 unsigned int status;
328
329 status = db1x_card_inserted(sock) ? SS_DETECT : 0;
330
331 cr = bcsr_read(BCSR_PCMCIA);
332 sr = bcsr_read(BCSR_STATUS);
333
334 /* PB1100/PB1500: voltage key bits are at [5:4] */
335 if (sock->board_type == BOARD_TYPE_PB1100)
336 sr >>= 4;
337
338 /* determine card type */
339 switch (GET_VS(sr, sock->nr)) {
340 case 0:
341 case 2:
342 status |= SS_3VCARD; /* 3V card */
343 case 3:
344 break; /* 5V card: set nothing */
345 default:
346 status |= SS_XVCARD; /* treated as unsupported in core */
347 }
348
349 /* if Vcc is not zero, we have applied power to a card */
350 status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0;
351
352 /* reset de-asserted? then we're ready */
353 status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET;
354
355 *value = status;
356
357 return 0;
358}
359
360static int db1x_pcmcia_sock_init(struct pcmcia_socket *skt)
361{
362 return 0;
363}
364
365static int db1x_pcmcia_sock_suspend(struct pcmcia_socket *skt)
366{
367 return 0;
368}
369
370static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
371 struct pccard_io_map *map)
372{
373 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
374
375 map->start = (u32)sock->virt_io;
376 map->stop = map->start + IO_MAP_SIZE;
377
378 return 0;
379}
380
381static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
382 struct pccard_mem_map *map)
383{
384 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
385
386 if (map->flags & MAP_ATTRIB)
387 map->static_start = sock->phys_attr + map->card_start;
388 else
389 map->static_start = sock->phys_mem + map->card_start;
390
391 return 0;
392}
393
394static struct pccard_operations db1x_pcmcia_operations = {
395 .init = db1x_pcmcia_sock_init,
396 .suspend = db1x_pcmcia_sock_suspend,
397 .get_status = db1x_pcmcia_get_status,
398 .set_socket = db1x_pcmcia_configure,
399 .set_io_map = au1x00_pcmcia_set_io_map,
400 .set_mem_map = au1x00_pcmcia_set_mem_map,
401};
402
403static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
404{
405 struct db1x_pcmcia_sock *sock;
406 struct resource *r;
407 int ret, bid;
408
409 sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL);
410 if (!sock)
411 return -ENOMEM;
412
413 sock->nr = pdev->id;
414
415 bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
416 switch (bid) {
417 case BCSR_WHOAMI_PB1500:
418 case BCSR_WHOAMI_PB1500R2:
419 case BCSR_WHOAMI_PB1100:
420 sock->board_type = BOARD_TYPE_PB1100;
421 break;
422 case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR:
423 sock->board_type = BOARD_TYPE_DEFAULT;
424 break;
425 case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:
426 sock->board_type = BOARD_TYPE_DB1200;
427 break;
428 default:
429 printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);
430 ret = -ENODEV;
431 goto out0;
432 };
433
434 /*
435 * gather resources necessary and optional nice-to-haves to
436 * operate a socket:
437 * This includes IRQs for Carddetection/ejection, the card
438 * itself and optional status change detection.
439 * Also, the memory areas covered by a socket. For these
440 * we require the 32bit "pseudo" addresses (see the au1000.h
441 * header for more information).
442 */
443
444 /* card: irq assigned to the card itself. */
445 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card");
446 sock->card_irq = r ? r->start : 0;
447
448 /* insert: irq which triggers on card insertion/ejection */
449 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert");
450 sock->insert_irq = r ? r->start : -1;
451
452 /* stschg: irq which trigger on card status change (optional) */
453 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg");
454 sock->stschg_irq = r ? r->start : -1;
455
456 /* eject: irq which triggers on ejection (DB1200/PB1200 only) */
457 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject");
458 sock->eject_irq = r ? r->start : -1;
459
460 ret = -ENODEV;
461
462 /*
463 * pseudo-attr: The 32bit address of the PCMCIA attribute space
464 * for this socket (usually the 36bit address shifted 4 to the
465 * right).
466 */
467 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
468 if (!r) {
469 printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",
470 sock->nr);
471 goto out0;
472 }
473 sock->phys_attr = r->start;
474
475 /*
476 * pseudo-mem: The 32bit address of the PCMCIA memory space for
477 * this socket (usually the 36bit address shifted 4 to the right)
478 */
479 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
480 if (!r) {
481 printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",
482 sock->nr);
483 goto out0;
484 }
485 sock->phys_mem = r->start;
486
487 /*
488 * pseudo-io: The 32bit address of the PCMCIA IO space for this
489 * socket (usually the 36bit address shifted 4 to the right).
490 */
491 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
492 if (!r) {
493 printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",
494 sock->nr);
495 goto out0;
496 }
497 sock->phys_io = r->start;
498
499 /*
500 * PCMCIA client drivers use the inb/outb macros to access
501 * the IO registers. Since mips_io_port_base is added
502 * to the access address of the mips implementation of
503 * inb/outb, we need to subtract it here because we want
504 * to access the I/O or MEM address directly, without
505 * going through this "mips_io_port_base" mechanism.
506 */
507 sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
508 mips_io_port_base);
509
510 if (!sock->virt_io) {
511 printk(KERN_ERR "pcmcia%d: cannot remap IO area\n",
512 sock->nr);
513 ret = -ENOMEM;
514 goto out0;
515 }
516
517 sock->socket.ops = &db1x_pcmcia_operations;
518 sock->socket.owner = THIS_MODULE;
519 sock->socket.pci_irq = sock->card_irq;
520 sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
521 sock->socket.map_size = MEM_MAP_SIZE;
522 sock->socket.io_offset = (unsigned long)sock->virt_io;
523 sock->socket.dev.parent = &pdev->dev;
524 sock->socket.resource_ops = &pccard_static_ops;
525
526 platform_set_drvdata(pdev, sock);
527
528 ret = db1x_pcmcia_setup_irqs(sock);
529 if (ret) {
530 printk(KERN_ERR "pcmcia%d cannot setup interrupts\n",
531 sock->nr);
532 goto out1;
533 }
534
535 set_stschg(sock, 0);
536
537 ret = pcmcia_register_socket(&sock->socket);
538 if (ret) {
539 printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr);
540 goto out2;
541 }
542
543 printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %09llx"
544 "(%p) %09llx %09llx card/insert/stschg/eject irqs @ %d "
545 "%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io,
546 sock->phys_attr, sock->phys_mem, sock->card_irq,
547 sock->insert_irq, sock->stschg_irq, sock->eject_irq);
548
549 return 0;
550
551out2:
552 db1x_pcmcia_free_irqs(sock);
553out1:
554 iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
555out0:
556 kfree(sock);
557 return ret;
558}
559
560static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
561{
562 struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
563
564 db1x_pcmcia_free_irqs(sock);
565 pcmcia_unregister_socket(&sock->socket);
566 iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
567 kfree(sock);
568
569 return 0;
570}
571
572#ifdef CONFIG_PM
573static int db1x_pcmcia_suspend(struct device *dev)
574{
575 return pcmcia_socket_dev_suspend(dev);
576}
577
578static int db1x_pcmcia_resume(struct device *dev)
579{
580 return pcmcia_socket_dev_resume(dev);
581}
582
583static struct dev_pm_ops db1x_pcmcia_pmops = {
584 .resume = db1x_pcmcia_resume,
585 .suspend = db1x_pcmcia_suspend,
586 .thaw = db1x_pcmcia_resume,
587 .freeze = db1x_pcmcia_suspend,
588};
589
590#define DB1XXX_SS_PMOPS &db1x_pcmcia_pmops
591
592#else
593
594#define DB1XXX_SS_PMOPS NULL
595
596#endif
597
598static struct platform_driver db1x_pcmcia_socket_driver = {
599 .driver = {
600 .name = "db1xxx_pcmcia",
601 .owner = THIS_MODULE,
602 .pm = DB1XXX_SS_PMOPS
603 },
604 .probe = db1x_pcmcia_socket_probe,
605 .remove = __devexit_p(db1x_pcmcia_socket_remove),
606};
607
608int __init db1x_pcmcia_socket_load(void)
609{
610 return platform_driver_register(&db1x_pcmcia_socket_driver);
611}
612
613void __exit db1x_pcmcia_socket_unload(void)
614{
615 platform_driver_unregister(&db1x_pcmcia_socket_driver);
616}
617
618module_init(db1x_pcmcia_socket_load);
619module_exit(db1x_pcmcia_socket_unload);
620
621MODULE_LICENSE("GPL");
622MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards");
623MODULE_AUTHOR("Manuel Lauss");
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
new file mode 100644
index 000000000000..61560cd6e287
--- /dev/null
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -0,0 +1,350 @@
1/*
2 * PCMCIA socket code for the MyCable XXS1500 system.
3 *
4 * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>
5 *
6 */
7
8#include <linux/delay.h>
9#include <linux/gpio.h>
10#include <linux/interrupt.h>
11#include <linux/io.h>
12#include <linux/ioport.h>
13#include <linux/mm.h>
14#include <linux/platform_device.h>
15#include <linux/pm.h>
16#include <linux/resource.h>
17#include <linux/spinlock.h>
18
19#include <pcmcia/cs_types.h>
20#include <pcmcia/cs.h>
21#include <pcmcia/ss.h>
22#include <pcmcia/cistpl.h>
23
24#include <asm/irq.h>
25#include <asm/system.h>
26#include <asm/mach-au1x00/au1000.h>
27
28#define MEM_MAP_SIZE 0x400000
29#define IO_MAP_SIZE 0x1000
30
31
32/*
33 * 3.3V cards only; all interfacing is done via gpios:
34 *
35 * 0/1: carddetect (00 = card present, xx = huh)
36 * 4: card irq
37 * 204: reset (high-act)
38 * 205: buffer enable (low-act)
39 * 208/209: card voltage key (00,01,10,11)
40 * 210: battwarn
41 * 211: batdead
42 * 214: power (low-act)
43 */
44#define GPIO_CDA 0
45#define GPIO_CDB 1
46#define GPIO_CARDIRQ 4
47#define GPIO_RESET 204
48#define GPIO_OUTEN 205
49#define GPIO_VSL 208
50#define GPIO_VSH 209
51#define GPIO_BATTDEAD 210
52#define GPIO_BATTWARN 211
53#define GPIO_POWER 214
54
55struct xxs1500_pcmcia_sock {
56 struct pcmcia_socket socket;
57 void *virt_io;
58
59 phys_addr_t phys_io;
60 phys_addr_t phys_attr;
61 phys_addr_t phys_mem;
62
63 /* previous flags for set_socket() */
64 unsigned int old_flags;
65};
66
67#define to_xxs_socket(x) container_of(x, struct xxs1500_pcmcia_sock, socket)
68
69static irqreturn_t cdirq(int irq, void *data)
70{
71 struct xxs1500_pcmcia_sock *sock = data;
72
73 pcmcia_parse_events(&sock->socket, SS_DETECT);
74
75 return IRQ_HANDLED;
76}
77
78static int xxs1500_pcmcia_configure(struct pcmcia_socket *skt,
79 struct socket_state_t *state)
80{
81 struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
82 unsigned int changed;
83
84 /* power control */
85 switch (state->Vcc) {
86 case 0:
87 gpio_set_value(GPIO_POWER, 1); /* power off */
88 break;
89 case 33:
90 gpio_set_value(GPIO_POWER, 0); /* power on */
91 break;
92 case 50:
93 default:
94 return -EINVAL;
95 }
96
97 changed = state->flags ^ sock->old_flags;
98
99 if (changed & SS_RESET) {
100 if (state->flags & SS_RESET) {
101 gpio_set_value(GPIO_RESET, 1); /* assert reset */
102 gpio_set_value(GPIO_OUTEN, 1); /* buffers off */
103 } else {
104 gpio_set_value(GPIO_RESET, 0); /* deassert reset */
105 gpio_set_value(GPIO_OUTEN, 0); /* buffers on */
106 msleep(500);
107 }
108 }
109
110 sock->old_flags = state->flags;
111
112 return 0;
113}
114
115static int xxs1500_pcmcia_get_status(struct pcmcia_socket *skt,
116 unsigned int *value)
117{
118 unsigned int status;
119 int i;
120
121 status = 0;
122
123 /* check carddetects: GPIO[0:1] must both be low */
124 if (!gpio_get_value(GPIO_CDA) && !gpio_get_value(GPIO_CDB))
125 status |= SS_DETECT;
126
127 /* determine card voltage: GPIO[208:209] binary value */
128 i = (!!gpio_get_value(GPIO_VSL)) | ((!!gpio_get_value(GPIO_VSH)) << 1);
129
130 switch (i) {
131 case 0:
132 case 1:
133 case 2:
134 status |= SS_3VCARD; /* 3V card */
135 break;
136 case 3: /* 5V card, unsupported */
137 default:
138 status |= SS_XVCARD; /* treated as unsupported in core */
139 }
140
141 /* GPIO214: low active power switch */
142 status |= gpio_get_value(GPIO_POWER) ? 0 : SS_POWERON;
143
144 /* GPIO204: high-active reset line */
145 status |= gpio_get_value(GPIO_RESET) ? SS_RESET : SS_READY;
146
147 /* other stuff */
148 status |= gpio_get_value(GPIO_BATTDEAD) ? 0 : SS_BATDEAD;
149 status |= gpio_get_value(GPIO_BATTWARN) ? 0 : SS_BATWARN;
150
151 *value = status;
152
153 return 0;
154}
155
156static int xxs1500_pcmcia_sock_init(struct pcmcia_socket *skt)
157{
158 gpio_direction_input(GPIO_CDA);
159 gpio_direction_input(GPIO_CDB);
160 gpio_direction_input(GPIO_VSL);
161 gpio_direction_input(GPIO_VSH);
162 gpio_direction_input(GPIO_BATTDEAD);
163 gpio_direction_input(GPIO_BATTWARN);
164 gpio_direction_output(GPIO_RESET, 1); /* assert reset */
165 gpio_direction_output(GPIO_OUTEN, 1); /* disable buffers */
166 gpio_direction_output(GPIO_POWER, 1); /* power off */
167
168 return 0;
169}
170
171static int xxs1500_pcmcia_sock_suspend(struct pcmcia_socket *skt)
172{
173 return 0;
174}
175
176static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
177 struct pccard_io_map *map)
178{
179 struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
180
181 map->start = (u32)sock->virt_io;
182 map->stop = map->start + IO_MAP_SIZE;
183
184 return 0;
185}
186
187static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
188 struct pccard_mem_map *map)
189{
190 struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
191
192 if (map->flags & MAP_ATTRIB)
193 map->static_start = sock->phys_attr + map->card_start;
194 else
195 map->static_start = sock->phys_mem + map->card_start;
196
197 return 0;
198}
199
200static struct pccard_operations xxs1500_pcmcia_operations = {
201 .init = xxs1500_pcmcia_sock_init,
202 .suspend = xxs1500_pcmcia_sock_suspend,
203 .get_status = xxs1500_pcmcia_get_status,
204 .set_socket = xxs1500_pcmcia_configure,
205 .set_io_map = au1x00_pcmcia_set_io_map,
206 .set_mem_map = au1x00_pcmcia_set_mem_map,
207};
208
209static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
210{
211 struct xxs1500_pcmcia_sock *sock;
212 struct resource *r;
213 int ret, irq;
214
215 sock = kzalloc(sizeof(struct xxs1500_pcmcia_sock), GFP_KERNEL);
216 if (!sock)
217 return -ENOMEM;
218
219 ret = -ENODEV;
220
221 /*
222 * pseudo-attr: The 32bit address of the PCMCIA attribute space
223 * for this socket (usually the 36bit address shifted 4 to the
224 * right).
225 */
226 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
227 if (!r) {
228 dev_err(&pdev->dev, "missing 'pcmcia-attr' resource!\n");
229 goto out0;
230 }
231 sock->phys_attr = r->start;
232
233 /*
234 * pseudo-mem: The 32bit address of the PCMCIA memory space for
235 * this socket (usually the 36bit address shifted 4 to the right)
236 */
237 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
238 if (!r) {
239 dev_err(&pdev->dev, "missing 'pcmcia-mem' resource!\n");
240 goto out0;
241 }
242 sock->phys_mem = r->start;
243
244 /*
245 * pseudo-io: The 32bit address of the PCMCIA IO space for this
246 * socket (usually the 36bit address shifted 4 to the right).
247 */
248 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
249 if (!r) {
250 dev_err(&pdev->dev, "missing 'pcmcia-io' resource!\n");
251 goto out0;
252 }
253 sock->phys_io = r->start;
254
255
256 /*
257 * PCMCIA client drivers use the inb/outb macros to access
258 * the IO registers. Since mips_io_port_base is added
259 * to the access address of the mips implementation of
260 * inb/outb, we need to subtract it here because we want
261 * to access the I/O or MEM address directly, without
262 * going through this "mips_io_port_base" mechanism.
263 */
264 sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
265 mips_io_port_base);
266
267 if (!sock->virt_io) {
268 dev_err(&pdev->dev, "cannot remap IO area\n");
269 ret = -ENOMEM;
270 goto out0;
271 }
272
273 sock->socket.ops = &xxs1500_pcmcia_operations;
274 sock->socket.owner = THIS_MODULE;
275 sock->socket.pci_irq = gpio_to_irq(GPIO_CARDIRQ);
276 sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
277 sock->socket.map_size = MEM_MAP_SIZE;
278 sock->socket.io_offset = (unsigned long)sock->virt_io;
279 sock->socket.dev.parent = &pdev->dev;
280 sock->socket.resource_ops = &pccard_static_ops;
281
282 platform_set_drvdata(pdev, sock);
283
284 /* setup carddetect irq: use one of the 2 GPIOs as an
285 * edge detector.
286 */
287 irq = gpio_to_irq(GPIO_CDA);
288 set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
289 ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
290 if (ret) {
291 dev_err(&pdev->dev, "cannot setup cd irq\n");
292 goto out1;
293 }
294
295 ret = pcmcia_register_socket(&sock->socket);
296 if (ret) {
297 dev_err(&pdev->dev, "failed to register\n");
298 goto out2;
299 }
300
301 printk(KERN_INFO "MyCable XXS1500 PCMCIA socket services\n");
302
303 return 0;
304
305out2:
306 free_irq(gpio_to_irq(GPIO_CDA), sock);
307out1:
308 iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
309out0:
310 kfree(sock);
311 return ret;
312}
313
314static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev)
315{
316 struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
317
318 pcmcia_unregister_socket(&sock->socket);
319 free_irq(gpio_to_irq(GPIO_CDA), sock);
320 iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
321 kfree(sock);
322
323 return 0;
324}
325
326static struct platform_driver xxs1500_pcmcia_socket_driver = {
327 .driver = {
328 .name = "xxs1500_pcmcia",
329 .owner = THIS_MODULE,
330 },
331 .probe = xxs1500_pcmcia_probe,
332 .remove = __devexit_p(xxs1500_pcmcia_remove),
333};
334
335int __init xxs1500_pcmcia_socket_load(void)
336{
337 return platform_driver_register(&xxs1500_pcmcia_socket_driver);
338}
339
340void __exit xxs1500_pcmcia_socket_unload(void)
341{
342 platform_driver_unregister(&xxs1500_pcmcia_socket_driver);
343}
344
345module_init(xxs1500_pcmcia_socket_load);
346module_exit(xxs1500_pcmcia_socket_unload);
347
348MODULE_LICENSE("GPL");
349MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems");
350MODULE_AUTHOR("Manuel Lauss");