1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/init.h>
37#include <linux/types.h>
38#include <linux/fcntl.h>
39#include <linux/string.h>
40#include <linux/errno.h>
41#include <linux/interrupt.h>
42#include <linux/timer.h>
43#include <linux/ioport.h>
44#include <linux/delay.h>
45#include <linux/workqueue.h>
46#include <linux/platform_device.h>
47#include <linux/bitops.h>
48
49#include <asm/io.h>
50#include <asm/system.h>
51
52#include <pcmcia/ss.h>
53#include "tcic.h"
54
55MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
56MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
57MODULE_LICENSE("Dual MPL/GPL");
58
59
60
61
62
63
64static unsigned long tcic_base = TCIC_BASE;
65
66
67static int ignore = -1;
68
69
70static int do_scan = 1;
71
72
73static u_int irq_mask = 0xffff;
74static int irq_list[16];
75static unsigned int irq_list_count;
76
77
78static int cs_irq;
79
80
81static int poll_interval;
82
83
84static int poll_quick = HZ/20;
85
86
87static int cycle_time = 70;
88
89module_param(tcic_base, ulong, 0444);
90module_param(ignore, int, 0444);
91module_param(do_scan, int, 0444);
92module_param(irq_mask, int, 0444);
93module_param_array(irq_list, int, &irq_list_count, 0444);
94module_param(cs_irq, int, 0444);
95module_param(poll_interval, int, 0444);
96module_param(poll_quick, int, 0444);
97module_param(cycle_time, int, 0444);
98
99
100
101static irqreturn_t tcic_interrupt(int irq, void *dev);
102static void tcic_timer(u_long data);
103static struct pccard_operations tcic_operations;
104
105struct tcic_socket {
106 u_short psock;
107 u_char last_sstat;
108 u_char id;
109 struct pcmcia_socket socket;
110};
111
112static struct timer_list poll_timer;
113static int tcic_timer_pending;
114
115static int sockets;
116static struct tcic_socket socket_table[2];
117
118
119
120
121
122#define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
123
124#ifdef DEBUG_X
125static u_char tcic_getb(u_char reg)
126{
127 u_char val = inb(tcic_base+reg);
128 printk(KERN_DEBUG "tcic_getb(%#lx) = %#x\n", tcic_base+reg, val);
129 return val;
130}
131
132static u_short tcic_getw(u_char reg)
133{
134 u_short val = inw(tcic_base+reg);
135 printk(KERN_DEBUG "tcic_getw(%#lx) = %#x\n", tcic_base+reg, val);
136 return val;
137}
138
139static void tcic_setb(u_char reg, u_char data)
140{
141 printk(KERN_DEBUG "tcic_setb(%#lx, %#x)\n", tcic_base+reg, data);
142 outb(data, tcic_base+reg);
143}
144
145static void tcic_setw(u_char reg, u_short data)
146{
147 printk(KERN_DEBUG "tcic_setw(%#lx, %#x)\n", tcic_base+reg, data);
148 outw(data, tcic_base+reg);
149}
150#else
151#define tcic_getb(reg) inb(tcic_base+reg)
152#define tcic_getw(reg) inw(tcic_base+reg)
153#define tcic_setb(reg, data) outb(data, tcic_base+reg)
154#define tcic_setw(reg, data) outw(data, tcic_base+reg)
155#endif
156
157static void tcic_setl(u_char reg, u_int data)
158{
159#ifdef DEBUG_X
160 printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
161#endif
162 outw(data & 0xffff, tcic_base+reg);
163 outw(data >> 16, tcic_base+reg+2);
164}
165
166static void tcic_aux_setb(u_short reg, u_char data)
167{
168 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
169 tcic_setb(TCIC_MODE, mode);
170 tcic_setb(TCIC_AUX, data);
171}
172
173static u_short tcic_aux_getw(u_short reg)
174{
175 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
176 tcic_setb(TCIC_MODE, mode);
177 return tcic_getw(TCIC_AUX);
178}
179
180static void tcic_aux_setw(u_short reg, u_short data)
181{
182 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
183 tcic_setb(TCIC_MODE, mode);
184 tcic_setw(TCIC_AUX, data);
185}
186
187
188
189
190
191static int to_cycles(int ns)
192{
193 if (ns < 14)
194 return 0;
195 else
196 return 2*(ns-14)/cycle_time;
197}
198
199
200
201static volatile u_int irq_hits;
202
203static irqreturn_t __init tcic_irq_count(int irq, void *dev)
204{
205 irq_hits++;
206 return IRQ_HANDLED;
207}
208
209static u_int __init try_irq(int irq)
210{
211 u_short cfg;
212
213 irq_hits = 0;
214 if (request_irq(irq, tcic_irq_count, 0, "irq scan", tcic_irq_count) != 0)
215 return -1;
216 mdelay(10);
217 if (irq_hits) {
218 free_irq(irq, tcic_irq_count);
219 return -1;
220 }
221
222
223 cfg = TCIC_SYSCFG_AUTOBUSY | 0x0a00;
224 tcic_aux_setw(TCIC_AUX_SYSCFG, cfg | TCIC_IRQ(irq));
225 tcic_setb(TCIC_IENA, TCIC_IENA_ERR | TCIC_IENA_CFG_HIGH);
226 tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM);
227
228 udelay(1000);
229 free_irq(irq, tcic_irq_count);
230
231
232 tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF);
233 while (tcic_getb(TCIC_ICSR))
234 tcic_setb(TCIC_ICSR, TCIC_ICSR_JAM);
235 tcic_aux_setw(TCIC_AUX_SYSCFG, cfg);
236
237 return (irq_hits != 1);
238}
239
240static u_int __init irq_scan(u_int mask0)
241{
242 u_int mask1;
243 int i;
244
245#ifdef __alpha__
246#define PIC 0x4d0
247
248 int level_mask = inb_p(PIC) | (inb_p(PIC+1) << 8);
249 if (level_mask)
250 mask0 &= ~level_mask;
251#endif
252
253 mask1 = 0;
254 if (do_scan) {
255 for (i = 0; i < 16; i++)
256 if ((mask0 & (1 << i)) && (try_irq(i) == 0))
257 mask1 |= (1 << i);
258 for (i = 0; i < 16; i++)
259 if ((mask1 & (1 << i)) && (try_irq(i) != 0)) {
260 mask1 ^= (1 << i);
261 }
262 }
263
264 if (mask1) {
265 printk("scanned");
266 } else {
267
268 for (i = 0; i < 16; i++)
269 if ((mask0 & (1 << i)) &&
270 (request_irq(i, tcic_irq_count, 0, "x", tcic_irq_count) == 0)) {
271 mask1 |= (1 << i);
272 free_irq(i, tcic_irq_count);
273 }
274 printk("default");
275 }
276
277 printk(") = ");
278 for (i = 0; i < 16; i++)
279 if (mask1 & (1<<i))
280 printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
281 printk(" ");
282
283 return mask1;
284}
285
286
287
288
289
290
291
292
293
294
295static int __init is_active(int s)
296{
297 u_short scf1, ioctl, base, num;
298 u_char pwr, sstat;
299 u_int addr;
300
301 tcic_setl(TCIC_ADDR, (s << TCIC_ADDR_SS_SHFT)
302 | TCIC_ADDR_INDREG | TCIC_SCF1(s));
303 scf1 = tcic_getw(TCIC_DATA);
304 pwr = tcic_getb(TCIC_PWR);
305 sstat = tcic_getb(TCIC_SSTAT);
306 addr = TCIC_IWIN(s, 0);
307 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
308 base = tcic_getw(TCIC_DATA);
309 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
310 ioctl = tcic_getw(TCIC_DATA);
311
312 if (ioctl & TCIC_ICTL_TINY)
313 num = 1;
314 else {
315 num = (base ^ (base-1));
316 base = base & (base-1);
317 }
318
319 if ((sstat & TCIC_SSTAT_CD) && (pwr & TCIC_PWR_VCC(s)) &&
320 (scf1 & TCIC_SCF1_IOSTS) && (ioctl & TCIC_ICTL_ENA) &&
321 ((base & 0xfeef) != 0x02e8)) {
322 struct resource *res = request_region(base, num, "tcic-2");
323 if (!res)
324 return 1;
325 release_region(base, num);
326 }
327
328 return 0;
329}
330
331
332
333
334
335
336
337static int __init get_tcic_id(void)
338{
339 u_short id;
340
341 tcic_aux_setw(TCIC_AUX_TEST, TCIC_TEST_DIAG);
342 id = tcic_aux_getw(TCIC_AUX_ILOCK);
343 id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
344 tcic_aux_setw(TCIC_AUX_TEST, 0);
345 return id;
346}
347
348
349
350static struct platform_driver tcic_driver = {
351 .driver = {
352 .name = "tcic-pcmcia",
353 .owner = THIS_MODULE,
354 },
355};
356
357static struct platform_device tcic_device = {
358 .name = "tcic-pcmcia",
359 .id = 0,
360};
361
362
363static int __init init_tcic(void)
364{
365 int i, sock, ret = 0;
366 u_int mask, scan;
367
368 if (platform_driver_register(&tcic_driver))
369 return -1;
370
371 printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
372 sock = 0;
373
374 if (!request_region(tcic_base, 16, "tcic-2")) {
375 printk("could not allocate ports,\n ");
376 platform_driver_unregister(&tcic_driver);
377 return -ENODEV;
378 }
379 else {
380 tcic_setw(TCIC_ADDR, 0);
381 if (tcic_getw(TCIC_ADDR) == 0) {
382 tcic_setw(TCIC_ADDR, 0xc3a5);
383 if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
384 }
385 if (sock == 0) {
386
387 tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
388 tcic_setb(TCIC_SCTRL, 0);
389 tcic_setw(TCIC_ADDR, 0);
390 if (tcic_getw(TCIC_ADDR) == 0) {
391 tcic_setw(TCIC_ADDR, 0xc3a5);
392 if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
393 }
394 }
395 }
396 if (sock == 0) {
397 printk("not found.\n");
398 release_region(tcic_base, 16);
399 platform_driver_unregister(&tcic_driver);
400 return -ENODEV;
401 }
402
403 sockets = 0;
404 for (i = 0; i < sock; i++) {
405 if ((i == ignore) || is_active(i)) continue;
406 socket_table[sockets].psock = i;
407 socket_table[sockets].id = get_tcic_id();
408
409 socket_table[sockets].socket.owner = THIS_MODULE;
410
411
412 socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
413
414 socket_table[sockets].socket.irq_mask = 0x4cf8;
415
416 socket_table[sockets].socket.map_size = 0x1000;
417 sockets++;
418 }
419
420 switch (socket_table[0].id) {
421 case TCIC_ID_DB86082:
422 printk("DB86082"); break;
423 case TCIC_ID_DB86082A:
424 printk("DB86082A"); break;
425 case TCIC_ID_DB86084:
426 printk("DB86084"); break;
427 case TCIC_ID_DB86084A:
428 printk("DB86084A"); break;
429 case TCIC_ID_DB86072:
430 printk("DB86072"); break;
431 case TCIC_ID_DB86184:
432 printk("DB86184"); break;
433 case TCIC_ID_DB86082B:
434 printk("DB86082B"); break;
435 default:
436 printk("Unknown ID 0x%02x", socket_table[0].id);
437 }
438
439
440 poll_timer.function = &tcic_timer;
441 poll_timer.data = 0;
442 init_timer(&poll_timer);
443
444
445 printk(KERN_CONT ", %d sockets\n", sockets);
446 printk(KERN_INFO " irq list (");
447 if (irq_list_count == 0)
448 mask = irq_mask;
449 else
450 for (i = mask = 0; i < irq_list_count; i++)
451 mask |= (1<<irq_list[i]);
452
453
454 mask &= 0x4cf8;
455
456 mask = irq_scan(mask);
457 for (i=0;i<sockets;i++)
458 socket_table[i].socket.irq_mask = mask;
459
460
461 scan = (mask & (mask-1));
462 if (((scan & (scan-1)) == 0) && (poll_interval == 0))
463 poll_interval = HZ;
464
465 if (poll_interval == 0) {
466
467 u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
468 for (i = 15; i > 0; i--)
469 if ((cs_mask & (1 << i)) &&
470 (request_irq(i, tcic_interrupt, 0, "tcic",
471 tcic_interrupt) == 0))
472 break;
473 cs_irq = i;
474 if (cs_irq == 0) poll_interval = HZ;
475 }
476
477 if (socket_table[0].socket.irq_mask & (1 << 11))
478 printk("sktirq is irq 11, ");
479 if (cs_irq != 0)
480 printk("status change on irq %d\n", cs_irq);
481 else
482 printk("polled status, interval = %d ms\n",
483 poll_interval * 1000 / HZ);
484
485 for (i = 0; i < sockets; i++) {
486 tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
487 socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
488 }
489
490
491 tcic_interrupt(0, NULL);
492
493 platform_device_register(&tcic_device);
494
495 for (i = 0; i < sockets; i++) {
496 socket_table[i].socket.ops = &tcic_operations;
497 socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
498 socket_table[i].socket.dev.parent = &tcic_device.dev;
499 ret = pcmcia_register_socket(&socket_table[i].socket);
500 if (ret && i)
501 pcmcia_unregister_socket(&socket_table[0].socket);
502 }
503
504 return ret;
505
506 return 0;
507
508}
509
510
511
512static void __exit exit_tcic(void)
513{
514 int i;
515
516 del_timer_sync(&poll_timer);
517 if (cs_irq != 0) {
518 tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
519 free_irq(cs_irq, tcic_interrupt);
520 }
521 release_region(tcic_base, 16);
522
523 for (i = 0; i < sockets; i++) {
524 pcmcia_unregister_socket(&socket_table[i].socket);
525 }
526
527 platform_device_unregister(&tcic_device);
528 platform_driver_unregister(&tcic_driver);
529}
530
531
532
533static irqreturn_t tcic_interrupt(int irq, void *dev)
534{
535 int i, quick = 0;
536 u_char latch, sstat;
537 u_short psock;
538 u_int events;
539 static volatile int active = 0;
540
541 if (active) {
542 printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
543 return IRQ_NONE;
544 } else
545 active = 1;
546
547 pr_debug("tcic_interrupt()\n");
548
549 for (i = 0; i < sockets; i++) {
550 psock = socket_table[i].psock;
551 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
552 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
553 sstat = tcic_getb(TCIC_SSTAT);
554 latch = sstat ^ socket_table[psock].last_sstat;
555 socket_table[i].last_sstat = sstat;
556 if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
557 tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
558 quick = 1;
559 }
560 if (latch == 0)
561 continue;
562 events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
563 events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
564 if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
565 events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
566 } else {
567 events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
568 events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
569 events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
570 }
571 if (events) {
572 pcmcia_parse_events(&socket_table[i].socket, events);
573 }
574 }
575
576
577 if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
578 poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
579 add_timer(&poll_timer);
580 tcic_timer_pending = 1;
581 }
582 active = 0;
583
584 pr_debug("interrupt done\n");
585 return IRQ_HANDLED;
586}
587
588static void tcic_timer(u_long data)
589{
590 pr_debug("tcic_timer()\n");
591 tcic_timer_pending = 0;
592 tcic_interrupt(0, NULL);
593}
594
595
596
597static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
598{
599 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
600 u_char reg;
601
602 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
603 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
604 reg = tcic_getb(TCIC_SSTAT);
605 *value = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;
606 *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
607 if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
608 *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
609 } else {
610 *value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;
611 *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
612 *value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
613 }
614 reg = tcic_getb(TCIC_PWR);
615 if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
616 *value |= SS_POWERON;
617 dev_dbg(&sock->dev, "GetStatus(%d) = %#2.2x\n", psock, *value);
618 return 0;
619}
620
621
622
623static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
624{
625 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
626 u_char reg;
627 u_short scf1, scf2;
628
629 dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
630 "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
631 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
632 tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
633
634 reg = tcic_getb(TCIC_PWR);
635 reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
636
637 if (state->Vcc == 50) {
638 switch (state->Vpp) {
639 case 0: reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
640 case 50: reg |= TCIC_PWR_VCC(psock); break;
641 case 120: reg |= TCIC_PWR_VPP(psock); break;
642 default: return -EINVAL;
643 }
644 } else if (state->Vcc != 0)
645 return -EINVAL;
646
647 if (reg != tcic_getb(TCIC_PWR))
648 tcic_setb(TCIC_PWR, reg);
649
650 reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
651 if (state->flags & SS_OUTPUT_ENA) {
652 tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
653 reg |= TCIC_ILOCK_CRESENA;
654 } else
655 tcic_setb(TCIC_SCTRL, 0);
656 if (state->flags & SS_RESET)
657 reg |= TCIC_ILOCK_CRESET;
658 tcic_aux_setb(TCIC_AUX_ILOCK, reg);
659
660 tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
661 scf1 = TCIC_SCF1_FINPACK;
662 scf1 |= TCIC_IRQ(state->io_irq);
663 if (state->flags & SS_IOCARD) {
664 scf1 |= TCIC_SCF1_IOSTS;
665 if (state->flags & SS_SPKR_ENA)
666 scf1 |= TCIC_SCF1_SPKR;
667 if (state->flags & SS_DMA_MODE)
668 scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
669 }
670 tcic_setw(TCIC_DATA, scf1);
671
672
673 reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
674 tcic_aux_setb(TCIC_AUX_WCTL, reg);
675 tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
676 TCIC_IRQ(cs_irq));
677
678
679 tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
680 scf2 = TCIC_SCF2_MALL;
681 if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
682 if (state->flags & SS_IOCARD) {
683 if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
684 } else {
685 if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
686 if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
687 if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
688 }
689 tcic_setw(TCIC_DATA, scf2);
690
691 tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
692
693 return 0;
694}
695
696
697
698static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
699{
700 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
701 u_int addr;
702 u_short base, len, ioctl;
703
704 dev_dbg(&sock->dev, "SetIOMap(%d, %d, %#2.2x, %d ns, "
705 "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,
706 (unsigned long long)io->start, (unsigned long long)io->stop);
707 if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
708 (io->stop < io->start)) return -EINVAL;
709 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
710 addr = TCIC_IWIN(psock, io->map);
711
712 base = io->start; len = io->stop - io->start;
713
714 if ((len & (len+1)) || (base & len)) return -EINVAL;
715 base |= (len+1)>>1;
716 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
717 tcic_setw(TCIC_DATA, base);
718
719 ioctl = (psock << TCIC_ICTL_SS_SHFT);
720 ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
721 ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
722 ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
723 if (!(io->flags & MAP_AUTOSZ)) {
724 ioctl |= TCIC_ICTL_QUIET;
725 ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
726 }
727 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
728 tcic_setw(TCIC_DATA, ioctl);
729
730 return 0;
731}
732
733
734
735static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
736{
737 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
738 u_short addr, ctl;
739 u_long base, len, mmap;
740
741 dev_dbg(&sock->dev, "SetMemMap(%d, %d, %#2.2x, %d ns, "
742 "%#llx-%#llx, %#x)\n", psock, mem->map, mem->flags,
743 mem->speed, (unsigned long long)mem->res->start,
744 (unsigned long long)mem->res->end, mem->card_start);
745 if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
746 (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
747 (mem->res->start > mem->res->end) || (mem->speed > 1000))
748 return -EINVAL;
749 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
750 addr = TCIC_MWIN(psock, mem->map);
751
752 base = mem->res->start; len = mem->res->end - mem->res->start;
753 if ((len & (len+1)) || (base & len)) return -EINVAL;
754 if (len == 0x0fff)
755 base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
756 else
757 base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
758 tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
759 tcic_setw(TCIC_DATA, base);
760
761 mmap = mem->card_start - mem->res->start;
762 mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
763 if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
764 tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
765 tcic_setw(TCIC_DATA, mmap);
766
767 ctl = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
768 ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
769 ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
770 ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
771 ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
772 tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
773 tcic_setw(TCIC_DATA, ctl);
774
775 return 0;
776}
777
778
779
780static int tcic_init(struct pcmcia_socket *s)
781{
782 int i;
783 struct resource res = { .start = 0, .end = 0x1000 };
784 pccard_io_map io = { 0, 0, 0, 0, 1 };
785 pccard_mem_map mem = { .res = &res, };
786
787 for (i = 0; i < 2; i++) {
788 io.map = i;
789 tcic_set_io_map(s, &io);
790 }
791 for (i = 0; i < 5; i++) {
792 mem.map = i;
793 tcic_set_mem_map(s, &mem);
794 }
795 return 0;
796}
797
798static struct pccard_operations tcic_operations = {
799 .init = tcic_init,
800 .get_status = tcic_get_status,
801 .set_socket = tcic_set_socket,
802 .set_io_map = tcic_set_io_map,
803 .set_mem_map = tcic_set_mem_map,
804};
805
806
807
808module_init(init_tcic);
809module_exit(exit_tcic);
810