[ubicom32]: move new files out from platform support patch
[openwrt.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 }