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