]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/pcmcia/m32r_cfc.c
Merge Paulus' tree
[karo-tx-linux.git] / drivers / pcmcia / m32r_cfc.c
1 /*
2  *  drivers/pcmcia/m32r_cfc.c
3  *
4  *  Device driver for the CFC functionality of M32R.
5  *
6  *  Copyright (c) 2001, 2002, 2003, 2004
7  *    Hiroyuki Kondo, Naoto Sugai, Hayato Fujiwara
8  */
9
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
12 #include <linux/init.h>
13 #include <linux/config.h>
14 #include <linux/types.h>
15 #include <linux/fcntl.h>
16 #include <linux/string.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/timer.h>
20 #include <linux/sched.h>
21 #include <linux/slab.h>
22 #include <linux/ioport.h>
23 #include <linux/delay.h>
24 #include <linux/workqueue.h>
25 #include <linux/interrupt.h>
26 #include <linux/platform_device.h>
27 #include <linux/bitops.h>
28 #include <asm/irq.h>
29 #include <asm/io.h>
30 #include <asm/system.h>
31
32 #include <pcmcia/cs_types.h>
33 #include <pcmcia/ss.h>
34 #include <pcmcia/cs.h>
35
36 #undef MAX_IO_WIN       /* FIXME */
37 #define MAX_IO_WIN 1
38 #undef MAX_WIN          /* FIXME */
39 #define MAX_WIN 1
40
41 #include "m32r_cfc.h"
42
43 #ifdef DEBUG
44 static int m32r_cfc_debug;
45 module_param(m32r_cfc_debug, int, 0644);
46 #define debug(lvl, fmt, arg...) do {                            \
47         if (m32r_cfc_debug > (lvl))                             \
48                 printk(KERN_DEBUG "m32r_cfc: " fmt , ## arg);   \
49 } while (0)
50 #else
51 #define debug(n, args...) do { } while (0)
52 #endif
53
54 /* Poll status interval -- 0 means default to interrupt */
55 static int poll_interval = 0;
56
57 typedef enum pcc_space { as_none = 0, as_comm, as_attr, as_io } pcc_as_t;
58
59 typedef struct pcc_socket {
60         u_short                 type, flags;
61         struct pcmcia_socket    socket;
62         unsigned int            number;
63         kio_addr_t              ioaddr;
64         u_long                  mapaddr;
65         u_long                  base;   /* PCC register base */
66         u_char                  cs_irq1, cs_irq2, intr;
67         pccard_io_map           io_map[MAX_IO_WIN];
68         pccard_mem_map          mem_map[MAX_WIN];
69         u_char                  io_win;
70         u_char                  mem_win;
71         pcc_as_t                current_space;
72         u_char                  last_iodbex;
73 #ifdef CONFIG_PROC_FS
74         struct proc_dir_entry *proc;
75 #endif
76 } pcc_socket_t;
77
78 static int pcc_sockets = 0;
79 static pcc_socket_t socket[M32R_MAX_PCC] = {
80         { 0, }, /* ... */
81 };
82
83 /*====================================================================*/
84
85 static unsigned int pcc_get(u_short, unsigned int);
86 static void pcc_set(u_short, unsigned int , unsigned int );
87
88 static DEFINE_SPINLOCK(pcc_lock);
89
90 #if !defined(CONFIG_PLAT_USRV)
91 static inline u_long pcc_port2addr(unsigned long port, int size) {
92         u_long addr = 0;
93         u_long odd;
94
95         if (size == 1) {        /* byte access */
96                 odd = (port&1) << 11;
97                 port -= port & 1;
98                 addr = CFC_IO_MAPBASE_BYTE - CFC_IOPORT_BASE + odd + port;
99         } else if (size == 2)
100                 addr = CFC_IO_MAPBASE_WORD - CFC_IOPORT_BASE + port;
101
102         return addr;
103 }
104 #else   /* CONFIG_PLAT_USRV */
105 static inline u_long pcc_port2addr(unsigned long port, int size) {
106         u_long odd;
107         u_long addr = ((port - CFC_IOPORT_BASE) & 0xf000) << 8;
108
109         if (size == 1) {        /* byte access */
110                 odd = port & 1;
111                 port -= odd;
112                 odd <<= 11;
113                 addr = (addr | CFC_IO_MAPBASE_BYTE) + odd + (port & 0xfff);
114         } else if (size == 2)   /* word access */
115                 addr = (addr | CFC_IO_MAPBASE_WORD) + (port & 0xfff);
116
117         return addr;
118 }
119 #endif  /* CONFIG_PLAT_USRV */
120
121 void pcc_ioread_byte(int sock, unsigned long port, void *buf, size_t size,
122         size_t nmemb, int flag)
123 {
124         u_long addr;
125         unsigned char *bp = (unsigned char *)buf;
126         unsigned long flags;
127
128         debug(3, "m32r_cfc: pcc_ioread_byte: sock=%d, port=%#lx, buf=%p, "
129                  "size=%u, nmemb=%d, flag=%d\n",
130                   sock, port, buf, size, nmemb, flag);
131
132         addr = pcc_port2addr(port, 1);
133         if (!addr) {
134                 printk("m32r_cfc:ioread_byte null port :%#lx\n",port);
135                 return;
136         }
137         debug(3, "m32r_cfc: pcc_ioread_byte: addr=%#lx\n", addr);
138
139         spin_lock_irqsave(&pcc_lock, flags);
140         /* read Byte */
141         while (nmemb--)
142                 *bp++ = readb(addr);
143         spin_unlock_irqrestore(&pcc_lock, flags);
144 }
145
146 void pcc_ioread_word(int sock, unsigned long port, void *buf, size_t size,
147         size_t nmemb, int flag)
148 {
149         u_long addr;
150         unsigned short *bp = (unsigned short *)buf;
151         unsigned long flags;
152
153         debug(3, "m32r_cfc: pcc_ioread_word: sock=%d, port=%#lx, "
154                  "buf=%p, size=%u, nmemb=%d, flag=%d\n",
155                  sock, port, buf, size, nmemb, flag);
156
157         if (size != 2)
158                 printk("m32r_cfc: ioread_word :illigal size %u : %#lx\n", size,
159                         port);
160         if (size == 9)
161                 printk("m32r_cfc: ioread_word :insw \n");
162
163         addr = pcc_port2addr(port, 2);
164         if (!addr) {
165                 printk("m32r_cfc:ioread_word null port :%#lx\n",port);
166                 return;
167         }
168         debug(3, "m32r_cfc: pcc_ioread_word: addr=%#lx\n", addr);
169
170         spin_lock_irqsave(&pcc_lock, flags);
171         /* read Word */
172         while (nmemb--)
173                 *bp++ = readw(addr);
174         spin_unlock_irqrestore(&pcc_lock, flags);
175 }
176
177 void pcc_iowrite_byte(int sock, unsigned long port, void *buf, size_t size,
178         size_t nmemb, int flag)
179 {
180         u_long addr;
181         unsigned char *bp = (unsigned char *)buf;
182         unsigned long flags;
183
184         debug(3, "m32r_cfc: pcc_iowrite_byte: sock=%d, port=%#lx, "
185                  "buf=%p, size=%u, nmemb=%d, flag=%d\n",
186                  sock, port, buf, size, nmemb, flag);
187
188         /* write Byte */
189         addr = pcc_port2addr(port, 1);
190         if (!addr) {
191                 printk("m32r_cfc:iowrite_byte null port:%#lx\n",port);
192                 return;
193         }
194         debug(3, "m32r_cfc: pcc_iowrite_byte: addr=%#lx\n", addr);
195
196         spin_lock_irqsave(&pcc_lock, flags);
197         while (nmemb--)
198                 writeb(*bp++, addr);
199         spin_unlock_irqrestore(&pcc_lock, flags);
200 }
201
202 void pcc_iowrite_word(int sock, unsigned long port, void *buf, size_t size,
203         size_t nmemb, int flag)
204 {
205         u_long addr;
206         unsigned short *bp = (unsigned short *)buf;
207         unsigned long flags;
208
209         debug(3, "m32r_cfc: pcc_iowrite_word: sock=%d, port=%#lx, "
210                  "buf=%p, size=%u, nmemb=%d, flag=%d\n",
211                  sock, port, buf, size, nmemb, flag);
212
213         if(size != 2)
214                 printk("m32r_cfc: iowrite_word :illigal size %u : %#lx\n",
215                         size, port);
216         if(size == 9)
217                 printk("m32r_cfc: iowrite_word :outsw \n");
218
219         addr = pcc_port2addr(port, 2);
220         if (!addr) {
221                 printk("m32r_cfc:iowrite_word null addr :%#lx\n",port);
222                 return;
223         }
224 #if 1
225         if (addr & 1) {
226                 printk("m32r_cfc:iowrite_word port addr (%#lx):%#lx\n", port,
227                         addr);
228                 return;
229         }
230 #endif
231         debug(3, "m32r_cfc: pcc_iowrite_word: addr=%#lx\n", addr);
232
233         spin_lock_irqsave(&pcc_lock, flags);
234         while (nmemb--)
235                 writew(*bp++, addr);
236         spin_unlock_irqrestore(&pcc_lock, flags);
237 }
238
239 /*====================================================================*/
240
241 #define IS_REGISTERED           0x2000
242 #define IS_ALIVE                0x8000
243
244 typedef struct pcc_t {
245         char                    *name;
246         u_short                 flags;
247 } pcc_t;
248
249 static pcc_t pcc[] = {
250 #if !defined(CONFIG_PLAT_USRV)
251         { "m32r_cfc", 0 }, { "", 0 },
252 #else   /* CONFIG_PLAT_USRV */
253         { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, { "m32r_cfc", 0 },
254         { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, { "", 0 },
255 #endif  /* CONFIG_PLAT_USRV */
256 };
257
258 static irqreturn_t pcc_interrupt(int, void *, struct pt_regs *);
259
260 /*====================================================================*/
261
262 static struct timer_list poll_timer;
263
264 static unsigned int pcc_get(u_short sock, unsigned int reg)
265 {
266         unsigned int val = inw(reg);
267         debug(3, "m32r_cfc: pcc_get: reg(0x%08x)=0x%04x\n", reg, val);
268         return val;
269 }
270
271
272 static void pcc_set(u_short sock, unsigned int reg, unsigned int data)
273 {
274         outw(data, reg);
275         debug(3, "m32r_cfc: pcc_set: reg(0x%08x)=0x%04x\n", reg, data);
276 }
277
278 /*======================================================================
279
280         See if a card is present, powered up, in IO mode, and already
281         bound to a (non PC Card) Linux driver.  We leave these alone.
282
283         We make an exception for cards that seem to be serial devices.
284
285 ======================================================================*/
286
287 static int __init is_alive(u_short sock)
288 {
289         unsigned int stat;
290
291         debug(3, "m32r_cfc: is_alive:\n");
292
293         printk("CF: ");
294         stat = pcc_get(sock, (unsigned int)PLD_CFSTS);
295         if (!stat)
296                 printk("No ");
297         printk("Card is detected at socket %d : stat = 0x%08x\n", sock, stat);
298         debug(3, "m32r_cfc: is_alive: sock stat is 0x%04x\n", stat);
299
300         return 0;
301 }
302
303 static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr)
304 {
305         pcc_socket_t *t = &socket[pcc_sockets];
306
307         debug(3, "m32r_cfc: add_pcc_socket: base=%#lx, irq=%d, "
308                  "mapaddr=%#lx, ioaddr=%08x\n",
309                  base, irq, mapaddr, ioaddr);
310
311         /* add sockets */
312         t->ioaddr = ioaddr;
313         t->mapaddr = mapaddr;
314 #if !defined(CONFIG_PLAT_USRV)
315         t->base = 0;
316         t->flags = 0;
317         t->cs_irq1 = irq;               // insert irq
318         t->cs_irq2 = irq + 1;           // eject irq
319 #else   /* CONFIG_PLAT_USRV */
320         t->base = base;
321         t->flags = 0;
322         t->cs_irq1 = 0;                 // insert irq
323         t->cs_irq2 = 0;                 // eject irq
324 #endif  /* CONFIG_PLAT_USRV */
325
326         if (is_alive(pcc_sockets))
327                 t->flags |= IS_ALIVE;
328
329         /* add pcc */
330 #if !defined(CONFIG_PLAT_USRV)
331         request_region((unsigned int)PLD_CFRSTCR, 0x20, "m32r_cfc");
332 #else   /* CONFIG_PLAT_USRV */
333         {
334                 unsigned int reg_base;
335
336                 reg_base = (unsigned int)PLD_CFRSTCR;
337                 reg_base |= pcc_sockets << 8;
338                 request_region(reg_base, 0x20, "m32r_cfc");
339         }
340 #endif  /* CONFIG_PLAT_USRV */
341         printk(KERN_INFO "  %s ", pcc[pcc_sockets].name);
342         printk("pcc at 0x%08lx\n", t->base);
343
344         /* Update socket interrupt information, capabilities */
345         t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP);
346         t->socket.map_size = M32R_PCC_MAPSIZE;
347         t->socket.io_offset = ioaddr;   /* use for io access offset */
348         t->socket.irq_mask = 0;
349 #if !defined(CONFIG_PLAT_USRV)
350         t->socket.pci_irq = PLD_IRQ_CFIREQ ;    /* card interrupt */
351 #else   /* CONFIG_PLAT_USRV */
352         t->socket.pci_irq = PLD_IRQ_CF0 + pcc_sockets;
353 #endif  /* CONFIG_PLAT_USRV */
354
355 #ifndef CONFIG_PLAT_USRV
356         /* insert interrupt */
357         request_irq(irq, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);
358         /* eject interrupt */
359         request_irq(irq+1, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);
360
361         debug(3, "m32r_cfc: enable CFMSK, RDYSEL\n");
362         pcc_set(pcc_sockets, (unsigned int)PLD_CFIMASK, 0x01);
363 #endif  /* CONFIG_PLAT_USRV */
364 #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
365         pcc_set(pcc_sockets, (unsigned int)PLD_CFCR1, 0x0200);
366 #endif
367         pcc_sockets++;
368
369         return;
370 }
371
372
373 /*====================================================================*/
374
375 static irqreturn_t pcc_interrupt(int irq, void *dev, struct pt_regs *regs)
376 {
377         int i;
378         u_int events = 0;
379         int handled = 0;
380
381         debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p, regs=%p\n",
382                 irq, dev, regs);
383         for (i = 0; i < pcc_sockets; i++) {
384                 if (socket[i].cs_irq1 != irq && socket[i].cs_irq2 != irq)
385                         continue;
386
387                 handled = 1;
388                 debug(3, "m32r_cfc: pcc_interrupt: socket %d irq 0x%02x ",
389                         i, irq);
390                 events |= SS_DETECT;    /* insert or eject */
391                 if (events)
392                         pcmcia_parse_events(&socket[i].socket, events);
393         }
394         debug(3, "m32r_cfc: pcc_interrupt: done\n");
395
396         return IRQ_RETVAL(handled);
397 } /* pcc_interrupt */
398
399 static void pcc_interrupt_wrapper(u_long data)
400 {
401         debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n");
402         pcc_interrupt(0, NULL, NULL);
403         init_timer(&poll_timer);
404         poll_timer.expires = jiffies + poll_interval;
405         add_timer(&poll_timer);
406 }
407
408 /*====================================================================*/
409
410 static int _pcc_get_status(u_short sock, u_int *value)
411 {
412         u_int status;
413
414         debug(3, "m32r_cfc: _pcc_get_status:\n");
415         status = pcc_get(sock, (unsigned int)PLD_CFSTS);
416         *value = (status) ? SS_DETECT : 0;
417         debug(3, "m32r_cfc: _pcc_get_status: status=0x%08x\n", status);
418
419 #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
420         if ( status ) {
421                 /* enable CF power */
422                 status = inw((unsigned int)PLD_CPCR);
423                 if (!(status & PLD_CPCR_CF)) {
424                         debug(3, "m32r_cfc: _pcc_get_status: "
425                                  "power on (CPCR=0x%08x)\n", status);
426                         status |= PLD_CPCR_CF;
427                         outw(status, (unsigned int)PLD_CPCR);
428                         udelay(100);
429                 }
430                 *value |= SS_POWERON;
431
432                 pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);/* enable buffer */
433                 udelay(100);
434
435                 *value |= SS_READY;             /* always ready */
436                 *value |= SS_3VCARD;
437         } else {
438                 /* disable CF power */
439                 status = inw((unsigned int)PLD_CPCR);
440                 status &= ~PLD_CPCR_CF;
441                 outw(status, (unsigned int)PLD_CPCR);
442                 udelay(100);
443                 debug(3, "m32r_cfc: _pcc_get_status: "
444                          "power off (CPCR=0x%08x)\n", status);
445         }
446 #elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
447         if ( status ) {
448                 status = pcc_get(sock, (unsigned int)PLD_CPCR);
449                 if (status == 0) { /* power off */
450                         pcc_set(sock, (unsigned int)PLD_CPCR, 1);
451                         pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */
452                         udelay(50);
453                 }
454                 *value |= SS_POWERON;
455
456                 pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
457                 udelay(50);
458                 pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
459                 udelay(25); /* for IDE reset */
460                 pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
461                 mdelay(2);  /* for IDE reset */
462
463                 *value |= SS_READY;
464                 *value |= SS_3VCARD;
465         } else {
466                 /* disable CF power */
467                 pcc_set(sock, (unsigned int)PLD_CPCR, 0);
468                 udelay(100);
469                 debug(3, "m32r_cfc: _pcc_get_status: "
470                          "power off (CPCR=0x%08x)\n", status);
471         }
472 #else
473 #error no platform configuration
474 #endif
475         debug(3, "m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n",
476                  sock, *value);
477         return 0;
478 } /* _get_status */
479
480 /*====================================================================*/
481
482 static int _pcc_get_socket(u_short sock, socket_state_t *state)
483 {
484 //      pcc_socket_t *t = &socket[sock];
485
486         state->flags = 0;
487         state->csc_mask = SS_DETECT;
488         state->csc_mask |= SS_READY;
489         state->io_irq = 0;
490         state->Vcc = 33;        /* 3.3V fixed */
491         state->Vpp = 33;
492
493         debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
494                   "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
495                   state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
496         return 0;
497 } /* _get_socket */
498
499 /*====================================================================*/
500
501 static int _pcc_set_socket(u_short sock, socket_state_t *state)
502 {
503         debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
504                   "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
505                   state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
506
507 #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
508         if (state->Vcc) {
509                 if ((state->Vcc != 50) && (state->Vcc != 33))
510                         return -EINVAL;
511                 /* accept 5V and 3.3V */
512         }
513 #endif
514         if (state->flags & SS_RESET) {
515                 debug(3, ":RESET\n");
516                 pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);
517         }else{
518                 pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x100);
519         }
520         if (state->flags & SS_OUTPUT_ENA){
521                 debug(3, ":OUTPUT_ENA\n");
522                 /* bit clear */
523                 pcc_set(sock,(unsigned int)PLD_CFBUFCR,0);
524         } else {
525                 pcc_set(sock,(unsigned int)PLD_CFBUFCR,1);
526         }
527
528 #ifdef DEBUG
529         if(state->flags & SS_IOCARD){
530                 debug(3, ":IOCARD");
531         }
532         if (state->flags & SS_PWR_AUTO) {
533                 debug(3, ":PWR_AUTO");
534         }
535         if (state->csc_mask & SS_DETECT)
536                 debug(3, ":csc-SS_DETECT");
537         if (state->flags & SS_IOCARD) {
538                 if (state->csc_mask & SS_STSCHG)
539                         debug(3, ":STSCHG");
540         } else {
541                 if (state->csc_mask & SS_BATDEAD)
542                         debug(3, ":BATDEAD");
543                 if (state->csc_mask & SS_BATWARN)
544                         debug(3, ":BATWARN");
545                 if (state->csc_mask & SS_READY)
546                         debug(3, ":READY");
547         }
548         debug(3, "\n");
549 #endif
550         return 0;
551 } /* _set_socket */
552
553 /*====================================================================*/
554
555 static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
556 {
557         u_char map;
558
559         debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, "
560                   "%#lx-%#lx)\n", sock, io->map, io->flags,
561                   io->speed, io->start, io->stop);
562         map = io->map;
563
564         return 0;
565 } /* _set_io_map */
566
567 /*====================================================================*/
568
569 static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
570 {
571
572         u_char map = mem->map;
573         u_long addr;
574         pcc_socket_t *t = &socket[sock];
575
576         debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, "
577                  "%#lx, %#x)\n", sock, map, mem->flags,
578                  mem->speed, mem->static_start, mem->card_start);
579
580         /*
581          * sanity check
582          */
583         if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){
584                 return -EINVAL;
585         }
586
587         /*
588          * de-activate
589          */
590         if ((mem->flags & MAP_ACTIVE) == 0) {
591                 t->current_space = as_none;
592                 return 0;
593         }
594
595         /*
596          * Set mode
597          */
598         if (mem->flags & MAP_ATTRIB) {
599                 t->current_space = as_attr;
600         } else {
601                 t->current_space = as_comm;
602         }
603
604         /*
605          * Set address
606          */
607         addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK);
608         mem->static_start = addr + mem->card_start;
609
610         return 0;
611
612 } /* _set_mem_map */
613
614 #if 0 /* driver model ordering issue */
615 /*======================================================================
616
617         Routines for accessing socket information and register dumps via
618         /proc/bus/pccard/...
619
620 ======================================================================*/
621
622 static ssize_t show_info(struct class_device *class_dev, char *buf)
623 {
624         pcc_socket_t *s = container_of(class_dev, struct pcc_socket,
625                 socket.dev);
626
627         return sprintf(buf, "type:     %s\nbase addr:    0x%08lx\n",
628                 pcc[s->type].name, s->base);
629 }
630
631 static ssize_t show_exca(struct class_device *class_dev, char *buf)
632 {
633         /* FIXME */
634
635         return 0;
636 }
637
638 static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
639 static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);
640 #endif
641
642 /*====================================================================*/
643
644 /* this is horribly ugly... proper locking needs to be done here at
645  * some time... */
646 #define LOCKED(x) do {                                  \
647         int retval;                                     \
648         unsigned long flags;                            \
649         spin_lock_irqsave(&pcc_lock, flags);            \
650         retval = x;                                     \
651         spin_unlock_irqrestore(&pcc_lock, flags);       \
652         return retval;                                  \
653 } while (0)
654
655
656 static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
657 {
658         unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
659
660         if (socket[sock].flags & IS_ALIVE) {
661                 debug(3, "m32r_cfc: pcc_get_status: sock(%d) -EINVAL\n", sock);
662                 *value = 0;
663                 return -EINVAL;
664         }
665         debug(3, "m32r_cfc: pcc_get_status: sock(%d)\n", sock);
666         LOCKED(_pcc_get_status(sock, value));
667 }
668
669 static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
670 {
671         unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
672
673         if (socket[sock].flags & IS_ALIVE) {
674                 debug(3, "m32r_cfc: pcc_get_socket: sock(%d) -EINVAL\n", sock);
675                 return -EINVAL;
676         }
677         debug(3, "m32r_cfc: pcc_get_socket: sock(%d)\n", sock);
678         LOCKED(_pcc_get_socket(sock, state));
679 }
680
681 static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
682 {
683         unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
684
685         if (socket[sock].flags & IS_ALIVE) {
686                 debug(3, "m32r_cfc: pcc_set_socket: sock(%d) -EINVAL\n", sock);
687                 return -EINVAL;
688         }
689         debug(3, "m32r_cfc: pcc_set_socket: sock(%d)\n", sock);
690         LOCKED(_pcc_set_socket(sock, state));
691 }
692
693 static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
694 {
695         unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
696
697         if (socket[sock].flags & IS_ALIVE) {
698                 debug(3, "m32r_cfc: pcc_set_io_map: sock(%d) -EINVAL\n", sock);
699                 return -EINVAL;
700         }
701         debug(3, "m32r_cfc: pcc_set_io_map: sock(%d)\n", sock);
702         LOCKED(_pcc_set_io_map(sock, io));
703 }
704
705 static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
706 {
707         unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
708
709         if (socket[sock].flags & IS_ALIVE) {
710                 debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d) -EINVAL\n", sock);
711                 return -EINVAL;
712         }
713         debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d)\n", sock);
714         LOCKED(_pcc_set_mem_map(sock, mem));
715 }
716
717 static int pcc_init(struct pcmcia_socket *s)
718 {
719         debug(3, "m32r_cfc: pcc_init()\n");
720         return 0;
721 }
722
723 static struct pccard_operations pcc_operations = {
724         .init                   = pcc_init,
725         .get_status             = pcc_get_status,
726         .get_socket             = pcc_get_socket,
727         .set_socket             = pcc_set_socket,
728         .set_io_map             = pcc_set_io_map,
729         .set_mem_map            = pcc_set_mem_map,
730 };
731
732 /*====================================================================*/
733
734 static struct device_driver pcc_driver = {
735         .name = "cfc",
736         .bus = &platform_bus_type,
737         .suspend = pcmcia_socket_dev_suspend,
738         .resume = pcmcia_socket_dev_resume,
739 };
740
741 static struct platform_device pcc_device = {
742         .name = "cfc",
743         .id = 0,
744 };
745
746 /*====================================================================*/
747
748 static int __init init_m32r_pcc(void)
749 {
750         int i, ret;
751
752         ret = driver_register(&pcc_driver);
753         if (ret)
754                 return ret;
755
756         ret = platform_device_register(&pcc_device);
757         if (ret){
758                 driver_unregister(&pcc_driver);
759                 return ret;
760         }
761
762 #if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
763         pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f);
764         pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);
765 #endif
766
767         pcc_sockets = 0;
768
769 #if !defined(CONFIG_PLAT_USRV)
770         add_pcc_socket(M32R_PCC0_BASE, PLD_IRQ_CFC_INSERT, CFC_ATTR_MAPBASE,
771                        CFC_IOPORT_BASE);
772 #else   /* CONFIG_PLAT_USRV */
773         {
774                 ulong base, mapaddr;
775                 kio_addr_t ioaddr;
776
777                 for (i = 0 ; i < M32R_MAX_PCC ; i++) {
778                         base = (ulong)PLD_CFRSTCR;
779                         base = base | (i << 8);
780                         ioaddr = (i + 1) << 12;
781                         mapaddr = CFC_ATTR_MAPBASE | (i << 20);
782                         add_pcc_socket(base, 0, mapaddr, ioaddr);
783                 }
784         }
785 #endif  /* CONFIG_PLAT_USRV */
786
787         if (pcc_sockets == 0) {
788                 printk("socket is not found.\n");
789                 platform_device_unregister(&pcc_device);
790                 driver_unregister(&pcc_driver);
791                 return -ENODEV;
792         }
793
794         /* Set up interrupt handler(s) */
795
796         for (i = 0 ; i < pcc_sockets ; i++) {
797                 socket[i].socket.dev.dev = &pcc_device.dev;
798                 socket[i].socket.ops = &pcc_operations;
799                 socket[i].socket.resource_ops = &pccard_nonstatic_ops;
800                 socket[i].socket.owner = THIS_MODULE;
801                 socket[i].number = i;
802                 ret = pcmcia_register_socket(&socket[i].socket);
803                 if (!ret)
804                         socket[i].flags |= IS_REGISTERED;
805
806 #if 0   /* driver model ordering issue */
807                 class_device_create_file(&socket[i].socket.dev,
808                                          &class_device_attr_info);
809                 class_device_create_file(&socket[i].socket.dev,
810                                          &class_device_attr_exca);
811 #endif
812         }
813
814         /* Finally, schedule a polling interrupt */
815         if (poll_interval != 0) {
816                 poll_timer.function = pcc_interrupt_wrapper;
817                 poll_timer.data = 0;
818                 init_timer(&poll_timer);
819                 poll_timer.expires = jiffies + poll_interval;
820                 add_timer(&poll_timer);
821         }
822
823         return 0;
824 } /* init_m32r_pcc */
825
826 static void __exit exit_m32r_pcc(void)
827 {
828         int i;
829
830         for (i = 0; i < pcc_sockets; i++)
831                 if (socket[i].flags & IS_REGISTERED)
832                         pcmcia_unregister_socket(&socket[i].socket);
833
834         platform_device_unregister(&pcc_device);
835         if (poll_interval != 0)
836                 del_timer_sync(&poll_timer);
837
838         driver_unregister(&pcc_driver);
839 } /* exit_m32r_pcc */
840
841 module_init(init_m32r_pcc);
842 module_exit(exit_m32r_pcc);
843 MODULE_LICENSE("Dual MPL/GPL");
844 /*====================================================================*/