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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [macintosh/] [via-cuda.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Device driver for the via-cuda on Apple Powermacs.
3
 *
4
 * The VIA (versatile interface adapter) interfaces to the CUDA,
5
 * a 6805 microprocessor core which controls the ADB (Apple Desktop
6
 * Bus) which connects to the keyboard and mouse.  The CUDA also
7
 * controls system power and the RTC (real time clock) chip.
8
 *
9
 * Copyright (C) 1996 Paul Mackerras.
10
 */
11
#include <stdarg.h>
12
#include <linux/types.h>
13
#include <linux/errno.h>
14
#include <linux/kernel.h>
15
#include <linux/delay.h>
16
#include <linux/adb.h>
17
#include <linux/cuda.h>
18
#include <linux/spinlock.h>
19
#include <linux/interrupt.h>
20
#ifdef CONFIG_PPC
21
#include <asm/prom.h>
22
#include <asm/machdep.h>
23
#else
24
#include <asm/macintosh.h>
25
#include <asm/macints.h>
26
#include <asm/machw.h>
27
#include <asm/mac_via.h>
28
#endif
29
#include <asm/io.h>
30
#include <asm/system.h>
31
#include <linux/init.h>
32
 
33
static volatile unsigned char __iomem *via;
34
static DEFINE_SPINLOCK(cuda_lock);
35
 
36
/* VIA registers - spaced 0x200 bytes apart */
37
#define RS              0x200           /* skip between registers */
38
#define B               0                /* B-side data */
39
#define A               RS              /* A-side data */
40
#define DIRB            (2*RS)          /* B-side direction (1=output) */
41
#define DIRA            (3*RS)          /* A-side direction (1=output) */
42
#define T1CL            (4*RS)          /* Timer 1 ctr/latch (low 8 bits) */
43
#define T1CH            (5*RS)          /* Timer 1 counter (high 8 bits) */
44
#define T1LL            (6*RS)          /* Timer 1 latch (low 8 bits) */
45
#define T1LH            (7*RS)          /* Timer 1 latch (high 8 bits) */
46
#define T2CL            (8*RS)          /* Timer 2 ctr/latch (low 8 bits) */
47
#define T2CH            (9*RS)          /* Timer 2 counter (high 8 bits) */
48
#define SR              (10*RS)         /* Shift register */
49
#define ACR             (11*RS)         /* Auxiliary control register */
50
#define PCR             (12*RS)         /* Peripheral control register */
51
#define IFR             (13*RS)         /* Interrupt flag register */
52
#define IER             (14*RS)         /* Interrupt enable register */
53
#define ANH             (15*RS)         /* A-side data, no handshake */
54
 
55
/* Bits in B data register: all active low */
56
#define TREQ            0x08            /* Transfer request (input) */
57
#define TACK            0x10            /* Transfer acknowledge (output) */
58
#define TIP             0x20            /* Transfer in progress (output) */
59
 
60
/* Bits in ACR */
61
#define SR_CTRL         0x1c            /* Shift register control bits */
62
#define SR_EXT          0x0c            /* Shift on external clock */
63
#define SR_OUT          0x10            /* Shift out if 1 */
64
 
65
/* Bits in IFR and IER */
66
#define IER_SET         0x80            /* set bits in IER */
67
#define IER_CLR         0                /* clear bits in IER */
68
#define SR_INT          0x04            /* Shift register full/empty */
69
 
70
static enum cuda_state {
71
    idle,
72
    sent_first_byte,
73
    sending,
74
    reading,
75
    read_done,
76
    awaiting_reply
77
} cuda_state;
78
 
79
static struct adb_request *current_req;
80
static struct adb_request *last_req;
81
static unsigned char cuda_rbuf[16];
82
static unsigned char *reply_ptr;
83
static int reading_reply;
84
static int data_index;
85
static int cuda_irq;
86
#ifdef CONFIG_PPC
87
static struct device_node *vias;
88
#endif
89
static int cuda_fully_inited;
90
 
91
#ifdef CONFIG_ADB
92
static int cuda_probe(void);
93
static int cuda_init(void);
94
static int cuda_send_request(struct adb_request *req, int sync);
95
static int cuda_adb_autopoll(int devs);
96
static int cuda_reset_adb_bus(void);
97
#endif /* CONFIG_ADB */
98
 
99
static int cuda_init_via(void);
100
static void cuda_start(void);
101
static irqreturn_t cuda_interrupt(int irq, void *arg);
102
static void cuda_input(unsigned char *buf, int nb);
103
void cuda_poll(void);
104
static int cuda_write(struct adb_request *req);
105
 
106
int cuda_request(struct adb_request *req,
107
                 void (*done)(struct adb_request *), int nbytes, ...);
108
 
109
#ifdef CONFIG_ADB
110
struct adb_driver via_cuda_driver = {
111
        "CUDA",
112
        cuda_probe,
113
        cuda_init,
114
        cuda_send_request,
115
        cuda_adb_autopoll,
116
        cuda_poll,
117
        cuda_reset_adb_bus
118
};
119
#endif /* CONFIG_ADB */
120
 
121
#ifdef CONFIG_PPC
122
int __init find_via_cuda(void)
123
{
124
    struct adb_request req;
125
    phys_addr_t taddr;
126
    const u32 *reg;
127
    int err;
128
 
129
    if (vias != 0)
130
        return 1;
131
    vias = of_find_node_by_name(NULL, "via-cuda");
132
    if (vias == 0)
133
        return 0;
134
 
135
    reg = of_get_property(vias, "reg", NULL);
136
    if (reg == NULL) {
137
            printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
138
            goto fail;
139
    }
140
    taddr = of_translate_address(vias, reg);
141
    if (taddr == 0) {
142
            printk(KERN_ERR "via-cuda: Can't translate address !\n");
143
            goto fail;
144
    }
145
    via = ioremap(taddr, 0x2000);
146
    if (via == NULL) {
147
            printk(KERN_ERR "via-cuda: Can't map address !\n");
148
            goto fail;
149
    }
150
 
151
    cuda_state = idle;
152
    sys_ctrler = SYS_CTRLER_CUDA;
153
 
154
    err = cuda_init_via();
155
    if (err) {
156
        printk(KERN_ERR "cuda_init_via() failed\n");
157
        via = NULL;
158
        return 0;
159
    }
160
 
161
    /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
162
    /* for us by the main VIA driver in arch/m68k/mac/via.c        */
163
 
164
    out_8(&via[IFR], 0x7f);     /* clear interrupts by writing 1s */
165
    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
166
 
167
    /* enable autopoll */
168
    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
169
    while (!req.complete)
170
        cuda_poll();
171
 
172
    return 1;
173
 
174
 fail:
175
    of_node_put(vias);
176
    vias = NULL;
177
    return 0;
178
}
179
#endif /* CONFIG_PPC */
180
 
181
static int __init via_cuda_start(void)
182
{
183
    if (via == NULL)
184
        return -ENODEV;
185
 
186
#ifdef CONFIG_MAC
187
    cuda_irq = IRQ_MAC_ADB;
188
#else /* CONFIG_MAC */
189
    cuda_irq = irq_of_parse_and_map(vias, 0);
190
    if (cuda_irq == NO_IRQ) {
191
        printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
192
               vias->full_name);
193
        return -ENODEV;
194
    }
195
#endif /* CONFIG_MAC */
196
 
197
    if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
198
        printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
199
        return -EAGAIN;
200
    }
201
 
202
    printk("Macintosh CUDA driver v0.5 for Unified ADB.\n");
203
 
204
    cuda_fully_inited = 1;
205
    return 0;
206
}
207
 
208
device_initcall(via_cuda_start);
209
 
210
#ifdef CONFIG_ADB
211
static int
212
cuda_probe(void)
213
{
214
#ifdef CONFIG_PPC
215
    if (sys_ctrler != SYS_CTRLER_CUDA)
216
        return -ENODEV;
217
#else
218
    if (macintosh_config->adb_type != MAC_ADB_CUDA)
219
        return -ENODEV;
220
    via = via1;
221
#endif
222
    return 0;
223
}
224
 
225
static int __init
226
cuda_init(void)
227
{
228
#ifdef CONFIG_PPC
229
    if (via == NULL)
230
        return -ENODEV;
231
    return 0;
232
#else 
233
    int err = cuda_init_via();
234
    if (err) {
235
        printk(KERN_ERR "cuda_init_via() failed\n");
236
        return -ENODEV;
237
    }
238
    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
239
 
240
    return via_cuda_start();
241
#endif
242
}
243
#endif /* CONFIG_ADB */
244
 
245
#define WAIT_FOR(cond, what)                                    \
246
    do {                                                        \
247
        int x;                                                  \
248
        for (x = 1000; !(cond); --x) {                          \
249
            if (x == 0) {                                        \
250
                printk("Timeout waiting for " what "\n");       \
251
                return -ENXIO;                                  \
252
            }                                                   \
253
            udelay(100);                                        \
254
        }                                                       \
255
    } while (0)
256
 
257
static int
258
cuda_init_via(void)
259
{
260
    out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ); /* TACK & TIP out */
261
    out_8(&via[B], in_8(&via[B]) | TACK | TIP);                 /* negate them */
262
    out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);    /* SR data in */
263
    (void)in_8(&via[SR]);                                               /* clear any left-over data */
264
#ifdef CONFIG_PPC
265
    out_8(&via[IER], 0x7f);                                     /* disable interrupts from VIA */
266
    (void)in_8(&via[IER]);
267
#else
268
    out_8(&via[IER], SR_INT);                                   /* disable SR interrupt from VIA */
269
#endif
270
 
271
    /* delay 4ms and then clear any pending interrupt */
272
    mdelay(4);
273
    (void)in_8(&via[SR]);
274
    out_8(&via[IFR], SR_INT);
275
 
276
    /* sync with the CUDA - assert TACK without TIP */
277
    out_8(&via[B], in_8(&via[B]) & ~TACK);
278
 
279
    /* wait for the CUDA to assert TREQ in response */
280
    WAIT_FOR((in_8(&via[B]) & TREQ) == 0, "CUDA response to sync");
281
 
282
    /* wait for the interrupt and then clear it */
283
    WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
284
    (void)in_8(&via[SR]);
285
    out_8(&via[IFR], SR_INT);
286
 
287
    /* finish the sync by negating TACK */
288
    out_8(&via[B], in_8(&via[B]) | TACK);
289
 
290
    /* wait for the CUDA to negate TREQ and the corresponding interrupt */
291
    WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)");
292
    WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
293
    (void)in_8(&via[SR]);
294
    out_8(&via[IFR], SR_INT);
295
    out_8(&via[B], in_8(&via[B]) | TIP);        /* should be unnecessary */
296
 
297
    return 0;
298
}
299
 
300
#ifdef CONFIG_ADB
301
/* Send an ADB command */
302
static int
303
cuda_send_request(struct adb_request *req, int sync)
304
{
305
    int i;
306
 
307
    if ((via == NULL) || !cuda_fully_inited) {
308
        req->complete = 1;
309
        return -ENXIO;
310
    }
311
 
312
    req->reply_expected = 1;
313
 
314
    i = cuda_write(req);
315
    if (i)
316
        return i;
317
 
318
    if (sync) {
319
        while (!req->complete)
320
            cuda_poll();
321
    }
322
    return 0;
323
}
324
 
325
 
326
/* Enable/disable autopolling */
327
static int
328
cuda_adb_autopoll(int devs)
329
{
330
    struct adb_request req;
331
 
332
    if ((via == NULL) || !cuda_fully_inited)
333
        return -ENXIO;
334
 
335
    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0));
336
    while (!req.complete)
337
        cuda_poll();
338
    return 0;
339
}
340
 
341
/* Reset adb bus - how do we do this?? */
342
static int
343
cuda_reset_adb_bus(void)
344
{
345
    struct adb_request req;
346
 
347
    if ((via == NULL) || !cuda_fully_inited)
348
        return -ENXIO;
349
 
350
    cuda_request(&req, NULL, 2, ADB_PACKET, 0);          /* maybe? */
351
    while (!req.complete)
352
        cuda_poll();
353
    return 0;
354
}
355
#endif /* CONFIG_ADB */
356
/* Construct and send a cuda request */
357
int
358
cuda_request(struct adb_request *req, void (*done)(struct adb_request *),
359
             int nbytes, ...)
360
{
361
    va_list list;
362
    int i;
363
 
364
    if (via == NULL) {
365
        req->complete = 1;
366
        return -ENXIO;
367
    }
368
 
369
    req->nbytes = nbytes;
370
    req->done = done;
371
    va_start(list, nbytes);
372
    for (i = 0; i < nbytes; ++i)
373
        req->data[i] = va_arg(list, int);
374
    va_end(list);
375
    req->reply_expected = 1;
376
    return cuda_write(req);
377
}
378
 
379
static int
380
cuda_write(struct adb_request *req)
381
{
382
    unsigned long flags;
383
 
384
    if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {
385
        req->complete = 1;
386
        return -EINVAL;
387
    }
388
    req->next = NULL;
389
    req->sent = 0;
390
    req->complete = 0;
391
    req->reply_len = 0;
392
 
393
    spin_lock_irqsave(&cuda_lock, flags);
394
    if (current_req != 0) {
395
        last_req->next = req;
396
        last_req = req;
397
    } else {
398
        current_req = req;
399
        last_req = req;
400
        if (cuda_state == idle)
401
            cuda_start();
402
    }
403
    spin_unlock_irqrestore(&cuda_lock, flags);
404
 
405
    return 0;
406
}
407
 
408
static void
409
cuda_start(void)
410
{
411
    struct adb_request *req;
412
 
413
    /* assert cuda_state == idle */
414
    /* get the packet to send */
415
    req = current_req;
416
    if (req == 0)
417
        return;
418
    if ((in_8(&via[B]) & TREQ) == 0)
419
        return;                 /* a byte is coming in from the CUDA */
420
 
421
    /* set the shift register to shift out and send a byte */
422
    out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT);
423
    out_8(&via[SR], req->data[0]);
424
    out_8(&via[B], in_8(&via[B]) & ~TIP);
425
    cuda_state = sent_first_byte;
426
}
427
 
428
void
429
cuda_poll(void)
430
{
431
    /* cuda_interrupt only takes a normal lock, we disable
432
     * interrupts here to avoid re-entering and thus deadlocking.
433
     */
434
    disable_irq(cuda_irq);
435
    cuda_interrupt(0, NULL);
436
    enable_irq(cuda_irq);
437
}
438
 
439
static irqreturn_t
440
cuda_interrupt(int irq, void *arg)
441
{
442
    int status;
443
    struct adb_request *req = NULL;
444
    unsigned char ibuf[16];
445
    int ibuf_len = 0;
446
    int complete = 0;
447
 
448
    spin_lock(&cuda_lock);
449
 
450
    /* On powermacs, this handler is registered for the VIA IRQ. But it uses
451
     * just the shift register IRQ -- other VIA interrupt sources are disabled.
452
     * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
453
     * we are polling, the shift register IRQ flag has already been cleared.
454
     */
455
 
456
#ifdef CONFIG_MAC
457
    if (!arg)
458
#endif
459
    {
460
        if ((in_8(&via[IFR]) & SR_INT) == 0) {
461
            spin_unlock(&cuda_lock);
462
            return IRQ_NONE;
463
        } else {
464
            out_8(&via[IFR], SR_INT);
465
        }
466
    }
467
 
468
    status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);
469
    /* printk("cuda_interrupt: state=%d status=%x\n", cuda_state, status); */
470
    switch (cuda_state) {
471
    case idle:
472
        /* CUDA has sent us the first byte of data - unsolicited */
473
        if (status != TREQ)
474
            printk("cuda: state=idle, status=%x\n", status);
475
        (void)in_8(&via[SR]);
476
        out_8(&via[B], in_8(&via[B]) & ~TIP);
477
        cuda_state = reading;
478
        reply_ptr = cuda_rbuf;
479
        reading_reply = 0;
480
        break;
481
 
482
    case awaiting_reply:
483
        /* CUDA has sent us the first byte of data of a reply */
484
        if (status != TREQ)
485
            printk("cuda: state=awaiting_reply, status=%x\n", status);
486
        (void)in_8(&via[SR]);
487
        out_8(&via[B], in_8(&via[B]) & ~TIP);
488
        cuda_state = reading;
489
        reply_ptr = current_req->reply;
490
        reading_reply = 1;
491
        break;
492
 
493
    case sent_first_byte:
494
        if (status == TREQ + TIP + SR_OUT) {
495
            /* collision */
496
            out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);
497
            (void)in_8(&via[SR]);
498
            out_8(&via[B], in_8(&via[B]) | TIP | TACK);
499
            cuda_state = idle;
500
        } else {
501
            /* assert status == TIP + SR_OUT */
502
            if (status != TIP + SR_OUT)
503
                printk("cuda: state=sent_first_byte status=%x\n", status);
504
            out_8(&via[SR], current_req->data[1]);
505
            out_8(&via[B], in_8(&via[B]) ^ TACK);
506
            data_index = 2;
507
            cuda_state = sending;
508
        }
509
        break;
510
 
511
    case sending:
512
        req = current_req;
513
        if (data_index >= req->nbytes) {
514
            out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);
515
            (void)in_8(&via[SR]);
516
            out_8(&via[B], in_8(&via[B]) | TACK | TIP);
517
            req->sent = 1;
518
            if (req->reply_expected) {
519
                cuda_state = awaiting_reply;
520
            } else {
521
                current_req = req->next;
522
                complete = 1;
523
                /* not sure about this */
524
                cuda_state = idle;
525
                cuda_start();
526
            }
527
        } else {
528
            out_8(&via[SR], req->data[data_index++]);
529
            out_8(&via[B], in_8(&via[B]) ^ TACK);
530
        }
531
        break;
532
 
533
    case reading:
534
        *reply_ptr++ = in_8(&via[SR]);
535
        if (status == TIP) {
536
            /* that's all folks */
537
            out_8(&via[B], in_8(&via[B]) | TACK | TIP);
538
            cuda_state = read_done;
539
        } else {
540
            /* assert status == TIP | TREQ */
541
            if (status != TIP + TREQ)
542
                printk("cuda: state=reading status=%x\n", status);
543
            out_8(&via[B], in_8(&via[B]) ^ TACK);
544
        }
545
        break;
546
 
547
    case read_done:
548
        (void)in_8(&via[SR]);
549
        if (reading_reply) {
550
            req = current_req;
551
            req->reply_len = reply_ptr - req->reply;
552
            if (req->data[0] == ADB_PACKET) {
553
                /* Have to adjust the reply from ADB commands */
554
                if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {
555
                    /* the 0x2 bit indicates no response */
556
                    req->reply_len = 0;
557
                } else {
558
                    /* leave just the command and result bytes in the reply */
559
                    req->reply_len -= 2;
560
                    memmove(req->reply, req->reply + 2, req->reply_len);
561
                }
562
            }
563
            current_req = req->next;
564
            complete = 1;
565
        } else {
566
            /* This is tricky. We must break the spinlock to call
567
             * cuda_input. However, doing so means we might get
568
             * re-entered from another CPU getting an interrupt
569
             * or calling cuda_poll(). I ended up using the stack
570
             * (it's only for 16 bytes) and moving the actual
571
             * call to cuda_input to outside of the lock.
572
             */
573
            ibuf_len = reply_ptr - cuda_rbuf;
574
            memcpy(ibuf, cuda_rbuf, ibuf_len);
575
        }
576
        if (status == TREQ) {
577
            out_8(&via[B], in_8(&via[B]) & ~TIP);
578
            cuda_state = reading;
579
            reply_ptr = cuda_rbuf;
580
            reading_reply = 0;
581
        } else {
582
            cuda_state = idle;
583
            cuda_start();
584
        }
585
        break;
586
 
587
    default:
588
        printk("cuda_interrupt: unknown cuda_state %d?\n", cuda_state);
589
    }
590
    spin_unlock(&cuda_lock);
591
    if (complete && req) {
592
        void (*done)(struct adb_request *) = req->done;
593
        mb();
594
        req->complete = 1;
595
        /* Here, we assume that if the request has a done member, the
596
         * struct request will survive to setting req->complete to 1
597
         */
598
        if (done)
599
                (*done)(req);
600
    }
601
    if (ibuf_len)
602
        cuda_input(ibuf, ibuf_len);
603
    return IRQ_HANDLED;
604
}
605
 
606
static void
607
cuda_input(unsigned char *buf, int nb)
608
{
609
    int i;
610
 
611
    switch (buf[0]) {
612
    case ADB_PACKET:
613
#ifdef CONFIG_XMON
614
        if (nb == 5 && buf[2] == 0x2c) {
615
            extern int xmon_wants_key, xmon_adb_keycode;
616
            if (xmon_wants_key) {
617
                xmon_adb_keycode = buf[3];
618
                return;
619
            }
620
        }
621
#endif /* CONFIG_XMON */
622
#ifdef CONFIG_ADB
623
        adb_input(buf+2, nb-2, buf[1] & 0x40);
624
#endif /* CONFIG_ADB */
625
        break;
626
 
627
    default:
628
        printk("data from cuda (%d bytes):", nb);
629
        for (i = 0; i < nb; ++i)
630
            printk(" %.2x", buf[i]);
631
        printk("\n");
632
    }
633
}

powered by: WebSVN 2.1.0

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