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