📄 usbohci.c
字号:
/*
* Set the bit which indicates that the ports are to be powered on
* a per-port basis
*/
uRegisterValue |= 0x100;
USB_OHCI_REG_WRITE (uHostControllerIndex,
(pOhciControllerInfo->uBaseAddress +
USB_OHCI_RH_DESCRIPTOR_A_REGISTER_OFFSET),
uRegisterValue);
USB_OHCI_REG_WRITE (uHostControllerIndex,
(pOhciControllerInfo->uBaseAddress +
USB_OHCI_RH_DESCRIPTOR_B_REGISTER_OFFSET),
0xFFFF0000);
/* Disable and power off the ports and again power on the ports */
usbOhciPowerOffPorts(uHostControllerIndex);
/*
* Clear any pending interrupts
*/
USB_OHCI_REG_WRITE (uHostControllerIndex,
(pOhciControllerInfo->uBaseAddress +
USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET),
USB_OHCI_INTERRUPT_MASK);
#ifndef USB_OHCI_POLLING_MODE
/* Create the ISR event */
pOhciControllerInfo->isrEvent = OS_CREATE_EVENT(OS_EVENT_NON_SIGNALED);
/* Check whether the event was created successfully */
if (OS_INVALID_EVENT_ID == pOhciControllerInfo->isrEvent)
{
/* Failed to create ISR event */
OS_LOG_MESSAGE_HIGH(
OHCD, "Failed to create ISR event.\n", 0, 0, 0, 0);
return FALSE;
}
/* Register the interrupt handler for the OHCI Controller */
uTemp = (UINT32) uHostControllerIndex;
/* Call the function to register an ISR */
if (pOhciBusInfo[uHostControllerIndex]->pFuncIntConnect != NULL)
uStatus = pOhciBusInfo[uHostControllerIndex]->pFuncIntConnect
(usbOhciIsr,
uTemp,
pOhciControllerInfo->uIrqNumber);
else
uStatus = BUS_OPERATION_FAILURE;
/* Check whether the interrupt handler was registered successfully */
if (uStatus == BUS_OPERATION_FAILURE)
{
/* Failed to register the interrupt handler */
return FALSE;
}
/* Enable all the OHCI interrupts */
USB_OHCI_REG_WRITE (uHostControllerIndex,
(pOhciControllerInfo->uBaseAddress +
USB_OHCI_INTERRUPT_ENABLE_REGISTER_OFFSET),
USB_OHCI_INTERRUPT_MASK);
#endif /* End of #ifndef USB_OHCI_POLLING_MODE */
/* Spawn the interrupt handler in polling mode */
pOhciControllerInfo->isrThreadId =
OS_CREATE_THREAD("usbOhciIsr", /* Task Name */
100, /* Task Priority */
usbOhciPollingIsr, /* Task Entry Function */
uHostControllerIndex); /* Argument to the task */
/* Check whether the interrupt handler thread was created successfully */
if (pOhciControllerInfo->isrThreadId == OS_THREAD_FAILURE)
{
/* Debug message */
OS_LOG_MESSAGE_HIGH (
OHCD,
"Failed to spawn the interrupt handler thread.....\n",
0,
0,
0,
0);
/* Failed to spawn the interrupt handler */
return FALSE;
}
/* Initialize the OHCI Controller (END) */
/* Set the flag to indicate the host controller is initialized */
pOhciControllerInfo->bHostControllerInitialized = TRUE;
OS_LOG_MESSAGE_LOW(
OHCD,
"Exiting the function: usbOhciInitializeHostController().\n",
0,
0,
0,
0);
return TRUE;
} /* End of function usbOhciInitializeHostController() */
VOID usbOhciPowerOffPorts
(
UINT32 uHostControllerIndex
)
{
/* To hold the base address of the OHCI Controller */
UINT32 uBaseAddress = 0;
/* To hold the value read from the registers */
UINT32 uRegisterValue = 0;
/* To hold the loop index */
UINT32 uIndex = 0;
/* To hold the offset of the port status register */
UINT32 uPortStatusRegisterOffset = 0;
/* To hold the number of downstream ports */
UINT32 uNumberOfDownstreamPorts = 0;
/* To hold the pointer to the host controller information */
PUSB_OHCI_INFORMATION pOhciControllerInfo = NULL;
OS_LOG_MESSAGE_LOW(
OHCD,
"Entering the function: usbOhciPowerOffPorts().\n",
0,
0,
0,
0);
/* Obtain the pointer to the host controller information */
pOhciControllerInfo = &usbOhciControllerInfo[uHostControllerIndex];
/* Obtain the base address */
uBaseAddress = pOhciControllerInfo->uBaseAddress;
/*
* NOTE: If the root hub supports ganged power on the down stream ports,
* power on all the downstream ports. Else power on the specified
* port.
*/
/* Read the contents of the root hub descriptor A register */
uRegisterValue =
USB_OHCI_REG_READ(uHostControllerIndex, uBaseAddress +
USB_OHCI_RH_DESCRIPTOR_A_REGISTER_OFFSET);
uNumberOfDownstreamPorts = USB_OHCI_REG_READ(uHostControllerIndex,
uBaseAddress + USB_OHCI_RH_DESCRIPTOR_A_REGISTER_OFFSET);
/* Mask the other fields of the root hub description register */
uNumberOfDownstreamPorts = uNumberOfDownstreamPorts & 0x000000FF;
/* Obtain the number of ports supported by the host controller (END) */
/* Disable all the downstream ports then power up the ports*/
for (uIndex = 1; uIndex <= uNumberOfDownstreamPorts; uIndex++)
{
uPortStatusRegisterOffset =
USB_OHCI_RH_PORT_STATUS_REGISTER_OFFSET(uIndex);
/* Read the contents of the port status register */
uRegisterValue = USB_OHCI_REG_READ(uHostControllerIndex,
uBaseAddress + uPortStatusRegisterOffset);
/* Clear Port Enable */
USB_OHCI_REG_WRITE(uHostControllerIndex,
(uBaseAddress + uPortStatusRegisterOffset),
USB_OHCI_RH_PORT_STATUS_CCS);
}
/*
* Check whether the root hub supports ganged power on the down
* stream ports.
*/
if ((uRegisterValue & USB_OHCI_RH_DESCRIPTOR_A_REGISTER__PSM_MASK) == 0)
{
/*
* NOTE: Write 1 to the Local Power Status Change (LPSC) bit
* to set the port power state.
*/
USB_OHCI_REG_WRITE(uHostControllerIndex,
(uBaseAddress + USB_OHCI_RH_STATUS_REGISTER_OFFSET),
USB_OHCI_RH_STATUS__LPS);
/* Return from the function */
return;
}
/*
* Read the contents of the root hub descriptor B
* register
*/
uRegisterValue = USB_OHCI_REG_READ(uHostControllerIndex,
uBaseAddress +
USB_OHCI_RH_DESCRIPTOR_B_REGISTER_OFFSET);
/*
* Check whether the Port Power Control Mask bit
* is set for the specified port.
*
* a) If this bit is set, the port's power state
* is only affected by per-port power control
* (Set/ClearPortPower).
* b) If this bit is cleared, th port is
* controlled by the global power switch
* (Set/ClearGlobalPower).
*/
if (0 ==
(uRegisterValue &
USB_OHCI_HC_RH_DESCRIPTOR_B_REGISTER__PPCM_MASK))
{
/*
* Port power state is controlled by the
* global power switch
*/
/*
* NOTE: Write 1 to the Local Power Status (LPS)
* bit to clear the port power state.
*/
/*
* Root hub supports ganged power. Power off
* all the down stream ports
*/
USB_OHCI_REG_WRITE(uHostControllerIndex,
(uBaseAddress + USB_OHCI_RH_STATUS_REGISTER_OFFSET),
USB_OHCI_RH_STATUS__LPS);
return;
}
/* Obtain the number of ports supported by the host controller (BEGIN) */
/* Read the contents of the root hub description register */
uNumberOfDownstreamPorts = USB_OHCI_REG_READ(uHostControllerIndex,
uBaseAddress +
USB_OHCI_RH_DESCRIPTOR_A_REGISTER_OFFSET);
/* Mask the other fields of the root hub description register */
uNumberOfDownstreamPorts = uNumberOfDownstreamPorts & 0x000000FF;
/* Obtain the number of ports supported by the host controller (END) */
/* Power on all the downstream ports */
for (uIndex = 1; uIndex <= uNumberOfDownstreamPorts; uIndex++)
{
/* Obtain the base address of the port status register */
uPortStatusRegisterOffset =
USB_OHCI_RH_PORT_STATUS_REGISTER_OFFSET(uIndex);
/* Read the contents of the port status register */
uRegisterValue =
USB_OHCI_REG_READ(uHostControllerIndex,
uBaseAddress + uPortStatusRegisterOffset);
/*
* NOTE: Write 1 to the Low Speed Device Attach
* (LSDA) bit to clear the port power state.
*/
/* Clear the port power state */
USB_OHCI_REG_WRITE(uHostControllerIndex,
(uBaseAddress + uPortStatusRegisterOffset),
USB_OHCI_RH_PORT_STATUS_LSDA);
}
OS_LOG_MESSAGE_LOW(
OHCD,
"Exiting the function: usbOhciPowerOffPorts().\n",
0,
0,
0,
0);
return;
} /* End of function usbOhciPowerOffPorts () */
/*******************************************************************************
*
* usbOhciDisable - function to disable the OHCI controller
*
* This function is called on a warm reboot. It power-offs all the port of the
* controller followed by resetting hte host controller.
*
* RETURNS: N/A
*
* ERRNO: none
*
* \NOMANUAL
*/
LOCAL VOID usbOhciDisable
(
int startType
)
{
/* To hold the pointer to the host controller information */
PUSB_OHCI_INFORMATION pOhciControllerInfo = NULL;
UINT8 index = 0;
/* if the global array is NULL, return */
if (usbOhciControllerInfo == NULL || maxOhciCount == 0)
return;
while (index < maxOhciCount)
{
pOhciControllerInfo = &usbOhciControllerInfo[index];
if (pOhciControllerInfo)
{
/* power off the ports */
usbOhciPowerOffPorts (index);
/* Reset the OHCI Controller */
USB_OHCI_REG_WRITE (index,
(pOhciControllerInfo->uBaseAddress +
USB_OHCI_COMMAND_STATUS_REGISTER_OFFSET),
USB_OHCI_COMMAND_STATUS_HCR);
#ifndef USB_OHCI_POLLING_MODE
/* Unregister the IRQ */
if ((pOhciBusInfo[index] != NULL) &&
(pOhciBusInfo[index]->pFuncIntDisconnect != NULL))
pOhciBusInfo[index]->pFuncIntDisconnect
(usbOhciIsr,
index,
pOhciControllerInfo->uIrqNumber);
#endif
}
index++;
}
return;
}
#ifdef NO_CACHE_COHERENCY
/***************************************************************************
*
* usbOhciRegWrite - write contents to a HC register
*
* This function is used to write the contents to a host controller register.
*
* RETURNS: None
*
* ERRNO:
* None.
*
* \NOMANUAL
*/
VOID usbOhciRegWrite
(
UINT32 index, /* Index of host controller */
UINT32 address,/* Address to which contents have to be written */
UINT32 value /* Value to be written */
)
{
(*((volatile UINT32 *) (address)) =
(USB_OHCD_SWAP_DATA (index, (value)))) ;
cacheFlush(DATA_CACHE,(pVOID)address, 4);
}
/***************************************************************************
*
* usbOhciRegRead - read contents of a HC register
*
* This function is used to read the contents of a host controller register.
*
* RETURNS: UINT32 value which indicates contents of the register
*
* ERRNO:
* None.
*
* \NOMANUAL
*/
UINT32 usbOhciRegRead
(
UINT32 index, /* Index of host controller */
UINT32 address /* Address from which contents have to be read */
)
{
cacheInvalidate(DATA_CACHE, (pVOID)address, 4);
return (USB_OHCD_SWAP_DATA (index, *((volatile UINT32 *)address)));
}
#endif /* End of NO_CACHE_COHERENCY */
/* End of File usbOhci.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -