OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pcmcia/] [tcic.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*======================================================================
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/init.h>
36
#include <linux/types.h>
37
#include <linux/fcntl.h>
38
#include <linux/string.h>
39
 
40
#include <asm/io.h>
41
#include <asm/bitops.h>
42
#include <asm/segment.h>
43
#include <asm/system.h>
44
 
45
#include <linux/kernel.h>
46
#include <linux/errno.h>
47
#include <linux/sched.h>
48
#include <linux/slab.h>
49
#include <linux/timer.h>
50
#include <linux/ioport.h>
51
#include <linux/delay.h>
52
#include <linux/proc_fs.h>
53
 
54
#include <pcmcia/version.h>
55
#include <pcmcia/cs_types.h>
56
#include <pcmcia/cs.h>
57
#include <pcmcia/ss.h>
58
#include "tcic.h"
59
 
60
#ifdef PCMCIA_DEBUG
61
static int pc_debug = PCMCIA_DEBUG;
62
MODULE_PARM(pc_debug, "i");
63
static const char *version =
64
"tcic.c 1.111 2000/02/15 04:13:12 (David Hinds)";
65
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
66
#else
67
#define DEBUG(n, args...)
68
#endif
69
 
70
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
71
MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
72
MODULE_LICENSE("Dual MPL/GPL");
73
 
74
/*====================================================================*/
75
 
76
/* Parameters that can be set with 'insmod' */
77
 
78
/* The base port address of the TCIC-2 chip */
79
static int tcic_base = TCIC_BASE;
80
 
81
/* Specify a socket number to ignore */
82
static int ignore = -1;
83
 
84
/* Probe for safe interrupts? */
85
static int do_scan = 1;
86
 
87
/* Bit map of interrupts to choose from */
88
static u_int irq_mask = 0xffff;
89
static int irq_list[16] = { -1 };
90
 
91
/* The card status change interrupt -- 0 means autoselect */
92
static int cs_irq = 0;
93
 
94
/* Poll status interval -- 0 means default to interrupt */
95
static int poll_interval = 0;
96
 
97
/* Delay for card status double-checking */
98
static int poll_quick = HZ/20;
99
 
100
/* CCLK external clock time, in nanoseconds.  70 ns = 14.31818 MHz */
101
static int cycle_time = 70;
102
 
103
MODULE_PARM(tcic_base, "i");
104
MODULE_PARM(ignore, "i");
105
MODULE_PARM(do_scan, "i");
106
MODULE_PARM(irq_mask, "i");
107
MODULE_PARM(irq_list, "1-16i");
108
MODULE_PARM(cs_irq, "i");
109
MODULE_PARM(poll_interval, "i");
110
MODULE_PARM(poll_quick, "i");
111
MODULE_PARM(cycle_time, "i");
112
 
113
/*====================================================================*/
114
 
115
static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
116
static void tcic_timer(u_long data);
117
static struct pccard_operations tcic_operations;
118
 
119
typedef struct socket_info_t {
120
    u_short     psock;
121
    void        (*handler)(void *info, u_int events);
122
    void        *info;
123
    u_char      last_sstat;
124
    u_char      id;
125
} socket_info_t;
126
 
127
static struct timer_list poll_timer;
128
static int tcic_timer_pending = 0;
129
 
130
static int sockets;
131
static socket_info_t socket_table[2];
132
 
133
static socket_cap_t tcic_cap = {
134
    /* only 16-bit cards, memory windows must be size-aligned */
135
    SS_CAP_PCCARD | SS_CAP_MEM_ALIGN,
136
    0x4cf8,             /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
137
    0x1000,             /* 4K minimum window size */
138
    0, 0          /* No PCI or CardBus support */
139
};
140
 
141
/*====================================================================*/
142
 
143
/* Trick when selecting interrupts: the TCIC sktirq pin is supposed
144
   to map to irq 11, but is coded as 0 or 1 in the irq registers. */
145
#define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
146
 
147
#ifdef PCMCIA_DEBUG_X
148
static u_char tcic_getb(u_char reg)
149
{
150
    u_char val = inb(tcic_base+reg);
151
    printk(KERN_DEBUG "tcic_getb(%#x) = %#x\n", tcic_base+reg, val);
152
    return val;
153
}
154
 
155
static u_short tcic_getw(u_char reg)
156
{
157
    u_short val = inw(tcic_base+reg);
158
    printk(KERN_DEBUG "tcic_getw(%#x) = %#x\n", tcic_base+reg, val);
159
    return val;
160
}
161
 
162
static void tcic_setb(u_char reg, u_char data)
163
{
164
    printk(KERN_DEBUG "tcic_setb(%#x, %#x)\n", tcic_base+reg, data);
165
    outb(data, tcic_base+reg);
166
}
167
 
168
static void tcic_setw(u_char reg, u_short data)
169
{
170
    printk(KERN_DEBUG "tcic_setw(%#x, %#x)\n", tcic_base+reg, data);
171
    outw(data, tcic_base+reg);
172
}
173
#else
174
#define tcic_getb(reg) inb(tcic_base+reg)
175
#define tcic_getw(reg) inw(tcic_base+reg)
176
#define tcic_setb(reg, data) outb(data, tcic_base+reg)
177
#define tcic_setw(reg, data) outw(data, tcic_base+reg)
178
#endif
179
 
180
static void tcic_setl(u_char reg, u_int data)
181
{
182
#ifdef PCMCIA_DEBUG_X
183
    printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
184
#endif
185
    outw(data & 0xffff, tcic_base+reg);
186
    outw(data >> 16, tcic_base+reg+2);
187
}
188
 
189
static u_char tcic_aux_getb(u_short reg)
190
{
191
    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
192
    tcic_setb(TCIC_MODE, mode);
193
    return tcic_getb(TCIC_AUX);
194
}
195
 
196
static void tcic_aux_setb(u_short reg, u_char data)
197
{
198
    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
199
    tcic_setb(TCIC_MODE, mode);
200
    tcic_setb(TCIC_AUX, data);
201
}
202
 
203
static u_short tcic_aux_getw(u_short reg)
204
{
205
    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
206
    tcic_setb(TCIC_MODE, mode);
207
    return tcic_getw(TCIC_AUX);
208
}
209
 
210
static void tcic_aux_setw(u_short reg, u_short data)
211
{
212
    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
213
    tcic_setb(TCIC_MODE, mode);
214
    tcic_setw(TCIC_AUX, data);
215
}
216
 
217
/*====================================================================*/
218
 
219
/* Time conversion functions */
220
 
221
static int to_cycles(int ns)
222
{
223
    if (ns < 14)
224
        return 0;
225
    else
226
        return 2*(ns-14)/cycle_time;
227
}
228
 
229
static int to_ns(int cycles)
230
{
231
    return (cycles*cycle_time)/2 + 14;
232
}
233
 
234
/*====================================================================*/
235
 
236
static volatile u_int irq_hits;
237
 
238
static void __init irq_count(int irq, void *dev, struct pt_regs *regs)
239
{
240
    irq_hits++;
241
}
242
 
243
static u_int __init try_irq(int irq)
244
{
245
    u_short cfg;
246
 
247
    irq_hits = 0;
248
    if (request_irq(irq, irq_count, 0, "irq scan", irq_count) != 0)
249
        return -1;
250
    mdelay(10);
251
    if (irq_hits) {
252
        free_irq(irq, irq_count);
253
        return -1;
254
    }
255
 
256
    /* Generate one interrupt */
257
    cfg = TCIC_SYSCFG_AUTOBUSY | 0x0a00;
258
    tcic_aux_setw(TCIC_AUX_SYSCFG, cfg | TCIC_IRQ(irq));
259
    tcic_setb(TCIC_IENA, TCIC_IENA_ERR | TCIC_IENA_CFG_HIGH);
260
    tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM);
261
 
262
    udelay(1000);
263
    free_irq(irq, irq_count);
264
 
265
    /* Turn off interrupts */
266
    tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF);
267
    while (tcic_getb(TCIC_ICSR))
268
        tcic_setb(TCIC_ICSR, TCIC_ICSR_JAM);
269
    tcic_aux_setw(TCIC_AUX_SYSCFG, cfg);
270
 
271
    return (irq_hits != 1);
272
}
273
 
274
static u_int __init irq_scan(u_int mask0)
275
{
276
    u_int mask1;
277
    int i;
278
 
279
#ifdef __alpha__
280
#define PIC 0x4d0
281
    /* Don't probe level-triggered interrupts -- reserved for PCI */
282
    int level_mask = inb_p(PIC) | (inb_p(PIC+1) << 8);
283
    if (level_mask)
284
        mask0 &= ~level_mask;
285
#endif
286
 
287
    mask1 = 0;
288
    if (do_scan) {
289
        for (i = 0; i < 16; i++)
290
            if ((mask0 & (1 << i)) && (try_irq(i) == 0))
291
                mask1 |= (1 << i);
292
        for (i = 0; i < 16; i++)
293
            if ((mask1 & (1 << i)) && (try_irq(i) != 0)) {
294
                mask1 ^= (1 << i);
295
            }
296
    }
297
 
298
    if (mask1) {
299
        printk("scanned");
300
    } else {
301
        /* Fallback: just find interrupts that aren't in use */
302
        for (i = 0; i < 16; i++)
303
            if ((mask0 & (1 << i)) &&
304
                (request_irq(i, irq_count, 0, "x", irq_count) == 0)) {
305
                mask1 |= (1 << i);
306
                free_irq(i, irq_count);
307
            }
308
        printk("default");
309
    }
310
 
311
    printk(") = ");
312
    for (i = 0; i < 16; i++)
313
        if (mask1 & (1<<i))
314
            printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
315
    printk(" ");
316
 
317
    return mask1;
318
}
319
 
320
/*======================================================================
321
 
322
    See if a card is present, powered up, in IO mode, and already
323
    bound to a (non-PCMCIA) Linux driver.
324
 
325
    We make an exception for cards that look like serial devices.
326
 
327
======================================================================*/
328
 
329
static int __init is_active(int s)
330
{
331
    u_short scf1, ioctl, base, num;
332
    u_char pwr, sstat;
333
    u_int addr;
334
 
335
    tcic_setl(TCIC_ADDR, (s << TCIC_ADDR_SS_SHFT)
336
              | TCIC_ADDR_INDREG | TCIC_SCF1(s));
337
    scf1 = tcic_getw(TCIC_DATA);
338
    pwr = tcic_getb(TCIC_PWR);
339
    sstat = tcic_getb(TCIC_SSTAT);
340
    addr = TCIC_IWIN(s, 0);
341
    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
342
    base = tcic_getw(TCIC_DATA);
343
    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
344
    ioctl = tcic_getw(TCIC_DATA);
345
 
346
    if (ioctl & TCIC_ICTL_TINY)
347
        num = 1;
348
    else {
349
        num = (base ^ (base-1));
350
        base = base & (base-1);
351
    }
352
 
353
    if ((sstat & TCIC_SSTAT_CD) && (pwr & TCIC_PWR_VCC(s)) &&
354
        (scf1 & TCIC_SCF1_IOSTS) && (ioctl & TCIC_ICTL_ENA) &&
355
        (check_region(base, num) != 0) && ((base & 0xfeef) != 0x02e8))
356
        return 1;
357
    else
358
        return 0;
359
}
360
 
361
/*======================================================================
362
 
363
    This returns the revision code for the specified socket.
364
 
365
======================================================================*/
366
 
367
static int __init get_tcic_id(void)
368
{
369
    u_short id;
370
 
371
    tcic_aux_setw(TCIC_AUX_TEST, TCIC_TEST_DIAG);
372
    id = tcic_aux_getw(TCIC_AUX_ILOCK);
373
    id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
374
    tcic_aux_setw(TCIC_AUX_TEST, 0);
375
    return id;
376
}
377
 
378
/*====================================================================*/
379
 
380
static int __init init_tcic(void)
381
{
382
    int i, sock;
383
    u_int mask, scan;
384
    servinfo_t serv;
385
 
386
    DEBUG(0, "%s\n", version);
387
    pcmcia_get_card_services_info(&serv);
388
    if (serv.Revision != CS_RELEASE_CODE) {
389
        printk(KERN_NOTICE "tcic: Card Services release "
390
               "does not match!\n");
391
        return -1;
392
    }
393
 
394
    printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
395
    sock = 0;
396
 
397
    if (check_region(tcic_base, 16) == 0) {
398
        tcic_setw(TCIC_ADDR, 0);
399
        if (tcic_getw(TCIC_ADDR) == 0) {
400
            tcic_setw(TCIC_ADDR, 0xc3a5);
401
            if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
402
        }
403
        if (sock == 0) {
404
            /* See if resetting the controller does any good */
405
            tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
406
            tcic_setb(TCIC_SCTRL, 0);
407
            tcic_setw(TCIC_ADDR, 0);
408
            if (tcic_getw(TCIC_ADDR) == 0) {
409
                tcic_setw(TCIC_ADDR, 0xc3a5);
410
                if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
411
            }
412
        }
413
    } else
414
        printk("could not allocate ports, ");
415
 
416
    if (sock == 0) {
417
        printk("not found.\n");
418
        return -ENODEV;
419
    }
420
 
421
    request_region(tcic_base, 16, "tcic-2");
422
 
423
    sockets = 0;
424
    for (i = 0; i < sock; i++) {
425
        if ((i == ignore) || is_active(i)) continue;
426
        socket_table[sockets].psock = i;
427
        socket_table[sockets].handler = NULL;
428
        socket_table[sockets].info = NULL;
429
        socket_table[sockets].id = get_tcic_id();
430
        sockets++;
431
    }
432
 
433
    switch (socket_table[0].id) {
434
    case TCIC_ID_DB86082:
435
        printk("DB86082"); break;
436
    case TCIC_ID_DB86082A:
437
        printk("DB86082A"); break;
438
    case TCIC_ID_DB86084:
439
        printk("DB86084"); break;
440
    case TCIC_ID_DB86084A:
441
        printk("DB86084A"); break;
442
    case TCIC_ID_DB86072:
443
        printk("DB86072"); break;
444
    case TCIC_ID_DB86184:
445
        printk("DB86184"); break;
446
    case TCIC_ID_DB86082B:
447
        printk("DB86082B"); break;
448
    default:
449
        printk("Unknown ID 0x%02x", socket_table[0].id);
450
    }
451
 
452
    /* Set up polling */
453
    poll_timer.function = &tcic_timer;
454
    poll_timer.data = 0;
455
    init_timer(&poll_timer);
456
 
457
    /* Build interrupt mask */
458
    printk(", %d sockets\n" KERN_INFO "  irq list (", sockets);
459
    if (irq_list[0] == -1)
460
        mask = irq_mask;
461
    else
462
        for (i = mask = 0; i < 16; i++)
463
            mask |= (1<<irq_list[i]);
464
    mask &= tcic_cap.irq_mask;
465
 
466
    /* Scan interrupts */
467
    mask = irq_scan(mask);
468
    tcic_cap.irq_mask = mask;
469
 
470
    /* Check for only two interrupts available */
471
    scan = (mask & (mask-1));
472
    if (((scan & (scan-1)) == 0) && (poll_interval == 0))
473
        poll_interval = HZ;
474
 
475
    if (poll_interval == 0) {
476
        /* Avoid irq 12 unless it is explicitly requested */
477
        u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
478
        for (i = 15; i > 0; i--)
479
            if ((cs_mask & (1 << i)) &&
480
                (request_irq(i, tcic_interrupt, 0, "tcic",
481
                             tcic_interrupt) == 0))
482
                break;
483
        cs_irq = i;
484
        if (cs_irq == 0) poll_interval = HZ;
485
    }
486
 
487
    if (tcic_cap.irq_mask & (1 << 11))
488
        printk("sktirq is irq 11, ");
489
    if (cs_irq != 0)
490
        printk("status change on irq %d\n", cs_irq);
491
    else
492
        printk("polled status, interval = %d ms\n",
493
               poll_interval * 1000 / HZ);
494
 
495
    for (i = 0; i < sockets; i++) {
496
        tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
497
        socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
498
    }
499
 
500
    /* jump start interrupt handler, if needed */
501
    tcic_interrupt(0, NULL, NULL);
502
 
503
    if (register_ss_entry(sockets, &tcic_operations) != 0) {
504
        printk(KERN_NOTICE "tcic: register_ss_entry() failed\n");
505
        release_region(tcic_base, 16);
506
        if (cs_irq != 0)
507
            free_irq(cs_irq, tcic_interrupt);
508
        return -ENODEV;
509
    }
510
 
511
    return 0;
512
 
513
} /* init_tcic */
514
 
515
/*====================================================================*/
516
 
517
static void __exit exit_tcic(void)
518
{
519
    u_long flags;
520
    unregister_ss_entry(&tcic_operations);
521
    save_flags(flags);
522
    cli();
523
    if (cs_irq != 0) {
524
        tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
525
        free_irq(cs_irq, tcic_interrupt);
526
    }
527
    if (tcic_timer_pending)
528
        del_timer(&poll_timer);
529
    restore_flags(flags);
530
    release_region(tcic_base, 16);
531
} /* exit_tcic */
532
 
533
/*====================================================================*/
534
 
535
static u_int pending_events[2];
536
static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
537
 
538
static void tcic_bh(void *dummy)
539
{
540
        u_int events;
541
        int i;
542
 
543
        for (i=0; i < sockets; i++) {
544
                spin_lock_irq(&pending_event_lock);
545
                events = pending_events[i];
546
                pending_events[i] = 0;
547
                spin_unlock_irq(&pending_event_lock);
548
                if (socket_table[i].handler)
549
                        socket_table[i].handler(socket_table[i].info, events);
550
        }
551
}
552
 
553
static struct tq_struct tcic_task = {
554
        routine:        tcic_bh
555
};
556
 
557
static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
558
{
559
    int i, quick = 0;
560
    u_char latch, sstat;
561
    u_short psock;
562
    u_int events;
563
    static volatile int active = 0;
564
 
565
    if (active) {
566
        printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
567
        return;
568
    } else
569
        active = 1;
570
 
571
    DEBUG(2, "tcic: tcic_interrupt()\n");
572
 
573
    for (i = 0; i < sockets; i++) {
574
        psock = socket_table[i].psock;
575
        tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
576
                  | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
577
        sstat = tcic_getb(TCIC_SSTAT);
578
        latch = sstat ^ socket_table[psock].last_sstat;
579
        socket_table[i].last_sstat = sstat;
580
        if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
581
            tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
582
            quick = 1;
583
        }
584
        if ((latch == 0) || (socket_table[psock].handler == NULL))
585
            continue;
586
        events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
587
        events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
588
        if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
589
            events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
590
        } else {
591
            events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
592
            events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
593
            events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
594
        }
595
        if (events) {
596
                spin_lock(&pending_event_lock);
597
                pending_events[i] |= events;
598
                spin_unlock(&pending_event_lock);
599
                schedule_task(&tcic_task);
600
        }
601
    }
602
 
603
    /* Schedule next poll, if needed */
604
    if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
605
        poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
606
        add_timer(&poll_timer);
607
        tcic_timer_pending = 1;
608
    }
609
    active = 0;
610
 
611
    DEBUG(2, "tcic: interrupt done\n");
612
 
613
} /* tcic_interrupt */
614
 
615
static void tcic_timer(u_long data)
616
{
617
    DEBUG(2, "tcic: tcic_timer()\n");
618
    tcic_timer_pending = 0;
619
    tcic_interrupt(0, NULL, NULL);
620
} /* tcic_timer */
621
 
622
/*====================================================================*/
623
 
624
static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
625
{
626
    socket_table[lsock].handler = handler;
627
    socket_table[lsock].info = info;
628
    if (handler == NULL) {
629
        MOD_DEC_USE_COUNT;
630
    } else {
631
        MOD_INC_USE_COUNT;
632
    }
633
    return 0;
634
} /* tcic_register_callback */
635
 
636
/*====================================================================*/
637
 
638
static int tcic_get_status(unsigned int lsock, u_int *value)
639
{
640
    u_short psock = socket_table[lsock].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, "tcic: GetStatus(%d) = %#2.2x\n", lsock, *value);
659
    return 0;
660
} /* tcic_get_status */
661
 
662
/*====================================================================*/
663
 
664
static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
665
{
666
    *cap = tcic_cap;
667
    return 0;
668
} /* tcic_inquire_socket */
669
 
670
/*====================================================================*/
671
 
672
static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
673
{
674
    u_short psock = socket_table[lsock].psock;
675
    u_char reg;
676
    u_short scf1, scf2;
677
 
678
    tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
679
              | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
680
    scf1 = tcic_getw(TCIC_DATA);
681
    state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;
682
    state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;
683
    state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;
684
    if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)
685
        state->flags |= SS_OUTPUT_ENA;
686
    state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;
687
    if (state->io_irq == 1) state->io_irq = 11;
688
 
689
    reg = tcic_getb(TCIC_PWR);
690
    state->Vcc = state->Vpp = 0;
691
    if (reg & TCIC_PWR_VCC(psock)) {
692
        if (reg & TCIC_PWR_VPP(psock))
693
            state->Vcc = 50;
694
        else
695
            state->Vcc = state->Vpp = 50;
696
    } else {
697
        if (reg & TCIC_PWR_VPP(psock)) {
698
            state->Vcc = 50;
699
            state->Vpp = 120;
700
        }
701
    }
702
    reg = tcic_aux_getb(TCIC_AUX_ILOCK);
703
    state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;
704
 
705
    /* Card status change interrupt mask */
706
    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
707
    scf2 = tcic_getw(TCIC_DATA);
708
    state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;
709
    if (state->flags & SS_IOCARD) {
710
        state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;
711
    } else {
712
        state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;
713
        state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;
714
        state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
715
    }
716
 
717
    DEBUG(1, "tcic: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
718
          "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
719
          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
720
    return 0;
721
} /* tcic_get_socket */
722
 
723
/*====================================================================*/
724
 
725
static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
726
{
727
    u_short psock = socket_table[lsock].psock;
728
    u_char reg;
729
    u_short scf1, scf2;
730
 
731
    DEBUG(1, "tcic: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
732
          "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
733
          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
734
    tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
735
 
736
    reg = tcic_getb(TCIC_PWR);
737
    reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
738
 
739
    if (state->Vcc == 50) {
740
        switch (state->Vpp) {
741
        case 0:   reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
742
        case 50:  reg |= TCIC_PWR_VCC(psock); break;
743
        case 120: reg |= TCIC_PWR_VPP(psock); break;
744
        default:  return -EINVAL;
745
        }
746
    } else if (state->Vcc != 0)
747
        return -EINVAL;
748
 
749
    if (reg != tcic_getb(TCIC_PWR))
750
        tcic_setb(TCIC_PWR, reg);
751
 
752
    reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
753
    if (state->flags & SS_OUTPUT_ENA) {
754
        tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
755
        reg |= TCIC_ILOCK_CRESENA;
756
    } else
757
        tcic_setb(TCIC_SCTRL, 0);
758
    if (state->flags & SS_RESET)
759
        reg |= TCIC_ILOCK_CRESET;
760
    tcic_aux_setb(TCIC_AUX_ILOCK, reg);
761
 
762
    tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
763
    scf1 = TCIC_SCF1_FINPACK;
764
    scf1 |= TCIC_IRQ(state->io_irq);
765
    if (state->flags & SS_IOCARD) {
766
        scf1 |= TCIC_SCF1_IOSTS;
767
        if (state->flags & SS_SPKR_ENA)
768
            scf1 |= TCIC_SCF1_SPKR;
769
        if (state->flags & SS_DMA_MODE)
770
            scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
771
    }
772
    tcic_setw(TCIC_DATA, scf1);
773
 
774
    /* Some general setup stuff, and configure status interrupt */
775
    reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
776
    tcic_aux_setb(TCIC_AUX_WCTL, reg);
777
    tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
778
                  TCIC_IRQ(cs_irq));
779
 
780
    /* Card status change interrupt mask */
781
    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
782
    scf2 = TCIC_SCF2_MALL;
783
    if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
784
    if (state->flags & SS_IOCARD) {
785
        if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
786
    } else {
787
        if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
788
        if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
789
        if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
790
    }
791
    tcic_setw(TCIC_DATA, scf2);
792
    /* For the ISA bus, the irq should be active-high totem-pole */
793
    tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
794
 
795
    return 0;
796
} /* tcic_set_socket */
797
 
798
/*====================================================================*/
799
 
800
static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io)
801
{
802
    u_short psock = socket_table[lsock].psock;
803
    u_short base, ioctl;
804
    u_int addr;
805
 
806
    if (io->map > 1) return -EINVAL;
807
    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
808
    addr = TCIC_IWIN(psock, io->map);
809
    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
810
    base = tcic_getw(TCIC_DATA);
811
    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
812
    ioctl = tcic_getw(TCIC_DATA);
813
 
814
    if (ioctl & TCIC_ICTL_TINY)
815
        io->start = io->stop = base;
816
    else {
817
        io->start = base & (base-1);
818
        io->stop = io->start + (base ^ (base-1));
819
    }
820
    io->speed = to_ns(ioctl & TCIC_ICTL_WSCNT_MASK);
821
    io->flags  = (ioctl & TCIC_ICTL_ENA) ? MAP_ACTIVE : 0;
822
    switch (ioctl & TCIC_ICTL_BW_MASK) {
823
    case TCIC_ICTL_BW_DYN:
824
        io->flags |= MAP_AUTOSZ; break;
825
    case TCIC_ICTL_BW_16:
826
        io->flags |= MAP_16BIT; break;
827
    default:
828
        break;
829
    }
830
    DEBUG(1, "tcic: GetIOMap(%d, %d) = %#2.2x, %d ns, "
831
          "%#4.4x-%#4.4x\n", lsock, io->map, io->flags,
832
          io->speed, io->start, io->stop);
833
    return 0;
834
} /* tcic_get_io_map */
835
 
836
/*====================================================================*/
837
 
838
static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
839
{
840
    u_short psock = socket_table[lsock].psock;
841
    u_int addr;
842
    u_short base, len, ioctl;
843
 
844
    DEBUG(1, "tcic: SetIOMap(%d, %d, %#2.2x, %d ns, "
845
          "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
846
          io->speed, io->start, io->stop);
847
    if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
848
        (io->stop < io->start)) return -EINVAL;
849
    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
850
    addr = TCIC_IWIN(psock, io->map);
851
 
852
    base = io->start; len = io->stop - io->start;
853
    /* Check to see that len+1 is power of two, etc */
854
    if ((len & (len+1)) || (base & len)) return -EINVAL;
855
    base |= (len+1)>>1;
856
    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
857
    tcic_setw(TCIC_DATA, base);
858
 
859
    ioctl  = (psock << TCIC_ICTL_SS_SHFT);
860
    ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
861
    ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
862
    ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
863
    if (!(io->flags & MAP_AUTOSZ)) {
864
        ioctl |= TCIC_ICTL_QUIET;
865
        ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
866
    }
867
    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
868
    tcic_setw(TCIC_DATA, ioctl);
869
 
870
    return 0;
871
} /* tcic_set_io_map */
872
 
873
/*====================================================================*/
874
 
875
static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
876
{
877
    u_short psock = socket_table[lsock].psock;
878
    u_short addr, ctl;
879
    u_long base, mmap;
880
 
881
    if (mem->map > 3) return -EINVAL;
882
    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
883
    addr = TCIC_MWIN(psock, mem->map);
884
 
885
    tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
886
    base = tcic_getw(TCIC_DATA);
887
    if (base & TCIC_MBASE_4K_BIT) {
888
        mem->sys_start = base & TCIC_MBASE_HA_MASK;
889
        mem->sys_stop = mem->sys_start;
890
    } else {
891
        base &= TCIC_MBASE_HA_MASK;
892
        mem->sys_start = (base & (base-1));
893
        mem->sys_stop = mem->sys_start + (base ^ (base-1));
894
    }
895
    mem->sys_start = mem->sys_start << TCIC_MBASE_HA_SHFT;
896
    mem->sys_stop = (mem->sys_stop << TCIC_MBASE_HA_SHFT) + 0x0fff;
897
 
898
    tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
899
    mmap = tcic_getw(TCIC_DATA);
900
    mem->flags = (mmap & TCIC_MMAP_REG) ? MAP_ATTRIB : 0;
901
    mmap &= TCIC_MMAP_CA_MASK;
902
    mem->card_start = mem->sys_start + (mmap << TCIC_MMAP_CA_SHFT);
903
    mem->card_start &= 0x3ffffff;
904
 
905
    tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
906
    ctl = tcic_getw(TCIC_DATA);
907
    mem->flags |= (ctl & TCIC_MCTL_ENA) ? MAP_ACTIVE : 0;
908
    mem->flags |= (ctl & TCIC_MCTL_B8) ? 0 : MAP_16BIT;
909
    mem->flags |= (ctl & TCIC_MCTL_WP) ? MAP_WRPROT : 0;
910
    mem->speed = to_ns(ctl & TCIC_MCTL_WSCNT_MASK);
911
 
912
    DEBUG(1, "tcic: GetMemMap(%d, %d) = %#2.2x, %d ns, "
913
          "%#5.5lx-%#5.5lx, %#5.5x\n", lsock, mem->map, mem->flags,
914
          mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
915
    return 0;
916
} /* tcic_get_mem_map */
917
 
918
/*====================================================================*/
919
 
920
static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
921
{
922
    u_short psock = socket_table[lsock].psock;
923
    u_short addr, ctl;
924
    u_long base, len, mmap;
925
 
926
    DEBUG(1, "tcic: SetMemMap(%d, %d, %#2.2x, %d ns, "
927
          "%#5.5lx-%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
928
          mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
929
    if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
930
        (mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) ||
931
        (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
932
        return -EINVAL;
933
    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
934
    addr = TCIC_MWIN(psock, mem->map);
935
 
936
    base = mem->sys_start; len = mem->sys_stop - mem->sys_start;
937
    if ((len & (len+1)) || (base & len)) return -EINVAL;
938
    if (len == 0x0fff)
939
        base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
940
    else
941
        base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
942
    tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
943
    tcic_setw(TCIC_DATA, base);
944
 
945
    mmap = mem->card_start - mem->sys_start;
946
    mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
947
    if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
948
    tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
949
    tcic_setw(TCIC_DATA, mmap);
950
 
951
    ctl  = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
952
    ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
953
    ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
954
    ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
955
    ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
956
    tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
957
    tcic_setw(TCIC_DATA, ctl);
958
 
959
    return 0;
960
} /* tcic_set_mem_map */
961
 
962
/*====================================================================*/
963
 
964
static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
965
{
966
}
967
 
968
static int tcic_init(unsigned int s)
969
{
970
        int i;
971
        pccard_io_map io = { 0, 0, 0, 0, 1 };
972
        pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
973
 
974
        mem.sys_stop = 0x1000;
975
        tcic_set_socket(s, &dead_socket);
976
        for (i = 0; i < 2; i++) {
977
                io.map = i;
978
                tcic_set_io_map(s, &io);
979
        }
980
        for (i = 0; i < 5; i++) {
981
                mem.map = i;
982
                tcic_set_mem_map(s, &mem);
983
        }
984
        return 0;
985
}
986
 
987
static int tcic_suspend(unsigned int sock)
988
{
989
        return tcic_set_socket(sock, &dead_socket);
990
}
991
 
992
static struct pccard_operations tcic_operations = {
993
        tcic_init,
994
        tcic_suspend,
995
        tcic_register_callback,
996
        tcic_inquire_socket,
997
        tcic_get_status,
998
        tcic_get_socket,
999
        tcic_set_socket,
1000
        tcic_get_io_map,
1001
        tcic_set_io_map,
1002
        tcic_get_mem_map,
1003
        tcic_set_mem_map,
1004
        tcic_proc_setup
1005
};
1006
 
1007
/*====================================================================*/
1008
 
1009
module_init(init_tcic);
1010
module_exit(exit_tcic);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.