blob: d093e67df75ce863a1cd4fe243de9adb037cec5c [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/** @file
2
3 Copyright (c) 2015, Linaro Limited. All rights reserved.
4 Copyright (c) 2015, Hisilicon Limited. All rights reserved.
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include <IndustryStandard/Usb.h>
17#include <Library/TimerLib.h>
18#include <Library/DebugLib.h>
19#include <Library/UefiBootServicesTableLib.h>
20#include <Library/UefiDriverEntryPoint.h>
21#include <Library/UefiRuntimeServicesTableLib.h>
22#include <Library/IoLib.h>
23#include <Library/MemoryAllocationLib.h>
24#include <Library/UncachedMemoryAllocationLib.h>
25#include <Library/CacheMaintenanceLib.h>
26#include <Library/BaseMemoryLib.h>
27#include <Library/BaseLib.h>
28#include <Protocol/UsbDevice.h>
29#include <Guid/ArmGlobalVariableHob.h>
30
31#include "DwUsbDxe.h"
32
33STATIC dwc_otg_dev_dma_desc_t *g_dma_desc,*g_dma_desc_ep0,*g_dma_desc_in;
34STATIC USB_DEVICE_REQUEST *p_ctrlreq;
35STATIC VOID *rx_buf;
36STATIC UINT32 rx_desc_bytes = 0;
37STATIC UINTN mNumDataBytes;
38
39#define USB_BLOCK_HIGH_SPEED_SIZE 512
40#define DATA_SIZE 32768
41#define CMD_SIZE 512
42#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
43
44STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor;
45
46// The config descriptor, interface descriptor, and endpoint descriptors in a
47// buffer (in that order)
48STATIC VOID *mDescriptors;
49// Convenience pointers to those descriptors inside the buffer:
50STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor;
51STATIC USB_CONFIG_DESCRIPTOR *mConfigDescriptor;
52STATIC USB_ENDPOINT_DESCRIPTOR *mEndpointDescriptors;
53
54STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback;
55STATIC USB_DEVICE_TX_CALLBACK mDataSentCallback;
56
57STATIC EFI_USB_STRING_DESCRIPTOR mLangStringDescriptor = {
58 4,
59 USB_DESC_TYPE_STRING,
60 {0x409}
61};
62
63STATIC EFI_USB_STRING_DESCRIPTOR mManufacturerStringDescriptor = {
64 18,
65 USB_DESC_TYPE_STRING,
66 {'9', '6', 'B', 'o', 'a', 'r', 'd', 's'}
67};
68
69STATIC EFI_USB_STRING_DESCRIPTOR mProductStringDescriptor = {
70 12,
71 USB_DESC_TYPE_STRING,
72 {'H', 'i', 'K', 'e', 'y'}
73};
74
75STATIC EFI_USB_STRING_DESCRIPTOR mSerialStringDescriptor = {
76 34,
77 USB_DESC_TYPE_STRING,
78 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}
79};
80
81// The time between interrupt polls, in units of 100 nanoseconds
82// 10 Microseconds
83#define DW_INTERRUPT_POLL_PERIOD 10000
84STATIC int usb_drv_port_speed(void) /*To detect which mode was run, high speed or full speed*/
85{
86 /*
87 * 2'b00: High speed (PHY clock is running at 30 or 60 MHz)
88 */
89 UINT32 val = READ_REG32(DSTS) & 2;
90 return (!val);
91}
92
93STATIC VOID reset_endpoints(void)
94{
95 /* EP0 IN ACTIVE NEXT=1 */
96 WRITE_REG32(DIEPCTL0, 0x8800);
97
98 /* EP0 OUT ACTIVE */
99 WRITE_REG32(DOEPCTL0, 0x8000);
100
101 /* Clear any pending OTG Interrupts */
102 WRITE_REG32(GOTGINT, 0xFFFFFFFF);
103
104 /* Clear any pending interrupts */
105 WRITE_REG32(GINTSTS, 0xFFFFFFFF);
106 WRITE_REG32(DIEPINT0, 0xFFFFFFFF);
107 WRITE_REG32(DOEPINT0, 0xFFFFFFFF);
108 WRITE_REG32(DIEPINT1, 0xFFFFFFFF);
109 WRITE_REG32(DOEPINT1, 0xFFFFFFFF);
110
111 /* IN EP interrupt mask */
112 WRITE_REG32(DIEPMSK, 0x0D);
113 /* OUT EP interrupt mask */
114 WRITE_REG32(DOEPMSK, 0x0D);
115 /* Enable interrupts on Ep0 */
116 WRITE_REG32(DAINTMSK, 0x00010001);
117
118 /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
119 WRITE_REG32(DOEPTSIZ0, 0x60080040);
120
121 //notes that:the compulsive conversion is expectable.
122 g_dma_desc_ep0->status.b.bs = 0x3;
123 g_dma_desc_ep0->status.b.mtrf = 0;
124 g_dma_desc_ep0->status.b.sr = 0;
125 g_dma_desc_ep0->status.b.l = 1;
126 g_dma_desc_ep0->status.b.ioc = 1;
127 g_dma_desc_ep0->status.b.sp = 0;
128 g_dma_desc_ep0->status.b.bytes = 64;
129 g_dma_desc_ep0->buf = (UINT32)(UINTN)(p_ctrlreq);
130 g_dma_desc_ep0->status.b.sts = 0;
131 g_dma_desc_ep0->status.b.bs = 0x0;
132 WRITE_REG32(DOEPDMA0, (unsigned long)(g_dma_desc_ep0));
133 /* EP0 OUT ENABLE CLEARNAK */
134 WRITE_REG32(DOEPCTL0, (READ_REG32(DOEPCTL0) | 0x84000000));
135}
136
137STATIC VOID ep_tx(IN UINT8 ep, CONST VOID *ptr, UINT32 len)
138{
139 UINT32 blocksize;
140 UINT32 packets;
141
142 /* EPx OUT ACTIVE */
143 WRITE_REG32(DIEPCTL(ep), (READ_REG32(DIEPCTL(ep))) | 0x8000);
144 if(!ep) {
145 blocksize = 64;
146 } else {
147 blocksize = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
148 }
149 packets = (len + blocksize - 1) / blocksize;
150
151 if (!len) { //send a null packet
152 /* one empty packet */
153 g_dma_desc_in->status.b.bs = 0x3;
154 g_dma_desc_in->status.b.l = 1;
155 g_dma_desc_in->status.b.ioc = 1;
156 g_dma_desc_in->status.b.sp = 1;
157 g_dma_desc_in->status.b.bytes = 0;
158 g_dma_desc_in->buf = 0;
159 g_dma_desc_in->status.b.sts = 0;
160 g_dma_desc_in->status.b.bs = 0x0;
161
162 WRITE_REG32(DIEPDMA(ep), (unsigned long)(g_dma_desc_in)); // DMA Address (DMAAddr) is zero
163 } else { //prepare to send a packet
164 /*WRITE_REG32((len | (packets << 19)), DIEPTSIZ(ep));*/ // packets+transfer size
165 WRITE_REG32(DIEPTSIZ(ep), len | (packets << 19));
166
167 //flush cache
168 WriteBackDataCacheRange ((void*)ptr, len);
169
170 g_dma_desc_in->status.b.bs = 0x3;
171 g_dma_desc_in->status.b.l = 1;
172 g_dma_desc_in->status.b.ioc = 1;
173 g_dma_desc_in->status.b.sp = 1;
174 g_dma_desc_in->status.b.bytes = len;
175 g_dma_desc_in->buf = (UINT32)((UINTN)ptr);
176 g_dma_desc_in->status.b.sts = 0;
177 g_dma_desc_in->status.b.bs = 0x0;
178 WRITE_REG32(DIEPDMA(ep), (unsigned long)(g_dma_desc_in)); // ptr is DMA address
179 }
180 asm("dsb sy");
181 asm("isb sy");
182 /* epena & cnak*/
183 WRITE_REG32(DIEPCTL(ep), READ_REG32(DIEPCTL(ep)) | 0x84000800);
184 return;
185}
186
187STATIC VOID ep_rx(unsigned ep, UINT32 len)
188{
189 /* EPx UNSTALL */
190 WRITE_REG32(DOEPCTL(ep), ((READ_REG32(DOEPCTL(ep))) & (~0x00200000)));
191 /* EPx OUT ACTIVE */
192 WRITE_REG32(DOEPCTL(ep), (READ_REG32(DOEPCTL(ep)) | 0x8000));
193
194 if (len >= DATA_SIZE)
195 rx_desc_bytes = DATA_SIZE;
196 else
197 rx_desc_bytes = len;
198
199 rx_buf = AllocatePool (DATA_SIZE);
200 ASSERT (rx_buf != NULL);
201
202 InvalidateDataCacheRange (rx_buf, len);
203
204 g_dma_desc->status.b.bs = 0x3;
205 g_dma_desc->status.b.mtrf = 0;
206 g_dma_desc->status.b.sr = 0;
207 g_dma_desc->status.b.l = 1;
208 g_dma_desc->status.b.ioc = 1;
209 g_dma_desc->status.b.sp = 0;
210 g_dma_desc->status.b.bytes = rx_desc_bytes;
211 g_dma_desc->buf = (UINT32)((UINTN)rx_buf);
212 g_dma_desc->status.b.sts = 0;
213 g_dma_desc->status.b.bs = 0x0;
214
215 asm("dsb sy");
216 asm("isb sy");
217 WRITE_REG32(DOEPDMA(ep), (UINT32)((UINTN)g_dma_desc));
218 /* EPx OUT ENABLE CLEARNAK */
219 WRITE_REG32(DOEPCTL(ep), (READ_REG32(DOEPCTL(ep)) | 0x84000000));
220}
221
222STATIC
223EFI_STATUS
224HandleGetDescriptor (
225 IN USB_DEVICE_REQUEST *Request
226 )
227{
228 UINT8 DescriptorType;
229 UINTN ResponseSize;
230 VOID *ResponseData;
231 CHAR16 SerialNo[16];
232 UINTN SerialNoLen;
233 EFI_STATUS Status;
234
235 ResponseSize = 0;
236 ResponseData = NULL;
237
238 // Pretty confused if bmRequestType is anything but this:
239 ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
240
241 // Choose the response
242 DescriptorType = Request->Value >> 8;
243 switch (DescriptorType) {
244 case USB_DESC_TYPE_DEVICE:
245 DEBUG ((EFI_D_INFO, "USB: Got a request for device descriptor\n"));
246 ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
247 ResponseData = mDeviceDescriptor;
248 break;
249 case USB_DESC_TYPE_CONFIG:
250 DEBUG ((EFI_D_INFO, "USB: Got a request for config descriptor\n"));
251 ResponseSize = mConfigDescriptor->TotalLength;
252 ResponseData = mDescriptors;
253 break;
254 case USB_DESC_TYPE_STRING:
255 DEBUG ((EFI_D_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
256 switch (Request->Value & 0xff) {
257 case 0:
258 ResponseSize = mLangStringDescriptor.Length;
259 ResponseData = &mLangStringDescriptor;
260 break;
261 case 1:
262 ResponseSize = mManufacturerStringDescriptor.Length;
263 ResponseData = &mManufacturerStringDescriptor;
264 break;
265 case 2:
266 ResponseSize = mProductStringDescriptor.Length;
267 ResponseData = &mProductStringDescriptor;
268 break;
269 case 3:
270 Status = gRT->GetVariable (
271 (CHAR16*)L"SerialNo",
272 &gArmGlobalVariableGuid,
273 NULL,
274 &SerialNoLen,
275 SerialNo
276 );
277 if (EFI_ERROR (Status) == 0) {
278 CopyMem (mSerialStringDescriptor.String, SerialNo, SerialNoLen);
279 }
280 ResponseSize = mSerialStringDescriptor.Length;
281 ResponseData = &mSerialStringDescriptor;
282 break;
283 }
284 break;
285 default:
286 DEBUG ((EFI_D_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
287 break;
288 }
289
290 // Send the response
291 if (ResponseData) {
292 ASSERT (ResponseSize != 0);
293
294 if (Request->Length < ResponseSize) {
295 // Truncate response
296 ResponseSize = Request->Length;
297 } else if (Request->Length > ResponseSize) {
298 DEBUG ((EFI_D_INFO, "USB: Info: ResponseSize < wLength\n"));
299 }
300
301 ep_tx(0, ResponseData, ResponseSize);
302 }
303
304 return EFI_SUCCESS;
305}
306
307STATIC
308EFI_STATUS
309HandleSetAddress (
310 IN USB_DEVICE_REQUEST *Request
311 )
312{
313 // Pretty confused if bmRequestType is anything but this:
314 ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
315 DEBUG ((EFI_D_INFO, "USB: Setting address to %d\n", Request->Value));
316 reset_endpoints();
317
318 WRITE_REG32(DCFG, (READ_REG32(DCFG) & ~0x7F0) | (Request->Value << 4));
319 ep_tx(0, 0, 0);
320
321 return EFI_SUCCESS;
322}
323
324int usb_drv_request_endpoint(unsigned int type, int dir)
325{
326 unsigned int ep = 1; /*FIXME*/
327 int ret;
328 unsigned long newbits;
329
330 ret = (int)ep | dir;
331 newbits = (type << 18) | 0x10000000;
332
333 /*
334 * (type << 18):Endpoint Type (EPType)
335 * 0x10000000:Endpoint Enable (EPEna)
336 * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
337 * (ep<<22):TxFIFO Number (TxFNum)
338 * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
339 */
340 if (dir) { // IN: to host
341 WRITE_REG32(DIEPCTL(ep), ((READ_REG32(DIEPCTL(ep)))& ~0x000C0000) | newbits | (ep<<22)|0x20000);
342 } else { // OUT: to device
343 WRITE_REG32(DOEPCTL(ep), ((READ_REG32(DOEPCTL(ep))) & ~0x000C0000) | newbits);
344 }
345
346 return ret;
347}
348STATIC
349EFI_STATUS
350HandleSetConfiguration (
351 IN USB_DEVICE_REQUEST *Request
352 )
353{
354 ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
355
356 // Cancel all transfers
357 reset_endpoints();
358
359 usb_drv_request_endpoint(2, 0);
360 usb_drv_request_endpoint(2, 0x80);
361
362 WRITE_REG32(DIEPCTL1, (READ_REG32(DIEPCTL1)) | 0x10088800);
363
364 /* Enable interrupts on all endpoints */
365 WRITE_REG32(DAINTMSK, 0xFFFFFFFF);
366
367 ep_rx(1, CMD_SIZE);
368 ep_tx(0, 0, 0);
369 return EFI_SUCCESS;
370}
371
372
373STATIC
374EFI_STATUS
375HandleDeviceRequest (
376 IN USB_DEVICE_REQUEST *Request
377 )
378{
379 EFI_STATUS Status;
380
381 switch (Request->Request) {
382 case USB_DEV_GET_DESCRIPTOR:
383 Status = HandleGetDescriptor (Request);
384 break;
385 case USB_DEV_SET_ADDRESS:
386 Status = HandleSetAddress (Request);
387 break;
388 case USB_DEV_SET_CONFIGURATION:
389 Status = HandleSetConfiguration (Request);
390 break;
391 default:
392 DEBUG ((EFI_D_ERROR,
393 "Didn't understand RequestType 0x%x Request 0x%x\n",
394 Request->RequestType, Request->Request));
395 Status = EFI_INVALID_PARAMETER;
396 break;
397 }
398
399 return Status;
400}
401
402
403// Instead of actually registering interrupt handlers, we poll the controller's
404// interrupt source register in this function.
405STATIC
406VOID
407CheckInterrupts (
408 IN EFI_EVENT Event,
409 IN VOID *Context
410 )
411{
412 UINT32 ints = READ_REG32(GINTSTS); // interrupt register
413 UINT32 epints;
414
415 /*
416 * bus reset
417 * The core sets this bit to indicate that a reset is detected on the USB.
418 */
419 if (ints & 0x1000) {
420 WRITE_REG32(DCFG, 0x800004);
421 reset_endpoints();
422 }
423
424 /*
425 * enumeration done, we now know the speed
426 * The core sets this bit to indicate that speed enumeration is complete. The
427 * application must read the Device Status (DSTS) register to obtain the
428 * enumerated speed.
429 */
430 if (ints & 0x2000) {
431 /* Set up the maximum packet sizes accordingly */
432 unsigned long maxpacket = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
433 //Set Maximum In Packet Size (MPS)
434 WRITE_REG32(DIEPCTL1, ((READ_REG32(DIEPCTL1)) & ~0x000003FF) | maxpacket);
435 //Set Maximum Out Packet Size (MPS)
436 WRITE_REG32(DOEPCTL1, ((READ_REG32(DOEPCTL1)) & ~0x000003FF) | maxpacket);
437 }
438
439 /*
440 * IN EP event
441 * The core sets this bit to indicate that an interrupt is pending on one of the IN
442 * endpoints of the core (in Device mode). The application must read the
443 * Device All Endpoints Interrupt (DAINT) register to determine the exact
444 * number of the IN endpoint on which the interrupt occurred, and then read
445 * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
446 * determine the exact cause of the interrupt. The application must clear the
447 * appropriate status bit in the corresponding DIEPINTn register to clear this bit.
448 */
449 if (ints & 0x40000) {
450 epints = READ_REG32(DIEPINT0);
451 WRITE_REG32(DIEPINT0, epints);
452 if (epints & 0x1) /* Transfer Completed Interrupt (XferCompl) */
453 DEBUG ((EFI_D_INFO, "INT: IN TX completed.DIEPTSIZ(0) = 0x%x.\n", READ_REG32(DIEPTSIZ0)));
454
455 epints = READ_REG32(DIEPINT1);
456 WRITE_REG32(DIEPINT1, epints);
457 if (epints & 0x1)
458 DEBUG ((EFI_D_INFO, "ep1: IN TX completed\n"));
459 }
460
461 /*
462 * OUT EP event
463 * The core sets this bit to indicate that an interrupt is pending on one of the
464 * OUT endpoints of the core (in Device mode). The application must read the
465 * Device All Endpoints Interrupt (DAINT) register to determine the exact
466 * number of the OUT endpoint on which the interrupt occurred, and then read
467 * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
468 * to determine the exact cause of the interrupt. The application must clear the
469 * appropriate status bit in the corresponding DOEPINTn register to clear this bit.
470 */
471 if (ints & 0x80000) {
472 /* indicates the status of an endpoint
473 * with respect to USB- and AHB-related events. */
474 epints = READ_REG32(DOEPINT0);
475 if(epints) {
476 WRITE_REG32(DOEPINT0, epints);
477 if (epints & 0x1)
478 DEBUG ((EFI_D_INFO,"INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32(DOEPTSIZ0)));
479 /*
480 *
481 IN Token Received When TxFIFO is Empty (INTknTXFEmp)
482 * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
483 * was empty. This interrupt is asserted on the endpoint for which the IN token
484 * was received.
485 */
486 if (epints & 0x8) { /* SETUP phase done */
487 // PRINT_DEBUG("Setup phase \n");
488 WRITE_REG32(DIEPCTL0, READ_REG32(DIEPCTL0) | 0x08000000);
489 WRITE_REG32(DOEPCTL0, READ_REG32(DOEPCTL0) | 0x08000000);
490 /*clear IN EP intr*/
491 WRITE_REG32(DIEPINT0, 0xffffffff);
492 HandleDeviceRequest((USB_DEVICE_REQUEST *)p_ctrlreq);
493 }
494
495 /* Make sure EP0 OUT is set up to accept the next request */
496 /* memset(p_ctrlreq, 0, NUM_ENDPOINTS*8); */
497 WRITE_REG32(DOEPTSIZ0, 0x60080040);
498 /*
499 * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
500 * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
501 * was empty. This interrupt is asserted on the endpoint for which the IN token
502 * was received.
503 */
504 g_dma_desc_ep0->status.b.bs = 0x3;
505 g_dma_desc_ep0->status.b.mtrf = 0;
506 g_dma_desc_ep0->status.b.sr = 0;
507 g_dma_desc_ep0->status.b.l = 1;
508 g_dma_desc_ep0->status.b.ioc = 1;
509 g_dma_desc_ep0->status.b.sp = 0;
510 g_dma_desc_ep0->status.b.bytes = 64;
511 g_dma_desc_ep0->buf = (UINT32)(UINTN)(p_ctrlreq);
512 g_dma_desc_ep0->status.b.sts = 0;
513 g_dma_desc_ep0->status.b.bs = 0x0;
514 WRITE_REG32(DOEPDMA0, (unsigned long)(g_dma_desc_ep0));
515 // endpoint enable; clear NAK
516 WRITE_REG32(DOEPCTL0, 0x84000000);
517 }
518
519 epints = (READ_REG32(DOEPINT1));
520 if(epints) {
521 WRITE_REG32(DOEPINT1, epints);
522 /* Transfer Completed Interrupt (XferCompl);Transfer completed */
523 if (epints & 0x1) {
524 asm("dsb sy");
525 asm("isb sy");
526
527 UINT32 bytes = rx_desc_bytes - g_dma_desc->status.b.bytes;
528 UINT32 len = 0;
529
530 if (MATCH_CMD_LITERAL ("download", rx_buf)) {
531 mNumDataBytes = AsciiStrHexToUint64 (rx_buf + sizeof ("download"));
532 } else {
533 if (mNumDataBytes != 0)
534 mNumDataBytes -= bytes;
535 }
536
537 mDataReceivedCallback (bytes, rx_buf);
538
539 if (mNumDataBytes == 0)
540 len = CMD_SIZE;
541 else if (mNumDataBytes > DATA_SIZE)
542 len = DATA_SIZE;
543 else
544 len = mNumDataBytes;
545
546 ep_rx(1, len);
547 }
548 }
549 }
550
551 //WRITE_REG32 clear ints
552 WRITE_REG32(GINTSTS, ints);
553}
554
555EFI_STATUS
556DwUsbSend (
557 IN UINT8 EndpointIndex,
558 IN UINTN Size,
559 IN CONST VOID *Buffer
560 )
561{
562 ep_tx(EndpointIndex, Buffer, Size);
563 return 0;
564}
565
566STATIC VOID phy_init()
567{
568 UINT32 val;
569
570 //setup clock
571 val = PHY_READ_REG32(0x200);
572 val |= BIT4;
573 PHY_WRITE_REG32(0x200, val);
574
575 //setup phy
576
577 val = PHY_READ_REG32(SC_PERIPH_RSTDIS0);
578 val |= RST0_USBOTG_BUS | RST0_POR_PICOPHY |
579 RST0_USBOTG | RST0_USBOTG_32K;
580 PHY_WRITE_REG32(SC_PERIPH_RSTDIS0, val);
581
582 val = PHY_READ_REG32(SC_PERIPH_CTRL5);
583 val &= ~CTRL5_PICOPHY_BC_MODE;
584 val |= CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB;
585 PHY_WRITE_REG32(SC_PERIPH_CTRL5, val);
586
587 val = PHY_READ_REG32(SC_PERIPH_CTRL4);
588 val &= ~(CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE);
589 val |= CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL |
590 CTRL4_OTG_PHY_SEL;
591 PHY_WRITE_REG32(SC_PERIPH_CTRL4, val);
592
593 PHY_WRITE_REG32(SC_PERIPH_CTRL8, EYE_PATTERN_PARA);
594}
595
596
597STATIC VOID usb_init()
598{
599 VOID* buf;
600
601 buf = UncachedAllocatePages (1);
602 g_dma_desc = buf;
603 g_dma_desc_ep0 = g_dma_desc + sizeof(struct dwc_otg_dev_dma_desc);
604 g_dma_desc_in = g_dma_desc_ep0 + sizeof(struct dwc_otg_dev_dma_desc);
605 p_ctrlreq = (USB_DEVICE_REQUEST *)g_dma_desc_in + sizeof(struct dwc_otg_dev_dma_desc);
606
607 SetMem(g_dma_desc, sizeof(struct dwc_otg_dev_dma_desc), 0);
608 SetMem(g_dma_desc_ep0, sizeof(struct dwc_otg_dev_dma_desc), 0);
609 SetMem(g_dma_desc_in, sizeof(struct dwc_otg_dev_dma_desc), 0);
610
611 /*Reset usb controller.*/
612 /* Wait for OTG AHB master idle */
613 while (!((READ_REG32(GRSTCTL)) & 0x80000000));
614
615 /* OTG: Assert Software Reset */
616 WRITE_REG32(GRSTCTL, 1);
617
618 /* Wait for OTG to ack reset */
619 while ((READ_REG32(GRSTCTL)) & 1);
620
621 /* Wait for OTG AHB master idle */
622 while (!((READ_REG32(GRSTCTL)) & 0x80000000));
623
624 WRITE_REG32(GDFIFOCFG, DATA_FIFO_CONFIG);
625 WRITE_REG32(GRXFSIZ, RX_SIZE);
626 WRITE_REG32(GNPTXFSIZ, ENDPOINT_TX_SIZE);
627 WRITE_REG32(DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
628
629 /*
630 * set Periodic TxFIFO Empty Level,
631 * Non-Periodic TxFIFO Empty Level,
632 * Enable DMA, Unmask Global Intr
633 */
634 WRITE_REG32(GAHBCFG, 0x1a1);
635
636 /*select 8bit UTMI+, ULPI Inerface*/
637 WRITE_REG32(GUSBCFG, 0x2400);
638
639 /* Detect usb work mode,host or device? */
640 while ((READ_REG32(GINTSTS)) & 1);
641 MicroSecondDelay(1);
642
643 /*Init global and device mode csr register.*/
644 /*set Non-Zero-Length status out handshake */
645 WRITE_REG32(DCFG, 0x800004);
646
647 /* Interrupt unmask: IN event, OUT event, bus reset */
648 WRITE_REG32(GINTMSK, 0xC3C08);
649
650 while ((READ_REG32(GINTSTS)) & 0x2000);
651
652 /* Clear any pending OTG Interrupts */
653 WRITE_REG32(GOTGINT, 0xFFFFFFFF);
654 /* Clear any pending interrupts */
655 WRITE_REG32(GINTSTS, 0xFFFFFFFF);
656 WRITE_REG32(GINTMSK, 0xFFFFFFFF);
657 WRITE_REG32(GOTGINT, READ_REG32(GOTGINT) & (~0x3000));
658 /*endpoint settings cfg*/
659 reset_endpoints();
660
661 /*init finish. and ready to transfer data*/
662
663 /* Soft Disconnect */
664 WRITE_REG32(DCTL, 0x802);
665 MicroSecondDelay(1);
666
667 /* Soft Reconnect */
668 WRITE_REG32(DCTL, 0x800);
669}
670
671EFI_STATUS
672EFIAPI
673DwUsbStart (
674 IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor,
675 IN VOID **Descriptors,
676 IN USB_DEVICE_RX_CALLBACK RxCallback,
677 IN USB_DEVICE_TX_CALLBACK TxCallback
678 )
679{
680 UINT8 *Ptr;
681 EFI_STATUS Status;
682 EFI_EVENT TimerEvent;
683
684 ASSERT (DeviceDescriptor != NULL);
685 ASSERT (Descriptors[0] != NULL);
686 ASSERT (RxCallback != NULL);
687 ASSERT (TxCallback != NULL);
688
689 usb_init();
690
691 mDeviceDescriptor = DeviceDescriptor;
692 mDescriptors = Descriptors[0];
693
694 // Right now we just support one configuration
695 ASSERT (mDeviceDescriptor->NumConfigurations == 1);
696 // ... and one interface
697 mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
698 ASSERT (mConfigDescriptor->NumInterfaces == 1);
699
700 Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
701 mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
702 Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
703
704 mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
705
706 mDataReceivedCallback = RxCallback;
707 mDataSentCallback = TxCallback;
708
709 // Register a timer event so CheckInterupts gets called periodically
710 Status = gBS->CreateEvent (
711 EVT_TIMER | EVT_NOTIFY_SIGNAL,
712 TPL_CALLBACK,
713 CheckInterrupts,
714 NULL,
715 &TimerEvent
716 );
717 ASSERT_EFI_ERROR (Status);
718 if (EFI_ERROR (Status)) {
719 return Status;
720 }
721
722 Status = gBS->SetTimer (
723 TimerEvent,
724 TimerPeriodic,
725 DW_INTERRUPT_POLL_PERIOD
726 );
727 ASSERT_EFI_ERROR (Status);
728
729 return Status;
730}
731
732USB_DEVICE_PROTOCOL mUsbDevice = {
733 DwUsbStart,
734 DwUsbSend
735};
736
737
738EFI_STATUS
739EFIAPI
740DwUsbEntryPoint (
741 IN EFI_HANDLE ImageHandle,
742 IN EFI_SYSTEM_TABLE *SystemTable
743 )
744{
745 EFI_HANDLE Handle;
746
747 phy_init();
748 Handle = NULL;
749 return gBS->InstallProtocolInterface (
750 &Handle,
751 &gUsbDeviceProtocolGuid,
752 EFI_NATIVE_INTERFACE,
753 &mUsbDevice
754 );
755}