ab876da8d6ca048db69c1c165f1ea2d5b77f60b0
[linux-2.4.git] / hd64465_ss.c
1 /*
2  * $Id$
3  *
4  * Device driver for the PCMCIA controller module of the
5  * Hitachi HD64465 handheld companion chip.
6  *
7  * Note that the HD64465 provides a very thin PCMCIA host bridge
8  * layer, requiring a lot of the work of supporting cards to be
9  * performed by the processor.  For example: mapping of card
10  * interrupts to processor IRQs is done by IRQ demuxing software;
11  * IO and memory mappings are fixed; setting voltages according
12  * to card Voltage Select pins etc is done in software.
13  *
14  * Note also that this driver uses only the simple, fixed,
15  * 16MB, 16-bit wide mappings to PCMCIA spaces defined by the
16  * HD64465.  Larger mappings, smaller mappings, or mappings of
17  * different width to the same socket, are all possible only by
18  * involving the SH7750's MMU, which is considered unnecessary here.
19  * The downside is that it may be possible for some drivers to
20  * break because they need or expect 8-bit mappings.
21  *
22  * This driver currently supports only the following configuration:
23  * SH7750 CPU, HD64465, TPS2206 voltage control chip.
24  *
25  * by Greg Banks <gbanks@pocketpenguins.com>
26  * (c) 2000 PocketPenguins Inc
27  *
28  */
29
30 #include <linux/types.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/string.h>
34 #include <linux/kernel.h>
35 #include <linux/ioport.h>
36 #include <linux/mm.h>
37 #include <linux/vmalloc.h>
38 #include <asm/errno.h>
39 #include <linux/irq.h>
40
41 #include <asm/io.h>
42 #include <asm/hd64465.h>
43
44 #include <pcmcia/version.h>
45 #include <pcmcia/cs_types.h>
46 #include <pcmcia/cs.h>
47 #include <pcmcia/ss.h>
48 #include <pcmcia/bulkmem.h>
49 #include <pcmcia/cistpl.h>
50 #include "cs_internal.h"
51
52 #define MODNAME "hd64465_ss"
53
54 /* #define HD64465_DEBUG 1 */
55
56 #ifndef HD64465_DEBUG
57 #define HD64465_DEBUG 0
58 #endif
59
60 #if HD64465_DEBUG
61 #define DPRINTK(args...)        printk(MODNAME ": " args)
62 #else
63 #define DPRINTK(args...)
64 #endif
65
66 extern int hd64465_io_debug;
67
68
69 /*============================================================*/
70
71 #define HS_IO_MAP_SIZE  (64*1024)
72
73 typedef struct hs_socket_t
74 {
75     u_int               irq;
76     u_long              mem_base;
77     u_long              mem_length;
78     void                (*handler)(void *info, u_int events);
79     void                *handler_info;
80     u_int               pending_events;
81     u_int               ctrl_base;
82     socket_state_t      state;
83     pccard_io_map       io_maps[MAX_IO_WIN];
84     pccard_mem_map      mem_maps[MAX_WIN];
85     struct vm_struct    *io_vma;    /* allocated kernel vm for mapping IO space */
86 } hs_socket_t;
87
88 #define HS_MAX_SOCKETS 2
89 static hs_socket_t hs_sockets[HS_MAX_SOCKETS];
90 static spinlock_t hs_pending_event_lock = SPIN_LOCK_UNLOCKED;
91
92 /* Calculate socket number from ptr into hs_sockets[] */
93 #define hs_sockno(sp)   (sp - hs_sockets)
94
95 static socket_cap_t hs_socket_cap =
96 {
97     SS_CAP_PCCARD           /* support 16 bit cards */
98     |SS_CAP_STATIC_MAP      /* mappings are fixed in host memory */
99     ,
100     0xffde/*0xffff*/,       /* IRQs mapped in s/w so can do any, really */
101     HD64465_PCC_WINDOW,     /* 16MB fixed window size */
102     0,                      /* no PCI support */
103     0,                      /* no CardBus support */
104     0                       /* no bus operations needed */
105 };
106
107 #define hs_in(sp, r)        inb((sp)->ctrl_base + (r))
108 #define hs_out(sp, v, r)    outb(v, (sp)->ctrl_base + (r))
109
110
111 /* translate a boolean value to a bit in a register */
112 #define bool_to_regbit(sp, r, bi, bo)           \
113     do {                                        \
114         unsigned short v = hs_in(sp, r);        \
115         if (bo)                                 \
116             v |= (bi);                          \
117         else                                    \
118             v &= ~(bi);                         \
119         hs_out(sp, v, r);                       \
120     } while(0)
121     
122 /* register offsets from HD64465_REG_PCC[01]ISR */
123 #define ISR     0x0
124 #define GCR     0x2
125 #define CSCR    0x4
126 #define CSCIER  0x6
127 #define SCR     0x8
128
129
130 /* Mask and values for CSCIER register */
131 #define IER_MASK    0x80
132 #define IER_ON      0x3f        /* interrupts on */
133 #define IER_OFF     0x00        /* interrupts off */
134
135 /*============================================================*/
136
137 #if HD64465_DEBUG > 10
138
139 static void cis_hex_dump(const unsigned char *x, int len)
140 {
141         int i;
142         
143         for (i=0 ; i<len ; i++)
144         {
145             if (!(i & 0xf))
146                 printk("\n%08x", (unsigned)(x + i));
147             printk(" %02x", *(volatile unsigned short*)x);
148             x += 2;
149         }
150         printk("\n");
151 }
152
153 #endif
154 /*============================================================*/
155
156 /*
157  * This code helps create the illusion that the IREQ line from
158  * the PC card is mapped to one of the CPU's IRQ lines by the
159  * host bridge hardware (which is how every host bridge *except*
160  * the HD64465 works).  In particular, it supports enabling
161  * and disabling the IREQ line by code which knows nothing
162  * about the host bridge (e.g. device drivers, IDE code) using
163  * the request_irq(), free_irq(), probe_irq_on() and probe_irq_off()
164  * functions.  Also, it supports sharing the mapped IRQ with
165  * real hardware IRQs from the -IRL0-3 lines.
166  */
167
168 #define HS_NUM_MAPPED_IRQS  16  /* Limitation of the PCMCIA code */
169 static struct
170 {
171     /* index is mapped irq number */
172     hs_socket_t *sock;
173     hw_irq_controller *old_handler;
174 } hs_mapped_irq[HS_NUM_MAPPED_IRQS];
175
176 static void hs_socket_enable_ireq(hs_socket_t *sp)
177 {
178         unsigned short cscier;
179         
180         DPRINTK("hs_socket_enable_ireq(sock=%d)\n", hs_sockno(sp));
181
182         cscier = hs_in(sp, CSCIER);
183         cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK;
184         cscier |= HD64465_PCCCSCIER_PIREQE_LEVEL;
185         hs_out(sp, cscier, CSCIER);
186 }
187
188 static void hs_socket_disable_ireq(hs_socket_t *sp)
189 {
190         unsigned short cscier;
191         
192         DPRINTK("hs_socket_disable_ireq(sock=%d)\n", hs_sockno(sp));
193         
194         cscier = hs_in(sp, CSCIER);
195         cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK;
196         hs_out(sp, cscier, CSCIER);
197 }
198
199 static unsigned int hs_startup_irq(unsigned int irq)
200 {
201         hs_socket_enable_ireq(hs_mapped_irq[irq].sock);
202         hs_mapped_irq[irq].old_handler->startup(irq);
203         return 0;
204 }
205
206 static void hs_shutdown_irq(unsigned int irq)
207 {
208         hs_socket_disable_ireq(hs_mapped_irq[irq].sock);
209         hs_mapped_irq[irq].old_handler->shutdown(irq);
210 }
211
212 static void hs_enable_irq(unsigned int irq)
213 {
214         hs_socket_enable_ireq(hs_mapped_irq[irq].sock);
215         hs_mapped_irq[irq].old_handler->enable(irq);
216 }
217
218 static void hs_disable_irq(unsigned int irq)
219 {
220         hs_socket_disable_ireq(hs_mapped_irq[irq].sock);
221         hs_mapped_irq[irq].old_handler->disable(irq);
222 }
223
224 extern struct hw_interrupt_type no_irq_type;
225
226 static void hs_mask_and_ack_irq(unsigned int irq)
227 {
228         hs_socket_disable_ireq(hs_mapped_irq[irq].sock);
229         /* ack_none() spuriously complains about an unexpected IRQ */
230         if (hs_mapped_irq[irq].old_handler != &no_irq_type)
231             hs_mapped_irq[irq].old_handler->ack(irq);
232 }
233
234 static void hs_end_irq(unsigned int irq)
235 {
236         hs_socket_enable_ireq(hs_mapped_irq[irq].sock);
237         hs_mapped_irq[irq].old_handler->end(irq);
238 }
239
240
241 static struct hw_interrupt_type hd64465_ss_irq_type = {
242         typename:       "PCMCIA-IRQ",
243         startup:        hs_startup_irq,
244         shutdown:       hs_shutdown_irq,
245         enable:         hs_enable_irq,
246         disable:        hs_disable_irq,
247         ack:            hs_mask_and_ack_irq,
248         end:            hs_end_irq
249 };
250
251 /* 
252  * This function should only ever be called with interrupts disabled.
253  */
254 static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
255 {
256         DPRINTK("hs_map_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq);
257         
258         if (irq >= HS_NUM_MAPPED_IRQS)
259             return;
260
261         hs_mapped_irq[irq].sock = sp;
262         /* insert ourselves as the irq controller */
263         hs_mapped_irq[irq].old_handler = irq_desc[irq].handler;
264         irq_desc[irq].handler = &hd64465_ss_irq_type;
265 }
266
267
268 /* 
269  * This function should only ever be called with interrupts disabled.
270  */
271 static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
272 {
273         DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq);
274         
275         if (irq >= HS_NUM_MAPPED_IRQS)
276             return;
277                 
278         /* restore the original irq controller */
279         irq_desc[irq].handler = hs_mapped_irq[irq].old_handler;
280 }
281
282 /*============================================================*/
283
284
285 /*
286  * Set Vpp and Vcc (in tenths of a Volt).  Does not
287  * support the hi-Z state.
288  *
289  * Note, this assumes the board uses a TPS2206 chip to control
290  * the Vcc and Vpp voltages to the hs_sockets.  If your board
291  * uses the MIC2563 (also supported by the HD64465) then you
292  * will have to modify this function.
293  */
294                                          /* 0V   3.3V  5.5V */
295 static const u_char hs_tps2206_avcc[3] = { 0x00, 0x04, 0x08 };
296 static const u_char hs_tps2206_bvcc[3] = { 0x00, 0x80, 0x40 };
297
298 static int hs_set_voltages(hs_socket_t *sp, int Vcc, int Vpp)
299 {
300         u_int psr;
301         u_int vcci = 0;
302         u_int sock = hs_sockno(sp);
303         
304         DPRINTK("hs_set_voltage(%d, %d, %d)\n", sock, Vcc, Vpp);
305
306         switch (Vcc)
307         {
308         case 0:  vcci = 0; break;
309         case 33: vcci = 1; break;
310         case 50: vcci = 2; break;
311         default: return 0;
312         }
313
314         /* Note: Vpp = 120 not supported -- Greg Banks */
315         if (Vpp != 0 && Vpp != Vcc)
316             return 0;
317         
318         /* The PSR register holds 8 of the 9 bits which control
319          * the TPS2206 via its serial interface.
320          */
321         psr = inw(HD64465_REG_PCCPSR);
322         switch (sock)
323         {
324         case 0:
325             psr &= 0x0f;
326             psr |= hs_tps2206_avcc[vcci];
327             psr |= (Vpp == 0 ? 0x00 : 0x02);
328             break;
329         case 1:
330             psr &= 0xf0;
331             psr |= hs_tps2206_bvcc[vcci];
332             psr |= (Vpp == 0 ? 0x00 : 0x20);
333             break;
334         };
335         outw(psr, HD64465_REG_PCCPSR);
336         
337         return 1;
338 }
339
340
341 /*============================================================*/
342
343 /*
344  * Drive the RESET line to the card.
345  */
346 static void hs_reset_socket(hs_socket_t *sp, int on)
347 {
348         unsigned short v;
349         
350         v = hs_in(sp, GCR);
351         if (on)
352             v |= HD64465_PCCGCR_PCCR;
353         else
354             v &= ~HD64465_PCCGCR_PCCR;
355         hs_out(sp, v, GCR);
356 }
357
358 /*============================================================*/
359
360 static int hs_init(unsigned int sock)
361 {
362         hs_socket_t *sp = &hs_sockets[sock];
363         
364         DPRINTK("hs_init(%d)\n", sock);
365         
366         sp->pending_events = 0;
367         sp->state.Vcc = 0;
368         sp->state.Vpp = 0;
369         hs_set_voltages(sp, 0, 0);
370         
371         return 0;
372 }
373
374 /*============================================================*/
375
376 static int hs_suspend(unsigned int sock)
377 {
378         DPRINTK("hs_suspend(%d)\n", sock);
379
380         /* TODO */
381         
382         return 0;
383 }
384
385 /*============================================================*/
386
387 static int hs_register_callback(unsigned int sock,
388             void (*handler)(void *, unsigned int), void * info)
389 {
390         hs_socket_t *sp = &hs_sockets[sock];
391         
392         DPRINTK("hs_register_callback(%d)\n", sock);
393         sp->handler = handler;
394         sp->handler_info = info;
395         if (handler == 0) {
396             MOD_DEC_USE_COUNT;
397         } else {
398             MOD_INC_USE_COUNT;
399         }
400         return 0;
401 }
402
403 /*============================================================*/
404
405 static int hs_inquire_socket(unsigned int sock, socket_cap_t *cap)
406 {
407         DPRINTK("hs_inquire_socket(%d)\n", sock);
408
409         *cap = hs_socket_cap;
410         return 0;
411 }
412
413 /*============================================================*/
414
415 static int hs_get_status(unsigned int sock, u_int *value)
416 {
417         hs_socket_t *sp = &hs_sockets[sock];
418         unsigned int isr;
419         u_int status = 0;
420         
421         
422         isr = hs_in(sp, ISR);
423
424         /* Card is seated and powered when *both* CD pins are low */
425         if ((isr & HD64465_PCCISR_PCD_MASK) == 0)
426         {
427             status |= SS_DETECT;    /* card present */
428
429             switch (isr & HD64465_PCCISR_PBVD_MASK)
430             {
431             case HD64465_PCCISR_PBVD_BATGOOD:   
432                 break;
433             case HD64465_PCCISR_PBVD_BATWARN:
434                 status |= SS_BATWARN;
435                 break;
436             default:
437                 status |= SS_BATDEAD;
438                 break;
439             }
440
441             if (isr & HD64465_PCCISR_PREADY)
442                 status |= SS_READY;
443
444             if (isr & HD64465_PCCISR_PMWP)
445                 status |= SS_WRPROT;
446                 
447             /* Voltage Select pins interpreted as per Table 4-5 of the std.
448              * Assuming we have the TPS2206, the socket is a "Low Voltage
449              * key, 3.3V and 5V available, no X.XV available".
450              */
451             switch (isr & (HD64465_PCCISR_PVS2|HD64465_PCCISR_PVS1))
452             {
453             case HD64465_PCCISR_PVS1:
454                 printk(KERN_NOTICE MODNAME ": cannot handle X.XV card, ignored\n");
455                 status = 0;
456                 break;
457             case 0:
458             case HD64465_PCCISR_PVS2:
459                 /* 3.3V */
460                 status |= SS_3VCARD;
461                 break;
462             case HD64465_PCCISR_PVS2|HD64465_PCCISR_PVS1:
463                 /* 5V */
464                 break;
465             }
466                 
467             /* TODO: SS_POWERON */
468             /* TODO: SS_STSCHG */
469         }       
470         
471         DPRINTK("hs_get_status(%d) = %x\n", sock, status);
472         
473         *value = status;
474         return 0;
475 }
476
477 /*============================================================*/
478
479 static int hs_get_socket(unsigned int sock, socket_state_t *state)
480 {
481         hs_socket_t *sp = &hs_sockets[sock];
482
483         DPRINTK("hs_get_socket(%d)\n", sock);
484         
485         *state = sp->state;
486         return 0;
487 }
488
489 /*============================================================*/
490
491 static int hs_set_socket(unsigned int sock, socket_state_t *state)
492 {
493         hs_socket_t *sp = &hs_sockets[sock];
494         u_long flags;
495         u_int changed;
496         unsigned short cscier;
497
498         DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n",
499             sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq);
500         
501         save_and_cli(flags);    /* Don't want interrupts happening here */
502
503         if (state->Vpp != sp->state.Vpp ||
504             state->Vcc != sp->state.Vcc) {
505             if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) {
506                 restore_flags(flags);
507                 return -EINVAL;
508             }
509         }
510
511 /*      hd64465_io_debug = 1; */
512         /*
513          * Handle changes in the Card Status Change mask,
514          * by propagating to the CSCR register
515          */     
516         changed = sp->state.csc_mask ^ state->csc_mask;
517         cscier = hs_in(sp, CSCIER);
518             
519         if (changed & SS_DETECT) {
520             if (state->csc_mask & SS_DETECT)
521                 cscier |= HD64465_PCCCSCIER_PCDE;
522             else
523                 cscier &= ~HD64465_PCCCSCIER_PCDE;
524         }
525
526         if (changed & SS_READY) {
527             if (state->csc_mask & SS_READY)
528                 cscier |= HD64465_PCCCSCIER_PRE;
529             else
530                 cscier &= ~HD64465_PCCCSCIER_PRE;
531         }
532
533         if (changed & SS_BATDEAD) {
534             if (state->csc_mask & SS_BATDEAD)
535                 cscier |= HD64465_PCCCSCIER_PBDE;
536             else
537                 cscier &= ~HD64465_PCCCSCIER_PBDE;
538         }
539
540         if (changed & SS_BATWARN) {
541             if (state->csc_mask & SS_BATWARN)
542                 cscier |= HD64465_PCCCSCIER_PBWE;
543             else
544                 cscier &= ~HD64465_PCCCSCIER_PBWE;
545         }
546
547         if (changed & SS_STSCHG) {
548             if (state->csc_mask & SS_STSCHG)
549                 cscier |= HD64465_PCCCSCIER_PSCE;
550             else
551                 cscier &= ~HD64465_PCCCSCIER_PSCE;
552         }
553
554         hs_out(sp, cscier, CSCIER);
555
556         if (sp->state.io_irq && !state->io_irq)
557             hs_unmap_irq(sp, sp->state.io_irq);
558         else if (!sp->state.io_irq && state->io_irq)
559             hs_map_irq(sp, state->io_irq);
560
561
562         /*
563          * Handle changes in the flags field,
564          * by propagating to config registers.
565          */     
566         changed = sp->state.flags ^ state->flags;
567
568         if (changed & SS_IOCARD) {
569             DPRINTK("card type: %s\n",
570                     (state->flags & SS_IOCARD ? "i/o" : "memory" ));
571             bool_to_regbit(sp, GCR, HD64465_PCCGCR_PCCT,
572                 state->flags & SS_IOCARD);
573         }
574
575         if (changed & SS_RESET) {
576             DPRINTK("%s reset card\n",
577                 (state->flags & SS_RESET ? "start" : "stop"));
578             bool_to_regbit(sp, GCR, HD64465_PCCGCR_PCCR,
579                 state->flags & SS_RESET);
580         }
581
582         if (changed & SS_OUTPUT_ENA) {
583             DPRINTK("%sabling card output\n",
584                 (state->flags & SS_OUTPUT_ENA ? "en" : "dis"));
585             bool_to_regbit(sp, GCR, HD64465_PCCGCR_PDRV,
586                 state->flags & SS_OUTPUT_ENA);
587         }
588
589         /* TODO: SS_SPKR_ENA */
590             
591 /*      hd64465_io_debug = 0; */
592         sp->state = *state;
593             
594         restore_flags(flags);
595
596 #if HD64465_DEBUG > 10
597         if (state->flags & SS_OUTPUT_ENA)   
598             cis_hex_dump((const unsigned char*)sp->mem_base, 0x100);
599 #endif
600         return 0;
601 }
602
603 /*============================================================*/
604
605 static int hs_get_io_map(unsigned int sock, struct pccard_io_map *io)
606 {
607         hs_socket_t *sp = &hs_sockets[sock];
608         int map = io->map;
609
610         DPRINTK("hs_get_io_map(%d, %d)\n", sock, map);
611         if (map >= MAX_IO_WIN)
612             return -EINVAL;
613         
614         *io = sp->io_maps[map];
615         return 0;
616 }
617
618 /*============================================================*/
619
620 static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io)
621 {
622         hs_socket_t *sp = &hs_sockets[sock];
623         int map = io->map;
624         struct pccard_io_map *sio;
625         pgprot_t prot;
626
627         DPRINTK("hs_set_io_map(sock=%d, map=%d, flags=0x%x, speed=%dns, start=0x%04x, stop=0x%04x)\n",
628             sock, map, io->flags, io->speed, io->start, io->stop);
629         if (map >= MAX_IO_WIN)
630             return -EINVAL;
631         sio = &sp->io_maps[map];
632
633         /* check for null changes */    
634         if (io->flags == sio->flags &&
635             io->start == sio->start &&
636             io->stop == sio->stop)
637             return 0;
638         
639         if (io->flags & MAP_AUTOSZ)
640             prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IODYN);
641         else if (io->flags & MAP_16BIT)
642             prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IO16);
643         else
644             prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IO8);
645
646         /* TODO: handle MAP_USE_WAIT */
647         if (io->flags & MAP_USE_WAIT)
648             printk(KERN_INFO MODNAME ": MAP_USE_WAIT unimplemented\n");
649         /* TODO: handle MAP_PREFETCH */
650         if (io->flags & MAP_PREFETCH)
651             printk(KERN_INFO MODNAME ": MAP_PREFETCH unimplemented\n");
652         /* TODO: handle MAP_WRPROT */
653         if (io->flags & MAP_WRPROT)
654             printk(KERN_INFO MODNAME ": MAP_WRPROT unimplemented\n");
655         /* TODO: handle MAP_0WS */
656         if (io->flags & MAP_0WS)
657             printk(KERN_INFO MODNAME ": MAP_0WS unimplemented\n");
658
659         if (io->flags & MAP_ACTIVE) {
660             unsigned long pstart, psize, paddrbase, vaddrbase;
661             
662             paddrbase = virt_to_phys((void*)(sp->mem_base + 2 * HD64465_PCC_WINDOW));
663             vaddrbase = (unsigned long)sp->io_vma->addr;
664             pstart = io->start & PAGE_MASK;
665             psize = ((io->stop + PAGE_SIZE) & PAGE_MASK) - pstart;
666
667             /*
668              * Change PTEs in only that portion of the mapping requested
669              * by the caller.  This means that most of the time, most of
670              * the PTEs in the io_vma will be unmapped and only the bottom
671              * page will be mapped.  But the code allows for weird cards
672              * that might want IO ports > 4K.
673              */
674             DPRINTK("remap_page_range(vaddr=0x%08lx, paddr=0x%08lx, size=0x%08lxx)\n",
675                 vaddrbase + pstart, paddrbase + pstart, psize);
676             remap_page_range(vaddrbase + pstart, paddrbase + pstart, psize, prot);
677             
678             /*
679              * Change the mapping used by inb() outb() etc
680              */
681             hd64465_port_map(
682                 io->start,
683                 io->stop - io->start + 1,
684                 vaddrbase + io->start,0);
685         } else {
686             hd64465_port_unmap(
687                 sio->start,
688                 sio->stop - sio->start + 1);
689             /* TODO: remap_page_range() to mark pages not present ? */
690         }
691         
692         *sio = *io;
693         return 0;
694 }
695
696 /*============================================================*/
697
698 static int hs_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
699 {
700         hs_socket_t *sp = &hs_sockets[sock];
701         int map = mem->map;
702
703         DPRINTK("hs_get_mem_map(%d, %d)\n", sock, map);
704         if (map >= MAX_WIN)
705             return -EINVAL;
706         
707         *mem = sp->mem_maps[map];
708         return 0;
709 }
710
711 /*============================================================*/
712
713 static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
714 {
715         hs_socket_t *sp = &hs_sockets[sock];
716         struct pccard_mem_map *smem;
717         int map = mem->map;
718         unsigned long paddr, size;
719
720 #if 0
721         DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n",
722             sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start);
723 #endif
724
725         if (map >= MAX_WIN)
726             return -EINVAL;
727         smem = &sp->mem_maps[map];
728         
729         size = mem->sys_stop - mem->sys_start + 1;
730         
731         paddr = sp->mem_base;               /* base of Attribute mapping */
732         if (!(mem->flags & MAP_ATTRIB))
733             paddr += HD64465_PCC_WINDOW;    /* base of Common mapping */
734         paddr += mem->card_start;
735
736         /* Because we specified SS_CAP_STATIC_MAP, we are obliged
737          * at this time to report the system address corresponding
738          * to the card address requested.  This is how Socket Services
739          * queries our fixed mapping.  I wish this fact had been
740          * documented - Greg Banks.
741          */
742         mem->sys_start = paddr;
743         mem->sys_stop = paddr + size - 1;
744         
745         *smem = *mem;
746         
747         return 0;
748 }
749
750 /* TODO: do we need to use the MMU to access Common memory ??? */
751
752 /*============================================================*/
753
754 static void hs_proc_setup(unsigned int sock, struct proc_dir_entry *base)
755 {
756         DPRINTK("hs_proc_setup(%d)\n", sock);
757 }
758
759 /*============================================================*/
760
761 /*
762  * This function is registered with the HD64465 glue code to do a
763  * secondary demux step on the PCMCIA interrupts.  It handles 
764  * mapping the IREQ request from the card to a standard Linux
765  * IRQ, as requested by SocketServices.
766  */
767 static int hs_irq_demux(int irq, void *dev)
768 {
769         hs_socket_t *sp = (hs_socket_t *)dev;
770         u_int cscr;
771         
772         DPRINTK("hs_irq_demux(irq=%d)\n", irq);
773
774         if (sp->state.io_irq &&
775             (cscr = hs_in(sp, CSCR)) & HD64465_PCCCSCR_PIREQ) {
776             cscr &= ~HD64465_PCCCSCR_PIREQ;
777             hs_out(sp, cscr, CSCR);
778             return sp->state.io_irq;
779         }
780             
781         return irq;
782 }
783
784 /*============================================================*/
785
786 /*
787  * Interrupt handling routine.
788  *
789  * This uses the schedule_task() technique to cause reportable events
790  * such as card insertion and removal to be handled in keventd's
791  * process context.
792  */
793  
794
795 static void hs_events_bh(void *dummy)
796 {
797         hs_socket_t *sp;
798         u_int events;
799         int i;
800
801         for (i=0; i<HS_MAX_SOCKETS; i++) {
802             sp = &hs_sockets[i];
803
804             spin_lock_irq(&hs_pending_event_lock);
805             events = sp->pending_events;
806             sp->pending_events = 0;
807             spin_unlock_irq(&hs_pending_event_lock);
808             
809             if (sp->handler)
810                 sp->handler(sp->handler_info, events);
811         }
812 }
813
814 static struct tq_struct hs_events_task = {
815         routine:        hs_events_bh
816 };
817
818 static void hs_interrupt(int irq, void *dev, struct pt_regs *regs)
819 {
820         hs_socket_t *sp = (hs_socket_t *)dev;
821         u_int events = 0;
822         u_int cscr;
823         
824         
825         cscr = hs_in(sp, CSCR);
826         
827         DPRINTK("hs_interrupt, cscr=%04x\n", cscr);
828
829         /* check for bus-related changes to be reported to Socket Services */
830         if (cscr & HD64465_PCCCSCR_PCDC) {
831             /* double-check for a 16-bit card, as we don't support CardBus */
832             if ((hs_in(sp, ISR) & HD64465_PCCISR_PCD_MASK) != 0) {
833                 printk(KERN_NOTICE MODNAME
834                     ": socket %d, card not a supported card type or not inserted correctly\n",
835                     hs_sockno(sp));
836                 /* Don't do the rest unless a card is present */
837                 cscr &= ~(HD64465_PCCCSCR_PCDC|
838                           HD64465_PCCCSCR_PRC|
839                           HD64465_PCCCSCR_PBW|
840                           HD64465_PCCCSCR_PBD|
841                           HD64465_PCCCSCR_PSC);
842             } else {
843                 cscr &= ~HD64465_PCCCSCR_PCDC;
844                 events |= SS_DETECT;            /* card insertion or removal */
845             }
846         }
847         if (cscr & HD64465_PCCCSCR_PRC) {
848             cscr &= ~HD64465_PCCCSCR_PRC;
849             events |= SS_READY;         /* ready signal changed */
850         }
851         if (cscr & HD64465_PCCCSCR_PBW) {
852             cscr &= ~HD64465_PCCCSCR_PSC;
853             events |= SS_BATWARN;       /* battery warning */
854         }
855         if (cscr & HD64465_PCCCSCR_PBD) {
856             cscr &= ~HD64465_PCCCSCR_PSC;
857             events |= SS_BATDEAD;       /* battery dead */
858         }
859         if (cscr & HD64465_PCCCSCR_PSC) {
860             cscr &= ~HD64465_PCCCSCR_PSC;
861             events |= SS_STSCHG;        /* STSCHG (status changed) signal */
862         }
863         
864         if (cscr & HD64465_PCCCSCR_PIREQ) {
865             cscr &= ~HD64465_PCCCSCR_PIREQ;
866
867             /* This should have been dealt with during irq demux */         
868             printk(KERN_NOTICE MODNAME ": unexpected IREQ from card\n");
869         }
870
871         hs_out(sp, cscr, CSCR);
872
873         if (events) {
874             /*
875              * Arrange for events to be reported to the registered
876              * event handler function (from CardServices) in a process
877              * context (keventd) "soon".
878              */
879             spin_lock(&hs_pending_event_lock);
880             sp->pending_events |= events;
881             spin_unlock(&hs_pending_event_lock);
882             
883             schedule_task(&hs_events_task);
884         }
885 }
886
887 /*============================================================*/
888
889 static struct pccard_operations hs_operations = {
890         hs_init,
891         hs_suspend,
892         hs_register_callback,
893         hs_inquire_socket,
894         hs_get_status,
895         hs_get_socket,
896         hs_set_socket,
897         hs_get_io_map,
898         hs_set_io_map,
899         hs_get_mem_map,
900         hs_set_mem_map,
901         hs_proc_setup
902 };
903
904 static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base,
905             unsigned int ctrl_base)
906 {
907         unsigned short v;
908         int i, err;
909
910         memset(sp, 0, sizeof(*sp));
911         sp->irq = irq;
912         sp->mem_base = mem_base;
913         sp->mem_length = 4*HD64465_PCC_WINDOW;  /* 16MB */
914         sp->ctrl_base = ctrl_base;
915         
916         for (i=0 ; i<MAX_IO_WIN ; i++)
917             sp->io_maps[i].map = i;
918         for (i=0 ; i<MAX_WIN ; i++)
919             sp->mem_maps[i].map = i;
920         
921         if ((sp->io_vma = get_vm_area(HS_IO_MAP_SIZE, VM_IOREMAP)) == 0)
922             return -ENOMEM;
923
924         hd64465_register_irq_demux(sp->irq, hs_irq_demux, sp);
925         
926         if ((err = request_irq(sp->irq, hs_interrupt, SA_INTERRUPT, MODNAME, sp)) < 0)
927             return err;
928         if (request_mem_region(sp->mem_base, sp->mem_length, MODNAME) == 0) {
929             sp->mem_base = 0;
930             return -ENOMEM;
931         }
932
933
934         /* According to section 3.2 of the PCMCIA standard, low-voltage
935          * capable cards must implement cold insertion, i.e. Vpp and
936          * Vcc set to 0 before card is inserted.
937          */
938         /*hs_set_voltages(sp, 0, 0);*/
939         
940         /* hi-Z the outputs to the card and set 16MB map mode */
941         v = hs_in(sp, GCR);
942         v &= ~HD64465_PCCGCR_PCCT;      /* memory-only card */
943         hs_out(sp, v, GCR);
944
945         v = hs_in(sp, GCR);
946         v |= HD64465_PCCGCR_PDRV;       /* enable outputs to card */
947         hs_out(sp, v, GCR);
948
949         v = hs_in(sp, GCR);
950         v |= HD64465_PCCGCR_PMMOD;      /* 16MB mapping mode */
951         hs_out(sp, v, GCR);
952
953         v = hs_in(sp, GCR);
954         /* lowest 16MB of Common */
955         v &= ~(HD64465_PCCGCR_PPA25|HD64465_PCCGCR_PPA24); 
956         hs_out(sp, v, GCR);
957         
958         hs_reset_socket(sp, 1);
959
960         return 0;
961 }
962
963 static void hs_exit_socket(hs_socket_t *sp)
964 {
965         unsigned short cscier, gcr;
966         
967         /* turn off interrupts in hardware */
968         cscier = hs_in(sp, CSCIER);
969         cscier = (cscier & IER_MASK) | IER_OFF;
970         hs_out(sp, cscier, CSCIER);
971         
972         /* hi-Z the outputs to the card */
973         gcr = hs_in(sp, GCR);
974         gcr &= HD64465_PCCGCR_PDRV;
975         hs_out(sp, gcr, GCR);
976
977         /* power the card down */
978         hs_set_voltages(sp, 0, 0);
979
980         if (sp->mem_base != 0)
981             release_mem_region(sp->mem_base, sp->mem_length);
982         if (sp->irq != 0) {
983             free_irq(sp->irq, hs_interrupt);
984             hd64465_unregister_irq_demux(sp->irq);
985         }
986         if (sp->io_vma != 0)
987             vfree(sp->io_vma->addr);
988 }
989
990
991 static int __init init_hs(void)
992 {
993         servinfo_t serv;
994         int i;
995         unsigned short v;
996
997         /*
998          * Check API version
999          */
1000         pcmcia_get_card_services_info(&serv);
1001         if (serv.Revision != CS_RELEASE_CODE) {
1002             printk(KERN_NOTICE MODNAME ": Card Services release does not match!\n");
1003             return -ENODEV;
1004         }
1005
1006 /*      hd64465_io_debug = 1; */
1007         
1008         /* Wake both sockets out of STANDBY mode */
1009         /* TODO: wait 15ms */
1010         v = inw(HD64465_REG_SMSCR);
1011         v &= ~(HD64465_SMSCR_PC0ST|HD64465_SMSCR_PC1ST);
1012         outw(v, HD64465_REG_SMSCR);
1013
1014         /* keep power controller out of shutdown mode */
1015         v = inb(HD64465_REG_PCC0SCR);
1016         v |= HD64465_PCCSCR_SHDN;
1017         outb(v, HD64465_REG_PCC0SCR);
1018
1019         /* use serial (TPS2206) power controller */
1020         v = inb(HD64465_REG_PCC0CSCR);
1021         v |= HD64465_PCCCSCR_PSWSEL;
1022         outb(v, HD64465_REG_PCC0CSCR);
1023
1024         hs_set_voltages(&hs_sockets[0], 0, 0);
1025         hs_set_voltages(&hs_sockets[1], 0, 0);
1026         
1027         /*
1028          * Setup hs_sockets[] structures and request system resources.
1029          * TODO: on memory allocation failure, power down the socket
1030          *       before quitting.
1031          */
1032         i = hs_init_socket(&hs_sockets[0],
1033             HD64465_IRQ_PCMCIA0,
1034             HD64465_PCC0_BASE,
1035             HD64465_REG_PCC0ISR);
1036         if (i < 0)
1037             return i;
1038         i = hs_init_socket(&hs_sockets[1],
1039             HD64465_IRQ_PCMCIA1,
1040             HD64465_PCC1_BASE,
1041             HD64465_REG_PCC1ISR);
1042         if (i < 0)
1043             return i;
1044
1045 /*      hd64465_io_debug = 0; */
1046             
1047
1048         if (register_ss_entry(HS_MAX_SOCKETS, &hs_operations) != 0) {
1049             for (i=0 ; i<HS_MAX_SOCKETS ; i++)
1050                 hs_exit_socket(&hs_sockets[i]);
1051             return -ENODEV;
1052         }
1053
1054         printk(KERN_INFO "HD64465 PCMCIA bridge:\n");
1055         for (i=0 ; i<HS_MAX_SOCKETS ; i++) {
1056             hs_socket_t *sp = &hs_sockets[i];
1057             
1058             printk(KERN_INFO "  socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n",
1059                 i, sp->mem_base, sp->irq,
1060                 sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr);
1061         }
1062
1063         return 0;
1064 }
1065
1066 static void __exit exit_hs(void)
1067 {
1068         u_long flags;
1069         int i;
1070         
1071         save_and_cli(flags);
1072
1073         /*
1074          * Release kernel resources
1075          */
1076         for (i=0 ; i<HS_MAX_SOCKETS ; i++)
1077             hs_exit_socket(&hs_sockets[i]);
1078         unregister_ss_entry(&hs_operations);
1079         
1080         restore_flags(flags);
1081 }
1082
1083 module_init(init_hs);
1084 module_exit(exit_hs);
1085
1086 /*============================================================*/
1087 /*END*/