Root/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
35static 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
44spinlock_t usb_tio_lock;
45
46/*
47 * usb_tio_set_hrt_interrupt()
48 */
49static inline void usb_tio_set_hrt_interrupt(void)
50{
51    ubicom32_set_interrupt(usb_node->dn.sendirq);
52}
53
54static inline void usb_tio_wait_hrt(void)
55{
56    while (unlikely(usb_node->pdesc));
57}
58
59#if defined(USB_TIO_DEBUG)
60static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req)
61{
62    BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2);
63}
64
65static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req)
66{
67    req->magic = 0;
68}
69#endif
70
71static 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 */
79static 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 */
96u8_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 */
130u8_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 */
168u8_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 */
196u8_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 */
224u8_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 */
263u8_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 */
295u8_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 */
324void 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}
357

Archive Download this file



interactive