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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [macintosh/] [macio-adb.c] - Blame information for rev 1275

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Driver for the ADB controller in the Mac I/O (Hydra) chip.
3
 */
4
#include <stdarg.h>
5
#include <linux/types.h>
6
#include <linux/errno.h>
7
#include <linux/kernel.h>
8
#include <linux/delay.h>
9
#include <linux/sched.h>
10
#include <linux/spinlock.h>
11
#include <asm/prom.h>
12
#include <linux/adb.h>
13
#include <asm/io.h>
14
#include <asm/pgtable.h>
15
#include <asm/hydra.h>
16
#include <asm/irq.h>
17
#include <asm/system.h>
18
#include <linux/init.h>
19
 
20
struct preg {
21
        unsigned char r;
22
        char pad[15];
23
};
24
 
25
struct adb_regs {
26
        struct preg intr;
27
        struct preg data[9];
28
        struct preg intr_enb;
29
        struct preg dcount;
30
        struct preg error;
31
        struct preg ctrl;
32
        struct preg autopoll;
33
        struct preg active_hi;
34
        struct preg active_lo;
35
        struct preg test;
36
};
37
 
38
/* Bits in intr and intr_enb registers */
39
#define DFB     1               /* data from bus */
40
#define TAG     2               /* transfer access grant */
41
 
42
/* Bits in dcount register */
43
#define HMB     0x0f            /* how many bytes */
44
#define APD     0x10            /* auto-poll data */
45
 
46
/* Bits in error register */
47
#define NRE     1               /* no response error */
48
#define DLE     2               /* data lost error */
49
 
50
/* Bits in ctrl register */
51
#define TAR     1               /* transfer access request */
52
#define DTB     2               /* data to bus */
53
#define CRE     4               /* command response expected */
54
#define ADB_RST 8               /* ADB reset */
55
 
56
/* Bits in autopoll register */
57
#define APE     1               /* autopoll enable */
58
 
59
static volatile struct adb_regs *adb;
60
static struct adb_request *current_req, *last_req;
61
static spinlock_t macio_lock = SPIN_LOCK_UNLOCKED;
62
 
63
static int macio_probe(void);
64
static int macio_init(void);
65
static void macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs);
66
static int macio_send_request(struct adb_request *req, int sync);
67
static int macio_adb_autopoll(int devs);
68
static void macio_adb_poll(void);
69
static int macio_adb_reset_bus(void);
70
 
71
struct adb_driver macio_adb_driver = {
72
        "MACIO",
73
        macio_probe,
74
        macio_init,
75
        macio_send_request,
76
        /*macio_write,*/
77
        macio_adb_autopoll,
78
        macio_adb_poll,
79
        macio_adb_reset_bus
80
};
81
 
82
int macio_probe(void)
83
{
84
        return find_compatible_devices("adb", "chrp,adb0")? 0: -ENODEV;
85
}
86
 
87
int macio_init(void)
88
{
89
        struct device_node *adbs;
90
 
91
        adbs = find_compatible_devices("adb", "chrp,adb0");
92
        if (adbs == 0)
93
                return -ENXIO;
94
 
95
#if 0
96
        { int i;
97
 
98
        printk("macio_adb_init: node = %p, addrs =", adbs->node);
99
        for (i = 0; i < adbs->n_addrs; ++i)
100
                printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size);
101
        printk(", intrs =");
102
        for (i = 0; i < adbs->n_intrs; ++i)
103
                printk(" %x", adbs->intrs[i].line);
104
        printk("\n"); }
105
#endif
106
 
107
        adb = (volatile struct adb_regs *)
108
                ioremap(adbs->addrs->address, sizeof(struct adb_regs));
109
 
110
        out_8(&adb->ctrl.r, 0);
111
        out_8(&adb->intr.r, 0);
112
        out_8(&adb->error.r, 0);
113
        out_8(&adb->active_hi.r, 0xff); /* for now, set all devices active */
114
        out_8(&adb->active_lo.r, 0xff);
115
        out_8(&adb->autopoll.r, APE);
116
 
117
        if (request_irq(adbs->intrs[0].line, macio_adb_interrupt,
118
                        0, "ADB", (void *)0)) {
119
                printk(KERN_ERR "ADB: can't get irq %d\n",
120
                       adbs->intrs[0].line);
121
                return -EAGAIN;
122
        }
123
        out_8(&adb->intr_enb.r, DFB | TAG);
124
 
125
        printk("adb: mac-io driver 1.0 for unified ADB\n");
126
 
127
        return 0;
128
}
129
 
130
static int macio_adb_autopoll(int devs)
131
{
132
        unsigned long flags;
133
 
134
        spin_lock_irqsave(&macio_lock, flags);
135
        out_8(&adb->active_hi.r, devs >> 8);
136
        out_8(&adb->active_lo.r, devs);
137
        out_8(&adb->autopoll.r, devs? APE: 0);
138
        spin_unlock_irqrestore(&macio_lock, flags);
139
        return 0;
140
}
141
 
142
static int macio_adb_reset_bus(void)
143
{
144
        unsigned long flags;
145
        int timeout = 1000000;
146
 
147
        /* Hrm... we may want to not lock interrupts for so
148
         * long ... oh well, who uses that chip anyway ? :)
149
         * That function will be seldomly used during boot
150
         * on rare machines, so...
151
         */
152
        spin_lock_irqsave(&macio_lock, flags);
153
        out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | ADB_RST);
154
        while ((in_8(&adb->ctrl.r) & ADB_RST) != 0) {
155
                if (--timeout == 0) {
156
                        out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) & ~ADB_RST);
157
                        return -1;
158
                }
159
        }
160
        spin_unlock_irqrestore(&macio_lock, flags);
161
        return 0;
162
}
163
 
164
/* Send an ADB command */
165
static int macio_send_request(struct adb_request *req, int sync)
166
{
167
        unsigned long flags;
168
        int i;
169
 
170
        if (req->data[0] != ADB_PACKET)
171
                return -EINVAL;
172
 
173
        for (i = 0; i < req->nbytes - 1; ++i)
174
                req->data[i] = req->data[i+1];
175
        --req->nbytes;
176
 
177
        req->next = 0;
178
        req->sent = 0;
179
        req->complete = 0;
180
        req->reply_len = 0;
181
 
182
        spin_lock_irqsave(&macio_lock, flags);
183
        if (current_req != 0) {
184
                last_req->next = req;
185
                last_req = req;
186
        } else {
187
                current_req = last_req = req;
188
                out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
189
        }
190
        spin_unlock_irqrestore(&macio_lock, flags);
191
 
192
        if (sync) {
193
                while (!req->complete)
194
                        macio_adb_poll();
195
        }
196
 
197
        return 0;
198
}
199
 
200
static void macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs)
201
{
202
        int i, n, err;
203
        struct adb_request *req;
204
        unsigned char ibuf[16];
205
        int ibuf_len = 0;
206
        int complete = 0;
207
        int autopoll = 0;
208
 
209
        spin_lock(&macio_lock);
210
        if (in_8(&adb->intr.r) & TAG) {
211
                if ((req = current_req) != 0) {
212
                        /* put the current request in */
213
                        for (i = 0; i < req->nbytes; ++i)
214
                                out_8(&adb->data[i].r, req->data[i]);
215
                        out_8(&adb->dcount.r, req->nbytes & HMB);
216
                        req->sent = 1;
217
                        if (req->reply_expected) {
218
                                out_8(&adb->ctrl.r, DTB + CRE);
219
                        } else {
220
                                out_8(&adb->ctrl.r, DTB);
221
                                current_req = req->next;
222
                                complete = 1;
223
                                if (current_req)
224
                                        out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
225
                        }
226
                }
227
                out_8(&adb->intr.r, 0);
228
        }
229
 
230
        if (in_8(&adb->intr.r) & DFB) {
231
                err = in_8(&adb->error.r);
232
                if (current_req && current_req->sent) {
233
                        /* this is the response to a command */
234
                        req = current_req;
235
                        if (err == 0) {
236
                                req->reply_len = in_8(&adb->dcount.r) & HMB;
237
                                for (i = 0; i < req->reply_len; ++i)
238
                                        req->reply[i] = in_8(&adb->data[i].r);
239
                        }
240
                        current_req = req->next;
241
                        complete = 1;
242
                        if (current_req)
243
                                out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
244
                } else if (err == 0) {
245
                        /* autopoll data */
246
                        n = in_8(&adb->dcount.r) & HMB;
247
                        for (i = 0; i < n; ++i)
248
                                ibuf[i] = in_8(&adb->data[i].r);
249
                        ibuf_len = n;
250
                        autopoll = (in_8(&adb->dcount.r) & APD) != 0;
251
                }
252
                out_8(&adb->error.r, 0);
253
                out_8(&adb->intr.r, 0);
254
        }
255
        spin_unlock(&macio_lock);
256
        if (complete && req) {
257
            void (*done)(struct adb_request *) = req->done;
258
            mb();
259
            req->complete = 1;
260
            /* Here, we assume that if the request has a done member, the
261
             * struct request will survive to setting req->complete to 1
262
             */
263
            if (done)
264
                (*done)(req);
265
        }
266
        if (ibuf_len)
267
                adb_input(ibuf, ibuf_len, regs, autopoll);
268
}
269
 
270
static void macio_adb_poll(void)
271
{
272
        unsigned long flags;
273
 
274
        local_irq_save(flags);
275
        if (in_8(&adb->intr.r) != 0)
276
                macio_adb_interrupt(0, 0, 0);
277
        local_irq_restore(flags);
278
}

powered by: WebSVN 2.1.0

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