forked from xuos/xiuos
Modify xhci functions for USB core
This commit is contained in:
parent
9f3edeb6b4
commit
83a4b774b5
|
@ -544,7 +544,30 @@ void USBH_IRQHandler(void *param)
|
|||
* Functions for xHCI drivers. These functions are called by USB core.
|
||||
*/
|
||||
int xhci_usb_hc_init(uint32_t id){
|
||||
return 0;
|
||||
USB_ASSERT(id < CONFIG_USBHOST_XHCI_NUM);
|
||||
int rc = 0;
|
||||
struct usbh_bus *bus = usbh_get_bus_of_index(id);
|
||||
USB_ASSERT(bus);
|
||||
struct xhci_host *xhci = &(xhci_host[id]);
|
||||
|
||||
size_t flag = usb_osal_enter_critical_section(); /* no interrupt when init hc */
|
||||
|
||||
usb_hc_low_level_init(id); /* set gic and memp */
|
||||
|
||||
memset(xhci, 0, sizeof(*xhci));
|
||||
xhci->bus = bus;
|
||||
bus->priv = xhci;
|
||||
if (rc = xhci_probe(xhci, usb_hc_get_register_base(id)) != 0) {
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
if (rc = xhci_open(xhci) != 0 ) {
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
err_open:
|
||||
usb_osal_leave_critical_section(flag);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -555,6 +578,200 @@ uint16_t xhci_usbh_get_frame_number(void){
|
|||
|
||||
|
||||
int xhci_usbh_roothub_control(struct usbh_bus *usb, struct usb_setup_packet *setup, uint8_t *buf){
|
||||
uint8_t nports;
|
||||
uint8_t port;
|
||||
uint32_t portsc;
|
||||
uint32_t status;
|
||||
int ret = 0;
|
||||
struct xhci_host *xhci = usb->priv;
|
||||
nports = CONFIG_USBHOST_MAX_RHPORTS;
|
||||
|
||||
port = setup->wIndex;
|
||||
|
||||
/*
|
||||
bmRequestType bit[4:0], define whether the request is directed to the device (0000b),
|
||||
specific interface (00001b), endpoint (00010b), or other element (00011b)
|
||||
bRequest, identifies the request
|
||||
wValue, pass the request-specific info to the device
|
||||
*/
|
||||
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) /* request is directed to device */
|
||||
{
|
||||
switch (setup->bRequest)
|
||||
{
|
||||
case HUB_REQUEST_CLEAR_FEATURE: /* disable the feature */
|
||||
switch (setup->wValue)
|
||||
{
|
||||
case HUB_FEATURE_HUB_C_LOCALPOWER:
|
||||
USB_LOG_ERR("HUB_FEATURE_HUB_C_LOCALPOWER not implmented.\n");
|
||||
break;
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
USB_LOG_ERR("HUB_FEATURE_HUB_C_OVERCURRENT not implmented.\n");
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE: /* set a value reported in the hub status */
|
||||
switch (setup->wValue)
|
||||
{
|
||||
case HUB_FEATURE_HUB_C_LOCALPOWER:
|
||||
USB_LOG_ERR("HUB_FEATURE_HUB_C_LOCALPOWER not implmented.\n");
|
||||
break;
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
USB_LOG_ERR("HUB_FEATURE_HUB_C_OVERCURRENT not implmented.\n");
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_DESCRIPTOR:
|
||||
USB_LOG_ERR("HUB_REQUEST_GET_DESCRIPTOR not implmented.\n");
|
||||
break;
|
||||
case HUB_REQUEST_GET_STATUS:
|
||||
USB_ASSERT(buf);
|
||||
memset(buf, 0, 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER)
|
||||
{
|
||||
switch (setup->bRequest)
|
||||
{
|
||||
case HUB_REQUEST_CLEAR_FEATURE:
|
||||
if (!port || port > nports)
|
||||
{
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
portsc = readl ( xhci->op + XHCI_OP_PORTSC ( port ) );
|
||||
switch (setup->wValue)
|
||||
{
|
||||
case HUB_PORT_FEATURE_ENABLE:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_SUSPEND:
|
||||
case HUB_PORT_FEATURE_C_SUSPEND:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_POWER:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_C_CONNECTION:
|
||||
portsc |= XHCI_PORTSC_CSC;
|
||||
break;
|
||||
case HUB_PORT_FEATURE_C_ENABLE:
|
||||
portsc |= XHCI_PORTSC_PEC;
|
||||
break;
|
||||
case HUB_PORT_FEATURE_C_OVER_CURREN:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_C_RESET:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
uint32_t pclear = portsc & XHCI_PORTSC_RW_MASK;
|
||||
/* clear port status */
|
||||
writel(pclear, xhci->op + XHCI_OP_PORTSC ( port ));
|
||||
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
if (!port || port > nports)
|
||||
{
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
switch (setup->wValue)
|
||||
{
|
||||
case HUB_PORT_FEATURE_SUSPEND:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_POWER:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_RESET:
|
||||
ret = xhci_port_enable(xhci, port);
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_STATUS:
|
||||
if (!port || port > nports)
|
||||
{
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
portsc = readl ( xhci->op + XHCI_OP_PORTSC ( port ) );
|
||||
status = 0;
|
||||
|
||||
if (portsc & XHCI_PORTSC_CSC)
|
||||
{
|
||||
/* Port connection status changed */
|
||||
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
|
||||
|
||||
/* always clear all the status change bits */
|
||||
uint32_t temp = portsc & ( XHCI_PORTSC_PRESERVE | XHCI_PORTSC_CHANGE );
|
||||
writel ( temp, xhci->op + XHCI_OP_PORTSC ( port ) );
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_PEC)
|
||||
{
|
||||
/* Port enabled status changed */
|
||||
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_OCC)
|
||||
{
|
||||
/* Port status changed due to over-current */
|
||||
status |= (1 << HUB_PORT_FEATURE_C_OVER_CURREN);
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_CCS)
|
||||
{
|
||||
/* Port connected */
|
||||
status |= (1 << HUB_PORT_FEATURE_CONNECTION);
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_PED)
|
||||
{
|
||||
/* Port enabled */
|
||||
status |= (1 << HUB_PORT_FEATURE_ENABLE);
|
||||
|
||||
const unsigned int speed = xhci_root_speed(xhci, port);
|
||||
USB_LOG_DBG("Port-%d speed = %d \r\n", port, speed);
|
||||
if (speed == USB_SPEED_LOW)
|
||||
{
|
||||
status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
|
||||
}
|
||||
else if (speed == USB_SPEED_HIGH)
|
||||
{
|
||||
status |= (1 << HUB_PORT_FEATURE_HIGHSPEED);
|
||||
}
|
||||
/* else is full-speed */
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_OCA)
|
||||
{
|
||||
/* Over-current condition */
|
||||
status |= (1 << HUB_PORT_FEATURE_OVERCURRENT);
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_PR)
|
||||
{
|
||||
/* Reset is in progress */
|
||||
status |= (1 << HUB_PORT_FEATURE_RESET);
|
||||
}
|
||||
|
||||
if (portsc & XHCI_PORTSC_PP)
|
||||
{
|
||||
/* Port is not power off */
|
||||
status |= (1 << HUB_PORT_FEATURE_POWER);
|
||||
}
|
||||
memcpy(buf, &status, 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue