aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/tcic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/pcmcia/tcic.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/pcmcia/tcic.c')
-rw-r--r--drivers/pcmcia/tcic.c903
1 files changed, 903 insertions, 0 deletions
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
new file mode 100644
index 000000000000..aacbbb5f055d
--- /dev/null
+++ b/drivers/pcmcia/tcic.c
@@ -0,0 +1,903 @@
1/*======================================================================
2
3 Device driver for Databook TCIC-2 PCMCIA controller
4
5 tcic.c 1.111 2000/02/15 04:13:12
6
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/
11
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.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General 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.
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/slab.h>
43#include <linux/timer.h>
44#include <linux/ioport.h>
45#include <linux/delay.h>
46#include <linux/workqueue.h>
47#include <linux/device.h>
48#include <linux/bitops.h>
49
50#include <asm/io.h>
51#include <asm/system.h>
52
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"
58
59#ifdef DEBUG
60static int pc_debug;
61
62module_param(pc_debug, int, 0644);
63static const char version[] =
64"tcic.c 1.111 2000/02/15 04:13:12 (David Hinds)";
65
66#define debug(lvl, fmt, arg...) do { \
67 if (pc_debug > (lvl)) \
68 printk(KERN_DEBUG "tcic: " fmt , ## arg); \
69} while (0)
70#else
71#define debug(lvl, fmt, arg...) do { } while (0)
72#endif
73
74MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
75MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
76MODULE_LICENSE("Dual MPL/GPL");
77
78/*====================================================================*/
79
80/* Parameters that can be set with 'insmod' */
81
82/* The base port address of the TCIC-2 chip */
83static unsigned long tcic_base = TCIC_BASE;
84
85/* Specify a socket number to ignore */
86static int ignore = -1;
87
88/* Probe for safe interrupts? */
89static int do_scan = 1;
90
91/* Bit map of interrupts to choose from */
92static u_int irq_mask = 0xffff;
93static int irq_list[16];
94static int irq_list_count;
95
96/* The card status change interrupt -- 0 means autoselect */
97static int cs_irq;
98
99/* Poll status interval -- 0 means default to interrupt */
100static int poll_interval;
101
102/* Delay for card status double-checking */
103static int poll_quick = HZ/20;
104
105/* CCLK external clock time, in nanoseconds. 70 ns = 14.31818 MHz */
106static int cycle_time = 70;
107
108module_param(tcic_base, ulong, 0444);
109module_param(ignore, int, 0444);
110module_param(do_scan, int, 0444);
111module_param(irq_mask, int, 0444);
112module_param_array(irq_list, int, &irq_list_count, 0444);
113module_param(cs_irq, int, 0444);
114module_param(poll_interval, int, 0444);
115module_param(poll_quick, int, 0444);
116module_param(cycle_time, int, 0444);
117
118/*====================================================================*/
119
120static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
121static void tcic_timer(u_long data);
122static struct pccard_operations tcic_operations;
123
124struct tcic_socket {
125 u_short psock;
126 u_char last_sstat;
127 u_char id;
128 struct pcmcia_socket socket;
129};
130
131static struct timer_list poll_timer;
132static int tcic_timer_pending;
133
134static int sockets;
135static struct tcic_socket socket_table[2];
136
137/*====================================================================*/
138
139/* Trick when selecting interrupts: the TCIC sktirq pin is supposed
140 to map to irq 11, but is coded as 0 or 1 in the irq registers. */
141#define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
142
143#ifdef DEBUG_X
144static u_char tcic_getb(u_char reg)
145{
146 u_char val = inb(tcic_base+reg);
147 printk(KERN_DEBUG "tcic_getb(%#lx) = %#x\n", tcic_base+reg, val);
148 return val;
149}
150
151static u_short tcic_getw(u_char reg)
152{
153 u_short val = inw(tcic_base+reg);
154 printk(KERN_DEBUG "tcic_getw(%#lx) = %#x\n", tcic_base+reg, val);
155 return val;
156}
157
158static void tcic_setb(u_char reg, u_char data)
159{
160 printk(KERN_DEBUG "tcic_setb(%#lx, %#x)\n", tcic_base+reg, data);
161 outb(data, tcic_base+reg);
162}
163
164static void tcic_setw(u_char reg, u_short data)
165{
166 printk(KERN_DEBUG "tcic_setw(%#lx, %#x)\n", tcic_base+reg, data);
167 outw(data, tcic_base+reg);
168}
169#else
170#define tcic_getb(reg) inb(tcic_base+reg)
171#define tcic_getw(reg) inw(tcic_base+reg)
172#define tcic_setb(reg, data) outb(data, tcic_base+reg)
173#define tcic_setw(reg, data) outw(data, tcic_base+reg)
174#endif
175
176static void tcic_setl(u_char reg, u_int data)
177{
178#ifdef DEBUG_X
179 printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
180#endif
181 outw(data & 0xffff, tcic_base+reg);
182 outw(data >> 16, tcic_base+reg+2);
183}
184
185static u_char tcic_aux_getb(u_short reg)
186{
187 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
188 tcic_setb(TCIC_MODE, mode);
189 return tcic_getb(TCIC_AUX);
190}
191
192static void tcic_aux_setb(u_short reg, u_char data)
193{
194 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
195 tcic_setb(TCIC_MODE, mode);
196 tcic_setb(TCIC_AUX, data);
197}
198
199static u_short tcic_aux_getw(u_short reg)
200{
201 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
202 tcic_setb(TCIC_MODE, mode);
203 return tcic_getw(TCIC_AUX);
204}
205
206static void tcic_aux_setw(u_short reg, u_short data)
207{
208 u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
209 tcic_setb(TCIC_MODE, mode);
210 tcic_setw(TCIC_AUX, data);
211}
212
213/*====================================================================*/
214
215/* Time conversion functions */
216
217static int to_cycles(int ns)
218{
219 if (ns < 14)
220 return 0;
221 else
222 return 2*(ns-14)/cycle_time;
223}
224
225/*====================================================================*/
226
227static volatile u_int irq_hits;
228
229static irqreturn_t __init tcic_irq_count(int irq, void *dev, struct pt_regs *regs)
230{
231 irq_hits++;
232 return IRQ_HANDLED;
233}
234
235static u_int __init try_irq(int irq)
236{
237 u_short cfg;
238
239 irq_hits = 0;
240 if (request_irq(irq, tcic_irq_count, 0, "irq scan", tcic_irq_count) != 0)
241 return -1;
242 mdelay(10);
243 if (irq_hits) {
244 free_irq(irq, tcic_irq_count);
245 return -1;
246 }
247
248 /* Generate one interrupt */
249 cfg = TCIC_SYSCFG_AUTOBUSY | 0x0a00;
250 tcic_aux_setw(TCIC_AUX_SYSCFG, cfg | TCIC_IRQ(irq));
251 tcic_setb(TCIC_IENA, TCIC_IENA_ERR | TCIC_IENA_CFG_HIGH);
252 tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM);
253
254 udelay(1000);
255 free_irq(irq, tcic_irq_count);
256
257 /* Turn off interrupts */
258 tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF);
259 while (tcic_getb(TCIC_ICSR))
260 tcic_setb(TCIC_ICSR, TCIC_ICSR_JAM);
261 tcic_aux_setw(TCIC_AUX_SYSCFG, cfg);
262
263 return (irq_hits != 1);
264}
265
266static u_int __init irq_scan(u_int mask0)
267{
268 u_int mask1;
269 int i;
270
271#ifdef __alpha__
272#define PIC 0x4d0
273 /* Don't probe level-triggered interrupts -- reserved for PCI */
274 int level_mask = inb_p(PIC) | (inb_p(PIC+1) << 8);
275 if (level_mask)
276 mask0 &= ~level_mask;
277#endif
278
279 mask1 = 0;
280 if (do_scan) {
281 for (i = 0; i < 16; i++)
282 if ((mask0 & (1 << i)) && (try_irq(i) == 0))
283 mask1 |= (1 << i);
284 for (i = 0; i < 16; i++)
285 if ((mask1 & (1 << i)) && (try_irq(i) != 0)) {
286 mask1 ^= (1 << i);
287 }
288 }
289
290 if (mask1) {
291 printk("scanned");
292 } else {
293 /* Fallback: just find interrupts that aren't in use */
294 for (i = 0; i < 16; i++)
295 if ((mask0 & (1 << i)) &&
296 (request_irq(i, tcic_irq_count, 0, "x", tcic_irq_count) == 0)) {
297 mask1 |= (1 << i);
298 free_irq(i, tcic_irq_count);
299 }
300 printk("default");
301 }
302
303 printk(") = ");
304 for (i = 0; i < 16; i++)
305 if (mask1 & (1<<i))
306 printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
307 printk(" ");
308
309 return mask1;
310}
311
312/*======================================================================
313
314 See if a card is present, powered up, in IO mode, and already
315 bound to a (non-PCMCIA) Linux driver.
316
317 We make an exception for cards that look like serial devices.
318
319======================================================================*/
320
321static int __init is_active(int s)
322{
323 u_short scf1, ioctl, base, num;
324 u_char pwr, sstat;
325 u_int addr;
326
327 tcic_setl(TCIC_ADDR, (s << TCIC_ADDR_SS_SHFT)
328 | TCIC_ADDR_INDREG | TCIC_SCF1(s));
329 scf1 = tcic_getw(TCIC_DATA);
330 pwr = tcic_getb(TCIC_PWR);
331 sstat = tcic_getb(TCIC_SSTAT);
332 addr = TCIC_IWIN(s, 0);
333 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
334 base = tcic_getw(TCIC_DATA);
335 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
336 ioctl = tcic_getw(TCIC_DATA);
337
338 if (ioctl & TCIC_ICTL_TINY)
339 num = 1;
340 else {
341 num = (base ^ (base-1));
342 base = base & (base-1);
343 }
344
345 if ((sstat & TCIC_SSTAT_CD) && (pwr & TCIC_PWR_VCC(s)) &&
346 (scf1 & TCIC_SCF1_IOSTS) && (ioctl & TCIC_ICTL_ENA) &&
347 ((base & 0xfeef) != 0x02e8)) {
348 struct resource *res = request_region(base, num, "tcic-2");
349 if (!res) /* region is busy */
350 return 1;
351 release_region(base, num);
352 }
353
354 return 0;
355}
356
357/*======================================================================
358
359 This returns the revision code for the specified socket.
360
361======================================================================*/
362
363static int __init get_tcic_id(void)
364{
365 u_short id;
366
367 tcic_aux_setw(TCIC_AUX_TEST, TCIC_TEST_DIAG);
368 id = tcic_aux_getw(TCIC_AUX_ILOCK);
369 id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
370 tcic_aux_setw(TCIC_AUX_TEST, 0);
371 return id;
372}
373
374/*====================================================================*/
375
376static int tcic_drv_suspend(struct device *dev, pm_message_t state, u32 level)
377{
378 int ret = 0;
379 if (level == SUSPEND_SAVE_STATE)
380 ret = pcmcia_socket_dev_suspend(dev, state);
381 return ret;
382}
383
384static int tcic_drv_resume(struct device *dev, u32 level)
385{
386 int ret = 0;
387 if (level == RESUME_RESTORE_STATE)
388 ret = pcmcia_socket_dev_resume(dev);
389 return ret;
390}
391
392static struct device_driver tcic_driver = {
393 .name = "tcic-pcmcia",
394 .bus = &platform_bus_type,
395 .suspend = tcic_drv_suspend,
396 .resume = tcic_drv_resume,
397};
398
399static struct platform_device tcic_device = {
400 .name = "tcic-pcmcia",
401 .id = 0,
402};
403
404
405static int __init init_tcic(void)
406{
407 int i, sock, ret = 0;
408 u_int mask, scan;
409
410 if (driver_register(&tcic_driver))
411 return -1;
412
413 printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
414 sock = 0;
415
416 if (!request_region(tcic_base, 16, "tcic-2")) {
417 printk("could not allocate ports,\n ");
418 driver_unregister(&tcic_driver);
419 return -ENODEV;
420 }
421 else {
422 tcic_setw(TCIC_ADDR, 0);
423 if (tcic_getw(TCIC_ADDR) == 0) {
424 tcic_setw(TCIC_ADDR, 0xc3a5);
425 if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
426 }
427 if (sock == 0) {
428 /* See if resetting the controller does any good */
429 tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
430 tcic_setb(TCIC_SCTRL, 0);
431 tcic_setw(TCIC_ADDR, 0);
432 if (tcic_getw(TCIC_ADDR) == 0) {
433 tcic_setw(TCIC_ADDR, 0xc3a5);
434 if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
435 }
436 }
437 }
438 if (sock == 0) {
439 printk("not found.\n");
440 release_region(tcic_base, 16);
441 driver_unregister(&tcic_driver);
442 return -ENODEV;
443 }
444
445 sockets = 0;
446 for (i = 0; i < sock; i++) {
447 if ((i == ignore) || is_active(i)) continue;
448 socket_table[sockets].psock = i;
449 socket_table[sockets].id = get_tcic_id();
450
451 socket_table[sockets].socket.owner = THIS_MODULE;
452 /* only 16-bit cards, memory windows must be size-aligned */
453 /* No PCI or CardBus support */
454 socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
455 /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
456 socket_table[sockets].socket.irq_mask = 0x4cf8;
457 /* 4K minimum window size */
458 socket_table[sockets].socket.map_size = 0x1000;
459 sockets++;
460 }
461
462 switch (socket_table[0].id) {
463 case TCIC_ID_DB86082:
464 printk("DB86082"); break;
465 case TCIC_ID_DB86082A:
466 printk("DB86082A"); break;
467 case TCIC_ID_DB86084:
468 printk("DB86084"); break;
469 case TCIC_ID_DB86084A:
470 printk("DB86084A"); break;
471 case TCIC_ID_DB86072:
472 printk("DB86072"); break;
473 case TCIC_ID_DB86184:
474 printk("DB86184"); break;
475 case TCIC_ID_DB86082B:
476 printk("DB86082B"); break;
477 default:
478 printk("Unknown ID 0x%02x", socket_table[0].id);
479 }
480
481 /* Set up polling */
482 poll_timer.function = &tcic_timer;
483 poll_timer.data = 0;
484 init_timer(&poll_timer);
485
486 /* Build interrupt mask */
487 printk(", %d sockets\n" KERN_INFO " irq list (", sockets);
488 if (irq_list_count == 0)
489 mask = irq_mask;
490 else
491 for (i = mask = 0; i < irq_list_count; i++)
492 mask |= (1<<irq_list[i]);
493
494 /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
495 mask &= 0x4cf8;
496 /* Scan interrupts */
497 mask = irq_scan(mask);
498 for (i=0;i<sockets;i++)
499 socket_table[i].socket.irq_mask = mask;
500
501 /* Check for only two interrupts available */
502 scan = (mask & (mask-1));
503 if (((scan & (scan-1)) == 0) && (poll_interval == 0))
504 poll_interval = HZ;
505
506 if (poll_interval == 0) {
507 /* Avoid irq 12 unless it is explicitly requested */
508 u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
509 for (i = 15; i > 0; i--)
510 if ((cs_mask & (1 << i)) &&
511 (request_irq(i, tcic_interrupt, 0, "tcic",
512 tcic_interrupt) == 0))
513 break;
514 cs_irq = i;
515 if (cs_irq == 0) poll_interval = HZ;
516 }
517
518 if (socket_table[0].socket.irq_mask & (1 << 11))
519 printk("sktirq is irq 11, ");
520 if (cs_irq != 0)
521 printk("status change on irq %d\n", cs_irq);
522 else
523 printk("polled status, interval = %d ms\n",
524 poll_interval * 1000 / HZ);
525
526 for (i = 0; i < sockets; i++) {
527 tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
528 socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
529 }
530
531 /* jump start interrupt handler, if needed */
532 tcic_interrupt(0, NULL, NULL);
533
534 platform_device_register(&tcic_device);
535
536 for (i = 0; i < sockets; i++) {
537 socket_table[i].socket.ops = &tcic_operations;
538 socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
539 socket_table[i].socket.dev.dev = &tcic_device.dev;
540 ret = pcmcia_register_socket(&socket_table[i].socket);
541 if (ret && i)
542 pcmcia_unregister_socket(&socket_table[0].socket);
543 }
544
545 return ret;
546
547 return 0;
548
549} /* init_tcic */
550
551/*====================================================================*/
552
553static void __exit exit_tcic(void)
554{
555 int i;
556
557 del_timer_sync(&poll_timer);
558 if (cs_irq != 0) {
559 tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
560 free_irq(cs_irq, tcic_interrupt);
561 }
562 release_region(tcic_base, 16);
563
564 for (i = 0; i < sockets; i++) {
565 pcmcia_unregister_socket(&socket_table[i].socket);
566 }
567
568 platform_device_unregister(&tcic_device);
569 driver_unregister(&tcic_driver);
570} /* exit_tcic */
571
572/*====================================================================*/
573
574static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
575{
576 int i, quick = 0;
577 u_char latch, sstat;
578 u_short psock;
579 u_int events;
580 static volatile int active = 0;
581
582 if (active) {
583 printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
584 return IRQ_NONE;
585 } else
586 active = 1;
587
588 debug(2, "tcic_interrupt()\n");
589
590 for (i = 0; i < sockets; i++) {
591 psock = socket_table[i].psock;
592 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
593 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
594 sstat = tcic_getb(TCIC_SSTAT);
595 latch = sstat ^ socket_table[psock].last_sstat;
596 socket_table[i].last_sstat = sstat;
597 if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
598 tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
599 quick = 1;
600 }
601 if (latch == 0)
602 continue;
603 events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
604 events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
605 if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
606 events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
607 } else {
608 events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
609 events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
610 events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
611 }
612 if (events) {
613 pcmcia_parse_events(&socket_table[i].socket, events);
614 }
615 }
616
617 /* Schedule next poll, if needed */
618 if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
619 poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
620 add_timer(&poll_timer);
621 tcic_timer_pending = 1;
622 }
623 active = 0;
624
625 debug(2, "interrupt done\n");
626 return IRQ_HANDLED;
627} /* tcic_interrupt */
628
629static void tcic_timer(u_long data)
630{
631 debug(2, "tcic_timer()\n");
632 tcic_timer_pending = 0;
633 tcic_interrupt(0, NULL, NULL);
634} /* tcic_timer */
635
636/*====================================================================*/
637
638static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
639{
640 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
641 u_char reg;
642
643 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
644 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
645 reg = tcic_getb(TCIC_SSTAT);
646 *value = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;
647 *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
648 if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
649 *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
650 } else {
651 *value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;
652 *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
653 *value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
654 }
655 reg = tcic_getb(TCIC_PWR);
656 if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
657 *value |= SS_POWERON;
658 debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value);
659 return 0;
660} /* tcic_get_status */
661
662/*====================================================================*/
663
664static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
665{
666 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
667 u_char reg;
668 u_short scf1, scf2;
669
670 tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
671 | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
672 scf1 = tcic_getw(TCIC_DATA);
673 state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;
674 state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;
675 state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;
676 if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)
677 state->flags |= SS_OUTPUT_ENA;
678 state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;
679 if (state->io_irq == 1) state->io_irq = 11;
680
681 reg = tcic_getb(TCIC_PWR);
682 state->Vcc = state->Vpp = 0;
683 if (reg & TCIC_PWR_VCC(psock)) {
684 if (reg & TCIC_PWR_VPP(psock))
685 state->Vcc = 50;
686 else
687 state->Vcc = state->Vpp = 50;
688 } else {
689 if (reg & TCIC_PWR_VPP(psock)) {
690 state->Vcc = 50;
691 state->Vpp = 120;
692 }
693 }
694 reg = tcic_aux_getb(TCIC_AUX_ILOCK);
695 state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;
696
697 /* Card status change interrupt mask */
698 tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
699 scf2 = tcic_getw(TCIC_DATA);
700 state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;
701 if (state->flags & SS_IOCARD) {
702 state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;
703 } else {
704 state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;
705 state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;
706 state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
707 }
708
709 debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
710 "io_irq %d, csc_mask %#2.2x\n", psock, state->flags,
711 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
712 return 0;
713} /* tcic_get_socket */
714
715/*====================================================================*/
716
717static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
718{
719 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
720 u_char reg;
721 u_short scf1, scf2;
722
723 debug(1, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
724 "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
725 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
726 tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
727
728 reg = tcic_getb(TCIC_PWR);
729 reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
730
731 if (state->Vcc == 50) {
732 switch (state->Vpp) {
733 case 0: reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
734 case 50: reg |= TCIC_PWR_VCC(psock); break;
735 case 120: reg |= TCIC_PWR_VPP(psock); break;
736 default: return -EINVAL;
737 }
738 } else if (state->Vcc != 0)
739 return -EINVAL;
740
741 if (reg != tcic_getb(TCIC_PWR))
742 tcic_setb(TCIC_PWR, reg);
743
744 reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
745 if (state->flags & SS_OUTPUT_ENA) {
746 tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
747 reg |= TCIC_ILOCK_CRESENA;
748 } else
749 tcic_setb(TCIC_SCTRL, 0);
750 if (state->flags & SS_RESET)
751 reg |= TCIC_ILOCK_CRESET;
752 tcic_aux_setb(TCIC_AUX_ILOCK, reg);
753
754 tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
755 scf1 = TCIC_SCF1_FINPACK;
756 scf1 |= TCIC_IRQ(state->io_irq);
757 if (state->flags & SS_IOCARD) {
758 scf1 |= TCIC_SCF1_IOSTS;
759 if (state->flags & SS_SPKR_ENA)
760 scf1 |= TCIC_SCF1_SPKR;
761 if (state->flags & SS_DMA_MODE)
762 scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
763 }
764 tcic_setw(TCIC_DATA, scf1);
765
766 /* Some general setup stuff, and configure status interrupt */
767 reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
768 tcic_aux_setb(TCIC_AUX_WCTL, reg);
769 tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
770 TCIC_IRQ(cs_irq));
771
772 /* Card status change interrupt mask */
773 tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
774 scf2 = TCIC_SCF2_MALL;
775 if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
776 if (state->flags & SS_IOCARD) {
777 if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
778 } else {
779 if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
780 if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
781 if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
782 }
783 tcic_setw(TCIC_DATA, scf2);
784 /* For the ISA bus, the irq should be active-high totem-pole */
785 tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
786
787 return 0;
788} /* tcic_set_socket */
789
790/*====================================================================*/
791
792static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
793{
794 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
795 u_int addr;
796 u_short base, len, ioctl;
797
798 debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
799 "%#lx-%#lx)\n", psock, io->map, io->flags,
800 io->speed, io->start, io->stop);
801 if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
802 (io->stop < io->start)) return -EINVAL;
803 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
804 addr = TCIC_IWIN(psock, io->map);
805
806 base = io->start; len = io->stop - io->start;
807 /* Check to see that len+1 is power of two, etc */
808 if ((len & (len+1)) || (base & len)) return -EINVAL;
809 base |= (len+1)>>1;
810 tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
811 tcic_setw(TCIC_DATA, base);
812
813 ioctl = (psock << TCIC_ICTL_SS_SHFT);
814 ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
815 ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
816 ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
817 if (!(io->flags & MAP_AUTOSZ)) {
818 ioctl |= TCIC_ICTL_QUIET;
819 ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
820 }
821 tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
822 tcic_setw(TCIC_DATA, ioctl);
823
824 return 0;
825} /* tcic_set_io_map */
826
827/*====================================================================*/
828
829static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
830{
831 u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
832 u_short addr, ctl;
833 u_long base, len, mmap;
834
835 debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, "
836 "%#lx-%#lx, %#x)\n", psock, mem->map, mem->flags,
837 mem->speed, mem->res->start, mem->res->end, mem->card_start);
838 if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
839 (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
840 (mem->res->start > mem->res->end) || (mem->speed > 1000))
841 return -EINVAL;
842 tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
843 addr = TCIC_MWIN(psock, mem->map);
844
845 base = mem->res->start; len = mem->res->end - mem->res->start;
846 if ((len & (len+1)) || (base & len)) return -EINVAL;
847 if (len == 0x0fff)
848 base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
849 else
850 base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
851 tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
852 tcic_setw(TCIC_DATA, base);
853
854 mmap = mem->card_start - mem->res->start;
855 mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
856 if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
857 tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
858 tcic_setw(TCIC_DATA, mmap);
859
860 ctl = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
861 ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
862 ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
863 ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
864 ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
865 tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
866 tcic_setw(TCIC_DATA, ctl);
867
868 return 0;
869} /* tcic_set_mem_map */
870
871/*====================================================================*/
872
873static int tcic_init(struct pcmcia_socket *s)
874{
875 int i;
876 struct resource res = { .start = 0, .end = 0x1000 };
877 pccard_io_map io = { 0, 0, 0, 0, 1 };
878 pccard_mem_map mem = { .res = &res, };
879
880 for (i = 0; i < 2; i++) {
881 io.map = i;
882 tcic_set_io_map(s, &io);
883 }
884 for (i = 0; i < 5; i++) {
885 mem.map = i;
886 tcic_set_mem_map(s, &mem);
887 }
888 return 0;
889}
890
891static struct pccard_operations tcic_operations = {
892 .init = tcic_init,
893 .get_status = tcic_get_status,
894 .get_socket = tcic_get_socket,
895 .set_socket = tcic_set_socket,
896 .set_io_map = tcic_set_io_map,
897 .set_mem_map = tcic_set_mem_map,
898};
899
900/*====================================================================*/
901
902module_init(init_tcic);
903module_exit(exit_tcic);