Root/
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 | |
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 __iomem *adb; |
60 | static struct adb_request *current_req, *last_req; |
61 | static DEFINE_SPINLOCK(macio_lock); |
62 | |
63 | static int macio_probe(void); |
64 | static int macio_init(void); |
65 | static irqreturn_t macio_adb_interrupt(int irq, void *arg); |
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 | 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 | |
94 | int 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 | |
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 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 */ |
166 | static 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 | |
201 | static 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 | |
276 | static 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 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9