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