Root/drivers/macintosh/macio-adb.c

1/*
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/spinlock.h>
10#include <linux/interrupt.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 <linux/init.h>
18#include <linux/ioport.h>
19
20struct preg {
21    unsigned char r;
22    char pad[15];
23};
24
25struct 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
59static volatile struct adb_regs __iomem *adb;
60static struct adb_request *current_req, *last_req;
61static DEFINE_SPINLOCK(macio_lock);
62
63static int macio_probe(void);
64static int macio_init(void);
65static irqreturn_t macio_adb_interrupt(int irq, void *arg);
66static int macio_send_request(struct adb_request *req, int sync);
67static int macio_adb_autopoll(int devs);
68static void macio_adb_poll(void);
69static int macio_adb_reset_bus(void);
70
71struct 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
82int macio_probe(void)
83{
84    struct device_node *np;
85
86    np = of_find_compatible_node(NULL, "adb", "chrp,adb0");
87    if (np) {
88        of_node_put(np);
89        return 0;
90    }
91    return -ENODEV;
92}
93
94int macio_init(void)
95{
96    struct device_node *adbs;
97    struct resource r;
98    unsigned int irq;
99
100    adbs = of_find_compatible_node(NULL, "adb", "chrp,adb0");
101    if (adbs == 0)
102        return -ENXIO;
103
104    if (of_address_to_resource(adbs, 0, &r)) {
105        of_node_put(adbs);
106        return -ENXIO;
107    }
108    adb = ioremap(r.start, 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    irq = irq_of_parse_and_map(adbs, 0);
118    of_node_put(adbs);
119    if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) {
120        printk(KERN_ERR "ADB: can't get irq %d\n", irq);
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
130static 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
142static 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 seldom 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            spin_unlock_irqrestore(&macio_lock, flags);
158            return -1;
159        }
160    }
161    spin_unlock_irqrestore(&macio_lock, flags);
162    return 0;
163}
164
165/* Send an ADB command */
166static int macio_send_request(struct adb_request *req, int sync)
167{
168    unsigned long flags;
169    int i;
170    
171    if (req->data[0] != ADB_PACKET)
172        return -EINVAL;
173    
174    for (i = 0; i < req->nbytes - 1; ++i)
175        req->data[i] = req->data[i+1];
176    --req->nbytes;
177    
178    req->next = NULL;
179    req->sent = 0;
180    req->complete = 0;
181    req->reply_len = 0;
182
183    spin_lock_irqsave(&macio_lock, flags);
184    if (current_req != 0) {
185        last_req->next = req;
186        last_req = req;
187    } else {
188        current_req = last_req = req;
189        out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
190    }
191    spin_unlock_irqrestore(&macio_lock, flags);
192    
193    if (sync) {
194        while (!req->complete)
195            macio_adb_poll();
196    }
197
198    return 0;
199}
200
201static irqreturn_t macio_adb_interrupt(int irq, void *arg)
202{
203    int i, n, err;
204    struct adb_request *req = NULL;
205    unsigned char ibuf[16];
206    int ibuf_len = 0;
207    int complete = 0;
208    int autopoll = 0;
209    int handled = 0;
210
211    spin_lock(&macio_lock);
212    if (in_8(&adb->intr.r) & TAG) {
213        handled = 1;
214        if ((req = current_req) != 0) {
215            /* put the current request in */
216            for (i = 0; i < req->nbytes; ++i)
217                out_8(&adb->data[i].r, req->data[i]);
218            out_8(&adb->dcount.r, req->nbytes & HMB);
219            req->sent = 1;
220            if (req->reply_expected) {
221                out_8(&adb->ctrl.r, DTB + CRE);
222            } else {
223                out_8(&adb->ctrl.r, DTB);
224                current_req = req->next;
225                complete = 1;
226                if (current_req)
227                    out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
228            }
229        }
230        out_8(&adb->intr.r, 0);
231    }
232
233    if (in_8(&adb->intr.r) & DFB) {
234        handled = 1;
235        err = in_8(&adb->error.r);
236        if (current_req && current_req->sent) {
237            /* this is the response to a command */
238            req = current_req;
239            if (err == 0) {
240                req->reply_len = in_8(&adb->dcount.r) & HMB;
241                for (i = 0; i < req->reply_len; ++i)
242                    req->reply[i] = in_8(&adb->data[i].r);
243            }
244            current_req = req->next;
245            complete = 1;
246            if (current_req)
247                out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
248        } else if (err == 0) {
249            /* autopoll data */
250            n = in_8(&adb->dcount.r) & HMB;
251            for (i = 0; i < n; ++i)
252                ibuf[i] = in_8(&adb->data[i].r);
253            ibuf_len = n;
254            autopoll = (in_8(&adb->dcount.r) & APD) != 0;
255        }
256        out_8(&adb->error.r, 0);
257        out_8(&adb->intr.r, 0);
258    }
259    spin_unlock(&macio_lock);
260    if (complete && req) {
261        void (*done)(struct adb_request *) = req->done;
262        mb();
263        req->complete = 1;
264        /* Here, we assume that if the request has a done member, the
265             * struct request will survive to setting req->complete to 1
266         */
267        if (done)
268        (*done)(req);
269    }
270    if (ibuf_len)
271        adb_input(ibuf, ibuf_len, autopoll);
272
273    return IRQ_RETVAL(handled);
274}
275
276static void macio_adb_poll(void)
277{
278    unsigned long flags;
279
280    local_irq_save(flags);
281    if (in_8(&adb->intr.r) != 0)
282        macio_adb_interrupt(0, NULL);
283    local_irq_restore(flags);
284}
285

Archive Download this file



interactive