]>
Commit | Line | Data |
---|---|---|
a1428969 TA |
1 | /* |
2 | * Mentor USB OTG Core host controller driver. | |
3 | * | |
4 | * Copyright (c) 2008 Texas Instruments | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation; either version 2 of | |
9 | * the License, or (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
19 | * MA 02111-1307 USA | |
20 | * | |
21 | * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include "musb_hcd.h" | |
26 | ||
27 | /* MSC control transfers */ | |
28 | #define USB_MSC_BBB_RESET 0xFF | |
29 | #define USB_MSC_BBB_GET_MAX_LUN 0xFE | |
30 | ||
31 | /* Endpoint configuration information */ | |
32 | static struct musb_epinfo epinfo[3] = { | |
33 | {MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */ | |
34 | {MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In - 512 Bytes */ | |
35 | {MUSB_INTR_EP, 0, 64} /* EP2 - Interrupt IN - 64 Bytes */ | |
36 | }; | |
37 | ||
321790f6 BW |
38 | /* --- Virtual Root Hub ---------------------------------------------------- */ |
39 | #ifdef MUSB_NO_MULTIPOINT | |
40 | static int rh_devnum; | |
41 | static u32 port_status; | |
42 | ||
43 | /* Device descriptor */ | |
44 | static u8 root_hub_dev_des[] = { | |
45 | 0x12, /* __u8 bLength; */ | |
46 | 0x01, /* __u8 bDescriptorType; Device */ | |
47 | 0x00, /* __u16 bcdUSB; v1.1 */ | |
48 | 0x02, | |
49 | 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ | |
50 | 0x00, /* __u8 bDeviceSubClass; */ | |
51 | 0x00, /* __u8 bDeviceProtocol; */ | |
52 | 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ | |
53 | 0x00, /* __u16 idVendor; */ | |
54 | 0x00, | |
55 | 0x00, /* __u16 idProduct; */ | |
56 | 0x00, | |
57 | 0x00, /* __u16 bcdDevice; */ | |
58 | 0x00, | |
59 | 0x00, /* __u8 iManufacturer; */ | |
60 | 0x01, /* __u8 iProduct; */ | |
61 | 0x00, /* __u8 iSerialNumber; */ | |
62 | 0x01 /* __u8 bNumConfigurations; */ | |
63 | }; | |
64 | ||
65 | /* Configuration descriptor */ | |
66 | static u8 root_hub_config_des[] = { | |
67 | 0x09, /* __u8 bLength; */ | |
68 | 0x02, /* __u8 bDescriptorType; Configuration */ | |
69 | 0x19, /* __u16 wTotalLength; */ | |
70 | 0x00, | |
71 | 0x01, /* __u8 bNumInterfaces; */ | |
72 | 0x01, /* __u8 bConfigurationValue; */ | |
73 | 0x00, /* __u8 iConfiguration; */ | |
74 | 0x40, /* __u8 bmAttributes; | |
75 | Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ | |
76 | 0x00, /* __u8 MaxPower; */ | |
77 | ||
78 | /* interface */ | |
79 | 0x09, /* __u8 if_bLength; */ | |
80 | 0x04, /* __u8 if_bDescriptorType; Interface */ | |
81 | 0x00, /* __u8 if_bInterfaceNumber; */ | |
82 | 0x00, /* __u8 if_bAlternateSetting; */ | |
83 | 0x01, /* __u8 if_bNumEndpoints; */ | |
84 | 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ | |
85 | 0x00, /* __u8 if_bInterfaceSubClass; */ | |
86 | 0x00, /* __u8 if_bInterfaceProtocol; */ | |
87 | 0x00, /* __u8 if_iInterface; */ | |
88 | ||
89 | /* endpoint */ | |
90 | 0x07, /* __u8 ep_bLength; */ | |
91 | 0x05, /* __u8 ep_bDescriptorType; Endpoint */ | |
92 | 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ | |
93 | 0x03, /* __u8 ep_bmAttributes; Interrupt */ | |
94 | 0x00, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ | |
95 | 0x02, | |
96 | 0xff /* __u8 ep_bInterval; 255 ms */ | |
97 | }; | |
98 | ||
99 | static unsigned char root_hub_str_index0[] = { | |
100 | 0x04, /* __u8 bLength; */ | |
101 | 0x03, /* __u8 bDescriptorType; String-descriptor */ | |
102 | 0x09, /* __u8 lang ID */ | |
103 | 0x04, /* __u8 lang ID */ | |
104 | }; | |
105 | ||
106 | static unsigned char root_hub_str_index1[] = { | |
107 | 0x1c, /* __u8 bLength; */ | |
108 | 0x03, /* __u8 bDescriptorType; String-descriptor */ | |
109 | 'M', /* __u8 Unicode */ | |
110 | 0, /* __u8 Unicode */ | |
111 | 'U', /* __u8 Unicode */ | |
112 | 0, /* __u8 Unicode */ | |
113 | 'S', /* __u8 Unicode */ | |
114 | 0, /* __u8 Unicode */ | |
115 | 'B', /* __u8 Unicode */ | |
116 | 0, /* __u8 Unicode */ | |
117 | ' ', /* __u8 Unicode */ | |
118 | 0, /* __u8 Unicode */ | |
119 | 'R', /* __u8 Unicode */ | |
120 | 0, /* __u8 Unicode */ | |
121 | 'o', /* __u8 Unicode */ | |
122 | 0, /* __u8 Unicode */ | |
123 | 'o', /* __u8 Unicode */ | |
124 | 0, /* __u8 Unicode */ | |
125 | 't', /* __u8 Unicode */ | |
126 | 0, /* __u8 Unicode */ | |
127 | ' ', /* __u8 Unicode */ | |
128 | 0, /* __u8 Unicode */ | |
129 | 'H', /* __u8 Unicode */ | |
130 | 0, /* __u8 Unicode */ | |
131 | 'u', /* __u8 Unicode */ | |
132 | 0, /* __u8 Unicode */ | |
133 | 'b', /* __u8 Unicode */ | |
134 | 0, /* __u8 Unicode */ | |
135 | }; | |
136 | #endif | |
137 | ||
a1428969 TA |
138 | /* |
139 | * This function writes the data toggle value. | |
140 | */ | |
141 | static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out) | |
142 | { | |
143 | u16 toggle = usb_gettoggle(dev, ep, dir_out); | |
144 | u16 csr; | |
145 | ||
146 | if (dir_out) { | |
147 | if (!toggle) | |
148 | writew(MUSB_TXCSR_CLRDATATOG, &musbr->txcsr); | |
149 | else { | |
150 | csr = readw(&musbr->txcsr); | |
151 | csr |= MUSB_TXCSR_H_WR_DATATOGGLE; | |
152 | writew(csr, &musbr->txcsr); | |
153 | csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT); | |
154 | writew(csr, &musbr->txcsr); | |
155 | } | |
156 | } else { | |
157 | if (!toggle) | |
158 | writew(MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr); | |
159 | else { | |
160 | csr = readw(&musbr->rxcsr); | |
161 | csr |= MUSB_RXCSR_H_WR_DATATOGGLE; | |
162 | writew(csr, &musbr->rxcsr); | |
163 | csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE); | |
164 | writew(csr, &musbr->rxcsr); | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | /* | |
170 | * This function checks if RxStall has occured on the endpoint. If a RxStall | |
171 | * has occured, the RxStall is cleared and 1 is returned. If RxStall has | |
172 | * not occured, 0 is returned. | |
173 | */ | |
174 | static u8 check_stall(u8 ep, u8 dir_out) | |
175 | { | |
176 | u16 csr; | |
177 | ||
178 | /* For endpoint 0 */ | |
179 | if (!ep) { | |
180 | csr = readw(&musbr->txcsr); | |
181 | if (csr & MUSB_CSR0_H_RXSTALL) { | |
182 | csr &= ~MUSB_CSR0_H_RXSTALL; | |
183 | writew(csr, &musbr->txcsr); | |
184 | return 1; | |
185 | } | |
186 | } else { /* For non-ep0 */ | |
187 | if (dir_out) { /* is it tx ep */ | |
188 | csr = readw(&musbr->txcsr); | |
189 | if (csr & MUSB_TXCSR_H_RXSTALL) { | |
190 | csr &= ~MUSB_TXCSR_H_RXSTALL; | |
191 | writew(csr, &musbr->txcsr); | |
192 | return 1; | |
193 | } | |
194 | } else { /* is it rx ep */ | |
195 | csr = readw(&musbr->rxcsr); | |
196 | if (csr & MUSB_RXCSR_H_RXSTALL) { | |
197 | csr &= ~MUSB_RXCSR_H_RXSTALL; | |
198 | writew(csr, &musbr->rxcsr); | |
199 | return 1; | |
200 | } | |
201 | } | |
202 | } | |
203 | return 0; | |
204 | } | |
205 | ||
206 | /* | |
207 | * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout | |
208 | * error and -2 for stall. | |
209 | */ | |
210 | static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask) | |
211 | { | |
212 | u16 csr; | |
213 | int result = 1; | |
c3a012ce | 214 | int timeout = CONFIG_MUSB_TIMEOUT; |
a1428969 TA |
215 | |
216 | while (result > 0) { | |
217 | csr = readw(&musbr->txcsr); | |
218 | if (csr & MUSB_CSR0_H_ERROR) { | |
219 | csr &= ~MUSB_CSR0_H_ERROR; | |
220 | writew(csr, &musbr->txcsr); | |
221 | dev->status = USB_ST_CRC_ERR; | |
222 | result = -1; | |
223 | break; | |
224 | } | |
225 | ||
226 | switch (bit_mask) { | |
227 | case MUSB_CSR0_TXPKTRDY: | |
228 | if (!(csr & MUSB_CSR0_TXPKTRDY)) { | |
229 | if (check_stall(MUSB_CONTROL_EP, 0)) { | |
230 | dev->status = USB_ST_STALLED; | |
231 | result = -2; | |
232 | } else | |
233 | result = 0; | |
234 | } | |
235 | break; | |
236 | ||
237 | case MUSB_CSR0_RXPKTRDY: | |
238 | if (check_stall(MUSB_CONTROL_EP, 0)) { | |
239 | dev->status = USB_ST_STALLED; | |
240 | result = -2; | |
241 | } else | |
242 | if (csr & MUSB_CSR0_RXPKTRDY) | |
243 | result = 0; | |
244 | break; | |
245 | ||
246 | case MUSB_CSR0_H_REQPKT: | |
247 | if (!(csr & MUSB_CSR0_H_REQPKT)) { | |
248 | if (check_stall(MUSB_CONTROL_EP, 0)) { | |
249 | dev->status = USB_ST_STALLED; | |
250 | result = -2; | |
251 | } else | |
252 | result = 0; | |
253 | } | |
254 | break; | |
255 | } | |
c3a012ce BW |
256 | |
257 | /* Check the timeout */ | |
258 | if (--timeout) | |
259 | udelay(1); | |
260 | else { | |
261 | dev->status = USB_ST_CRC_ERR; | |
262 | result = -1; | |
263 | break; | |
264 | } | |
a1428969 | 265 | } |
c3a012ce | 266 | |
a1428969 TA |
267 | return result; |
268 | } | |
269 | ||
270 | /* | |
271 | * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error. | |
272 | */ | |
273 | static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep) | |
274 | { | |
275 | u16 csr; | |
c3a012ce | 276 | int timeout = CONFIG_MUSB_TIMEOUT; |
a1428969 TA |
277 | |
278 | do { | |
279 | if (check_stall(ep, 1)) { | |
280 | dev->status = USB_ST_STALLED; | |
281 | return 0; | |
282 | } | |
283 | ||
284 | csr = readw(&musbr->txcsr); | |
285 | if (csr & MUSB_TXCSR_H_ERROR) { | |
286 | dev->status = USB_ST_CRC_ERR; | |
287 | return 0; | |
288 | } | |
c3a012ce BW |
289 | |
290 | /* Check the timeout */ | |
291 | if (--timeout) | |
292 | udelay(1); | |
293 | else { | |
294 | dev->status = USB_ST_CRC_ERR; | |
295 | return -1; | |
296 | } | |
297 | ||
a1428969 TA |
298 | } while (csr & MUSB_TXCSR_TXPKTRDY); |
299 | return 1; | |
300 | } | |
301 | ||
302 | /* | |
303 | * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error. | |
304 | */ | |
305 | static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep) | |
306 | { | |
307 | u16 csr; | |
c3a012ce | 308 | int timeout = CONFIG_MUSB_TIMEOUT; |
a1428969 TA |
309 | |
310 | do { | |
311 | if (check_stall(ep, 0)) { | |
312 | dev->status = USB_ST_STALLED; | |
313 | return 0; | |
314 | } | |
315 | ||
316 | csr = readw(&musbr->rxcsr); | |
317 | if (csr & MUSB_RXCSR_H_ERROR) { | |
318 | dev->status = USB_ST_CRC_ERR; | |
319 | return 0; | |
320 | } | |
c3a012ce BW |
321 | |
322 | /* Check the timeout */ | |
323 | if (--timeout) | |
324 | udelay(1); | |
325 | else { | |
326 | dev->status = USB_ST_CRC_ERR; | |
327 | return -1; | |
328 | } | |
329 | ||
a1428969 TA |
330 | } while (!(csr & MUSB_RXCSR_RXPKTRDY)); |
331 | return 1; | |
332 | } | |
333 | ||
334 | /* | |
335 | * This function performs the setup phase of the control transfer | |
336 | */ | |
337 | static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup) | |
338 | { | |
339 | int result; | |
340 | u16 csr; | |
341 | ||
342 | /* write the control request to ep0 fifo */ | |
343 | write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup); | |
344 | ||
345 | /* enable transfer of setup packet */ | |
346 | csr = readw(&musbr->txcsr); | |
347 | csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT); | |
348 | writew(csr, &musbr->txcsr); | |
349 | ||
350 | /* wait until the setup packet is transmitted */ | |
351 | result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY); | |
352 | dev->act_len = 0; | |
353 | return result; | |
354 | } | |
355 | ||
356 | /* | |
357 | * This function handles the control transfer in data phase | |
358 | */ | |
359 | static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer) | |
360 | { | |
361 | u16 csr; | |
362 | u32 rxlen = 0; | |
363 | u32 nextlen = 0; | |
364 | u8 maxpktsize = (1 << dev->maxpacketsize) * 8; | |
365 | u8 *rxbuff = (u8 *)buffer; | |
366 | u8 rxedlength; | |
367 | int result; | |
368 | ||
369 | while (rxlen < len) { | |
370 | /* Determine the next read length */ | |
371 | nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen); | |
372 | ||
373 | /* Set the ReqPkt bit */ | |
374 | csr = readw(&musbr->txcsr); | |
375 | writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr); | |
376 | result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY); | |
377 | if (result < 0) | |
378 | return result; | |
379 | ||
380 | /* Actual number of bytes received by usb */ | |
381 | rxedlength = readb(&musbr->rxcount); | |
382 | ||
383 | /* Read the data from the RxFIFO */ | |
384 | read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]); | |
385 | ||
386 | /* Clear the RxPktRdy Bit */ | |
387 | csr = readw(&musbr->txcsr); | |
388 | csr &= ~MUSB_CSR0_RXPKTRDY; | |
389 | writew(csr, &musbr->txcsr); | |
390 | ||
391 | /* short packet? */ | |
392 | if (rxedlength != nextlen) { | |
393 | dev->act_len += rxedlength; | |
394 | break; | |
395 | } | |
396 | rxlen += nextlen; | |
397 | dev->act_len = rxlen; | |
398 | } | |
399 | return 0; | |
400 | } | |
401 | ||
402 | /* | |
403 | * This function handles the control transfer out data phase | |
404 | */ | |
405 | static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer) | |
406 | { | |
407 | u16 csr; | |
408 | u32 txlen = 0; | |
409 | u32 nextlen = 0; | |
410 | u8 maxpktsize = (1 << dev->maxpacketsize) * 8; | |
411 | u8 *txbuff = (u8 *)buffer; | |
412 | int result = 0; | |
413 | ||
414 | while (txlen < len) { | |
415 | /* Determine the next write length */ | |
416 | nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen); | |
417 | ||
418 | /* Load the data to send in FIFO */ | |
419 | write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]); | |
420 | ||
421 | /* Set TXPKTRDY bit */ | |
422 | csr = readw(&musbr->txcsr); | |
423 | writew(csr | MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY, | |
424 | &musbr->txcsr); | |
425 | result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY); | |
426 | if (result < 0) | |
427 | break; | |
428 | ||
429 | txlen += nextlen; | |
430 | dev->act_len = txlen; | |
431 | } | |
432 | return result; | |
433 | } | |
434 | ||
435 | /* | |
436 | * This function handles the control transfer out status phase | |
437 | */ | |
438 | static int ctrlreq_out_status_phase(struct usb_device *dev) | |
439 | { | |
440 | u16 csr; | |
441 | int result; | |
442 | ||
443 | /* Set the StatusPkt bit */ | |
444 | csr = readw(&musbr->txcsr); | |
445 | csr |= (MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY | | |
446 | MUSB_CSR0_H_STATUSPKT); | |
447 | writew(csr, &musbr->txcsr); | |
448 | ||
449 | /* Wait until TXPKTRDY bit is cleared */ | |
450 | result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY); | |
451 | return result; | |
452 | } | |
453 | ||
454 | /* | |
455 | * This function handles the control transfer in status phase | |
456 | */ | |
457 | static int ctrlreq_in_status_phase(struct usb_device *dev) | |
458 | { | |
459 | u16 csr; | |
460 | int result; | |
461 | ||
462 | /* Set the StatusPkt bit and ReqPkt bit */ | |
463 | csr = MUSB_CSR0_H_DIS_PING | MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT; | |
464 | writew(csr, &musbr->txcsr); | |
465 | result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT); | |
466 | ||
467 | /* clear StatusPkt bit and RxPktRdy bit */ | |
468 | csr = readw(&musbr->txcsr); | |
469 | csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT); | |
470 | writew(csr, &musbr->txcsr); | |
471 | return result; | |
472 | } | |
473 | ||
474 | /* | |
475 | * determines the speed of the device (High/Full/Slow) | |
476 | */ | |
477 | static u8 get_dev_speed(struct usb_device *dev) | |
478 | { | |
479 | return (dev->speed & USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH : | |
480 | ((dev->speed & USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW : | |
481 | MUSB_TYPE_SPEED_FULL); | |
482 | } | |
483 | ||
484 | /* | |
485 | * configure the hub address and the port address. | |
486 | */ | |
487 | static void config_hub_port(struct usb_device *dev, u8 ep) | |
488 | { | |
489 | u8 chid; | |
490 | u8 hub; | |
491 | ||
492 | /* Find out the nearest parent which is high speed */ | |
493 | while (dev->parent->parent != NULL) | |
494 | if (get_dev_speed(dev->parent) != MUSB_TYPE_SPEED_HIGH) | |
495 | dev = dev->parent; | |
496 | else | |
497 | break; | |
498 | ||
499 | /* determine the port address at that hub */ | |
500 | hub = dev->parent->devnum; | |
501 | for (chid = 0; chid < USB_MAXCHILDREN; chid++) | |
502 | if (dev->parent->children[chid] == dev) | |
503 | break; | |
504 | ||
8868fd44 | 505 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
506 | /* configure the hub address and the port address */ |
507 | writeb(hub, &musbr->tar[ep].txhubaddr); | |
508 | writeb((chid + 1), &musbr->tar[ep].txhubport); | |
509 | writeb(hub, &musbr->tar[ep].rxhubaddr); | |
510 | writeb((chid + 1), &musbr->tar[ep].rxhubport); | |
8868fd44 | 511 | #endif |
a1428969 TA |
512 | } |
513 | ||
321790f6 BW |
514 | #ifdef MUSB_NO_MULTIPOINT |
515 | ||
516 | static void musb_port_reset(int do_reset) | |
517 | { | |
518 | u8 power = readb(&musbr->power); | |
519 | ||
520 | if (do_reset) { | |
521 | power &= 0xf0; | |
522 | writeb(power | MUSB_POWER_RESET, &musbr->power); | |
523 | port_status |= USB_PORT_STAT_RESET; | |
524 | port_status &= ~USB_PORT_STAT_ENABLE; | |
525 | udelay(30000); | |
526 | } else { | |
527 | writeb(power & ~MUSB_POWER_RESET, &musbr->power); | |
528 | ||
529 | power = readb(&musbr->power); | |
530 | if (power & MUSB_POWER_HSMODE) | |
531 | port_status |= USB_PORT_STAT_HIGH_SPEED; | |
532 | ||
533 | port_status &= ~(USB_PORT_STAT_RESET | (USB_PORT_STAT_C_CONNECTION << 16)); | |
534 | port_status |= USB_PORT_STAT_ENABLE | |
535 | | (USB_PORT_STAT_C_RESET << 16) | |
536 | | (USB_PORT_STAT_C_ENABLE << 16); | |
537 | } | |
538 | } | |
539 | ||
540 | /* | |
541 | * root hub control | |
542 | */ | |
543 | static int musb_submit_rh_msg(struct usb_device *dev, unsigned long pipe, | |
544 | void *buffer, int transfer_len, | |
545 | struct devrequest *cmd) | |
546 | { | |
547 | int leni = transfer_len; | |
548 | int len = 0; | |
549 | int stat = 0; | |
550 | u32 datab[4]; | |
551 | u8 *data_buf = (u8 *) datab; | |
552 | u16 bmRType_bReq; | |
553 | u16 wValue; | |
554 | u16 wIndex; | |
555 | u16 wLength; | |
556 | u16 int_usb; | |
557 | ||
558 | if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { | |
559 | debug("Root-Hub submit IRQ: NOT implemented\n"); | |
560 | return 0; | |
561 | } | |
562 | ||
563 | bmRType_bReq = cmd->requesttype | (cmd->request << 8); | |
564 | wValue = swap_16(cmd->value); | |
565 | wIndex = swap_16(cmd->index); | |
566 | wLength = swap_16(cmd->length); | |
567 | ||
568 | debug("--- HUB ----------------------------------------\n"); | |
569 | debug("submit rh urb, req=%x val=%#x index=%#x len=%d\n", | |
570 | bmRType_bReq, wValue, wIndex, wLength); | |
571 | debug("------------------------------------------------\n"); | |
572 | ||
573 | switch (bmRType_bReq) { | |
574 | case RH_GET_STATUS: | |
575 | debug("RH_GET_STATUS\n"); | |
576 | ||
577 | *(__u16 *) data_buf = swap_16(1); | |
578 | len = 2; | |
579 | break; | |
580 | ||
581 | case RH_GET_STATUS | RH_INTERFACE: | |
582 | debug("RH_GET_STATUS | RH_INTERFACE\n"); | |
583 | ||
584 | *(__u16 *) data_buf = swap_16(0); | |
585 | len = 2; | |
586 | break; | |
587 | ||
588 | case RH_GET_STATUS | RH_ENDPOINT: | |
589 | debug("RH_GET_STATUS | RH_ENDPOINT\n"); | |
590 | ||
591 | *(__u16 *) data_buf = swap_16(0); | |
592 | len = 2; | |
593 | break; | |
594 | ||
595 | case RH_GET_STATUS | RH_CLASS: | |
596 | debug("RH_GET_STATUS | RH_CLASS\n"); | |
597 | ||
598 | *(__u32 *) data_buf = swap_32(0); | |
599 | len = 4; | |
600 | break; | |
601 | ||
602 | case RH_GET_STATUS | RH_OTHER | RH_CLASS: | |
603 | debug("RH_GET_STATUS | RH_OTHER | RH_CLASS\n"); | |
604 | ||
605 | int_usb = readw(&musbr->intrusb); | |
606 | if (int_usb & MUSB_INTR_CONNECT) { | |
607 | port_status |= USB_PORT_STAT_CONNECTION | |
608 | | (USB_PORT_STAT_C_CONNECTION << 16); | |
609 | port_status |= USB_PORT_STAT_HIGH_SPEED | |
610 | | USB_PORT_STAT_ENABLE; | |
611 | } | |
612 | ||
613 | if (port_status & USB_PORT_STAT_RESET) | |
614 | musb_port_reset(0); | |
615 | ||
616 | *(__u32 *) data_buf = swap_32(port_status); | |
617 | len = 4; | |
618 | break; | |
619 | ||
620 | case RH_CLEAR_FEATURE | RH_ENDPOINT: | |
621 | debug("RH_CLEAR_FEATURE | RH_ENDPOINT\n"); | |
622 | ||
623 | switch (wValue) { | |
624 | case RH_ENDPOINT_STALL: | |
625 | debug("C_HUB_ENDPOINT_STALL\n"); | |
626 | len = 0; | |
627 | break; | |
628 | } | |
629 | port_status &= ~(1 << wValue); | |
630 | break; | |
631 | ||
632 | case RH_CLEAR_FEATURE | RH_CLASS: | |
633 | debug("RH_CLEAR_FEATURE | RH_CLASS\n"); | |
634 | ||
635 | switch (wValue) { | |
636 | case RH_C_HUB_LOCAL_POWER: | |
637 | debug("C_HUB_LOCAL_POWER\n"); | |
638 | len = 0; | |
639 | break; | |
640 | ||
641 | case RH_C_HUB_OVER_CURRENT: | |
642 | debug("C_HUB_OVER_CURRENT\n"); | |
643 | len = 0; | |
644 | break; | |
645 | } | |
646 | port_status &= ~(1 << wValue); | |
647 | break; | |
648 | ||
649 | case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: | |
650 | debug("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS\n"); | |
651 | ||
652 | switch (wValue) { | |
653 | case RH_PORT_ENABLE: | |
654 | len = 0; | |
655 | break; | |
656 | ||
657 | case RH_PORT_SUSPEND: | |
658 | len = 0; | |
659 | break; | |
660 | ||
661 | case RH_PORT_POWER: | |
662 | len = 0; | |
663 | break; | |
664 | ||
665 | case RH_C_PORT_CONNECTION: | |
666 | len = 0; | |
667 | break; | |
668 | ||
669 | case RH_C_PORT_ENABLE: | |
670 | len = 0; | |
671 | break; | |
672 | ||
673 | case RH_C_PORT_SUSPEND: | |
674 | len = 0; | |
675 | break; | |
676 | ||
677 | case RH_C_PORT_OVER_CURRENT: | |
678 | len = 0; | |
679 | break; | |
680 | ||
681 | case RH_C_PORT_RESET: | |
682 | len = 0; | |
683 | break; | |
684 | ||
685 | default: | |
686 | debug("invalid wValue\n"); | |
687 | stat = USB_ST_STALLED; | |
688 | } | |
689 | ||
690 | port_status &= ~(1 << wValue); | |
691 | break; | |
692 | ||
693 | case RH_SET_FEATURE | RH_OTHER | RH_CLASS: | |
694 | debug("RH_SET_FEATURE | RH_OTHER | RH_CLASS\n"); | |
695 | ||
696 | switch (wValue) { | |
697 | case RH_PORT_SUSPEND: | |
698 | len = 0; | |
699 | break; | |
700 | ||
701 | case RH_PORT_RESET: | |
702 | musb_port_reset(1); | |
703 | len = 0; | |
704 | break; | |
705 | ||
706 | case RH_PORT_POWER: | |
707 | len = 0; | |
708 | break; | |
709 | ||
710 | case RH_PORT_ENABLE: | |
711 | len = 0; | |
712 | break; | |
713 | ||
714 | default: | |
715 | debug("invalid wValue\n"); | |
716 | stat = USB_ST_STALLED; | |
717 | } | |
718 | ||
719 | port_status |= 1 << wValue; | |
720 | break; | |
721 | ||
722 | case RH_SET_ADDRESS: | |
723 | debug("RH_SET_ADDRESS\n"); | |
724 | ||
725 | rh_devnum = wValue; | |
726 | len = 0; | |
727 | break; | |
728 | ||
729 | case RH_GET_DESCRIPTOR: | |
730 | debug("RH_GET_DESCRIPTOR: %x, %d\n", wValue, wLength); | |
731 | ||
732 | switch (wValue) { | |
733 | case (USB_DT_DEVICE << 8): /* device descriptor */ | |
734 | len = min_t(unsigned int, | |
735 | leni, min_t(unsigned int, | |
736 | sizeof(root_hub_dev_des), | |
737 | wLength)); | |
738 | data_buf = root_hub_dev_des; | |
739 | break; | |
740 | ||
741 | case (USB_DT_CONFIG << 8): /* configuration descriptor */ | |
742 | len = min_t(unsigned int, | |
743 | leni, min_t(unsigned int, | |
744 | sizeof(root_hub_config_des), | |
745 | wLength)); | |
746 | data_buf = root_hub_config_des; | |
747 | break; | |
748 | ||
749 | case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */ | |
750 | len = min_t(unsigned int, | |
751 | leni, min_t(unsigned int, | |
752 | sizeof(root_hub_str_index0), | |
753 | wLength)); | |
754 | data_buf = root_hub_str_index0; | |
755 | break; | |
756 | ||
757 | case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */ | |
758 | len = min_t(unsigned int, | |
759 | leni, min_t(unsigned int, | |
760 | sizeof(root_hub_str_index1), | |
761 | wLength)); | |
762 | data_buf = root_hub_str_index1; | |
763 | break; | |
764 | ||
765 | default: | |
766 | debug("invalid wValue\n"); | |
767 | stat = USB_ST_STALLED; | |
768 | } | |
769 | ||
770 | break; | |
771 | ||
772 | case RH_GET_DESCRIPTOR | RH_CLASS: | |
773 | debug("RH_GET_DESCRIPTOR | RH_CLASS\n"); | |
774 | ||
775 | data_buf[0] = 0x09; /* min length; */ | |
776 | data_buf[1] = 0x29; | |
777 | data_buf[2] = 0x1; /* 1 port */ | |
778 | data_buf[3] = 0x01; /* per-port power switching */ | |
779 | data_buf[3] |= 0x10; /* no overcurrent reporting */ | |
780 | ||
781 | /* Corresponds to data_buf[4-7] */ | |
782 | data_buf[4] = 0; | |
783 | data_buf[5] = 5; | |
784 | data_buf[6] = 0; | |
785 | data_buf[7] = 0x02; | |
786 | data_buf[8] = 0xff; | |
787 | ||
788 | len = min_t(unsigned int, leni, | |
789 | min_t(unsigned int, data_buf[0], wLength)); | |
790 | break; | |
791 | ||
792 | case RH_GET_CONFIGURATION: | |
793 | debug("RH_GET_CONFIGURATION\n"); | |
794 | ||
795 | *(__u8 *) data_buf = 0x01; | |
796 | len = 1; | |
797 | break; | |
798 | ||
799 | case RH_SET_CONFIGURATION: | |
800 | debug("RH_SET_CONFIGURATION\n"); | |
801 | ||
802 | len = 0; | |
803 | break; | |
804 | ||
805 | default: | |
806 | debug("*** *** *** unsupported root hub command *** *** ***\n"); | |
807 | stat = USB_ST_STALLED; | |
808 | } | |
809 | ||
810 | len = min_t(int, len, leni); | |
811 | if (buffer != data_buf) | |
812 | memcpy(buffer, data_buf, len); | |
813 | ||
814 | dev->act_len = len; | |
815 | dev->status = stat; | |
816 | debug("dev act_len %d, status %d\n", dev->act_len, dev->status); | |
817 | ||
818 | return stat; | |
819 | } | |
820 | ||
821 | static void musb_rh_init(void) | |
822 | { | |
823 | rh_devnum = 0; | |
824 | port_status = 0; | |
825 | } | |
826 | ||
827 | #else | |
828 | ||
829 | static void musb_rh_init(void) {} | |
830 | ||
831 | #endif | |
832 | ||
a1428969 TA |
833 | /* |
834 | * do a control transfer | |
835 | */ | |
836 | int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, | |
837 | int len, struct devrequest *setup) | |
838 | { | |
839 | int devnum = usb_pipedevice(pipe); | |
840 | u16 csr; | |
841 | u8 devspeed; | |
842 | ||
321790f6 BW |
843 | #ifdef MUSB_NO_MULTIPOINT |
844 | /* Control message is for the HUB? */ | |
845 | if (devnum == rh_devnum) | |
846 | return musb_submit_rh_msg(dev, pipe, buffer, len, setup); | |
847 | #endif | |
848 | ||
a1428969 TA |
849 | /* select control endpoint */ |
850 | writeb(MUSB_CONTROL_EP, &musbr->index); | |
851 | csr = readw(&musbr->txcsr); | |
852 | ||
8868fd44 | 853 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
854 | /* target addr and (for multipoint) hub addr/port */ |
855 | writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr); | |
856 | writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr); | |
8868fd44 | 857 | #endif |
a1428969 TA |
858 | |
859 | /* configure the hub address and the port number as required */ | |
860 | devspeed = get_dev_speed(dev); | |
861 | if ((musb_ishighspeed()) && (dev->parent != NULL) && | |
862 | (devspeed != MUSB_TYPE_SPEED_HIGH)) { | |
863 | config_hub_port(dev, MUSB_CONTROL_EP); | |
864 | writeb(devspeed << 6, &musbr->txtype); | |
865 | } else { | |
866 | writeb(musb_cfg.musb_speed << 6, &musbr->txtype); | |
8868fd44 | 867 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
868 | writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr); |
869 | writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport); | |
870 | writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr); | |
871 | writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport); | |
8868fd44 | 872 | #endif |
a1428969 TA |
873 | } |
874 | ||
875 | /* Control transfer setup phase */ | |
876 | if (ctrlreq_setup_phase(dev, setup) < 0) | |
877 | return 0; | |
878 | ||
879 | switch (setup->request) { | |
880 | case USB_REQ_GET_DESCRIPTOR: | |
881 | case USB_REQ_GET_CONFIGURATION: | |
882 | case USB_REQ_GET_INTERFACE: | |
883 | case USB_REQ_GET_STATUS: | |
884 | case USB_MSC_BBB_GET_MAX_LUN: | |
885 | /* control transfer in-data-phase */ | |
886 | if (ctrlreq_in_data_phase(dev, len, buffer) < 0) | |
887 | return 0; | |
888 | /* control transfer out-status-phase */ | |
889 | if (ctrlreq_out_status_phase(dev) < 0) | |
890 | return 0; | |
891 | break; | |
892 | ||
893 | case USB_REQ_SET_ADDRESS: | |
894 | case USB_REQ_SET_CONFIGURATION: | |
895 | case USB_REQ_SET_FEATURE: | |
896 | case USB_REQ_SET_INTERFACE: | |
897 | case USB_REQ_CLEAR_FEATURE: | |
898 | case USB_MSC_BBB_RESET: | |
899 | /* control transfer in status phase */ | |
900 | if (ctrlreq_in_status_phase(dev) < 0) | |
901 | return 0; | |
902 | break; | |
903 | ||
904 | case USB_REQ_SET_DESCRIPTOR: | |
905 | /* control transfer out data phase */ | |
906 | if (ctrlreq_out_data_phase(dev, len, buffer) < 0) | |
907 | return 0; | |
908 | /* control transfer in status phase */ | |
909 | if (ctrlreq_in_status_phase(dev) < 0) | |
910 | return 0; | |
911 | break; | |
912 | ||
913 | default: | |
914 | /* unhandled control transfer */ | |
915 | return -1; | |
916 | } | |
917 | ||
918 | dev->status = 0; | |
919 | dev->act_len = len; | |
93ceb479 BW |
920 | |
921 | #ifdef MUSB_NO_MULTIPOINT | |
922 | /* Set device address to USB_FADDR register */ | |
923 | if (setup->request == USB_REQ_SET_ADDRESS) | |
924 | writeb(dev->devnum, &musbr->faddr); | |
925 | #endif | |
926 | ||
a1428969 TA |
927 | return len; |
928 | } | |
929 | ||
930 | /* | |
931 | * do a bulk transfer | |
932 | */ | |
933 | int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, | |
934 | void *buffer, int len) | |
935 | { | |
936 | int dir_out = usb_pipeout(pipe); | |
937 | int ep = usb_pipeendpoint(pipe); | |
8868fd44 | 938 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 | 939 | int devnum = usb_pipedevice(pipe); |
8868fd44 | 940 | #endif |
a1428969 TA |
941 | u8 type; |
942 | u16 csr; | |
943 | u32 txlen = 0; | |
944 | u32 nextlen = 0; | |
945 | u8 devspeed; | |
946 | ||
947 | /* select bulk endpoint */ | |
948 | writeb(MUSB_BULK_EP, &musbr->index); | |
949 | ||
8868fd44 | 950 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
951 | /* write the address of the device */ |
952 | if (dir_out) | |
953 | writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr); | |
954 | else | |
955 | writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr); | |
8868fd44 | 956 | #endif |
a1428969 TA |
957 | |
958 | /* configure the hub address and the port number as required */ | |
959 | devspeed = get_dev_speed(dev); | |
960 | if ((musb_ishighspeed()) && (dev->parent != NULL) && | |
961 | (devspeed != MUSB_TYPE_SPEED_HIGH)) { | |
962 | /* | |
963 | * MUSB is in high speed and the destination device is full | |
964 | * speed device. So configure the hub address and port | |
965 | * address registers. | |
966 | */ | |
967 | config_hub_port(dev, MUSB_BULK_EP); | |
968 | } else { | |
8868fd44 | 969 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
970 | if (dir_out) { |
971 | writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr); | |
972 | writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport); | |
973 | } else { | |
974 | writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr); | |
975 | writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport); | |
976 | } | |
8868fd44 | 977 | #endif |
a1428969 TA |
978 | devspeed = musb_cfg.musb_speed; |
979 | } | |
980 | ||
981 | /* Write the saved toggle bit value */ | |
982 | write_toggle(dev, ep, dir_out); | |
983 | ||
984 | if (dir_out) { /* bulk-out transfer */ | |
985 | /* Program the TxType register */ | |
986 | type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | | |
987 | (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) | | |
988 | (ep & MUSB_TYPE_REMOTE_END); | |
989 | writeb(type, &musbr->txtype); | |
990 | ||
991 | /* Write maximum packet size to the TxMaxp register */ | |
992 | writew(dev->epmaxpacketout[ep], &musbr->txmaxp); | |
993 | while (txlen < len) { | |
994 | nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ? | |
995 | (len-txlen) : dev->epmaxpacketout[ep]; | |
996 | ||
8dd7a230 BW |
997 | #ifdef CONFIG_USB_BLACKFIN |
998 | /* Set the transfer data size */ | |
999 | writew(nextlen, &musbr->txcount); | |
1000 | #endif | |
1001 | ||
a1428969 TA |
1002 | /* Write the data to the FIFO */ |
1003 | write_fifo(MUSB_BULK_EP, nextlen, | |
1004 | (void *)(((u8 *)buffer) + txlen)); | |
1005 | ||
1006 | /* Set the TxPktRdy bit */ | |
1007 | csr = readw(&musbr->txcsr); | |
1008 | writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr); | |
1009 | ||
1010 | /* Wait until the TxPktRdy bit is cleared */ | |
1011 | if (!wait_until_txep_ready(dev, MUSB_BULK_EP)) { | |
1012 | readw(&musbr->txcsr); | |
1013 | usb_settoggle(dev, ep, dir_out, | |
1014 | (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1); | |
1015 | dev->act_len = txlen; | |
1016 | return 0; | |
1017 | } | |
1018 | txlen += nextlen; | |
1019 | } | |
1020 | ||
1021 | /* Keep a copy of the data toggle bit */ | |
1022 | csr = readw(&musbr->txcsr); | |
1023 | usb_settoggle(dev, ep, dir_out, | |
1024 | (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1); | |
1025 | } else { /* bulk-in transfer */ | |
1026 | /* Write the saved toggle bit value */ | |
1027 | write_toggle(dev, ep, dir_out); | |
1028 | ||
1029 | /* Program the RxType register */ | |
1030 | type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | | |
1031 | (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) | | |
1032 | (ep & MUSB_TYPE_REMOTE_END); | |
1033 | writeb(type, &musbr->rxtype); | |
1034 | ||
1035 | /* Write the maximum packet size to the RxMaxp register */ | |
1036 | writew(dev->epmaxpacketin[ep], &musbr->rxmaxp); | |
1037 | while (txlen < len) { | |
1038 | nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ? | |
1039 | (len-txlen) : dev->epmaxpacketin[ep]; | |
1040 | ||
1041 | /* Set the ReqPkt bit */ | |
bc72a919 BW |
1042 | csr = readw(&musbr->rxcsr); |
1043 | writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr); | |
a1428969 TA |
1044 | |
1045 | /* Wait until the RxPktRdy bit is set */ | |
1046 | if (!wait_until_rxep_ready(dev, MUSB_BULK_EP)) { | |
1047 | csr = readw(&musbr->rxcsr); | |
1048 | usb_settoggle(dev, ep, dir_out, | |
1049 | (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); | |
1050 | csr &= ~MUSB_RXCSR_RXPKTRDY; | |
1051 | writew(csr, &musbr->rxcsr); | |
1052 | dev->act_len = txlen; | |
1053 | return 0; | |
1054 | } | |
1055 | ||
1056 | /* Read the data from the FIFO */ | |
1057 | read_fifo(MUSB_BULK_EP, nextlen, | |
1058 | (void *)(((u8 *)buffer) + txlen)); | |
1059 | ||
1060 | /* Clear the RxPktRdy bit */ | |
1061 | csr = readw(&musbr->rxcsr); | |
1062 | csr &= ~MUSB_RXCSR_RXPKTRDY; | |
1063 | writew(csr, &musbr->rxcsr); | |
1064 | txlen += nextlen; | |
1065 | } | |
1066 | ||
1067 | /* Keep a copy of the data toggle bit */ | |
1068 | csr = readw(&musbr->rxcsr); | |
1069 | usb_settoggle(dev, ep, dir_out, | |
1070 | (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); | |
1071 | } | |
1072 | ||
1073 | /* bulk transfer is complete */ | |
1074 | dev->status = 0; | |
1075 | dev->act_len = len; | |
1076 | return 0; | |
1077 | } | |
1078 | ||
1079 | /* | |
1080 | * This function initializes the usb controller module. | |
1081 | */ | |
1082 | int usb_lowlevel_init(void) | |
1083 | { | |
1084 | u8 power; | |
1085 | u32 timeout; | |
1086 | ||
321790f6 BW |
1087 | musb_rh_init(); |
1088 | ||
a1428969 TA |
1089 | if (musb_platform_init() == -1) |
1090 | return -1; | |
1091 | ||
1092 | /* Configure all the endpoint FIFO's and start usb controller */ | |
1093 | musbr = musb_cfg.regs; | |
1094 | musb_configure_ep(&epinfo[0], | |
1095 | sizeof(epinfo) / sizeof(struct musb_epinfo)); | |
1096 | musb_start(); | |
1097 | ||
1098 | /* | |
1099 | * Wait until musb is enabled in host mode with a timeout. There | |
1100 | * should be a usb device connected. | |
1101 | */ | |
1102 | timeout = musb_cfg.timeout; | |
1103 | while (timeout--) | |
1104 | if (readb(&musbr->devctl) & MUSB_DEVCTL_HM) | |
1105 | break; | |
1106 | ||
1107 | /* if musb core is not in host mode, then return */ | |
1108 | if (!timeout) | |
1109 | return -1; | |
1110 | ||
1111 | /* start usb bus reset */ | |
1112 | power = readb(&musbr->power); | |
1113 | writeb(power | MUSB_POWER_RESET, &musbr->power); | |
1114 | ||
1115 | /* After initiating a usb reset, wait for about 20ms to 30ms */ | |
1116 | udelay(30000); | |
1117 | ||
1118 | /* stop usb bus reset */ | |
1119 | power = readb(&musbr->power); | |
1120 | power &= ~MUSB_POWER_RESET; | |
1121 | writeb(power, &musbr->power); | |
1122 | ||
1123 | /* Determine if the connected device is a high/full/low speed device */ | |
1124 | musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ? | |
1125 | MUSB_TYPE_SPEED_HIGH : | |
1126 | ((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ? | |
1127 | MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW); | |
1128 | return 0; | |
1129 | } | |
1130 | ||
1131 | /* | |
1132 | * This function stops the operation of the davinci usb module. | |
1133 | */ | |
1134 | int usb_lowlevel_stop(void) | |
1135 | { | |
1136 | /* Reset the USB module */ | |
1137 | musb_platform_deinit(); | |
1138 | writeb(0, &musbr->devctl); | |
1139 | return 0; | |
1140 | } | |
1141 | ||
1142 | /* | |
1143 | * This function supports usb interrupt transfers. Currently, usb interrupt | |
1144 | * transfers are not supported. | |
1145 | */ | |
1146 | int submit_int_msg(struct usb_device *dev, unsigned long pipe, | |
1147 | void *buffer, int len, int interval) | |
1148 | { | |
1149 | int dir_out = usb_pipeout(pipe); | |
1150 | int ep = usb_pipeendpoint(pipe); | |
8868fd44 | 1151 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 | 1152 | int devnum = usb_pipedevice(pipe); |
8868fd44 | 1153 | #endif |
a1428969 TA |
1154 | u8 type; |
1155 | u16 csr; | |
1156 | u32 txlen = 0; | |
1157 | u32 nextlen = 0; | |
1158 | u8 devspeed; | |
1159 | ||
1160 | /* select interrupt endpoint */ | |
1161 | writeb(MUSB_INTR_EP, &musbr->index); | |
1162 | ||
8868fd44 | 1163 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
1164 | /* write the address of the device */ |
1165 | if (dir_out) | |
1166 | writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr); | |
1167 | else | |
1168 | writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr); | |
8868fd44 | 1169 | #endif |
a1428969 TA |
1170 | |
1171 | /* configure the hub address and the port number as required */ | |
1172 | devspeed = get_dev_speed(dev); | |
1173 | if ((musb_ishighspeed()) && (dev->parent != NULL) && | |
1174 | (devspeed != MUSB_TYPE_SPEED_HIGH)) { | |
1175 | /* | |
1176 | * MUSB is in high speed and the destination device is full | |
1177 | * speed device. So configure the hub address and port | |
1178 | * address registers. | |
1179 | */ | |
1180 | config_hub_port(dev, MUSB_INTR_EP); | |
1181 | } else { | |
8868fd44 | 1182 | #ifndef MUSB_NO_MULTIPOINT |
a1428969 TA |
1183 | if (dir_out) { |
1184 | writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr); | |
1185 | writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport); | |
1186 | } else { | |
1187 | writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr); | |
1188 | writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport); | |
1189 | } | |
8868fd44 | 1190 | #endif |
a1428969 TA |
1191 | devspeed = musb_cfg.musb_speed; |
1192 | } | |
1193 | ||
1194 | /* Write the saved toggle bit value */ | |
1195 | write_toggle(dev, ep, dir_out); | |
1196 | ||
1197 | if (!dir_out) { /* intrrupt-in transfer */ | |
1198 | /* Write the saved toggle bit value */ | |
1199 | write_toggle(dev, ep, dir_out); | |
1200 | writeb(interval, &musbr->rxinterval); | |
1201 | ||
1202 | /* Program the RxType register */ | |
1203 | type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | | |
1204 | (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) | | |
1205 | (ep & MUSB_TYPE_REMOTE_END); | |
1206 | writeb(type, &musbr->rxtype); | |
1207 | ||
1208 | /* Write the maximum packet size to the RxMaxp register */ | |
1209 | writew(dev->epmaxpacketin[ep], &musbr->rxmaxp); | |
1210 | ||
1211 | while (txlen < len) { | |
1212 | nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ? | |
1213 | (len-txlen) : dev->epmaxpacketin[ep]; | |
1214 | ||
1215 | /* Set the ReqPkt bit */ | |
bc72a919 BW |
1216 | csr = readw(&musbr->rxcsr); |
1217 | writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr); | |
a1428969 TA |
1218 | |
1219 | /* Wait until the RxPktRdy bit is set */ | |
1220 | if (!wait_until_rxep_ready(dev, MUSB_INTR_EP)) { | |
1221 | csr = readw(&musbr->rxcsr); | |
1222 | usb_settoggle(dev, ep, dir_out, | |
1223 | (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); | |
1224 | csr &= ~MUSB_RXCSR_RXPKTRDY; | |
1225 | writew(csr, &musbr->rxcsr); | |
1226 | dev->act_len = txlen; | |
1227 | return 0; | |
1228 | } | |
1229 | ||
1230 | /* Read the data from the FIFO */ | |
1231 | read_fifo(MUSB_INTR_EP, nextlen, | |
1232 | (void *)(((u8 *)buffer) + txlen)); | |
1233 | ||
1234 | /* Clear the RxPktRdy bit */ | |
1235 | csr = readw(&musbr->rxcsr); | |
1236 | csr &= ~MUSB_RXCSR_RXPKTRDY; | |
1237 | writew(csr, &musbr->rxcsr); | |
1238 | txlen += nextlen; | |
1239 | } | |
1240 | ||
1241 | /* Keep a copy of the data toggle bit */ | |
1242 | csr = readw(&musbr->rxcsr); | |
1243 | usb_settoggle(dev, ep, dir_out, | |
1244 | (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); | |
1245 | } | |
1246 | ||
1247 | /* interrupt transfer is complete */ | |
1248 | dev->irq_status = 0; | |
1249 | dev->irq_act_len = len; | |
1250 | dev->irq_handle(dev); | |
1251 | dev->status = 0; | |
1252 | dev->act_len = len; | |
1253 | return 0; | |
1254 | } | |
1255 | ||
1256 | ||
1257 | #ifdef CONFIG_SYS_USB_EVENT_POLL | |
1258 | /* | |
1259 | * This function polls for USB keyboard data. | |
1260 | */ | |
1261 | void usb_event_poll() | |
1262 | { | |
52cb4d4f | 1263 | struct stdio_dev *dev; |
a1428969 | 1264 | struct usb_device *usb_kbd_dev; |
8f8bd565 | 1265 | struct usb_interface *iface; |
a1428969 TA |
1266 | struct usb_endpoint_descriptor *ep; |
1267 | int pipe; | |
1268 | int maxp; | |
1269 | ||
1270 | /* Get the pointer to USB Keyboard device pointer */ | |
52cb4d4f | 1271 | dev = stdio_get_by_name("usbkbd"); |
a1428969 TA |
1272 | usb_kbd_dev = (struct usb_device *)dev->priv; |
1273 | iface = &usb_kbd_dev->config.if_desc[0]; | |
1274 | ep = &iface->ep_desc[0]; | |
1275 | pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress); | |
1276 | ||
1277 | /* Submit a interrupt transfer request */ | |
1278 | maxp = usb_maxpacket(usb_kbd_dev, pipe); | |
1279 | usb_submit_int_msg(usb_kbd_dev, pipe, &new[0], | |
1280 | maxp > 8 ? 8 : maxp, ep->bInterval); | |
1281 | } | |
1282 | #endif /* CONFIG_SYS_USB_EVENT_POLL */ |