Commit | Line | Data |
---|---|---|
236dd4d1 AV |
1 | /* |
2 | * Freescale QUICC Engine USB Host Controller Driver | |
3 | * | |
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | |
5 | * Shlomi Gridish <gridish@freescale.com> | |
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | |
7 | * Copyright (c) Logic Product Development, Inc. 2007 | |
8 | * Peter Barada <peterb@logicpd.com> | |
9 | * Copyright (c) MontaVista Software, Inc. 2008. | |
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. | |
16 | */ | |
17 | ||
18 | #include <linux/kernel.h> | |
19 | #include <linux/types.h> | |
20 | #include <linux/errno.h> | |
5a0e3ad6 | 21 | #include <linux/slab.h> |
236dd4d1 AV |
22 | #include <linux/list.h> |
23 | #include <linux/io.h> | |
24 | #include <linux/usb.h> | |
27729aad | 25 | #include <linux/usb/hcd.h> |
236dd4d1 AV |
26 | #include "fhci.h" |
27 | ||
28 | #define DUMMY_BD_BUFFER 0xdeadbeef | |
29 | #define DUMMY2_BD_BUFFER 0xbaadf00d | |
30 | ||
31 | /* Transaction Descriptors bits */ | |
32 | #define TD_R 0x8000 /* ready bit */ | |
33 | #define TD_W 0x2000 /* wrap bit */ | |
34 | #define TD_I 0x1000 /* interrupt on completion */ | |
35 | #define TD_L 0x0800 /* last */ | |
36 | #define TD_TC 0x0400 /* transmit CRC */ | |
37 | #define TD_CNF 0x0200 /* CNF - Must be always 1 */ | |
38 | #define TD_LSP 0x0100 /* Low-speed transaction */ | |
39 | #define TD_PID 0x00c0 /* packet id */ | |
40 | #define TD_RXER 0x0020 /* Rx error or not */ | |
41 | ||
42 | #define TD_NAK 0x0010 /* No ack. */ | |
25985edc | 43 | #define TD_STAL 0x0008 /* Stall received */ |
236dd4d1 AV |
44 | #define TD_TO 0x0004 /* time out */ |
45 | #define TD_UN 0x0002 /* underrun */ | |
46 | #define TD_NO 0x0010 /* Rx Non Octet Aligned Packet */ | |
47 | #define TD_AB 0x0008 /* Frame Aborted */ | |
48 | #define TD_CR 0x0004 /* CRC Error */ | |
49 | #define TD_OV 0x0002 /* Overrun */ | |
50 | #define TD_BOV 0x0001 /* Buffer Overrun */ | |
51 | ||
52 | #define TD_ERRORS (TD_NAK | TD_STAL | TD_TO | TD_UN | \ | |
53 | TD_NO | TD_AB | TD_CR | TD_OV | TD_BOV) | |
54 | ||
55 | #define TD_PID_DATA0 0x0080 /* Data 0 toggle */ | |
56 | #define TD_PID_DATA1 0x00c0 /* Data 1 toggle */ | |
57 | #define TD_PID_TOGGLE 0x00c0 /* Data 0/1 toggle mask */ | |
58 | ||
59 | #define TD_TOK_SETUP 0x0000 | |
60 | #define TD_TOK_OUT 0x4000 | |
61 | #define TD_TOK_IN 0x8000 | |
62 | #define TD_ISO 0x1000 | |
63 | #define TD_ENDP 0x0780 | |
64 | #define TD_ADDR 0x007f | |
65 | ||
66 | #define TD_ENDP_SHIFT 7 | |
67 | ||
68 | struct usb_td { | |
69 | __be16 status; | |
70 | __be16 length; | |
71 | __be32 buf_ptr; | |
72 | __be16 extra; | |
73 | __be16 reserved; | |
74 | }; | |
75 | ||
76 | static struct usb_td __iomem *next_bd(struct usb_td __iomem *base, | |
77 | struct usb_td __iomem *td, | |
78 | u16 status) | |
79 | { | |
80 | if (status & TD_W) | |
81 | return base; | |
82 | else | |
83 | return ++td; | |
84 | } | |
85 | ||
86 | void fhci_push_dummy_bd(struct endpoint *ep) | |
87 | { | |
88 | if (ep->already_pushed_dummy_bd == false) { | |
89 | u16 td_status = in_be16(&ep->empty_td->status); | |
90 | ||
91 | out_be32(&ep->empty_td->buf_ptr, DUMMY_BD_BUFFER); | |
92 | /* get the next TD in the ring */ | |
93 | ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status); | |
94 | ep->already_pushed_dummy_bd = true; | |
95 | } | |
96 | } | |
97 | ||
98 | /* destroy an USB endpoint */ | |
99 | void fhci_ep0_free(struct fhci_usb *usb) | |
100 | { | |
101 | struct endpoint *ep; | |
102 | int size; | |
103 | ||
104 | ep = usb->ep0; | |
105 | if (ep) { | |
106 | if (ep->td_base) | |
107 | cpm_muram_free(cpm_muram_offset(ep->td_base)); | |
108 | ||
4c743d0a | 109 | if (kfifo_initialized(&ep->conf_frame_Q)) { |
45465487 | 110 | size = cq_howmany(&ep->conf_frame_Q); |
236dd4d1 | 111 | for (; size; size--) { |
45465487 | 112 | struct packet *pkt = cq_get(&ep->conf_frame_Q); |
236dd4d1 AV |
113 | |
114 | kfree(pkt); | |
115 | } | |
45465487 | 116 | cq_delete(&ep->conf_frame_Q); |
236dd4d1 AV |
117 | } |
118 | ||
4c743d0a | 119 | if (kfifo_initialized(&ep->empty_frame_Q)) { |
45465487 | 120 | size = cq_howmany(&ep->empty_frame_Q); |
236dd4d1 | 121 | for (; size; size--) { |
45465487 | 122 | struct packet *pkt = cq_get(&ep->empty_frame_Q); |
236dd4d1 AV |
123 | |
124 | kfree(pkt); | |
125 | } | |
45465487 | 126 | cq_delete(&ep->empty_frame_Q); |
236dd4d1 AV |
127 | } |
128 | ||
4c743d0a | 129 | if (kfifo_initialized(&ep->dummy_packets_Q)) { |
45465487 | 130 | size = cq_howmany(&ep->dummy_packets_Q); |
236dd4d1 | 131 | for (; size; size--) { |
45465487 | 132 | u8 *buff = cq_get(&ep->dummy_packets_Q); |
236dd4d1 AV |
133 | |
134 | kfree(buff); | |
135 | } | |
45465487 | 136 | cq_delete(&ep->dummy_packets_Q); |
236dd4d1 AV |
137 | } |
138 | ||
139 | kfree(ep); | |
140 | usb->ep0 = NULL; | |
141 | } | |
142 | } | |
143 | ||
144 | /* | |
145 | * create the endpoint structure | |
146 | * | |
147 | * arguments: | |
148 | * usb A pointer to the data structure of the USB | |
149 | * data_mem The data memory partition(BUS) | |
150 | * ring_len TD ring length | |
151 | */ | |
152 | u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, | |
153 | u32 ring_len) | |
154 | { | |
155 | struct endpoint *ep; | |
156 | struct usb_td __iomem *td; | |
157 | unsigned long ep_offset; | |
158 | char *err_for = "enpoint PRAM"; | |
159 | int ep_mem_size; | |
160 | u32 i; | |
161 | ||
162 | /* we need at least 3 TDs in the ring */ | |
163 | if (!(ring_len > 2)) { | |
164 | fhci_err(usb->fhci, "illegal TD ring length parameters\n"); | |
165 | return -EINVAL; | |
166 | } | |
167 | ||
168 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | |
169 | if (!ep) | |
170 | return -ENOMEM; | |
171 | ||
172 | ep_mem_size = ring_len * sizeof(*td) + sizeof(struct fhci_ep_pram); | |
173 | ep_offset = cpm_muram_alloc(ep_mem_size, 32); | |
174 | if (IS_ERR_VALUE(ep_offset)) | |
175 | goto err; | |
176 | ep->td_base = cpm_muram_addr(ep_offset); | |
177 | ||
178 | /* zero all queue pointers */ | |
45465487 SS |
179 | if (cq_new(&ep->conf_frame_Q, ring_len + 2) || |
180 | cq_new(&ep->empty_frame_Q, ring_len + 2) || | |
181 | cq_new(&ep->dummy_packets_Q, ring_len + 2)) { | |
236dd4d1 AV |
182 | err_for = "frame_queues"; |
183 | goto err; | |
184 | } | |
185 | ||
186 | for (i = 0; i < (ring_len + 1); i++) { | |
187 | struct packet *pkt; | |
188 | u8 *buff; | |
189 | ||
190 | pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); | |
191 | if (!pkt) { | |
192 | err_for = "frame"; | |
193 | goto err; | |
194 | } | |
195 | ||
196 | buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL); | |
197 | if (!buff) { | |
198 | kfree(pkt); | |
199 | err_for = "buffer"; | |
200 | goto err; | |
201 | } | |
45465487 SS |
202 | cq_put(&ep->empty_frame_Q, pkt); |
203 | cq_put(&ep->dummy_packets_Q, buff); | |
236dd4d1 AV |
204 | } |
205 | ||
206 | /* we put the endpoint parameter RAM right behind the TD ring */ | |
207 | ep->ep_pram_ptr = (void __iomem *)ep->td_base + sizeof(*td) * ring_len; | |
208 | ||
209 | ep->conf_td = ep->td_base; | |
210 | ep->empty_td = ep->td_base; | |
211 | ||
212 | ep->already_pushed_dummy_bd = false; | |
213 | ||
214 | /* initialize tds */ | |
215 | td = ep->td_base; | |
216 | for (i = 0; i < ring_len; i++) { | |
217 | out_be32(&td->buf_ptr, 0); | |
218 | out_be16(&td->status, 0); | |
219 | out_be16(&td->length, 0); | |
220 | out_be16(&td->extra, 0); | |
221 | td++; | |
222 | } | |
223 | td--; | |
224 | out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ | |
225 | out_be16(&td->length, 0); | |
226 | ||
227 | /* endpoint structure has been created */ | |
228 | usb->ep0 = ep; | |
229 | ||
230 | return 0; | |
231 | err: | |
232 | fhci_ep0_free(usb); | |
233 | kfree(ep); | |
234 | fhci_err(usb->fhci, "no memory for the %s\n", err_for); | |
235 | return -ENOMEM; | |
236 | } | |
237 | ||
238 | /* | |
239 | * initialize the endpoint register according to the given parameters | |
240 | * | |
241 | * artuments: | |
242 | * usb A pointer to the data strucutre of the USB | |
243 | * ep A pointer to the endpoint structre | |
244 | * data_mem The data memory partition(BUS) | |
245 | */ | |
246 | void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep, | |
247 | enum fhci_mem_alloc data_mem) | |
248 | { | |
249 | u8 rt; | |
250 | ||
251 | /* set the endpoint registers according to the endpoint */ | |
252 | out_be16(&usb->fhci->regs->usb_ep[0], | |
253 | USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE); | |
254 | out_be16(&usb->fhci->pram->ep_ptr[0], | |
255 | cpm_muram_offset(ep->ep_pram_ptr)); | |
256 | ||
257 | rt = (BUS_MODE_BO_BE | BUS_MODE_GBL); | |
258 | #ifdef MULTI_DATA_BUS | |
259 | if (data_mem == MEM_SECONDARY) | |
260 | rt |= BUS_MODE_DTB; | |
261 | #endif | |
262 | out_8(&ep->ep_pram_ptr->rx_func_code, rt); | |
263 | out_8(&ep->ep_pram_ptr->tx_func_code, rt); | |
264 | out_be16(&ep->ep_pram_ptr->rx_buff_len, 1028); | |
265 | out_be16(&ep->ep_pram_ptr->rx_base, 0); | |
266 | out_be16(&ep->ep_pram_ptr->tx_base, cpm_muram_offset(ep->td_base)); | |
267 | out_be16(&ep->ep_pram_ptr->rx_bd_ptr, 0); | |
268 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, cpm_muram_offset(ep->td_base)); | |
269 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | |
270 | } | |
271 | ||
272 | /* | |
273 | * Collect the submitted frames and inform the application about them | |
48e34d0f JM |
274 | * It is also preparing the TDs for new frames. If the Tx interrupts |
275 | * are disabled, the application should call that routine to get | |
236dd4d1 | 276 | * confirmation about the submitted frames. Otherwise, the routine is |
25985edc | 277 | * called from the interrupt service routine during the Tx interrupt. |
236dd4d1 AV |
278 | * In that case the application is informed by calling the application |
279 | * specific 'fhci_transaction_confirm' routine | |
280 | */ | |
281 | static void fhci_td_transaction_confirm(struct fhci_usb *usb) | |
282 | { | |
283 | struct endpoint *ep = usb->ep0; | |
284 | struct packet *pkt; | |
285 | struct usb_td __iomem *td; | |
286 | u16 extra_data; | |
287 | u16 td_status; | |
288 | u16 td_length; | |
289 | u32 buf; | |
290 | ||
291 | /* | |
292 | * collect transmitted BDs from the chip. The routine clears all BDs | |
293 | * with R bit = 0 and the pointer to data buffer is not NULL, that is | |
294 | * BDs which point to the transmitted data buffer | |
295 | */ | |
296 | while (1) { | |
297 | td = ep->conf_td; | |
298 | td_status = in_be16(&td->status); | |
299 | td_length = in_be16(&td->length); | |
300 | buf = in_be32(&td->buf_ptr); | |
301 | extra_data = in_be16(&td->extra); | |
302 | ||
303 | /* check if the TD is empty */ | |
304 | if (!(!(td_status & TD_R) && ((td_status & ~TD_W) || buf))) | |
305 | break; | |
306 | /* check if it is a dummy buffer */ | |
307 | else if ((buf == DUMMY_BD_BUFFER) && !(td_status & ~TD_W)) | |
308 | break; | |
309 | ||
310 | /* mark TD as empty */ | |
311 | clrbits16(&td->status, ~TD_W); | |
312 | out_be16(&td->length, 0); | |
313 | out_be32(&td->buf_ptr, 0); | |
314 | out_be16(&td->extra, 0); | |
315 | /* advance the TD pointer */ | |
316 | ep->conf_td = next_bd(ep->td_base, ep->conf_td, td_status); | |
317 | ||
318 | /* check if it is a dummy buffer(type2) */ | |
319 | if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W)) | |
320 | continue; | |
321 | ||
45465487 | 322 | pkt = cq_get(&ep->conf_frame_Q); |
236dd4d1 AV |
323 | if (!pkt) |
324 | fhci_err(usb->fhci, "no frame to confirm\n"); | |
325 | ||
326 | if (td_status & TD_ERRORS) { | |
327 | if (td_status & TD_RXER) { | |
328 | if (td_status & TD_CR) | |
329 | pkt->status = USB_TD_RX_ER_CRC; | |
330 | else if (td_status & TD_AB) | |
331 | pkt->status = USB_TD_RX_ER_BITSTUFF; | |
332 | else if (td_status & TD_OV) | |
333 | pkt->status = USB_TD_RX_ER_OVERUN; | |
334 | else if (td_status & TD_BOV) | |
335 | pkt->status = USB_TD_RX_DATA_OVERUN; | |
336 | else if (td_status & TD_NO) | |
337 | pkt->status = USB_TD_RX_ER_NONOCT; | |
338 | else | |
339 | fhci_err(usb->fhci, "illegal error " | |
25985edc | 340 | "occurred\n"); |
236dd4d1 AV |
341 | } else if (td_status & TD_NAK) |
342 | pkt->status = USB_TD_TX_ER_NAK; | |
343 | else if (td_status & TD_TO) | |
344 | pkt->status = USB_TD_TX_ER_TIMEOUT; | |
345 | else if (td_status & TD_UN) | |
346 | pkt->status = USB_TD_TX_ER_UNDERUN; | |
347 | else if (td_status & TD_STAL) | |
348 | pkt->status = USB_TD_TX_ER_STALL; | |
349 | else | |
25985edc | 350 | fhci_err(usb->fhci, "illegal error occurred\n"); |
236dd4d1 AV |
351 | } else if ((extra_data & TD_TOK_IN) && |
352 | pkt->len > td_length - CRC_SIZE) { | |
353 | pkt->status = USB_TD_RX_DATA_UNDERUN; | |
354 | } | |
355 | ||
356 | if (extra_data & TD_TOK_IN) | |
357 | pkt->len = td_length - CRC_SIZE; | |
358 | else if (pkt->info & PKT_ZLP) | |
359 | pkt->len = 0; | |
360 | else | |
361 | pkt->len = td_length; | |
362 | ||
363 | fhci_transaction_confirm(usb, pkt); | |
364 | } | |
365 | } | |
366 | ||
367 | /* | |
368 | * Submitting a data frame to a specified endpoint of a USB device | |
369 | * The frame is put in the driver's transmit queue for this endpoint | |
370 | * | |
371 | * Arguments: | |
372 | * usb A pointer to the USB structure | |
373 | * pkt A pointer to the user frame structure | |
374 | * trans_type Transaction tyep - IN,OUT or SETUP | |
375 | * dest_addr Device address - 0~127 | |
376 | * dest_ep Endpoint number of the device - 0~16 | |
377 | * trans_mode Pipe type - ISO,Interrupt,bulk or control | |
378 | * dest_speed USB speed - Low speed or FULL speed | |
379 | * data_toggle Data sequence toggle - 0 or 1 | |
380 | */ | |
381 | u32 fhci_host_transaction(struct fhci_usb *usb, | |
382 | struct packet *pkt, | |
383 | enum fhci_ta_type trans_type, | |
384 | u8 dest_addr, | |
385 | u8 dest_ep, | |
386 | enum fhci_tf_mode trans_mode, | |
387 | enum fhci_speed dest_speed, u8 data_toggle) | |
388 | { | |
389 | struct endpoint *ep = usb->ep0; | |
390 | struct usb_td __iomem *td; | |
391 | u16 extra_data; | |
392 | u16 td_status; | |
393 | ||
394 | fhci_usb_disable_interrupt(usb); | |
395 | /* start from the next BD that should be filled */ | |
396 | td = ep->empty_td; | |
397 | td_status = in_be16(&td->status); | |
398 | ||
399 | if (td_status & TD_R && in_be16(&td->length)) { | |
400 | /* if the TD is not free */ | |
401 | fhci_usb_enable_interrupt(usb); | |
402 | return -1; | |
403 | } | |
404 | ||
405 | /* get the next TD in the ring */ | |
406 | ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status); | |
407 | fhci_usb_enable_interrupt(usb); | |
408 | pkt->priv_data = td; | |
409 | out_be32(&td->buf_ptr, virt_to_phys(pkt->data)); | |
410 | /* sets up transaction parameters - addr,endp,dir,and type */ | |
411 | extra_data = (dest_ep << TD_ENDP_SHIFT) | dest_addr; | |
412 | switch (trans_type) { | |
413 | case FHCI_TA_IN: | |
414 | extra_data |= TD_TOK_IN; | |
415 | break; | |
416 | case FHCI_TA_OUT: | |
417 | extra_data |= TD_TOK_OUT; | |
418 | break; | |
419 | case FHCI_TA_SETUP: | |
420 | extra_data |= TD_TOK_SETUP; | |
421 | break; | |
422 | } | |
423 | if (trans_mode == FHCI_TF_ISO) | |
424 | extra_data |= TD_ISO; | |
425 | out_be16(&td->extra, extra_data); | |
426 | ||
427 | /* sets up the buffer descriptor */ | |
428 | td_status = ((td_status & TD_W) | TD_R | TD_L | TD_I | TD_CNF); | |
429 | if (!(pkt->info & PKT_NO_CRC)) | |
430 | td_status |= TD_TC; | |
431 | ||
432 | switch (trans_type) { | |
433 | case FHCI_TA_IN: | |
434 | if (data_toggle) | |
435 | pkt->info |= PKT_PID_DATA1; | |
436 | else | |
437 | pkt->info |= PKT_PID_DATA0; | |
438 | break; | |
439 | default: | |
440 | if (data_toggle) { | |
441 | td_status |= TD_PID_DATA1; | |
442 | pkt->info |= PKT_PID_DATA1; | |
443 | } else { | |
444 | td_status |= TD_PID_DATA0; | |
445 | pkt->info |= PKT_PID_DATA0; | |
446 | } | |
447 | break; | |
448 | } | |
449 | ||
450 | if ((dest_speed == FHCI_LOW_SPEED) && | |
451 | (usb->port_status == FHCI_PORT_FULL)) | |
452 | td_status |= TD_LSP; | |
453 | ||
454 | out_be16(&td->status, td_status); | |
455 | ||
456 | /* set up buffer length */ | |
457 | if (trans_type == FHCI_TA_IN) | |
458 | out_be16(&td->length, pkt->len + CRC_SIZE); | |
459 | else | |
460 | out_be16(&td->length, pkt->len); | |
461 | ||
462 | /* put the frame to the confirmation queue */ | |
45465487 | 463 | cq_put(&ep->conf_frame_Q, pkt); |
236dd4d1 | 464 | |
45465487 | 465 | if (cq_howmany(&ep->conf_frame_Q) == 1) |
236dd4d1 AV |
466 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); |
467 | ||
468 | return 0; | |
469 | } | |
470 | ||
471 | /* Reset the Tx BD ring */ | |
472 | void fhci_flush_bds(struct fhci_usb *usb) | |
473 | { | |
474 | u16 extra_data; | |
475 | u16 td_status; | |
476 | u32 buf; | |
477 | struct usb_td __iomem *td; | |
478 | struct endpoint *ep = usb->ep0; | |
479 | ||
480 | td = ep->td_base; | |
481 | while (1) { | |
482 | td_status = in_be16(&td->status); | |
483 | buf = in_be32(&td->buf_ptr); | |
484 | extra_data = in_be16(&td->extra); | |
485 | ||
486 | /* if the TD is not empty - we'll confirm it as Timeout */ | |
487 | if (td_status & TD_R) | |
488 | out_be16(&td->status, (td_status & ~TD_R) | TD_TO); | |
489 | /* if this TD is dummy - let's skip this TD */ | |
490 | else if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) | |
491 | out_be32(&td->buf_ptr, DUMMY2_BD_BUFFER); | |
492 | /* if this is the last TD - break */ | |
493 | if (td_status & TD_W) | |
494 | break; | |
495 | ||
496 | td++; | |
497 | } | |
498 | ||
499 | fhci_td_transaction_confirm(usb); | |
500 | ||
501 | td = ep->td_base; | |
502 | do { | |
503 | out_be16(&td->status, 0); | |
504 | out_be16(&td->length, 0); | |
505 | out_be32(&td->buf_ptr, 0); | |
506 | out_be16(&td->extra, 0); | |
507 | td++; | |
508 | } while (!(in_be16(&td->status) & TD_W)); | |
509 | out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ | |
510 | out_be16(&td->length, 0); | |
511 | out_be32(&td->buf_ptr, 0); | |
512 | out_be16(&td->extra, 0); | |
513 | ||
514 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, | |
515 | in_be16(&ep->ep_pram_ptr->tx_base)); | |
516 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | |
517 | out_be16(&ep->ep_pram_ptr->tx_cnt, 0); | |
518 | ep->empty_td = ep->td_base; | |
519 | ep->conf_td = ep->td_base; | |
520 | } | |
521 | ||
522 | /* | |
523 | * Flush all transmitted packets from TDs in the actual frame. | |
524 | * This routine is called when something wrong with the controller and | |
525 | * we want to get rid of the actual frame and start again next frame | |
526 | */ | |
527 | void fhci_flush_actual_frame(struct fhci_usb *usb) | |
528 | { | |
529 | u8 mode; | |
530 | u16 tb_ptr; | |
531 | u16 extra_data; | |
532 | u16 td_status; | |
533 | u32 buf_ptr; | |
534 | struct usb_td __iomem *td; | |
535 | struct endpoint *ep = usb->ep0; | |
536 | ||
537 | /* disable the USB controller */ | |
538 | mode = in_8(&usb->fhci->regs->usb_mod); | |
539 | out_8(&usb->fhci->regs->usb_mod, mode & ~USB_MODE_EN); | |
540 | ||
541 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); | |
542 | td = cpm_muram_addr(tb_ptr); | |
543 | td_status = in_be16(&td->status); | |
544 | buf_ptr = in_be32(&td->buf_ptr); | |
545 | extra_data = in_be16(&td->extra); | |
546 | do { | |
547 | if (td_status & TD_R) { | |
548 | out_be16(&td->status, (td_status & ~TD_R) | TD_TO); | |
549 | } else { | |
550 | out_be32(&td->buf_ptr, 0); | |
551 | ep->already_pushed_dummy_bd = false; | |
552 | break; | |
553 | } | |
554 | ||
555 | /* advance the TD pointer */ | |
556 | td = next_bd(ep->td_base, td, td_status); | |
557 | td_status = in_be16(&td->status); | |
558 | buf_ptr = in_be32(&td->buf_ptr); | |
559 | extra_data = in_be16(&td->extra); | |
560 | } while ((td_status & TD_R) || buf_ptr); | |
561 | ||
562 | fhci_td_transaction_confirm(usb); | |
563 | ||
564 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, | |
565 | in_be16(&ep->ep_pram_ptr->tx_base)); | |
566 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | |
567 | out_be16(&ep->ep_pram_ptr->tx_cnt, 0); | |
568 | ep->empty_td = ep->td_base; | |
569 | ep->conf_td = ep->td_base; | |
570 | ||
571 | usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; | |
572 | ||
573 | /* reset the event register */ | |
574 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | |
575 | /* enable the USB controller */ | |
576 | out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | |
577 | } | |
578 | ||
579 | /* handles Tx confirm and Tx error interrupt */ | |
580 | void fhci_tx_conf_interrupt(struct fhci_usb *usb) | |
581 | { | |
582 | fhci_td_transaction_confirm(usb); | |
583 | ||
584 | /* | |
585 | * Schedule another transaction to this frame only if we have | |
586 | * already confirmed all transaction in the frame. | |
587 | */ | |
588 | if (((fhci_get_sof_timer_count(usb) < usb->max_frame_usage) || | |
589 | (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION)) && | |
590 | (list_empty(&usb->actual_frame->tds_list))) | |
591 | fhci_schedule_transactions(usb); | |
592 | } | |
593 | ||
594 | void fhci_host_transmit_actual_frame(struct fhci_usb *usb) | |
595 | { | |
596 | u16 tb_ptr; | |
597 | u16 td_status; | |
598 | struct usb_td __iomem *td; | |
599 | struct endpoint *ep = usb->ep0; | |
600 | ||
601 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); | |
602 | td = cpm_muram_addr(tb_ptr); | |
603 | ||
604 | if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) { | |
605 | struct usb_td __iomem *old_td = td; | |
606 | ||
607 | ep->already_pushed_dummy_bd = false; | |
608 | td_status = in_be16(&td->status); | |
609 | /* gets the next TD in the ring */ | |
610 | td = next_bd(ep->td_base, td, td_status); | |
611 | tb_ptr = cpm_muram_offset(td); | |
612 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, tb_ptr); | |
613 | ||
614 | /* start transmit only if we have something in the TDs */ | |
615 | if (in_be16(&td->status) & TD_R) | |
616 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | |
617 | ||
618 | if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) { | |
619 | out_be32(&old_td->buf_ptr, 0); | |
620 | ep->conf_td = next_bd(ep->td_base, ep->conf_td, | |
621 | td_status); | |
622 | } else { | |
623 | out_be32(&old_td->buf_ptr, DUMMY2_BD_BUFFER); | |
624 | } | |
625 | } | |
626 | } |