+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-\r
-#include <IndustryStandard/Usb.h>\r
-\r
-#include <Protocol/UsbDevice.h>\r
-\r
-#include "Isp1761UsbDxe.h"\r
-\r
-/*\r
- Driver for using the NXP ISP1761 as a USB Peripheral controller.\r
- Doesn't use USB OTG - just sets it in Pure Peripheral mode.\r
-\r
- The ISP1582 datasheet has a little more info on the Peripheral controller\r
- registers than the ISP1761 datasheet\r
-\r
- We don't do string descriptors. They're optional.\r
- We currently assume the device has one configuration, one interface, one IN\r
- endpoint, and one OUT endpoint (plus the default control endpoint).\r
-\r
- In fact, this driver is the minimum required to implement fastboot.\r
-*/\r
-\r
-// TODO Make sure the controller isn't sending empty packets when it shouldn't\r
-// (check behaviour in cases when Buffer Length isn't explicitly set)\r
-\r
-// ISP1582 Datasheet:\r
-// "Data transfers preceding the status stage must first be fully\r
-// completed before the STATUS bit can be set."\r
-// This variable stores whether some control data has been pended in the EP0TX\r
-// Tx buffer, so that when an EP0TX interrupt is received we can set the STATUS\r
-// bit to go to the Status stage of the control transfer.\r
-STATIC BOOLEAN mControlTxPending = FALSE;\r
-\r
-STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor;\r
-\r
-// The config descriptor, interface descriptor, and endpoint descriptors in a\r
-// buffer (in that order)\r
-STATIC VOID *mDescriptors;\r
-// Convenience pointers to those descriptors inside the buffer:\r
-STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor;\r
-STATIC USB_CONFIG_DESCRIPTOR *mConfigDescriptor;\r
-STATIC USB_ENDPOINT_DESCRIPTOR *mEndpointDescriptors;\r
-\r
-STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback;\r
-STATIC USB_DEVICE_TX_CALLBACK mDataSentCallback;\r
-\r
-// The time between interrupt polls, in units of 100 nanoseconds\r
-// 10 Microseconds\r
-#define ISP1761_INTERRUPT_POLL_PERIOD 10000\r
-\r
-STATIC\r
-VOID\r
-SelectEndpoint (\r
- IN UINT8 Endpoint\r
- )\r
-{\r
- // The DMA Endpoint Index must not point to the same as the\r
- // Endpoint Index Register.\r
- WRITE_REG32 (ISP1761_DMA_ENDPOINT_INDEX, ((Endpoint + 2) % ISP1761_NUM_ENDPOINTS));\r
- WRITE_REG32 (ISP1761_ENDPOINT_INDEX, Endpoint);\r
-}\r
-\r
-// Enable going to the Data stage of a control transfer\r
-STATIC\r
-VOID\r
-DataStageEnable (\r
- IN UINT8 Endpoint\r
- )\r
-{\r
- SelectEndpoint (Endpoint);\r
- WRITE_REG32 (ISP1761_CTRL_FUNCTION, ISP1761_CTRL_FUNCTION_DSEN);\r
-}\r
-\r
-// Go to the Status stage of a successful control transfer\r
-STATIC\r
-VOID\r
-StatusAcknowledge (\r
- IN UINT8 Endpoint\r
-)\r
-{\r
- SelectEndpoint (Endpoint);\r
- WRITE_REG32 (ISP1761_CTRL_FUNCTION, ISP1761_CTRL_FUNCTION_STATUS);\r
-}\r
-\r
-// Read the FIFO for the endpoint indexed by Endpoint, into the buffer pointed\r
-// at by Buffer, whose size is *Size bytes.\r
-//\r
-// If *Size is less than the number of bytes in the FIFO, return EFI_BUFFER_TOO_SMALL\r
-//\r
-// Update *Size with the number of bytes of data in the FIFO.\r
-STATIC\r
-EFI_STATUS\r
-ReadEndpointBuffer (\r
- IN UINT8 Endpoint,\r
- IN OUT UINTN *Size,\r
- IN OUT VOID *Buffer\r
- )\r
-{\r
- UINT16 NumBytesAvailable;\r
- UINT32 Val32;\r
- UINTN Index;\r
- UINTN NumBytesRead;\r
-\r
- SelectEndpoint (Endpoint);\r
-\r
- NumBytesAvailable = READ_REG16 (ISP1761_BUFFER_LENGTH);\r
-\r
- if (NumBytesAvailable > *Size) {\r
- *Size = NumBytesAvailable;\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
- *Size = NumBytesAvailable;\r
-\r
- /* -- NB! --\r
- The datasheet says the Data Port is 16 bits but it actually appears to\r
- be 32 bits.\r
- */\r
-\r
- // Read 32-bit chunks\r
- for (Index = 0; Index < NumBytesAvailable / 4; Index++) {\r
- ((UINT32 *) Buffer)[Index] = READ_REG32 (ISP1761_DATA_PORT);\r
- }\r
-\r
- // Read remaining bytes\r
-\r
- // Round NumBytesAvailable down to nearest power of 4\r
- NumBytesRead = NumBytesAvailable & (~0x3);\r
- if (NumBytesRead != NumBytesAvailable) {\r
- Val32 = READ_REG32 (ISP1761_DATA_PORT);\r
- // Copy each required byte of 32-bit word into buffer\r
- for (Index = 0; Index < NumBytesAvailable % 4; Index++) {\r
- ((UINT8 *) Buffer)[NumBytesRead + Index] = Val32 >> (Index * 8);\r
- }\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/*\r
- Write an endpoint buffer. Parameters:\r
- Endpoint Endpoint index (see Endpoint Index Register in datasheet)\r
- MaxPacketSize The MaxPacketSize this endpoint is configured for\r
- Size The size of the Buffer\r
- Buffer The data\r
-\r
- Assumes MaxPacketSize is a multiple of 4.\r
- (It seems that all valid values for MaxPacketSize _are_ multiples of 4)\r
-*/\r
-STATIC\r
-EFI_STATUS\r
-WriteEndpointBuffer (\r
- IN UINT8 Endpoint,\r
- IN UINTN MaxPacketSize,\r
- IN UINTN Size,\r
- IN CONST VOID *Buffer\r
- )\r
-{\r
- UINTN Index;\r
- UINT32 *DwordBuffer;\r
-\r
- DwordBuffer = (UINT32 *) Buffer;\r
- SelectEndpoint (Endpoint);\r
-\r
- /* -- NB! --\r
- The datasheet says the Data Port is 16 bits but it actually appears to\r
- be 32 bits.\r
- */\r
-\r
- // Write packets of size MaxPacketSize\r
- while (Size > MaxPacketSize) {\r
- for (Index = 0; Index < MaxPacketSize / 4; Index++) {\r
- WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[Index]);\r
- }\r
- Size -= MaxPacketSize;\r
- DwordBuffer += (MaxPacketSize / sizeof (UINT32));\r
- }\r
-\r
- // Write remaining data\r
-\r
- if (Size > 0) {\r
- WRITE_REG32 (ISP1761_BUFFER_LENGTH, Size);\r
-\r
- while (Size > 4) {\r
- WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[0]);\r
- Size -= 4;\r
- DwordBuffer++;\r
- }\r
-\r
- if (Size > 0) {\r
- WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[0]);\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-HandleGetDescriptor (\r
- IN USB_DEVICE_REQUEST *Request\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 DescriptorType;\r
- UINTN ResponseSize;\r
- VOID *ResponseData;\r
-\r
- ResponseSize = 0;\r
- ResponseData = NULL;\r
- Status = EFI_SUCCESS;\r
-\r
- // Pretty confused if bmRequestType is anything but this:\r
- ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);\r
-\r
- // Choose the response\r
- DescriptorType = Request->Value >> 8;\r
- switch (DescriptorType) {\r
- case USB_DESC_TYPE_DEVICE:\r
- DEBUG ((EFI_D_INFO, "USB: Got a request for device descriptor\n"));\r
- ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);\r
- ResponseData = mDeviceDescriptor;\r
- break;\r
- case USB_DESC_TYPE_CONFIG:\r
- DEBUG ((EFI_D_INFO, "USB: Got a request for config descriptor\n"));\r
- ResponseSize = mConfigDescriptor->TotalLength;\r
- ResponseData = mDescriptors;\r
- break;\r
- case USB_DESC_TYPE_STRING:\r
- DEBUG ((EFI_D_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));\r
- break;\r
- default:\r
- DEBUG ((EFI_D_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));\r
- Status = EFI_NOT_FOUND;\r
- break;\r
- }\r
-\r
- // Send the response\r
- if (ResponseData) {\r
- ASSERT (ResponseSize != 0);\r
-\r
- if (Request->Length < ResponseSize) {\r
- // Truncate response\r
- ResponseSize = Request->Length;\r
- } else if (Request->Length > ResponseSize) {\r
- DEBUG ((EFI_D_INFO, "USB: Info: ResponseSize < wLength\n"));\r
- }\r
-\r
- DataStageEnable (ISP1761_EP0TX);\r
- Status = WriteEndpointBuffer (\r
- ISP1761_EP0TX,\r
- MAX_PACKET_SIZE_CONTROL,\r
- ResponseSize,\r
- ResponseData\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- // Setting this value should cause us to go to the Status stage on the\r
- // next EP0TX interrupt\r
- mControlTxPending = TRUE;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-HandleSetAddress (\r
- IN USB_DEVICE_REQUEST *Request\r
- )\r
-{\r
- // Pretty confused if bmRequestType is anything but this:\r
- ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);\r
- // USB Spec: "The USB device does not change its device address until after\r
- // the Status stage of this request is completed successfully."\r
- // ISP1582 datasheet: "The new device address is activated when the\r
- // device receives an acknowledgment from the host for the empty packet\r
- // token". (StatusAcknowledge causes an empty packet to be sent).\r
- // So, we write the Address register _before_ acking the SET_ADDRESS.\r
- DEBUG ((EFI_D_INFO, "USB: Setting address to %d\n", Request->Value));\r
- WRITE_REG32 (ISP1761_ADDRESS, Request->Value | ISP1761_ADDRESS_DEVEN);\r
- StatusAcknowledge (ISP1761_EP0TX);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-// Move the device to the Configured state.\r
-// (This code only supports one configuration for a device, so the configuration\r
-// index is ignored)\r
-STATIC\r
-EFI_STATUS\r
-HandleSetConfiguration (\r
- IN USB_DEVICE_REQUEST *Request\r
- )\r
-{\r
- USB_ENDPOINT_DESCRIPTOR *EPDesc;\r
- UINTN Index;\r
- UINT8 EndpointIndex;\r
-\r
- ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);\r
- DEBUG ((EFI_D_INFO, "USB: Setting configuration.\n"));\r
-\r
- // Configure endpoints\r
- for (Index = 0; Index < mInterfaceDescriptor->NumEndpoints; Index++) {\r
- EPDesc = &mEndpointDescriptors[Index];\r
-\r
- // To simplify for now, assume endpoints aren't "sparse", and are in order.\r
- ASSERT ((EPDesc->EndpointAddress & 0xF) == ((Index / 2) + 1));\r
-\r
- // Convert from USB endpoint index to ISP1761 endpoint Index\r
- // USB: Endpoint number is bits [3:0], IN/OUT is bit [7]\r
- // ISP1761: Endpoint number is bits [4:1], IN/OUT is bit [0]\r
- EndpointIndex = ((EPDesc->EndpointAddress & 0xF) << 1) |\r
- ((EPDesc->EndpointAddress & BIT7) >> 7);\r
- SelectEndpoint (EndpointIndex);\r
- // Set endpoint type (Bulk/Isochronous/Interrupt)\r
- WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, EPDesc->MaxPacketSize);\r
- // Hardware foible (bug?): Although the datasheet seems to suggest it should\r
- // automatically be set to MaxPacketSize, the Buffer Length register appears\r
- // to be reset to 0, which causes an empty packet to be sent in response to\r
- // the first IN token of the session. The NOEMPKT field of the Endpoint Type\r
- // register sounds like it might fix this problem, but it doesn't\r
- // (it's "applicable only in the DMA mode").\r
- WRITE_REG32 (ISP1761_BUFFER_LENGTH, EPDesc->MaxPacketSize);\r
- WRITE_REG32 (ISP1761_ENDPOINT_TYPE, (EPDesc->Attributes & 0x3) |\r
- ISP1761_ENDPOINT_TYPE_ENABLE);\r
- }\r
-\r
- StatusAcknowledge (ISP1761_EP0TX);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-HandleDeviceRequest (\r
- IN USB_DEVICE_REQUEST *Request\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- switch (Request->Request) {\r
- case USB_DEV_GET_DESCRIPTOR:\r
- Status = HandleGetDescriptor (Request);\r
- break;\r
- case USB_DEV_SET_ADDRESS:\r
- Status = HandleSetAddress (Request);\r
- break;\r
- case USB_DEV_SET_CONFIGURATION:\r
- Status = HandleSetConfiguration (Request);\r
- break;\r
- default:\r
- DEBUG ((EFI_D_ERROR,\r
- "Didn't understand RequestType 0x%x Request 0x%x\n",\r
- Request->RequestType, Request->Request));\r
- Status = EFI_INVALID_PARAMETER;\r
- break;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-// Instead of actually registering interrupt handlers, we poll the controller's\r
-// interrupt source register in this function.\r
-STATIC\r
-VOID\r
-CheckInterrupts (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- UINT32 DcInterrupts;\r
- UINTN NumBytes;\r
- UINTN MoreBytes;\r
- UINT8 Packet[512];\r
- VOID *DataPacket;\r
- UINT32 HandledInterrupts;\r
- UINT32 UnhandledInterrupts;\r
- EFI_STATUS Status;\r
-\r
- // Set bits in HandledInterrupts to mark the interrupt source handled.\r
- HandledInterrupts = 0;\r
-\r
- WRITE_REG32 (ISP1761_DEVICE_UNLOCK, ISP1761_DEVICE_UNLOCK_MAGIC);\r
-\r
- DcInterrupts = READ_REG32 (ISP1761_DC_INTERRUPT);\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_SUSP) {\r
- DEBUG ((EFI_D_INFO, "USB: Suspend\n"));\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_SUSP;\r
- }\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_RESUME) {\r
- DEBUG ((EFI_D_INFO, "USB: Resume\n"));\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_RESUME;\r
- }\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0SETUP) {\r
- NumBytes = 512;\r
- ReadEndpointBuffer (0x20, &NumBytes, &Packet);\r
- ASSERT (NumBytes == 8);\r
- HandleDeviceRequest ((USB_DEVICE_REQUEST *) Packet);\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0SETUP;\r
- }\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0RX) {\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0RX;\r
- }\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0TX) {\r
- if (mControlTxPending) {\r
- // We previously put some data in the Control Endpoint's IN (Tx) FIFO.\r
- // We assume that that data has now been sent in response to the IN token\r
- // that triggered this interrupt. We can therefore go to the Status stage\r
- // of the control transfer.\r
- StatusAcknowledge (ISP1761_EP0TX);\r
- mControlTxPending = FALSE;\r
- }\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0TX;\r
- }\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_EP1RX) {\r
- NumBytes = 512;\r
- DataPacket = AllocatePool (NumBytes);\r
- Status = ReadEndpointBuffer (ISP1761_EP1RX, &NumBytes, DataPacket);\r
- if (EFI_ERROR (Status) || NumBytes == 0) {\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Couldn't read EP1RX data: %r\n", Status));\r
- }\r
- FreePool (DataPacket);\r
- } else {\r
- // Signal this event again so we poll again ASAP\r
- gBS->SignalEvent (Event);\r
- mDataReceivedCallback (NumBytes, DataPacket);\r
- }\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_EP1RX;\r
- }\r
- if (DcInterrupts & ISP1761_DC_INTERRUPT_EP1TX) {\r
- mDataSentCallback (1);\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_EP1TX;\r
- }\r
- if (DcInterrupts & (ISP1761_DC_INTERRUPT_SOF | ISP1761_DC_INTERRUPT_PSOF)) {\r
- // Don't care about SOFs or pseudo-SOFs\r
- HandledInterrupts |= (ISP1761_DC_INTERRUPT_SOF | ISP1761_DC_INTERRUPT_PSOF);\r
- }\r
- if (ISP1761_DC_INTERRUPT_BRESET) {\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_BRESET;\r
- }\r
- if (ISP1761_DC_INTERRUPT_HS_STAT) {\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_HS_STAT;\r
- }\r
- if (ISP1761_DC_INTERRUPT_VBUS) {\r
- HandledInterrupts |= ISP1761_DC_INTERRUPT_VBUS;\r
- }\r
-\r
- UnhandledInterrupts = DcInterrupts & (~HandledInterrupts) & ISP1761_DC_INTERRUPT_MASK;\r
- if (UnhandledInterrupts) {\r
- DEBUG ((EFI_D_ERROR, "USB: Unhandled DC Interrupts: 0x%08x\n",\r
- UnhandledInterrupts));\r
- }\r
-\r
- // Check if we received any more data while we were handling the interrupt.\r
- SelectEndpoint (ISP1761_EP1RX);\r
- MoreBytes = READ_REG16 (ISP1761_BUFFER_LENGTH);\r
- if (MoreBytes) {\r
- HandledInterrupts &= ~ISP1761_DC_INTERRUPT_EP1RX;\r
- }\r
-\r
- WRITE_REG32 (ISP1761_DC_INTERRUPT, HandledInterrupts);\r
-}\r
-\r
-EFI_STATUS\r
-Isp1761PeriphSend (\r
- IN UINT8 EndpointIndex,\r
- IN UINTN Size,\r
- IN CONST VOID *Buffer\r
- )\r
-{\r
- return WriteEndpointBuffer (\r
- (EndpointIndex << 1) | 0x1, //Convert to ISP1761 endpoint index, Tx\r
- MAX_PACKET_SIZE_BULK,\r
- Size,\r
- Buffer\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-Isp1761PeriphStart (\r
- IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor,\r
- IN VOID **Descriptors,\r
- IN USB_DEVICE_RX_CALLBACK RxCallback,\r
- IN USB_DEVICE_TX_CALLBACK TxCallback\r
- )\r
-{\r
- UINT16 OtgStatus;\r
- UINT8 *Ptr;\r
- EFI_STATUS Status;\r
- EFI_EVENT TimerEvent;\r
-\r
- ASSERT (DeviceDescriptor != NULL);\r
- ASSERT (Descriptors[0] != NULL);\r
- ASSERT (RxCallback != NULL);\r
- ASSERT (TxCallback != NULL);\r
-\r
- WRITE_REG32 (ISP1761_DEVICE_UNLOCK, ISP1761_DEVICE_UNLOCK_MAGIC);\r
-\r
- WRITE_REG32 (ISP1761_SW_RESET_REG, ISP1761_SW_RESET_ALL);\r
- while (READ_REG32 (ISP1761_SW_RESET_REG) & ISP1761_SW_RESET_ALL) {\r
- //busy wait\r
- }\r
- WRITE_REG32 (ISP1761_MODE, ISP1761_MODE_SFRESET);\r
- while (READ_REG32 (ISP1761_MODE) & ISP1761_MODE_SFRESET) {\r
- //busy wait\r
- }\r
- DEBUG ((EFI_D_INFO, "USB: Software reset done\n"));\r
-\r
- WRITE_REG32 (ISP1761_DC_INTERRUPT_ENABLE, 0x03FFFFFF);\r
- WRITE_REG32 (ISP1761_OTG_INTERRUPT_ENABLE_RISE, 0x07FF);\r
-\r
- WRITE_REG8 (ISP1761_ADDRESS, ISP1761_ADDRESS_DEVEN);\r
- WRITE_REG8 (ISP1761_MODE, ISP1761_MODE_WKUPCS | ISP1761_MODE_CLKAON);\r
-\r
- // Use port 1 as peripheral controller (magic - disagrees with datasheet)\r
- WRITE_REG32 (ISP1761_OTG_CTRL_SET, 0xffff0000);\r
- WRITE_REG32 (ISP1761_OTG_CTRL_SET, 0x000014d1);\r
-\r
- OtgStatus = READ_REG16 (ISP1761_OTG_STATUS);\r
- if ((OtgStatus & ISP1761_OTG_STATUS_B_SESS_END) != 0) {\r
- DEBUG ((EFI_D_ERROR, "USB: Vbus not powered.\n"));\r
- }\r
- if ((OtgStatus & ISP1761_OTG_STATUS_A_B_SESS_VLD) == 0) {\r
- DEBUG ((EFI_D_ERROR, "USB: Session not valid.\n"));\r
- }\r
-\r
- // Configure Control endpoints\r
- SelectEndpoint (0x20);\r
- WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL);\r
- WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE);\r
- SelectEndpoint (0x0);\r
- WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL);\r
- WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE);\r
- SelectEndpoint (0x1);\r
- WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL);\r
- WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE);\r
-\r
- // Interrupt on all ACK and NAK\r
- WRITE_REG32 (ISP1761_INTERRUPT_CONFIG, ISP1761_INTERRUPT_CONFIG_ACK_ONLY);\r
-\r
- mDeviceDescriptor = DeviceDescriptor;\r
- mDescriptors = Descriptors[0];\r
-\r
- // Right now we just support one configuration\r
- ASSERT (mDeviceDescriptor->NumConfigurations == 1);\r
- // ... and one interface\r
- mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;\r
- ASSERT (mConfigDescriptor->NumInterfaces == 1);\r
-\r
- Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);\r
- mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;\r
- Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);\r
-\r
- mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
-\r
- mDataReceivedCallback = RxCallback;\r
- mDataSentCallback = TxCallback;\r
-\r
- // Register a timer event so CheckInterrupts gets called periodically\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- CheckInterrupts,\r
- NULL,\r
- &TimerEvent\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->SetTimer (\r
- TimerEvent,\r
- TimerPeriodic,\r
- ISP1761_INTERRUPT_POLL_PERIOD\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
-\r
-USB_DEVICE_PROTOCOL mUsbDevice = {\r
- Isp1761PeriphStart,\r
- Isp1761PeriphSend\r
-};\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-Isp1761PeriphEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- UINT32 DeviceId;\r
- EFI_HANDLE Handle;\r
-\r
- DeviceId = READ_REG32 (ISP1761_DEVICE_ID);\r
-\r
- if (DeviceId != ISP1761_DEVICE_ID_VAL) {\r
- DEBUG ((EFI_D_ERROR,\r
- "ERROR: Read incorrect device ID for ISP1761: 0x%08x, expected 0x%08x\n",\r
- DeviceId , ISP1761_DEVICE_ID_VAL\r
- ));\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Handle = NULL;\r
- return gBS->InstallProtocolInterface (\r
- &Handle,\r
- &gUsbDeviceProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &mUsbDevice\r
- );\r
-}\r
+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#ifndef __ISP1761_USB_DXE_H__\r
-#define __ISP1761_USB_DXE_H__\r
-\r
-#define ISP1761_USB_BASE FixedPcdGet32 (PcdIsp1761BaseAddress)\r
-\r
-#define READ_REG32(Offset) MmioRead32 (ISP1761_USB_BASE + Offset)\r
-#define READ_REG16(Offset) (UINT16) READ_REG32 (Offset)\r
-#define WRITE_REG32(Offset, Val) MmioWrite32 (ISP1761_USB_BASE + Offset, Val)\r
-#define WRITE_REG16(Offset, Val) MmioWrite32 (ISP1761_USB_BASE + Offset, (UINT32) Val)\r
-#define WRITE_REG8(Offset, Val) MmioWrite32 (ISP1761_USB_BASE + Offset, (UINT32) Val)\r
-\r
-// Max packet size in bytes (For Full Speed USB 64 is the only valid value)\r
-#define MAX_PACKET_SIZE_CONTROL 64\r
-\r
-#define MAX_PACKET_SIZE_BULK 512\r
-\r
-// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer\r
-#define ISP1761_NUM_ENDPOINTS 16\r
-\r
-// Endpoint Indexes\r
-#define ISP1761_EP0SETUP 0x20\r
-#define ISP1761_EP0RX 0x00\r
-#define ISP1761_EP0TX 0x01\r
-#define ISP1761_EP1RX 0x02\r
-#define ISP1761_EP1TX 0x03\r
-\r
-// DcInterrupt bits\r
-#define ISP1761_DC_INTERRUPT_BRESET BIT0\r
-#define ISP1761_DC_INTERRUPT_SOF BIT1\r
-#define ISP1761_DC_INTERRUPT_PSOF BIT2\r
-#define ISP1761_DC_INTERRUPT_SUSP BIT3\r
-#define ISP1761_DC_INTERRUPT_RESUME BIT4\r
-#define ISP1761_DC_INTERRUPT_HS_STAT BIT5\r
-#define ISP1761_DC_INTERRUPT_DMA BIT6\r
-#define ISP1761_DC_INTERRUPT_VBUS BIT7\r
-#define ISP1761_DC_INTERRUPT_EP0SETUP BIT8\r
-#define ISP1761_DC_INTERRUPT_EP0RX BIT10\r
-#define ISP1761_DC_INTERRUPT_EP0TX BIT11\r
-#define ISP1761_DC_INTERRUPT_EP1RX BIT12\r
-#define ISP1761_DC_INTERRUPT_EP1TX BIT13\r
-// All valid peripheral controller interrupts\r
-#define ISP1761_DC_INTERRUPT_MASK 0x003FFFDFF\r
-\r
-#define ISP1761_ADDRESS 0x200\r
-#define ISP1761_ADDRESS_DEVEN BIT7\r
-\r
-#define ISP1761_MODE 0x20C\r
-#define ISP1761_MODE_DATA_BUS_WIDTH BIT8\r
-#define ISP1761_MODE_CLKAON BIT7\r
-#define ISP1761_MODE_SFRESET BIT4\r
-#define ISP1761_MODE_WKUPCS BIT2\r
-\r
-#define ISP1761_ENDPOINT_MAX_PACKET_SIZE 0x204\r
-\r
-#define ISP1761_ENDPOINT_TYPE 0x208\r
-#define ISP1761_ENDPOINT_TYPE_NOEMPKT BIT4\r
-#define ISP1761_ENDPOINT_TYPE_ENABLE BIT3\r
-\r
-#define ISP1761_INTERRUPT_CONFIG 0x210\r
-// Interrupt config value to only interrupt on ACK of IN and OUT tokens\r
-#define ISP1761_INTERRUPT_CONFIG_ACK_ONLY BIT2 | BIT5 | BIT6\r
-\r
-#define ISP1761_DC_INTERRUPT 0x218\r
-#define ISP1761_DC_INTERRUPT_ENABLE 0x214\r
-\r
-#define ISP1761_CTRL_FUNCTION 0x228\r
-#define ISP1761_CTRL_FUNCTION_VENDP BIT3\r
-#define ISP1761_CTRL_FUNCTION_DSEN BIT2\r
-#define ISP1761_CTRL_FUNCTION_STATUS BIT1\r
-\r
-#define ISP1761_DEVICE_UNLOCK 0x27C\r
-#define ISP1761_DEVICE_UNLOCK_MAGIC 0xAA37\r
-\r
-#define ISP1761_SW_RESET_REG 0x30C\r
-#define ISP1761_SW_RESET_ALL BIT0\r
-\r
-#define ISP1761_DEVICE_ID 0x370\r
-\r
-#define ISP1761_OTG_CTRL_SET 0x374\r
-#define ISP1761_OTG_CTRL_CLR OTG_CTRL_SET + 2\r
-#define ISP1761_OTG_CTRL_OTG_DISABLE BIT10\r
-#define ISP1761_OTG_CTRL_VBUS_CHRG BIT6\r
-#define ISP1761_OTG_CTRL_VBUS_DISCHRG BIT5\r
-#define ISP1761_OTG_CTRL_DM_PULLDOWN BIT2\r
-#define ISP1761_OTG_CTRL_DP_PULLDOWN BIT1\r
-#define ISP1761_OTG_CTRL_DP_PULLUP BIT0\r
-\r
-#define ISP1761_OTG_STATUS 0x378\r
-#define ISP1761_OTG_STATUS_B_SESS_END BIT7\r
-#define ISP1761_OTG_STATUS_A_B_SESS_VLD BIT1\r
-\r
-#define ISP1761_OTG_INTERRUPT_LATCH_SET 0x37C\r
-#define ISP1761_OTG_INTERRUPT_LATCH_CLR 0x37E\r
-#define ISP1761_OTG_INTERRUPT_ENABLE_RISE 0x384\r
-\r
-#define ISP1761_DMA_ENDPOINT_INDEX 0x258\r
-\r
-#define ISP1761_ENDPOINT_INDEX 0x22c\r
-#define ISP1761_DATA_PORT 0x220\r
-#define ISP1761_BUFFER_LENGTH 0x21c\r
-\r
-// Device ID Values\r
-#define PHILLIPS_VENDOR_ID_VAL 0x04cc\r
-#define ISP1761_PRODUCT_ID_VAL 0x1761\r
-#define ISP1761_DEVICE_ID_VAL ((ISP1761_PRODUCT_ID_VAL << 16) |\\r
- PHILLIPS_VENDOR_ID_VAL)\r
-\r
-#endif //ifndef __ISP1761_USB_DXE_H__\r