[ubicom32]: move new files out from platform support patch
[openwrt/svn-archive/archive.git] / target / linux / ubicom32 / files / arch / ubicom32 / mach-common / usb_tio.c
1 /*
2 * arch/ubicom32/mach-common/usb_tio.c
3 * Linux side Ubicom USB TIO driver
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 */
28 #include <linux/module.h>
29 #include <linux/spinlock.h>
30 #include <linux/slab.h>
31 #include <asm/devtree.h>
32 #include "usb_tio.h"
33
34 #ifdef CONFIG_SMP
35 static DEFINE_SPINLOCK(tio_lock);
36 #define USB_TIO_LOCK(lock, flag) spin_lock_irqsave(lock, flag)
37 #define USB_TIO_UNLOCK(lock, flag) spin_unlock_irqrestore(lock, flag)
38 #define USB_TIO_LOCK_ISLOCKED(lock) spin_try_lock(lock)
39 #else
40 #define USB_TIO_LOCK(lock, flag) local_irq_save(flag)
41 #define USB_TIO_UNLOCK(lock, flag) local_irq_restore(flag)
42 #endif
43
44 spinlock_t usb_tio_lock;
45
46 /*
47 * usb_tio_set_hrt_interrupt()
48 */
49 static inline void usb_tio_set_hrt_interrupt(void)
50 {
51 ubicom32_set_interrupt(usb_node->dn.sendirq);
52 }
53
54 static inline void usb_tio_wait_hrt(void)
55 {
56 while (unlikely(usb_node->pdesc));
57 }
58
59 #if defined(USB_TIO_DEBUG)
60 static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req)
61 {
62 BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2);
63 }
64
65 static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req)
66 {
67 req->magic = 0;
68 }
69 #endif
70
71 static void usb_tio_request_set_magic(volatile struct usb_tio_request *req)
72 {
73 req->magic = USB_TIO_REQUEST_MAGIC1;
74 }
75
76 /*
77 * usb_tio_commit_request()
78 */
79 static inline void usb_tio_commit_request(volatile struct usb_tio_request *request)
80 {
81 wmb();
82 usb_node->pdesc = request;
83
84 /*
85 * next thing to do is alway checking if (usb_node->pdesc == NULL)
86 * to see if the request is done, so add a mb() here
87 */
88 mb();
89 usb_tio_set_hrt_interrupt();
90 }
91
92 /*
93 * usb_tio_read_u16()
94 * Synchronously read 16 bits.
95 */
96 u8_t usb_tio_read_u16(u32_t address, u16_t *data)
97 {
98 volatile struct usb_tio_request *tio_req = &usb_node->request;
99 unsigned long flag;
100
101 /*
102 * Wait for any previous request to complete and then make this request.
103 */
104 USB_TIO_LOCK(&tio_lock, flag);
105 usb_tio_wait_hrt();
106
107 /*
108 * Fill in the request.
109 */
110 tio_req->address = address;
111 tio_req->cmd = USB_TIO_READ16_SYNC;
112 USB_TIO_REQUEST_SET_MAGIC(tio_req);
113 usb_tio_commit_request(tio_req);
114
115 /*
116 * Wait for the result to show up.
117 */
118 usb_tio_wait_hrt();
119 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
120 *data = (u16_t)tio_req->data;
121 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
122 USB_TIO_UNLOCK(&tio_lock, flag);
123 return USB_TIO_OK;
124 }
125
126 /*
127 * usb_tio_read_u8()
128 * Synchronously read 16 bits.
129 */
130 u8_t usb_tio_read_u8(u32_t address, u8_t *data)
131 {
132 volatile struct usb_tio_request *tio_req = &usb_node->request;
133 unsigned long flag;
134
135 /*
136 * Wait for any previous request to complete and then make this request.
137 */
138 USB_TIO_LOCK(&tio_lock, flag);
139 usb_tio_wait_hrt();
140
141 /*
142 * Fill in the request.
143 */
144 tio_req->address = address;
145 tio_req->cmd = USB_TIO_READ8_SYNC;
146 USB_TIO_REQUEST_SET_MAGIC(tio_req);
147
148 /*
149 * commit the request
150 */
151 usb_tio_commit_request(tio_req);
152
153 /*
154 * Wait for the result to show up.
155 */
156 usb_tio_wait_hrt();
157 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
158 *data = (u8_t)tio_req->data;
159 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
160 USB_TIO_UNLOCK(&tio_lock, flag);
161 return USB_TIO_OK;
162 }
163
164 /*
165 * usb_tio_write_u16()
166 * Asynchronously write 16 bits.
167 */
168 u8_t usb_tio_write_u16(u32_t address, u16_t data)
169 {
170 volatile struct usb_tio_request *tio_req = &usb_node->request;
171 unsigned long flag;
172
173 /*
174 * Wait for any previous write or pending read to complete.
175 */
176 USB_TIO_LOCK(&tio_lock, flag);
177 usb_tio_wait_hrt();
178
179 tio_req->address = address;
180 tio_req->data = data;
181 tio_req->cmd = USB_TIO_WRITE16_ASYNC;
182 USB_TIO_REQUEST_SET_MAGIC(tio_req);
183
184 /*
185 * commit the request
186 */
187 usb_tio_commit_request(tio_req);
188 USB_TIO_UNLOCK(&tio_lock, flag);
189 return USB_TIO_OK;
190 }
191
192 /*
193 * usb_tio_write_u8()
194 * Asynchronously write 8 bits.
195 */
196 u8_t usb_tio_write_u8(u32_t address, u8_t data)
197 {
198 volatile struct usb_tio_request *tio_req = &usb_node->request;
199 unsigned long flag;
200
201 /*
202 * Wait for any previous write or pending read to complete.
203 */
204 USB_TIO_LOCK(&tio_lock, flag);
205 usb_tio_wait_hrt();
206
207 tio_req->address = address;
208 tio_req->data = data;
209 tio_req->cmd = USB_TIO_WRITE8_ASYNC;
210 USB_TIO_REQUEST_SET_MAGIC(tio_req);
211
212 /*
213 * commit the request
214 */
215 usb_tio_commit_request(tio_req);
216 USB_TIO_UNLOCK(&tio_lock, flag);
217 return USB_TIO_OK;
218 }
219
220 /*
221 * usb_tio_read_fifo()
222 * Synchronously read FIFO.
223 */
224 u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes)
225 {
226 volatile struct usb_tio_request *tio_req = &usb_node->request;
227 unsigned long flag;
228
229 /*
230 * Wait for any previous request to complete and then make this request.
231 */
232 USB_TIO_LOCK(&tio_lock, flag);
233 usb_tio_wait_hrt();
234
235 /*
236 * Fill in the request.
237 */
238 tio_req->address = address;
239 tio_req->cmd = USB_TIO_READ_FIFO_SYNC;
240 tio_req->buffer = buffer;
241 tio_req->transfer_length = bytes;
242 USB_TIO_REQUEST_SET_MAGIC(tio_req);
243
244 /*
245 * commit the request
246 */
247 usb_tio_commit_request(tio_req);
248
249 /*
250 * Wait for the result to show up.
251 */
252 usb_tio_wait_hrt();
253 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
254 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
255 USB_TIO_UNLOCK(&tio_lock, flag);
256 return USB_TIO_OK;
257 }
258
259 /*
260 * usb_tio_write_fifo()
261 * Synchronously write 32 bits.
262 */
263 u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes)
264 {
265 volatile struct usb_tio_request *tio_req = &usb_node->request;
266 unsigned long flag;
267
268 USB_TIO_LOCK(&tio_lock, flag);
269 usb_tio_wait_hrt();
270
271 tio_req->address = address;
272 tio_req->buffer = buffer;
273 tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
274 tio_req->transfer_length = bytes;
275 USB_TIO_REQUEST_SET_MAGIC(tio_req);
276 /*
277 * commit the request
278 */
279 usb_tio_commit_request(tio_req);
280
281 /*
282 * Wait for the result to show up.
283 */
284 usb_tio_wait_hrt();
285 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
286 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
287 USB_TIO_UNLOCK(&tio_lock, flag);
288 return USB_TIO_OK;
289 }
290
291 /*
292 * usb_tio_write_fifo_async()
293 * Asynchronously write 32 bits.
294 */
295 u8_t usb_tio_write_fifo_async(u32_t address, u32_t buffer, u32_t bytes)
296 {
297 volatile struct usb_tio_request *tio_req = &usb_node->request;
298 unsigned long flag;
299
300 USB_TIO_LOCK(&tio_lock, flag);
301 usb_tio_wait_hrt();
302
303 tio_req->address = address;
304
305 /*
306 * Is it necessary to make a local copy of the buffer? Any chance the URB is aborted before TIO finished the FIFO write?
307 */
308 tio_req->buffer = buffer;
309 tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
310 tio_req->transfer_length = bytes;
311 USB_TIO_REQUEST_SET_MAGIC(tio_req);
312 /*
313 * commit the request
314 */
315 usb_tio_commit_request(tio_req);
316 USB_TIO_UNLOCK(&tio_lock, flag);
317 return USB_TIO_OK;
318 }
319
320 /*
321 * usb_tio_read_int_status()
322 * read and clear the interrupt status registers
323 */
324 void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
325 {
326
327 /*
328 * clear the interrupt must be syncronized with the TIO thread to prevent the racing condiiton
329 * that TIO thread try to set it at same time
330 */
331 asm volatile (
332 "1: bset (%0), (%0), #0 \n\t" \
333 " jmpne.f 1b \n\t" \
334 :
335 : "a" (&usb_node->usb_vp_control)
336 : "memory", "cc"
337 );
338
339 *int_usb = usb_node->usb_vp_hw_int_usb;
340 *int_tx = cpu_to_le16(usb_node->usb_vp_hw_int_tx);
341 *int_rx = cpu_to_le16(usb_node->usb_vp_hw_int_rx);
342
343 //printk(KERN_INFO "int read %x, %x, %x\n", *int_usb, *int_tx, *int_rx);
344
345 /*
346 * The interrupt status register is read-clean, so clear it now
347 */
348 usb_node->usb_vp_hw_int_usb = 0;
349 usb_node->usb_vp_hw_int_tx = 0;
350 usb_node->usb_vp_hw_int_rx = 0;
351
352 /*
353 * release the lock bit
354 */
355 usb_node->usb_vp_control &= 0xfffe;
356 }