- pre6:
[davej-history.git] / drivers / pcmcia / tcic.c
bloba4d43e168543c48ad57277dd53398c9a158d9267
1 /*======================================================================
3 Device driver for Databook TCIC-2 PCMCIA controller
5 tcic.c 1.111 2000/02/15 04:13:12
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
32 ======================================================================*/
34 #include <linux/module.h>
35 #include <linux/init.h>
36 #include <linux/types.h>
37 #include <linux/fcntl.h>
38 #include <linux/string.h>
40 #include <asm/io.h>
41 #include <asm/bitops.h>
42 #include <asm/segment.h>
43 #include <asm/system.h>
45 #include <linux/kernel.h>
46 #include <linux/errno.h>
47 #include <linux/sched.h>
48 #include <linux/malloc.h>
49 #include <linux/timer.h>
50 #include <linux/ioport.h>
51 #include <linux/delay.h>
53 #include <pcmcia/version.h>
54 #include <pcmcia/cs_types.h>
55 #include <pcmcia/cs.h>
56 #include <pcmcia/ss.h>
57 #include "tcic.h"
59 #ifdef PCMCIA_DEBUG
60 static int pc_debug = PCMCIA_DEBUG;
61 MODULE_PARM(pc_debug, "i");
62 static const char *version =
63 "tcic.c 1.111 2000/02/15 04:13:12 (David Hinds)";
64 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
65 #else
66 #define DEBUG(n, args...)
67 #endif
69 MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
70 MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
72 /*====================================================================*/
74 /* Parameters that can be set with 'insmod' */
76 /* The base port address of the TCIC-2 chip */
77 static int tcic_base = TCIC_BASE;
79 /* Specify a socket number to ignore */
80 static int ignore = -1;
82 /* Probe for safe interrupts? */
83 static int do_scan = 1;
85 /* Bit map of interrupts to choose from */
86 static u_int irq_mask = 0xffff;
87 static int irq_list[16] = { -1 };
89 /* The card status change interrupt -- 0 means autoselect */
90 static int cs_irq = 0;
92 /* Poll status interval -- 0 means default to interrupt */
93 static int poll_interval = 0;
95 /* Delay for card status double-checking */
96 static int poll_quick = HZ/20;
98 /* CCLK external clock time, in nanoseconds. 70 ns = 14.31818 MHz */
99 static int cycle_time = 70;
101 MODULE_PARM(tcic_base, "i");
102 MODULE_PARM(ignore, "i");
103 MODULE_PARM(do_scan, "i");
104 MODULE_PARM(irq_mask, "i");
105 MODULE_PARM(irq_list, "1-16i");
106 MODULE_PARM(cs_irq, "i");
107 MODULE_PARM(poll_interval, "i");
108 MODULE_PARM(poll_quick, "i");
109 MODULE_PARM(cycle_time, "i");
111 /*====================================================================*/
113 static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
114 static void tcic_timer(u_long data);
115 static struct pccard_operations tcic_operations;
117 typedef struct socket_info_t {
118 u_short psock;
119 void (*handler)(void *info, u_int events);
120 void *info;
121 u_char last_sstat;
122 u_char id;
123 } socket_info_t;
125 static struct timer_list poll_timer;
126 static int tcic_timer_pending = 0;
128 static int sockets;
129 static socket_info_t socket_table[2];
131 static socket_cap_t tcic_cap = {
132 /* only 16-bit cards, memory windows must be size-aligned */
133 SS_CAP_PCCARD | SS_CAP_MEM_ALIGN,
134 0x4cf8, /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
135 0x1000, /* 4K minimum window size */
136 0, 0 /* No PCI or CardBus support */
139 /*====================================================================*/
141 /* Trick when selecting interrupts: the TCIC sktirq pin is supposed
142 to map to irq 11, but is coded as 0 or 1 in the irq registers. */
143 #define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
145 #ifdef PCMCIA_DEBUG_X
146 static u_char tcic_getb(u_char reg)
148 u_char val = inb(tcic_base+reg);
149 printk(KERN_DEBUG "tcic_getb(%#x) = %#x\n", tcic_base+reg, val);
150 return val;
153 static u_short tcic_getw(u_char reg)
155 u_short val = inw(tcic_base+reg);
156 printk(KERN_DEBUG "tcic_getw(%#x) = %#x\n", tcic_base+reg, val);
157 return val;
160 static void tcic_setb(u_char reg, u_char data)
162 printk(KERN_DEBUG "tcic_setb(%#x, %#x)\n", tcic_base+reg, data);
163 outb(data, tcic_base+reg);
166 static void tcic_setw(u_char reg, u_short data)
168 printk(KERN_DEBUG "tcic_setw(%#x, %#x)\n", tcic_base+reg, data);
169 outw(data, tcic_base+reg);
171 #else
172 #define tcic_getb(reg) inb(tcic_base+reg)
173 #define tcic_getw(reg) inw(tcic_base+reg)
174 #define tcic_setb(reg, data) outb(data, tcic_base+reg)
175 #define tcic_setw(reg, data) outw(data, tcic_base+reg)
176 #endif
178 static void tcic_setl(u_char reg, u_int data)
180 #ifdef PCMCIA_DEBUG_X
181 printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
182 #endif
183 outw(data & 0xffff, tcic_base+reg);
184 outw(data >> 16, tcic_base+reg+2);
187 static u_char tcic_aux_getb(u_short reg)
189 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
190 tcic_setb(TCIC_MODE, mode);
191 return tcic_getb(TCIC_AUX);
194 static void tcic_aux_setb(u_short reg, u_char data)
196 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
197 tcic_setb(TCIC_MODE, mode);
198 tcic_setb(TCIC_AUX, data);
201 static u_short tcic_aux_getw(u_short reg)
203 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
204 tcic_setb(TCIC_MODE, mode);
205 return tcic_getw(TCIC_AUX);
208 static void tcic_aux_setw(u_short reg, u_short data)
210 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
211 tcic_setb(TCIC_MODE, mode);
212 tcic_setw(TCIC_AUX, data);
215 /*====================================================================*/
217 /* Time conversion functions */
219 static int to_cycles(int ns)
221 if (ns < 14)
222 return 0;
223 else
224 return 2*(ns-14)/cycle_time;
227 static int to_ns(int cycles)
229 return (cycles*cycle_time)/2 + 14;
232 /*====================================================================*/
234 static volatile u_int irq_hits;
236 static void __init irq_count(int irq, void *dev, struct pt_regs *regs)
238 irq_hits++;
241 static u_int __init try_irq(int irq)
243 u_short cfg;
245 irq_hits = 0;
246 if (request_irq(irq, irq_count, 0, "irq scan", irq_count) != 0)
247 return -1;
248 mdelay(10);
249 if (irq_hits) {
250 free_irq(irq, irq_count);
251 return -1;
254 /* Generate one interrupt */
255 cfg = TCIC_SYSCFG_AUTOBUSY | 0x0a00;
256 tcic_aux_setw(TCIC_AUX_SYSCFG, cfg | TCIC_IRQ(irq));
257 tcic_setb(TCIC_IENA, TCIC_IENA_ERR | TCIC_IENA_CFG_HIGH);
258 tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM);
260 udelay(1000);
261 free_irq(irq, irq_count);
263 /* Turn off interrupts */
264 tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF);
265 while (tcic_getb(TCIC_ICSR))
266 tcic_setb(TCIC_ICSR, TCIC_ICSR_JAM);
267 tcic_aux_setw(TCIC_AUX_SYSCFG, cfg);
269 return (irq_hits != 1);
272 static u_int __init irq_scan(u_int mask0)
274 u_int mask1;
275 int i;
277 #ifdef __alpha__
278 #define PIC 0x4d0
279 /* Don't probe level-triggered interrupts -- reserved for PCI */
280 int level_mask = inb_p(PIC) | (inb_p(PIC+1) << 8);
281 if (level_mask)
282 mask0 &= ~level_mask;
283 #endif
285 mask1 = 0;
286 if (do_scan) {
287 for (i = 0; i < 16; i++)
288 if ((mask0 & (1 << i)) && (try_irq(i) == 0))
289 mask1 |= (1 << i);
290 for (i = 0; i < 16; i++)
291 if ((mask1 & (1 << i)) && (try_irq(i) != 0)) {
292 mask1 ^= (1 << i);
296 if (mask1) {
297 printk("scanned");
298 } else {
299 /* Fallback: just find interrupts that aren't in use */
300 for (i = 0; i < 16; i++)
301 if ((mask0 & (1 << i)) &&
302 (request_irq(i, irq_count, 0, "x", irq_count) == 0)) {
303 mask1 |= (1 << i);
304 free_irq(i, irq_count);
306 printk("default");
309 printk(") = ");
310 for (i = 0; i < 16; i++)
311 if (mask1 & (1<<i))
312 printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
313 printk(" ");
315 return mask1;
318 /*======================================================================
320 See if a card is present, powered up, in IO mode, and already
321 bound to a (non-PCMCIA) Linux driver.
323 We make an exception for cards that look like serial devices.
325 ======================================================================*/
327 static int __init is_active(int s)
329 u_short scf1, ioctl, base, num;
330 u_char pwr, sstat;
331 u_int addr;
333 tcic_setl(TCIC_ADDR, (s << TCIC_ADDR_SS_SHFT)
334 | TCIC_ADDR_INDREG | TCIC_SCF1(s));
335 scf1 = tcic_getw(TCIC_DATA);
336 pwr = tcic_getb(TCIC_PWR);
337 sstat = tcic_getb(TCIC_SSTAT);
338 addr = TCIC_IWIN(s, 0);
339 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
340 base = tcic_getw(TCIC_DATA);
341 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
342 ioctl = tcic_getw(TCIC_DATA);
344 if (ioctl & TCIC_ICTL_TINY)
345 num = 1;
346 else {
347 num = (base ^ (base-1));
348 base = base & (base-1);
351 if ((sstat & TCIC_SSTAT_CD) && (pwr & TCIC_PWR_VCC(s)) &&
352 (scf1 & TCIC_SCF1_IOSTS) && (ioctl & TCIC_ICTL_ENA) &&
353 (check_region(base, num) != 0) && ((base & 0xfeef) != 0x02e8))
354 return 1;
355 else
356 return 0;
359 /*======================================================================
361 This returns the revision code for the specified socket.
363 ======================================================================*/
365 static int __init get_tcic_id(void)
367 u_short id;
369 tcic_aux_setw(TCIC_AUX_TEST, TCIC_TEST_DIAG);
370 id = tcic_aux_getw(TCIC_AUX_ILOCK);
371 id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
372 tcic_aux_setw(TCIC_AUX_TEST, 0);
373 return id;
376 /*====================================================================*/
378 static int __init init_tcic(void)
380 int i, sock;
381 u_int mask, scan;
382 servinfo_t serv;
384 DEBUG(0, "%s\n", version);
385 pcmcia_get_card_services_info(&serv);
386 if (serv.Revision != CS_RELEASE_CODE) {
387 printk(KERN_NOTICE "tcic: Card Services release "
388 "does not match!\n");
389 return -1;
392 printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
393 sock = 0;
395 if (check_region(tcic_base, 16) == 0) {
396 tcic_setw(TCIC_ADDR, 0);
397 if (tcic_getw(TCIC_ADDR) == 0) {
398 tcic_setw(TCIC_ADDR, 0xc3a5);
399 if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
401 if (sock == 0) {
402 /* See if resetting the controller does any good */
403 tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
404 tcic_setb(TCIC_SCTRL, 0);
405 tcic_setw(TCIC_ADDR, 0);
406 if (tcic_getw(TCIC_ADDR) == 0) {
407 tcic_setw(TCIC_ADDR, 0xc3a5);
408 if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
411 } else
412 printk("could not allocate ports, ");
414 if (sock == 0) {
415 printk("not found.\n");
416 return -ENODEV;
419 request_region(tcic_base, 16, "tcic-2");
421 sockets = 0;
422 for (i = 0; i < sock; i++) {
423 if ((i == ignore) || is_active(i)) continue;
424 socket_table[sockets].psock = i;
425 socket_table[sockets].handler = NULL;
426 socket_table[sockets].info = NULL;
427 socket_table[sockets].id = get_tcic_id();
428 sockets++;
431 switch (socket_table[0].id) {
432 case TCIC_ID_DB86082:
433 printk("DB86082"); break;
434 case TCIC_ID_DB86082A:
435 printk("DB86082A"); break;
436 case TCIC_ID_DB86084:
437 printk("DB86084"); break;
438 case TCIC_ID_DB86084A:
439 printk("DB86084A"); break;
440 case TCIC_ID_DB86072:
441 printk("DB86072"); break;
442 case TCIC_ID_DB86184:
443 printk("DB86184"); break;
444 case TCIC_ID_DB86082B:
445 printk("DB86082B"); break;
446 default:
447 printk("Unknown ID 0x%02x", socket_table[0].id);
450 /* Set up polling */
451 poll_timer.function = &tcic_timer;
452 poll_timer.data = 0;
453 init_timer(&poll_timer);
455 /* Build interrupt mask */
456 printk(", %d sockets\n" KERN_INFO " irq list (", sockets);
457 if (irq_list[0] == -1)
458 mask = irq_mask;
459 else
460 for (i = mask = 0; i < 16; i++)
461 mask |= (1<<irq_list[i]);
462 mask &= tcic_cap.irq_mask;
464 /* Scan interrupts */
465 mask = irq_scan(mask);
466 tcic_cap.irq_mask = mask;
468 /* Check for only two interrupts available */
469 scan = (mask & (mask-1));
470 if (((scan & (scan-1)) == 0) && (poll_interval == 0))
471 poll_interval = HZ;
473 if (poll_interval == 0) {
474 /* Avoid irq 12 unless it is explicitly requested */
475 u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
476 for (i = 15; i > 0; i--)
477 if ((cs_mask & (1 << i)) &&
478 (request_irq(i, tcic_interrupt, 0, "tcic",
479 tcic_interrupt) == 0))
480 break;
481 cs_irq = i;
482 if (cs_irq == 0) poll_interval = HZ;
485 if (tcic_cap.irq_mask & (1 << 11))
486 printk("sktirq is irq 11, ");
487 if (cs_irq != 0)
488 printk("status change on irq %d\n", cs_irq);
489 else
490 printk("polled status, interval = %d ms\n",
491 poll_interval * 1000 / HZ);
493 for (i = 0; i < sockets; i++) {
494 tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
495 socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
498 /* jump start interrupt handler, if needed */
499 tcic_interrupt(0, NULL, NULL);
501 if (register_ss_entry(sockets, &tcic_operations) != 0) {
502 printk(KERN_NOTICE "tcic: register_ss_entry() failed\n");
503 release_region(tcic_base, 16);
504 if (cs_irq != 0)
505 free_irq(cs_irq, tcic_interrupt);
506 return -ENODEV;
509 return 0;
511 } /* init_tcic */
513 /*====================================================================*/
515 static void __exit exit_tcic(void)
517 u_long flags;
518 unregister_ss_entry(&tcic_operations);
519 save_flags(flags);
520 cli();
521 if (cs_irq != 0) {
522 tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
523 free_irq(cs_irq, tcic_interrupt);
525 if (tcic_timer_pending)
526 del_timer(&poll_timer);
527 restore_flags(flags);
528 release_region(tcic_base, 16);
529 } /* exit_tcic */
531 /*====================================================================*/
533 static u_int pending_events[2];
534 static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
536 static void tcic_bh(void *dummy)
538 u_int events;
539 int i;
541 for (i=0; i < sockets; i++) {
542 spin_lock_irq(&pending_event_lock);
543 events = pending_events[i];
544 pending_events[i] = 0;
545 spin_unlock_irq(&pending_event_lock);
546 if (socket_table[i].handler)
547 socket_table[i].handler(socket_table[i].info, events);
551 static struct tq_struct tcic_task = {
552 routine: tcic_bh
555 static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
557 int i, quick = 0;
558 u_char latch, sstat;
559 u_short psock;
560 u_int events;
561 static volatile int active = 0;
563 if (active) {
564 printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
565 return;
566 } else
567 active = 1;
569 DEBUG(2, "tcic: tcic_interrupt()\n");
571 for (i = 0; i < sockets; i++) {
572 psock = socket_table[i].psock;
573 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
574 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
575 sstat = tcic_getb(TCIC_SSTAT);
576 latch = sstat ^ socket_table[psock].last_sstat;
577 socket_table[i].last_sstat = sstat;
578 if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
579 tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
580 quick = 1;
582 if ((latch == 0) || (socket_table[psock].handler == NULL))
583 continue;
584 events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
585 events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
586 if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
587 events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
588 } else {
589 events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
590 events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
591 events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
593 if (events) {
594 spin_lock(&pending_event_lock);
595 pending_events[i] |= events;
596 spin_unlock(&pending_event_lock);
597 schedule_task(&tcic_task);
601 /* Schedule next poll, if needed */
602 if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
603 poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
604 add_timer(&poll_timer);
605 tcic_timer_pending = 1;
607 active = 0;
609 DEBUG(2, "tcic: interrupt done\n");
611 } /* tcic_interrupt */
613 static void tcic_timer(u_long data)
615 DEBUG(2, "tcic: tcic_timer()\n");
616 tcic_timer_pending = 0;
617 tcic_interrupt(0, NULL, NULL);
618 } /* tcic_timer */
620 /*====================================================================*/
622 static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
624 socket_table[lsock].handler = handler;
625 socket_table[lsock].info = info;
626 if (handler == NULL) {
627 MOD_DEC_USE_COUNT;
628 } else {
629 MOD_INC_USE_COUNT;
631 return 0;
632 } /* tcic_register_callback */
634 /*====================================================================*/
636 static int tcic_get_status(unsigned int lsock, u_int *value)
638 u_short psock = socket_table[lsock].psock;
639 u_char reg;
641 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
642 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
643 reg = tcic_getb(TCIC_SSTAT);
644 *value = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;
645 *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
646 if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
647 *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
648 } else {
649 *value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;
650 *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
651 *value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
653 reg = tcic_getb(TCIC_PWR);
654 if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
655 *value |= SS_POWERON;
656 DEBUG(1, "tcic: GetStatus(%d) = %#2.2x\n", lsock, *value);
657 return 0;
658 } /* tcic_get_status */
660 /*====================================================================*/
662 static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
664 *cap = tcic_cap;
665 return 0;
666 } /* tcic_inquire_socket */
668 /*====================================================================*/
670 static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
672 u_short psock = socket_table[lsock].psock;
673 u_char reg;
674 u_short scf1, scf2;
676 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
677 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
678 scf1 = tcic_getw(TCIC_DATA);
679 state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;
680 state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;
681 state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;
682 if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)
683 state->flags |= SS_OUTPUT_ENA;
684 state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;
685 if (state->io_irq == 1) state->io_irq = 11;
687 reg = tcic_getb(TCIC_PWR);
688 state->Vcc = state->Vpp = 0;
689 if (reg & TCIC_PWR_VCC(psock)) {
690 if (reg & TCIC_PWR_VPP(psock))
691 state->Vcc = 50;
692 else
693 state->Vcc = state->Vpp = 50;
694 } else {
695 if (reg & TCIC_PWR_VPP(psock)) {
696 state->Vcc = 50;
697 state->Vpp = 120;
700 reg = tcic_aux_getb(TCIC_AUX_ILOCK);
701 state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;
703 /* Card status change interrupt mask */
704 tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
705 scf2 = tcic_getw(TCIC_DATA);
706 state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;
707 if (state->flags & SS_IOCARD) {
708 state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;
709 } else {
710 state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;
711 state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;
712 state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
715 DEBUG(1, "tcic: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
716 "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
717 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
718 return 0;
719 } /* tcic_get_socket */
721 /*====================================================================*/
723 static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
725 u_short psock = socket_table[lsock].psock;
726 u_char reg;
727 u_short scf1, scf2;
729 DEBUG(1, "tcic: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
730 "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
731 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
732 tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
734 reg = tcic_getb(TCIC_PWR);
735 reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
737 if (state->Vcc == 50) {
738 switch (state->Vpp) {
739 case 0: reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
740 case 50: reg |= TCIC_PWR_VCC(psock); break;
741 case 120: reg |= TCIC_PWR_VPP(psock); break;
742 default: return -EINVAL;
744 } else if (state->Vcc != 0)
745 return -EINVAL;
747 if (reg != tcic_getb(TCIC_PWR))
748 tcic_setb(TCIC_PWR, reg);
750 reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
751 if (state->flags & SS_OUTPUT_ENA) {
752 tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
753 reg |= TCIC_ILOCK_CRESENA;
754 } else
755 tcic_setb(TCIC_SCTRL, 0);
756 if (state->flags & SS_RESET)
757 reg |= TCIC_ILOCK_CRESET;
758 tcic_aux_setb(TCIC_AUX_ILOCK, reg);
760 tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
761 scf1 = TCIC_SCF1_FINPACK;
762 scf1 |= TCIC_IRQ(state->io_irq);
763 if (state->flags & SS_IOCARD) {
764 scf1 |= TCIC_SCF1_IOSTS;
765 if (state->flags & SS_SPKR_ENA)
766 scf1 |= TCIC_SCF1_SPKR;
767 if (state->flags & SS_DMA_MODE)
768 scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
770 tcic_setw(TCIC_DATA, scf1);
772 /* Some general setup stuff, and configure status interrupt */
773 reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
774 tcic_aux_setb(TCIC_AUX_WCTL, reg);
775 tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
776 TCIC_IRQ(cs_irq));
778 /* Card status change interrupt mask */
779 tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
780 scf2 = TCIC_SCF2_MALL;
781 if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
782 if (state->flags & SS_IOCARD) {
783 if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
784 } else {
785 if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
786 if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
787 if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
789 tcic_setw(TCIC_DATA, scf2);
790 /* For the ISA bus, the irq should be active-high totem-pole */
791 tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
793 return 0;
794 } /* tcic_set_socket */
796 /*====================================================================*/
798 static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io)
800 u_short psock = socket_table[lsock].psock;
801 u_short base, ioctl;
802 u_int addr;
804 if (io->map > 1) return -EINVAL;
805 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
806 addr = TCIC_IWIN(psock, io->map);
807 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
808 base = tcic_getw(TCIC_DATA);
809 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
810 ioctl = tcic_getw(TCIC_DATA);
812 if (ioctl & TCIC_ICTL_TINY)
813 io->start = io->stop = base;
814 else {
815 io->start = base & (base-1);
816 io->stop = io->start + (base ^ (base-1));
818 io->speed = to_ns(ioctl & TCIC_ICTL_WSCNT_MASK);
819 io->flags = (ioctl & TCIC_ICTL_ENA) ? MAP_ACTIVE : 0;
820 switch (ioctl & TCIC_ICTL_BW_MASK) {
821 case TCIC_ICTL_BW_DYN:
822 io->flags |= MAP_AUTOSZ; break;
823 case TCIC_ICTL_BW_16:
824 io->flags |= MAP_16BIT; break;
825 default:
826 break;
828 DEBUG(1, "tcic: GetIOMap(%d, %d) = %#2.2x, %d ns, "
829 "%#4.4x-%#4.4x\n", lsock, io->map, io->flags,
830 io->speed, io->start, io->stop);
831 return 0;
832 } /* tcic_get_io_map */
834 /*====================================================================*/
836 static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
838 u_short psock = socket_table[lsock].psock;
839 u_int addr;
840 u_short base, len, ioctl;
842 DEBUG(1, "tcic: SetIOMap(%d, %d, %#2.2x, %d ns, "
843 "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
844 io->speed, io->start, io->stop);
845 if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
846 (io->stop < io->start)) return -EINVAL;
847 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
848 addr = TCIC_IWIN(psock, io->map);
850 base = io->start; len = io->stop - io->start;
851 /* Check to see that len+1 is power of two, etc */
852 if ((len & (len+1)) || (base & len)) return -EINVAL;
853 base |= (len+1)>>1;
854 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
855 tcic_setw(TCIC_DATA, base);
857 ioctl = (psock << TCIC_ICTL_SS_SHFT);
858 ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
859 ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
860 ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
861 if (!(io->flags & MAP_AUTOSZ)) {
862 ioctl |= TCIC_ICTL_QUIET;
863 ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
865 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
866 tcic_setw(TCIC_DATA, ioctl);
868 return 0;
869 } /* tcic_set_io_map */
871 /*====================================================================*/
873 static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
875 u_short psock = socket_table[lsock].psock;
876 u_short addr, ctl;
877 u_long base, mmap;
879 if (mem->map > 3) return -EINVAL;
880 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
881 addr = TCIC_MWIN(psock, mem->map);
883 tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
884 base = tcic_getw(TCIC_DATA);
885 if (base & TCIC_MBASE_4K_BIT) {
886 mem->sys_start = base & TCIC_MBASE_HA_MASK;
887 mem->sys_stop = mem->sys_start;
888 } else {
889 base &= TCIC_MBASE_HA_MASK;
890 mem->sys_start = (base & (base-1));
891 mem->sys_stop = mem->sys_start + (base ^ (base-1));
893 mem->sys_start = mem->sys_start << TCIC_MBASE_HA_SHFT;
894 mem->sys_stop = (mem->sys_stop << TCIC_MBASE_HA_SHFT) + 0x0fff;
896 tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
897 mmap = tcic_getw(TCIC_DATA);
898 mem->flags = (mmap & TCIC_MMAP_REG) ? MAP_ATTRIB : 0;
899 mmap &= TCIC_MMAP_CA_MASK;
900 mem->card_start = mem->sys_start + (mmap << TCIC_MMAP_CA_SHFT);
901 mem->card_start &= 0x3ffffff;
903 tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
904 ctl = tcic_getw(TCIC_DATA);
905 mem->flags |= (ctl & TCIC_MCTL_ENA) ? MAP_ACTIVE : 0;
906 mem->flags |= (ctl & TCIC_MCTL_B8) ? 0 : MAP_16BIT;
907 mem->flags |= (ctl & TCIC_MCTL_WP) ? MAP_WRPROT : 0;
908 mem->speed = to_ns(ctl & TCIC_MCTL_WSCNT_MASK);
910 DEBUG(1, "tcic: GetMemMap(%d, %d) = %#2.2x, %d ns, "
911 "%#5.5lx-%#5.5lx, %#5.5x\n", lsock, mem->map, mem->flags,
912 mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
913 return 0;
914 } /* tcic_get_mem_map */
916 /*====================================================================*/
918 static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
920 u_short psock = socket_table[lsock].psock;
921 u_short addr, ctl;
922 u_long base, len, mmap;
924 DEBUG(1, "tcic: SetMemMap(%d, %d, %#2.2x, %d ns, "
925 "%#5.5lx-%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
926 mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
927 if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
928 (mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) ||
929 (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
930 return -EINVAL;
931 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
932 addr = TCIC_MWIN(psock, mem->map);
934 base = mem->sys_start; len = mem->sys_stop - mem->sys_start;
935 if ((len & (len+1)) || (base & len)) return -EINVAL;
936 if (len == 0x0fff)
937 base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
938 else
939 base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
940 tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
941 tcic_setw(TCIC_DATA, base);
943 mmap = mem->card_start - mem->sys_start;
944 mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
945 if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
946 tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
947 tcic_setw(TCIC_DATA, mmap);
949 ctl = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
950 ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
951 ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
952 ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
953 ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
954 tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
955 tcic_setw(TCIC_DATA, ctl);
957 return 0;
958 } /* tcic_set_mem_map */
960 /*====================================================================*/
962 static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
966 static int tcic_init(unsigned int s)
968 int i;
969 pccard_io_map io = { 0, 0, 0, 0, 1 };
970 pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
972 mem.sys_stop = 0x1000;
973 tcic_set_socket(s, &dead_socket);
974 for (i = 0; i < 2; i++) {
975 io.map = i;
976 tcic_set_io_map(s, &io);
978 for (i = 0; i < 5; i++) {
979 mem.map = i;
980 tcic_set_mem_map(s, &mem);
982 return 0;
985 static int tcic_suspend(unsigned int sock)
987 return tcic_set_socket(sock, &dead_socket);
990 static struct pccard_operations tcic_operations = {
991 tcic_init,
992 tcic_suspend,
993 tcic_register_callback,
994 tcic_inquire_socket,
995 tcic_get_status,
996 tcic_get_socket,
997 tcic_set_socket,
998 tcic_get_io_map,
999 tcic_set_io_map,
1000 tcic_get_mem_map,
1001 tcic_set_mem_map,
1002 tcic_proc_setup
1005 /*====================================================================*/
1007 module_init(init_tcic);
1008 module_exit(exit_tcic);