A27系列优化I2C/RTC处理,新增版本A270Y
This commit is contained in:
619
A27-STEPLDR/Src/usb/ark_dwc2.c
Normal file
619
A27-STEPLDR/Src/usb/ark_dwc2.c
Normal file
@ -0,0 +1,619 @@
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <asm/dma-mapping.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include "core.h"
|
||||
#include "hcd.h"
|
||||
#include "ark_dwc2.h"
|
||||
#include "usbroothubdes.h"
|
||||
#include "sysctl.h"
|
||||
|
||||
struct dwc2_host_data {
|
||||
struct dwc2_hsotg *host;
|
||||
struct usb_hcd hcd;
|
||||
enum usb_device_speed host_speed;
|
||||
int root_hub_devnum;
|
||||
//struct usb_host_endpoint hep;
|
||||
struct urb urb_in[16];
|
||||
struct urb urb_out[16];
|
||||
struct usb_host_endpoint hep_in[16];
|
||||
struct usb_host_endpoint hep_out[16];
|
||||
struct hc_driver *dw2_hc_driver;
|
||||
List_t free_urb_list;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
int dwc2_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
|
||||
int dwc2_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
|
||||
extern int dwc2_driver_init(struct dwc2_hsotg **dev, struct usb_hcd *hcd);
|
||||
extern int dwc2_driver_uninit(struct dwc2_hsotg *hsotg);
|
||||
extern struct hc_driver* dwc2_get_driver();
|
||||
static int dwc_otg_submit_rh_msg(struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int txlen,
|
||||
struct devrequest *cmd);
|
||||
|
||||
|
||||
|
||||
struct dwc2_host_data dwc2_host;
|
||||
|
||||
static void dwc2_host_complete_urb(struct urb *urb)
|
||||
{
|
||||
urb->dev->status &= ~USB_ST_NOT_PROC;
|
||||
urb->dev->act_len = urb->actual_length;
|
||||
//printf("actual_length:%d\r\n", urb->actual_length);
|
||||
urb->urb_complete = 1;
|
||||
}
|
||||
|
||||
static void usb_urb_release(struct urb *urb)
|
||||
{
|
||||
if (NULL == urb)
|
||||
return;
|
||||
spin_lock(&dwc2_host.lock);
|
||||
list_add_tail(&urb->urb_list, &dwc2_host.free_urb_list);
|
||||
spin_unlock(&dwc2_host.lock);
|
||||
}
|
||||
|
||||
static struct urb *usb_urb_alloc(struct dwc2_host_data *ctx,
|
||||
int iso_desc_count,
|
||||
gfp_t mem_flags)
|
||||
{
|
||||
struct urb *urb = NULL;
|
||||
u32 size = sizeof(*urb);
|
||||
|
||||
ListItem_t *pxListItem = NULL;
|
||||
int found = 0, flags;
|
||||
spin_lock_irqsave(&ctx->lock, flags);
|
||||
list_for_each_entry(pxListItem, urb, &ctx->free_urb_list) {
|
||||
if (urb->number_of_packets == iso_desc_count) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
list_del_init(&urb->urb_list);
|
||||
spin_unlock_irqrestore(&ctx->lock, flags);
|
||||
memset(urb, 0, sizeof(struct urb));
|
||||
INIT_LIST_ITEM(&urb->urb_list);
|
||||
listSET_LIST_ITEM_OWNER(&urb->urb_list, urb);
|
||||
urb->urb_complete = 0;
|
||||
return urb;
|
||||
}
|
||||
spin_unlock_irqrestore(&ctx->lock, flags);
|
||||
|
||||
urb = (struct urb *)kzalloc(size, mem_flags);
|
||||
if (urb) {
|
||||
urb->number_of_packets = iso_desc_count;
|
||||
INIT_LIST_ITEM(&urb->urb_list);
|
||||
listSET_LIST_ITEM_OWNER(&urb->urb_list, urb);
|
||||
urb->urb_complete = 0;
|
||||
}
|
||||
|
||||
return urb;
|
||||
}
|
||||
|
||||
|
||||
static void construct_urb(struct urb *urb, struct usb_host_endpoint *hep,
|
||||
struct usb_device *dev, int endpoint_type,
|
||||
unsigned long pipe, void *buffer, int len,
|
||||
struct devrequest *setup, int interval)
|
||||
{
|
||||
int epnum = usb_pipeendpoint(pipe);
|
||||
int is_in = usb_pipein(pipe);
|
||||
|
||||
INIT_LIST_HEAD(&hep->urb_list);
|
||||
INIT_LIST_ITEM(&urb->urb_list);
|
||||
urb->urb_list.pvOwner = (void *)urb;
|
||||
urb->ep = hep;
|
||||
urb->complete = dwc2_host_complete_urb;
|
||||
urb->status = -EINPROGRESS;
|
||||
urb->dev = dev;
|
||||
urb->pipe = pipe;
|
||||
urb->transfer_buffer = buffer;
|
||||
urb->transfer_dma = (dma_addr_t)buffer;
|
||||
urb->transfer_buffer_length = len;
|
||||
urb->setup_packet = (unsigned char *)setup;
|
||||
urb->setup_dma = (dma_addr_t)setup;
|
||||
urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |
|
||||
URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
|
||||
URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
|
||||
URB_DMA_SG_COMBINED);
|
||||
urb->transfer_flags |= (is_in ? URB_DIR_IN : URB_DIR_OUT);
|
||||
|
||||
urb->ep->desc.wMaxPacketSize =
|
||||
__cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] :
|
||||
dev->epmaxpacketout[epnum]);
|
||||
urb->ep->desc.bmAttributes = endpoint_type;
|
||||
urb->ep->desc.bEndpointAddress =
|
||||
(is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum;
|
||||
urb->ep->desc.bInterval = interval;
|
||||
}
|
||||
|
||||
static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dwc2_urb_enqueue(hcd, urb, 0);
|
||||
if (ret < 0) {
|
||||
PrintVariableValueHex("Failed to enqueue URB to controller ret", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _dwc2_submit_control_msg(struct dwc2_host_data *host,
|
||||
struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int len, struct devrequest *setup, int timeout)
|
||||
{
|
||||
struct urb *urb = NULL;
|
||||
struct usb_host_endpoint *hep = NULL;
|
||||
int epnum = usb_pipeendpoint(pipe);
|
||||
int is_in = usb_pipein(pipe);
|
||||
int ret = 0;
|
||||
unsigned int start_time;
|
||||
|
||||
if (epnum > 8 || epnum < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (is_in) {
|
||||
hep = &host->hep_in[epnum];
|
||||
} else {
|
||||
hep = &host->hep_out[epnum];
|
||||
}
|
||||
urb = usb_urb_alloc(host, 0, IRQ_NONE);
|
||||
if (urb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
construct_urb(urb, hep, dev, USB_ENDPOINT_XFER_CONTROL,
|
||||
pipe, buffer, len, setup, 0);
|
||||
|
||||
/* Fix speed for non hub-attached devices */
|
||||
if (!usb_dev_get_parent(dev))
|
||||
dev->speed = host->host_speed;
|
||||
//unsigned char *a = urb->setup_packet;
|
||||
//if (a)
|
||||
//printf("setup-->%02x %02x %02x %02x %02x %02x %02x %02x\r\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
|
||||
ret = submit_urb(&host->hcd, urb);
|
||||
if (ret < 0) {
|
||||
dwc2_urb_dequeue(&host->hcd, urb, 0);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
start_time = get_timer(0);
|
||||
ret = pdTRUE;
|
||||
do {
|
||||
if (get_timer(start_time) > timeout) {
|
||||
ret = pdFALSE;
|
||||
break;
|
||||
}
|
||||
} while(!urb->urb_complete);
|
||||
if (ret != pdTRUE || 0 != urb->status) {//timeout
|
||||
dwc2_urb_dequeue(&host->hcd, urb, 0);
|
||||
if (0 != urb->status)
|
||||
PrintVariableValueHex("usb control urb error", urb->status);
|
||||
ret = urb->status;
|
||||
} else {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
exit:
|
||||
usb_urb_release(urb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int *actual_length, int timeout)
|
||||
{
|
||||
struct urb *urb = NULL;
|
||||
struct usb_host_endpoint *hep = NULL;
|
||||
int epnum = usb_pipeendpoint(pipe);
|
||||
int is_in = usb_pipein(pipe);
|
||||
int ret = 0;
|
||||
struct dwc2_host_data *host = &dwc2_host;
|
||||
unsigned int start_time;
|
||||
|
||||
if (epnum > 8 || epnum < 0)
|
||||
return -EINVAL;
|
||||
if (is_in) {
|
||||
hep = &host->hep_in[epnum];
|
||||
} else {
|
||||
hep = &host->hep_out[epnum];
|
||||
}
|
||||
|
||||
urb = usb_urb_alloc(host, 0, IRQ_NONE);
|
||||
if (urb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
construct_urb(urb, hep, dev, USB_ENDPOINT_XFER_BULK,
|
||||
pipe, buffer, transfer_len, NULL, 0);
|
||||
ret = submit_urb(&host->hcd, urb);
|
||||
if (ret < 0) {
|
||||
dwc2_urb_dequeue(&host->hcd, urb, 0);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
start_time = get_timer(0);
|
||||
ret = pdTRUE;
|
||||
do {
|
||||
if (get_timer(start_time) > timeout) {
|
||||
ret = pdFALSE;
|
||||
break;
|
||||
}
|
||||
} while(!urb->urb_complete);
|
||||
if (ret != pdTRUE || 0 != urb->status) {//timeout
|
||||
dwc2_urb_dequeue(&host->hcd, urb, 0);
|
||||
if (actual_length)
|
||||
*actual_length = 0;
|
||||
if (0 != urb->status)
|
||||
PrintVariableValueHex("usb bulk urb error", urb->status);
|
||||
ret = urb->status;
|
||||
} else {
|
||||
if (actual_length)
|
||||
*actual_length = urb->actual_length;
|
||||
}
|
||||
|
||||
exit:
|
||||
usb_urb_release(urb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usb_reset_endpoint()
|
||||
{
|
||||
int i;
|
||||
struct dwc2_host_data *host = &dwc2_host;
|
||||
|
||||
if ((NULL == host->dw2_hc_driver) || (NULL == host->dw2_hc_driver->endpoint_reset))
|
||||
return;
|
||||
for (i = 0; i < 16; i++) {
|
||||
host->dw2_hc_driver->endpoint_reset(&(host->hcd), &host->hep_in[i]);
|
||||
host->dw2_hc_driver->endpoint_reset(&(host->hcd), &host->hep_out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_disable_endpoint()
|
||||
{
|
||||
int i;
|
||||
struct dwc2_host_data *host = &dwc2_host;
|
||||
|
||||
if ((NULL == host->dw2_hc_driver) || (NULL == host->dw2_hc_driver->endpoint_disable))
|
||||
return;
|
||||
for (i = 0; i < 16; i++) {
|
||||
host->dw2_hc_driver->endpoint_disable(&(host->hcd), &host->hep_in[i]);
|
||||
host->dw2_hc_driver->endpoint_disable(&(host->hcd), &host->hep_out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void reset_usb_phy()
|
||||
{
|
||||
vSysctlConfigure(SYS_SOFT_RST, 30, 1, 0);//phy reset
|
||||
mdelay(10);
|
||||
vSysctlConfigure(SYS_SOFT_RST, 30, 1, 1);//phy reset
|
||||
}
|
||||
|
||||
void usb_sysctrl_init()
|
||||
{
|
||||
vSysctlConfigure(SYS_ANA_CFG, 8, 0xff, 4);
|
||||
|
||||
vSysctlConfigure(SYS_SOFT_RST, 30, 1, 0);//phy reset
|
||||
vSysctlConfigure(SYS_SOFT_RST, 3, 1, 0);
|
||||
mdelay(10);
|
||||
vSysctlConfigure(SYS_SOFT_RST, 30, 1, 1);//phy reset
|
||||
vSysctlConfigure(SYS_SOFT_RST, 3, 1, 1);
|
||||
vSysctlConfigure(SYS_ANA_CFG, 24, 3, 1);
|
||||
mdelay(10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int hub_status_data(char buf[8])
|
||||
{
|
||||
int ret = 1;
|
||||
struct dwc2_host_data *host = &dwc2_host;
|
||||
//printf("prvUsbPortScanTimerCallback\r\n");
|
||||
ret = host->dw2_hc_driver->hub_status_data(&(host->hcd), buf);
|
||||
if (ret != 0) {
|
||||
//printf("state:%d usb state changed now!\r\n", buf[0]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usb_dwc2_lowlevel_restart()
|
||||
{
|
||||
struct dwc2_host_data *host = &dwc2_host;
|
||||
|
||||
if (host->dw2_hc_driver && host->dw2_hc_driver->stop) {
|
||||
host->dw2_hc_driver->stop(&(host->hcd));
|
||||
}
|
||||
msleep(50);
|
||||
if (host->dw2_hc_driver && host->dw2_hc_driver->start) {
|
||||
host->dw2_hc_driver->start(&(host->hcd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#define mainTIMER_SCAN_FREQUENCY_MS pdMS_TO_TICKS( 1000UL )
|
||||
|
||||
int usb_dwc2_lowlevel_init()
|
||||
{
|
||||
struct dwc2_host_data *host = &dwc2_host;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&host->free_urb_list);
|
||||
spin_lock_init(&host->lock);
|
||||
|
||||
ret = dwc2_driver_init(&host->host, &(host->hcd));
|
||||
if (!host->host) {
|
||||
SendUartString("MUSB host is not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
host->dw2_hc_driver = dwc2_get_driver();
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_dwc2_lowlevel_uninit()
|
||||
{
|
||||
if (!dwc2_host.host) {
|
||||
SendUartString("MUSB host is not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dwc2_driver_uninit(dwc2_host.host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int submit_control_msg(struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int length, struct devrequest *setup, int timeout)
|
||||
{
|
||||
if (dev->parent == NULL) {
|
||||
return dwc_otg_submit_rh_msg(dev, pipe, buffer, length, setup);
|
||||
} else {
|
||||
return _dwc2_submit_control_msg(&dwc2_host, dev, pipe, buffer, length, setup, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DWC2 to USB API interface
|
||||
*/
|
||||
/* Direction: In ; Request: Status */
|
||||
static int dwc_otg_submit_rh_msg_in_status(struct usb_device *dev, void *buffer,
|
||||
int txlen, struct devrequest *cmd)
|
||||
{
|
||||
int len = 0;
|
||||
int stat = 0;
|
||||
|
||||
switch (cmd->requesttype & ~USB_DIR_IN) {
|
||||
case 0:
|
||||
*(uint16_t *)buffer = cpu_to_le16(1);
|
||||
len = 2;
|
||||
break;
|
||||
case USB_RECIP_INTERFACE:
|
||||
case USB_RECIP_ENDPOINT:
|
||||
*(uint16_t *)buffer = cpu_to_le16(0);
|
||||
len = 2;
|
||||
break;
|
||||
case USB_TYPE_CLASS:
|
||||
*(uint32_t *)buffer = cpu_to_le32(0);
|
||||
len = 4;
|
||||
break;
|
||||
case USB_RECIP_OTHER | USB_TYPE_CLASS:
|
||||
len = 4;
|
||||
stat = dwc2_host.dw2_hc_driver->hub_control(&dwc2_host.hcd, (cmd->requesttype << 8) | (cmd->request),
|
||||
cmd->value, cmd->index, (char*)buffer, len);
|
||||
|
||||
break;
|
||||
default:
|
||||
//puts("unsupported root hub command\n");
|
||||
stat = USB_ST_STALLED;
|
||||
}
|
||||
|
||||
dev->act_len = min(len, txlen);
|
||||
dev->status = stat;
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
/* Direction: In ; Request: Descriptor */
|
||||
|
||||
/* roothub.a masks */
|
||||
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* over current protection mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xffUL << 24) /* power on to power good time */
|
||||
|
||||
/* roothub.b masks */
|
||||
#define RH_B_DR 0x0000ffff /* device removable flags */
|
||||
#define RH_B_PPCM 0xffff0000 /* port power control mask */
|
||||
|
||||
static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev,
|
||||
void *buffer, int txlen,
|
||||
struct devrequest *cmd)
|
||||
{
|
||||
|
||||
unsigned char data[32];
|
||||
uint32_t dsc;
|
||||
int len = 0;
|
||||
int stat = 0;
|
||||
uint16_t wValue = cpu_to_le16(cmd->value);
|
||||
uint16_t wLength = cpu_to_le16(cmd->length);
|
||||
|
||||
switch (cmd->requesttype & ~USB_DIR_IN) {
|
||||
case 0:
|
||||
{
|
||||
switch (wValue & 0xff00) {
|
||||
case 0x0100: /* device descriptor */
|
||||
len = min3(txlen, (int)sizeof(root_hub_dev_des), (int)wLength);
|
||||
memcpy(buffer, root_hub_dev_des, len);
|
||||
break;
|
||||
case 0x0200: /* configuration descriptor */
|
||||
len = min3(txlen, (int)sizeof(root_hub_config_des), (int)wLength);
|
||||
memcpy(buffer, root_hub_config_des, len);
|
||||
break;
|
||||
case 0x0300: /* string descriptors */
|
||||
switch (wValue & 0xff) {
|
||||
case 0x00:
|
||||
len = min3(txlen, (int)sizeof(root_hub_str_index0),
|
||||
(int)wLength);
|
||||
memcpy(buffer, root_hub_str_index0, len);
|
||||
break;
|
||||
case 0x01:
|
||||
len = min3(txlen, (int)sizeof(root_hub_str_index1),
|
||||
(int)wLength);
|
||||
memcpy(buffer, root_hub_str_index1, len);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stat = USB_ST_STALLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_TYPE_CLASS:
|
||||
/* Root port config, set 1 port and nothing else. */
|
||||
dsc = 0x00000001;
|
||||
|
||||
data[0] = 9; /* min length; */
|
||||
data[1] = 0x29;
|
||||
data[2] = dsc & RH_A_NDP;
|
||||
data[3] = 0;
|
||||
if (dsc & RH_A_PSM)
|
||||
data[3] |= 0x1;
|
||||
if (dsc & RH_A_NOCP)
|
||||
data[3] |= 0x10;
|
||||
else if (dsc & RH_A_OCPM)
|
||||
data[3] |= 0x8;
|
||||
|
||||
/* corresponds to data[4-7] */
|
||||
data[5] = (dsc & RH_A_POTPGT) >> 24;
|
||||
data[7] = dsc & RH_B_DR;
|
||||
if (data[2] < 7) {
|
||||
data[8] = 0xff;
|
||||
} else {
|
||||
data[0] += 2;
|
||||
data[8] = (dsc & RH_B_DR) >> 8;
|
||||
data[9] = 0xff;
|
||||
data[10] = data[9];
|
||||
}
|
||||
|
||||
len = min3(txlen, (int)data[0], (int)wLength);
|
||||
memcpy(buffer, data, len);
|
||||
break;
|
||||
default:
|
||||
//puts("unsupported root hub command\n");
|
||||
stat = USB_ST_STALLED;
|
||||
}
|
||||
|
||||
dev->act_len = min(len, txlen);
|
||||
dev->status = stat;
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
/* Direction: In ; Request: Configuration */
|
||||
static int dwc_otg_submit_rh_msg_in_configuration(struct usb_device *dev,
|
||||
void *buffer, int txlen,
|
||||
struct devrequest *cmd)
|
||||
{
|
||||
int len = 0;
|
||||
int stat = 0;
|
||||
|
||||
switch (cmd->requesttype & ~USB_DIR_IN) {
|
||||
case 0:
|
||||
*(uint8_t *)buffer = 0x01;
|
||||
len = 1;
|
||||
break;
|
||||
default:
|
||||
//puts("unsupported root hub command\n");
|
||||
stat = USB_ST_STALLED;
|
||||
}
|
||||
|
||||
dev->act_len = min(len, txlen);
|
||||
dev->status = stat;
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
/* Direction: In */
|
||||
static int dwc_otg_submit_rh_msg_in(
|
||||
struct usb_device *dev, void *buffer,
|
||||
int txlen, struct devrequest *cmd)
|
||||
{
|
||||
switch (cmd->request) {
|
||||
case USB_REQ_GET_STATUS:
|
||||
return dwc_otg_submit_rh_msg_in_status(dev, buffer,
|
||||
txlen, cmd);
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
return dwc_otg_submit_rh_msg_in_descriptor(dev, buffer,
|
||||
txlen, cmd);
|
||||
case USB_REQ_GET_CONFIGURATION:
|
||||
return dwc_otg_submit_rh_msg_in_configuration(dev, buffer,
|
||||
txlen, cmd);
|
||||
default:
|
||||
//puts("unsupported root hub command\n");
|
||||
return USB_ST_STALLED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Direction: Out */
|
||||
static int dwc_otg_submit_rh_msg_out(
|
||||
struct usb_device *dev,
|
||||
void *buffer, int txlen,
|
||||
struct devrequest *cmd)
|
||||
{
|
||||
int len = 0;
|
||||
int stat = 0;
|
||||
uint16_t bmrtype_breq = cmd->requesttype | (cmd->request << 8);
|
||||
uint16_t wValue = cpu_to_le16(cmd->value);
|
||||
switch (bmrtype_breq & ~USB_DIR_IN) {
|
||||
case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_ENDPOINT:
|
||||
case (USB_REQ_CLEAR_FEATURE << 8) | USB_TYPE_CLASS:
|
||||
break;
|
||||
|
||||
case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
|
||||
case (USB_REQ_SET_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
|
||||
dwc2_host.dw2_hc_driver->hub_control(&dwc2_host.hcd, (cmd->requesttype << 8) | (cmd->request),
|
||||
cmd->value, cmd->index, (char*)buffer, txlen);
|
||||
break;
|
||||
case (USB_REQ_SET_ADDRESS << 8):
|
||||
dwc2_host.root_hub_devnum = wValue;
|
||||
dwc2_host.dw2_hc_driver->hub_control(&dwc2_host.hcd, (cmd->requesttype << 8) | (cmd->request),
|
||||
cmd->value, cmd->index, (char*)buffer, txlen);
|
||||
break;
|
||||
case (USB_REQ_SET_CONFIGURATION << 8):
|
||||
break;
|
||||
default:
|
||||
//puts("unsupported root hub command\n");
|
||||
stat = USB_ST_STALLED;
|
||||
}
|
||||
|
||||
len = min(len, txlen);
|
||||
|
||||
dev->act_len = len;
|
||||
dev->status = stat;
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int dwc_otg_submit_rh_msg(struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int txlen,
|
||||
struct devrequest *cmd)
|
||||
{
|
||||
int stat = 0;
|
||||
if (usb_pipeint(pipe)) {
|
||||
//puts("Root-Hub submit IRQ: NOT implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd->requesttype & USB_DIR_IN)
|
||||
stat = dwc_otg_submit_rh_msg_in(dev, buffer, txlen, cmd);
|
||||
else
|
||||
stat = dwc_otg_submit_rh_msg_out(dev, buffer, txlen, cmd);
|
||||
|
||||
stat = dev->act_len;
|
||||
return stat;
|
||||
}
|
||||
|
19
A27-STEPLDR/Src/usb/ark_dwc2.h
Normal file
19
A27-STEPLDR/Src/usb/ark_dwc2.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* MUSB OTG driver u-boot specific functions
|
||||
*
|
||||
* Copyright © 2015 Hans de Goede <hdegoede@redhat.com>
|
||||
*/
|
||||
#ifndef __ARK_USB_DWC2_H__
|
||||
#define __ARK_USB_DWC2_H__
|
||||
|
||||
int usb_dwc2_lowlevel_init();
|
||||
int usb_dwc2_lowlevel_uninit();
|
||||
void usb_sysctrl_init();
|
||||
void reset_usb_phy();
|
||||
void usb_disable_endpoint();
|
||||
void usb_reset_endpoint();
|
||||
void usb_dwc2_lowlevel_restart();
|
||||
|
||||
|
||||
#endif
|
296
A27-STEPLDR/Src/usb/core.c
Normal file
296
A27-STEPLDR/Src/usb/core.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* core.c - DesignWare HS OTG Controller common routines
|
||||
*
|
||||
* Copyright (C) 2004-2013 Synopsys, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The Core code provides basic services for accessing and managing the
|
||||
* DWC_otg hardware. These services are used by both the Host Controller
|
||||
* Driver and the Peripheral Controller Driver.
|
||||
*/
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <asm/dma-mapping.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "hcd.h"
|
||||
|
||||
/**
|
||||
* dwc2_wait_for_mode() - Waits for the controller mode.
|
||||
* @hsotg: Programming view of the DWC_otg controller.
|
||||
* @host_mode: If true, waits for host mode, otherwise device mode.
|
||||
*/
|
||||
static void dwc2_wait_for_mode(struct dwc2_hsotg *hsotg,
|
||||
bool host_mode)
|
||||
{
|
||||
uint32_t tick = get_timer(0);
|
||||
unsigned int timeout = 110;//ms
|
||||
|
||||
dev_vdbg(hsotg->dev, "Waiting for %s mode\n",
|
||||
host_mode ? "host" : "device");
|
||||
|
||||
while (1) {
|
||||
__s64 ms;
|
||||
|
||||
if (dwc2_is_host_mode(hsotg) == host_mode) {
|
||||
dev_vdbg(hsotg->dev, "%s mode set\n",
|
||||
host_mode ? "Host" : "Device");
|
||||
break;
|
||||
}
|
||||
|
||||
ms = get_timer(tick);
|
||||
if (ms >= (__s64)timeout) {
|
||||
dev_warn(hsotg->dev, "%s: Couldn't set %s mode\n",
|
||||
__func__, host_mode ? "host" : "device");
|
||||
break;
|
||||
}
|
||||
//vTaskDelay(2000 / portTICK_RATE_MS);
|
||||
mdelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do core a soft reset of the core. Be careful with this because it
|
||||
* resets all the internal state machines of the core.
|
||||
*/
|
||||
int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
|
||||
{
|
||||
u32 greset;
|
||||
int count = 0;
|
||||
bool wait_for_host_mode = false;
|
||||
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
/*
|
||||
* If the current mode is host, either due to the force mode
|
||||
* bit being set (which persists after core reset) or the
|
||||
* connector id pin, a core soft reset will temporarily reset
|
||||
* the mode to device. A delay from the IDDIG debounce filter
|
||||
* will occur before going back to host mode.
|
||||
*
|
||||
* Determine whether we will go back into host mode after a
|
||||
* reset and account for this delay after the reset.
|
||||
*/
|
||||
|
||||
/* Core Soft Reset */
|
||||
greset = dwc2_readl(hsotg->regs + GRSTCTL);
|
||||
greset |= GRSTCTL_CSFTRST;
|
||||
dwc2_writel(greset, hsotg->regs + GRSTCTL);
|
||||
do {
|
||||
udelay(1);
|
||||
greset = dwc2_readl(hsotg->regs + GRSTCTL);
|
||||
if (++count > 50) {
|
||||
dev_warn(hsotg->dev,
|
||||
"%s() HANG! Soft Reset GRSTCTL=%0x\n",
|
||||
__func__, greset);
|
||||
return -EBUSY;
|
||||
}
|
||||
} while (greset & GRSTCTL_CSFTRST);
|
||||
|
||||
/* Wait for AHB master IDLE state */
|
||||
count = 0;
|
||||
do {
|
||||
udelay(1);
|
||||
greset = dwc2_readl(hsotg->regs + GRSTCTL);
|
||||
if (++count > 50) {
|
||||
dev_warn(hsotg->dev,
|
||||
"%s() HANG! AHB Idle GRSTCTL=%0x\n",
|
||||
__func__, greset);
|
||||
return -EBUSY;
|
||||
}
|
||||
} while (!(greset & GRSTCTL_AHBIDLE));
|
||||
|
||||
if (wait_for_host_mode && !skip_wait)
|
||||
dwc2_wait_for_mode(hsotg, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets or clears force mode based on the dr_mode parameter.
|
||||
*/
|
||||
void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
switch (hsotg->dr_mode) {
|
||||
case USB_DR_MODE_HOST:
|
||||
/*
|
||||
* NOTE: This is required for some rockchip soc based
|
||||
* platforms on their host-only dwc2.
|
||||
*/
|
||||
msleep(50);
|
||||
|
||||
break;
|
||||
default:
|
||||
dev_warn(hsotg->dev, "%s() Invalid dr_mode=%d\n",
|
||||
__func__, hsotg->dr_mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do core a soft reset of the core. Be careful with this because it
|
||||
* resets all the internal state machines of the core.
|
||||
*
|
||||
* Additionally this will apply force mode as per the hsotg->dr_mode
|
||||
* parameter.
|
||||
*/
|
||||
int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = dwc2_core_reset(hsotg, false);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
dwc2_force_dr_mode(hsotg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_flush_tx_fifo() - Flushes a Tx FIFO
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
* @num: Tx FIFO to flush
|
||||
*/
|
||||
void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num)
|
||||
{
|
||||
u32 greset;
|
||||
int count = 0;
|
||||
|
||||
dev_vdbg(hsotg->dev, "Flush Tx FIFO %d\n", num);
|
||||
|
||||
greset = GRSTCTL_TXFFLSH;
|
||||
greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK;
|
||||
dwc2_writel(greset, hsotg->regs + GRSTCTL);
|
||||
|
||||
do {
|
||||
greset = dwc2_readl(hsotg->regs + GRSTCTL);
|
||||
if (++count > 10000) {
|
||||
dev_warn(hsotg->dev,
|
||||
"%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
|
||||
__func__, greset,
|
||||
dwc2_readl(hsotg->regs + GNPTXSTS));
|
||||
break;
|
||||
}
|
||||
udelay(1);
|
||||
} while (greset & GRSTCTL_TXFFLSH);
|
||||
|
||||
/* Wait for at least 3 PHY Clocks */
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_flush_rx_fifo() - Flushes the Rx FIFO
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*/
|
||||
void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 greset;
|
||||
int count = 0;
|
||||
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
greset = GRSTCTL_RXFFLSH;
|
||||
dwc2_writel(greset, hsotg->regs + GRSTCTL);
|
||||
|
||||
do {
|
||||
greset = dwc2_readl(hsotg->regs + GRSTCTL);
|
||||
if (++count > 10000) {
|
||||
dev_warn(hsotg->dev, "%s() HANG! GRSTCTL=%0x\n",
|
||||
__func__, greset);
|
||||
break;
|
||||
}
|
||||
udelay(1);
|
||||
} while (greset & GRSTCTL_RXFFLSH);
|
||||
|
||||
/* Wait for at least 3 PHY Clocks */
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_enable_global_interrupts() - Enables the controller's Global
|
||||
* Interrupt in the AHB Config register
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*/
|
||||
void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
|
||||
|
||||
ahbcfg |= GAHBCFG_GLBL_INTR_EN;
|
||||
dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_disable_global_interrupts() - Disables the controller's Global
|
||||
* Interrupt in the AHB Config register
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*/
|
||||
void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
|
||||
|
||||
ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
|
||||
dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
|
||||
}
|
||||
|
||||
/* Returns the controller's GHWCFG2.OTG_MODE. */
|
||||
unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 ghwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
|
||||
|
||||
return (ghwcfg2 & GHWCFG2_OP_MODE_MASK) >>
|
||||
GHWCFG2_OP_MODE_SHIFT;
|
||||
}
|
||||
|
||||
/* Returns true if the controller is host-only. */
|
||||
bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
unsigned int op_mode = dwc2_op_mode(hsotg);
|
||||
|
||||
return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_HOST) ||
|
||||
(op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST);
|
||||
}
|
1032
A27-STEPLDR/Src/usb/core.h
Normal file
1032
A27-STEPLDR/Src/usb/core.h
Normal file
File diff suppressed because it is too large
Load Diff
269
A27-STEPLDR/Src/usb/core_intr.c
Normal file
269
A27-STEPLDR/Src/usb/core_intr.c
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* core_intr.c - DesignWare HS OTG Controller common interrupt handling
|
||||
*
|
||||
* Copyright (C) 2004-2013 Synopsys, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the common interrupt handlers
|
||||
*/
|
||||
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <asm/dma-mapping.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "hcd.h"
|
||||
|
||||
const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
switch (hsotg->op_state) {
|
||||
case OTG_STATE_A_HOST:
|
||||
return "a_host";
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
return "a_suspend";
|
||||
case OTG_STATE_A_PERIPHERAL:
|
||||
return "a_peripheral";
|
||||
case OTG_STATE_B_PERIPHERAL:
|
||||
return "b_peripheral";
|
||||
case OTG_STATE_B_HOST:
|
||||
return "b_host";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*/
|
||||
static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
/* Clear interrupt */
|
||||
dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
|
||||
|
||||
dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
|
||||
dwc2_is_host_mode(hsotg) ? "Host" : "Device");
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_handle_otg_intr() - Handles the OTG Interrupts. It reads the OTG
|
||||
* Interrupt Register (GOTGINT) to determine what interrupt has occurred.
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*/
|
||||
static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 gotgint;
|
||||
|
||||
gotgint = dwc2_readl(hsotg->regs + GOTGINT);
|
||||
|
||||
/* Clear GOTGINT */
|
||||
dwc2_writel(gotgint, hsotg->regs + GOTGINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_handle_conn_id_status_change_intr() - Handles the Connector ID Status
|
||||
* Change Interrupt
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*
|
||||
* Reads the OTG Interrupt Register (GOTCTL) to determine whether this is a
|
||||
* Device to Host Mode transition or a Host to Device Mode transition. This only
|
||||
* occurs when the cable is connected/removed from the PHY connector.
|
||||
*/
|
||||
static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 gintmsk;
|
||||
|
||||
/* Clear interrupt */
|
||||
dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
|
||||
|
||||
/* Need to disable SOF interrupt immediately */
|
||||
gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
|
||||
gintmsk &= ~GINTSTS_SOF;
|
||||
dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
|
||||
|
||||
dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++ (%s)\n",
|
||||
dwc2_is_host_mode(hsotg) ? "Host" : "Device");
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_handle_session_req_intr() - This interrupt indicates that a device is
|
||||
* initiating the Session Request Protocol to request the host to turn on bus
|
||||
* power so a new session can begin
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*
|
||||
* This handler responds by turning on bus power. If the DWC_otg controller is
|
||||
* in low power mode, this handler brings the controller out of low power mode
|
||||
* before turning on bus power.
|
||||
*/
|
||||
static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
/* Clear interrupt */
|
||||
dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
|
||||
|
||||
dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
|
||||
hsotg->lx_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* This interrupt indicates that a device has been disconnected from the
|
||||
* root port
|
||||
*/
|
||||
static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
|
||||
|
||||
dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
|
||||
dwc2_is_host_mode(hsotg) ? "Host" : "Device",
|
||||
dwc2_op_state_str(hsotg));
|
||||
|
||||
if (hsotg->op_state == OTG_STATE_A_HOST)
|
||||
dwc2_hcd_disconnect(hsotg, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* This interrupt indicates that SUSPEND state has been detected on the USB.
|
||||
*
|
||||
* For HNP the USB Suspend interrupt signals the change from "a_peripheral"
|
||||
* to "a_host".
|
||||
*
|
||||
* When power management is enabled the core will be put in low power mode.
|
||||
*/
|
||||
static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
/* Clear interrupt */
|
||||
dwc2_writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
|
||||
|
||||
dev_dbg(hsotg->dev, "USB SUSPEND\n");
|
||||
|
||||
if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
|
||||
dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
|
||||
|
||||
/* Change to L2 (suspend) state */
|
||||
hsotg->lx_state = DWC2_L2;
|
||||
/* Clear the a_peripheral flag, back to a_host */
|
||||
spin_unlock(&hsotg->lock);
|
||||
dwc2_hcd_start_isr(hsotg);
|
||||
spin_lock(&hsotg->lock);
|
||||
hsotg->op_state = OTG_STATE_A_HOST;
|
||||
}
|
||||
}
|
||||
|
||||
#define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \
|
||||
GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT | \
|
||||
GINTSTS_MODEMIS | GINTSTS_DISCONNINT | \
|
||||
GINTSTS_USBSUSP | GINTSTS_PRTINT)
|
||||
|
||||
/*
|
||||
* This function returns the Core Interrupt register
|
||||
*/
|
||||
static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 gintsts;
|
||||
u32 gintmsk;
|
||||
u32 gahbcfg;
|
||||
u32 gintmsk_common = GINTMSK_COMMON;
|
||||
|
||||
gintsts = dwc2_readl(hsotg->regs + GINTSTS);
|
||||
gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
|
||||
gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
|
||||
|
||||
/* If any common interrupts set */
|
||||
if (gintsts & gintmsk_common)
|
||||
dev_dbg(hsotg->dev, "gintsts=%08x gintmsk=%08x\n",
|
||||
gintsts, gintmsk);
|
||||
|
||||
if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
|
||||
return gintsts & gintmsk & gintmsk_common;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common interrupt handler
|
||||
*
|
||||
* The common interrupts are those that occur in both Host and Device mode.
|
||||
* This handler handles the following interrupts:
|
||||
* - Mode Mismatch Interrupt
|
||||
* - OTG Interrupt
|
||||
* - Connector ID Status Change Interrupt
|
||||
* - Disconnect Interrupt
|
||||
* - Session Request Interrupt
|
||||
* - Resume / Remote Wakeup Detected Interrupt
|
||||
* - Suspend Interrupt
|
||||
*/
|
||||
irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
|
||||
{
|
||||
struct dwc2_hsotg *hsotg = dev;
|
||||
u32 gintsts;
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
|
||||
if (!dwc2_is_controller_alive(hsotg)) {
|
||||
dev_warn(hsotg->dev, "Controller is dead\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gintsts = dwc2_read_common_intr(hsotg);
|
||||
if (gintsts & ~GINTSTS_PRTINT)
|
||||
retval = IRQ_HANDLED;
|
||||
|
||||
if (gintsts & GINTSTS_MODEMIS)
|
||||
dwc2_handle_mode_mismatch_intr(hsotg);
|
||||
if (gintsts & GINTSTS_OTGINT)
|
||||
dwc2_handle_otg_intr(hsotg);
|
||||
if (gintsts & GINTSTS_CONIDSTSCHNG)
|
||||
dwc2_handle_conn_id_status_change_intr(hsotg);
|
||||
if (gintsts & GINTSTS_DISCONNINT)
|
||||
dwc2_handle_disconnect_intr(hsotg);
|
||||
if (gintsts & GINTSTS_SESSREQINT)
|
||||
dwc2_handle_session_req_intr(hsotg);
|
||||
|
||||
if (gintsts & GINTSTS_USBSUSP)
|
||||
dwc2_handle_usb_suspend_intr(hsotg);
|
||||
|
||||
if (gintsts & GINTSTS_PRTINT) {
|
||||
/*
|
||||
* The port interrupt occurs while in device mode with HPRT0
|
||||
* Port Enable/Disable
|
||||
*/
|
||||
}
|
||||
|
||||
out:
|
||||
return retval;
|
||||
}
|
138
A27-STEPLDR/Src/usb/dwc2_compat.h
Normal file
138
A27-STEPLDR/Src/usb/dwc2_compat.h
Normal file
@ -0,0 +1,138 @@
|
||||
#ifndef _DWC2_COMPAT_H
|
||||
#define _DWC2_COMPAT_H
|
||||
|
||||
|
||||
/* OTG defines lots of enumeration states before device reset */
|
||||
enum usb_otg_state {
|
||||
OTG_STATE_UNDEFINED = 0,
|
||||
|
||||
/* single-role peripheral, and dual-role default-b */
|
||||
OTG_STATE_B_IDLE,
|
||||
OTG_STATE_B_SRP_INIT,
|
||||
OTG_STATE_B_PERIPHERAL,
|
||||
|
||||
/* extra dual-role default-b states */
|
||||
OTG_STATE_B_WAIT_ACON,
|
||||
OTG_STATE_B_HOST,
|
||||
|
||||
/* dual-role default-a */
|
||||
OTG_STATE_A_IDLE,
|
||||
OTG_STATE_A_WAIT_VRISE,
|
||||
OTG_STATE_A_WAIT_BCON,
|
||||
OTG_STATE_A_HOST,
|
||||
OTG_STATE_A_SUSPEND,
|
||||
OTG_STATE_A_PERIPHERAL,
|
||||
OTG_STATE_A_WAIT_VFALL,
|
||||
OTG_STATE_A_VBUS_ERR,
|
||||
};
|
||||
|
||||
|
||||
enum usb_dr_mode {
|
||||
USB_DR_MODE_UNKNOWN,
|
||||
USB_DR_MODE_HOST,
|
||||
USB_DR_MODE_PERIPHERAL,
|
||||
USB_DR_MODE_OTG,
|
||||
};
|
||||
|
||||
#define URB_DIR_IN 0x0200 /* Transfer from device to host */
|
||||
#define URB_DIR_OUT 0
|
||||
#define URB_DIR_MASK URB_DIR_IN
|
||||
|
||||
#define URB_DMA_MAP_SINGLE 0x00010000 /* Non-scatter-gather mapping */
|
||||
#define URB_DMA_MAP_PAGE 0x00020000 /* HCD-unsupported S-G */
|
||||
#define URB_DMA_MAP_SG 0x00040000 /* HCD-supported S-G */
|
||||
#define URB_MAP_LOCAL 0x00080000 /* HCD-local-memory mapping */
|
||||
#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */
|
||||
#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */
|
||||
#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */
|
||||
#define URB_ALIGNED_TEMP_BUFFER 0x00800000 /* Temp buffer was alloc'd */
|
||||
|
||||
|
||||
#define USB_RESUME_TIMEOUT 40 /* ms */
|
||||
|
||||
|
||||
|
||||
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
||||
#define HUB_CLASS_REQ(dir, type, request) ((((dir) | (type)) << 8) | (request))
|
||||
/* GetBusState and SetHubDescriptor are optional, omitted */
|
||||
#define ClearHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_CLEAR_FEATURE)
|
||||
#define ClearPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_CLEAR_FEATURE)
|
||||
#define GetHubDescriptor HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, USB_REQ_GET_DESCRIPTOR)
|
||||
#define GetHubStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, USB_REQ_GET_STATUS)
|
||||
#define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, USB_REQ_GET_STATUS)
|
||||
#define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_SET_FEATURE)
|
||||
#define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_SET_FEATURE)
|
||||
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#define USB_PORT_FEAT_CONNECTION 0
|
||||
#define USB_PORT_FEAT_ENABLE 1
|
||||
#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */
|
||||
#define USB_PORT_FEAT_OVER_CURRENT 3
|
||||
#define USB_PORT_FEAT_RESET 4
|
||||
#define USB_PORT_FEAT_L1 5 /* L1 suspend */
|
||||
#define USB_PORT_FEAT_POWER 8
|
||||
#define USB_PORT_FEAT_LOWSPEED 9 /* Should never be used */
|
||||
#define USB_PORT_FEAT_C_CONNECTION 16
|
||||
#define USB_PORT_FEAT_C_ENABLE 17
|
||||
#define USB_PORT_FEAT_C_SUSPEND 18
|
||||
#define USB_PORT_FEAT_C_OVER_CURRENT 19
|
||||
#define USB_PORT_FEAT_C_RESET 20
|
||||
#define USB_PORT_FEAT_TEST 21
|
||||
#define USB_PORT_FEAT_INDICATOR 22
|
||||
#define USB_PORT_FEAT_C_PORT_L1 23
|
||||
|
||||
/*
|
||||
* wPortChange bit field
|
||||
* See USB 2.0 spec Table 11-22 and USB 2.0 LPM ECN Table-4.10
|
||||
* Bits 0 to 5 shown, bits 6 to 15 are reserved
|
||||
*/
|
||||
#define USB_PORT_STAT_C_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_C_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_C_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_C_RESET 0x0010
|
||||
#define USB_PORT_STAT_C_L1 0x0020
|
||||
|
||||
/*
|
||||
* wPortStatus bit field
|
||||
* See USB 2.0 spec Table 11-21
|
||||
*/
|
||||
#define USB_PORT_STAT_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
#define USB_PORT_STAT_L1 0x0020
|
||||
/* bits 6 to 7 are reserved */
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400
|
||||
#define USB_PORT_STAT_TEST 0x0800
|
||||
#define USB_PORT_STAT_INDICATOR 0x1000
|
||||
/* bits 13 to 15 are reserved */
|
||||
|
||||
/*
|
||||
* wHubCharacteristics (masks)
|
||||
* See USB 2.0 spec Table 11-13, offset 3
|
||||
*/
|
||||
#define HUB_CHAR_LPSM 0x0003 /* Logical Power Switching Mode mask */
|
||||
#define HUB_CHAR_COMMON_LPSM 0x0000 /* All ports power control at once */
|
||||
#define HUB_CHAR_INDV_PORT_LPSM 0x0001 /* per-port power control */
|
||||
#define HUB_CHAR_NO_LPSM 0x0002 /* no power switching */
|
||||
|
||||
#define HUB_CHAR_COMPOUND 0x0004 /* hub is part of a compound device */
|
||||
|
||||
#define HUB_CHAR_OCPM 0x0018 /* Over-Current Protection Mode mask */
|
||||
#define HUB_CHAR_COMMON_OCPM 0x0000 /* All ports Over-Current reporting */
|
||||
#define HUB_CHAR_INDV_PORT_OCPM 0x0008 /* per-port Over-current reporting */
|
||||
#define HUB_CHAR_NO_OCPM 0x0010 /* No Over-current Protection support */
|
||||
|
||||
#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */
|
||||
#define HUB_CHAR_PORTIND 0x0080 /* per-port indicators (LEDs) */
|
||||
|
||||
|
||||
#endif
|
3703
A27-STEPLDR/Src/usb/hcd.c
Normal file
3703
A27-STEPLDR/Src/usb/hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
793
A27-STEPLDR/Src/usb/hcd.h
Normal file
793
A27-STEPLDR/Src/usb/hcd.h
Normal file
@ -0,0 +1,793 @@
|
||||
/*
|
||||
* hcd.h - DesignWare HS OTG Controller host-mode declarations
|
||||
*
|
||||
* Copyright (C) 2004-2013 Synopsys, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __DWC2_HCD_H__
|
||||
#define __DWC2_HCD_H__
|
||||
|
||||
#include "usb-compat.h"
|
||||
|
||||
/*
|
||||
* This file contains the structures, constants, and interfaces for the
|
||||
* Host Contoller Driver (HCD)
|
||||
*
|
||||
* The Host Controller Driver (HCD) is responsible for translating requests
|
||||
* from the USB Driver into the appropriate actions on the DWC_otg controller.
|
||||
* It isolates the USBD from the specifics of the controller by providing an
|
||||
* API to the USBD.
|
||||
*/
|
||||
|
||||
struct dwc2_qh;
|
||||
|
||||
/**
|
||||
* struct dwc2_host_chan - Software host channel descriptor
|
||||
*
|
||||
* @hc_num: Host channel number, used for register address lookup
|
||||
* @dev_addr: Address of the device
|
||||
* @ep_num: Endpoint of the device
|
||||
* @ep_is_in: Endpoint direction
|
||||
* @speed: Device speed. One of the following values:
|
||||
* - USB_SPEED_LOW
|
||||
* - USB_SPEED_FULL
|
||||
* - USB_SPEED_HIGH
|
||||
* @ep_type: Endpoint type. One of the following values:
|
||||
* - USB_ENDPOINT_XFER_CONTROL: 0
|
||||
* - USB_ENDPOINT_XFER_ISOC: 1
|
||||
* - USB_ENDPOINT_XFER_BULK: 2
|
||||
* - USB_ENDPOINT_XFER_INTR: 3
|
||||
* @max_packet: Max packet size in bytes
|
||||
* @data_pid_start: PID for initial transaction.
|
||||
* 0: DATA0
|
||||
* 1: DATA2
|
||||
* 2: DATA1
|
||||
* 3: MDATA (non-Control EP),
|
||||
* SETUP (Control EP)
|
||||
* @multi_count: Number of additional periodic transactions per
|
||||
* (micro)frame
|
||||
* @xfer_buf: Pointer to current transfer buffer position
|
||||
* @xfer_dma: DMA address of xfer_buf
|
||||
* @align_buf: In Buffer DMA mode this will be used if xfer_buf is not
|
||||
* DWORD aligned
|
||||
* @xfer_len: Total number of bytes to transfer
|
||||
* @xfer_count: Number of bytes transferred so far
|
||||
* @start_pkt_count: Packet count at start of transfer
|
||||
* @xfer_started: True if the transfer has been started
|
||||
* @ping: True if a PING request should be issued on this channel
|
||||
* @error_state: True if the error count for this transaction is non-zero
|
||||
* @halt_on_queue: True if this channel should be halted the next time a
|
||||
* request is queued for the channel. This is necessary in
|
||||
* slave mode if no request queue space is available when
|
||||
* an attempt is made to halt the channel.
|
||||
* @halt_pending: True if the host channel has been halted, but the core
|
||||
* is not finished flushing queued requests
|
||||
* @do_split: Enable split for the channel
|
||||
* @complete_split: Enable complete split
|
||||
* @hub_addr: Address of high speed hub for the split
|
||||
* @hub_port: Port of the low/full speed device for the split
|
||||
* @xact_pos: Split transaction position. One of the following values:
|
||||
* - DWC2_HCSPLT_XACTPOS_MID
|
||||
* - DWC2_HCSPLT_XACTPOS_BEGIN
|
||||
* - DWC2_HCSPLT_XACTPOS_END
|
||||
* - DWC2_HCSPLT_XACTPOS_ALL
|
||||
* @requests: Number of requests issued for this channel since it was
|
||||
* assigned to the current transfer (not counting PINGs)
|
||||
* @schinfo: Scheduling micro-frame bitmap
|
||||
* @ntd: Number of transfer descriptors for the transfer
|
||||
* @halt_status: Reason for halting the host channel
|
||||
* @hcint Contents of the HCINT register when the interrupt came
|
||||
* @qh: QH for the transfer being processed by this channel
|
||||
* @hc_list_entry: For linking to list of host channels
|
||||
* @desc_list_addr: Current QH's descriptor list DMA address
|
||||
* @desc_list_sz: Current QH's descriptor list size
|
||||
* @split_order_list_entry: List entry for keeping track of the order of splits
|
||||
*
|
||||
* This structure represents the state of a single host channel when acting in
|
||||
* host mode. It contains the data items needed to transfer packets to an
|
||||
* endpoint via a host channel.
|
||||
*/
|
||||
struct dwc2_host_chan {
|
||||
u8 hc_num;
|
||||
|
||||
unsigned dev_addr:7;
|
||||
unsigned ep_num:4;
|
||||
unsigned ep_is_in:1;
|
||||
unsigned speed:4;
|
||||
unsigned ep_type:2;
|
||||
unsigned max_packet:11;
|
||||
unsigned data_pid_start:2;
|
||||
#define DWC2_HC_PID_DATA0 TSIZ_SC_MC_PID_DATA0
|
||||
#define DWC2_HC_PID_DATA2 TSIZ_SC_MC_PID_DATA2
|
||||
#define DWC2_HC_PID_DATA1 TSIZ_SC_MC_PID_DATA1
|
||||
#define DWC2_HC_PID_MDATA TSIZ_SC_MC_PID_MDATA
|
||||
#define DWC2_HC_PID_SETUP TSIZ_SC_MC_PID_SETUP
|
||||
|
||||
unsigned multi_count:2;
|
||||
|
||||
u8 *xfer_buf;
|
||||
dma_addr_t xfer_dma;
|
||||
dma_addr_t align_buf;
|
||||
u32 xfer_len;
|
||||
u32 xfer_count;
|
||||
u16 start_pkt_count;
|
||||
u8 xfer_started;
|
||||
u8 do_ping;
|
||||
u8 error_state;
|
||||
u8 halt_on_queue;
|
||||
u8 halt_pending;
|
||||
u8 do_split;
|
||||
u8 complete_split;
|
||||
u8 hub_addr;
|
||||
u8 hub_port;
|
||||
u8 xact_pos;
|
||||
#define DWC2_HCSPLT_XACTPOS_MID HCSPLT_XACTPOS_MID
|
||||
#define DWC2_HCSPLT_XACTPOS_END HCSPLT_XACTPOS_END
|
||||
#define DWC2_HCSPLT_XACTPOS_BEGIN HCSPLT_XACTPOS_BEGIN
|
||||
#define DWC2_HCSPLT_XACTPOS_ALL HCSPLT_XACTPOS_ALL
|
||||
|
||||
u8 requests;
|
||||
u8 schinfo;
|
||||
u16 ntd;
|
||||
enum dwc2_halt_status halt_status;
|
||||
u32 hcint;
|
||||
struct dwc2_qh *qh;
|
||||
ListItem_t hc_list_entry;
|
||||
ListItem_t split_order_list_entry;
|
||||
};
|
||||
|
||||
struct dwc2_hcd_pipe_info {
|
||||
u8 dev_addr;
|
||||
u8 ep_num;
|
||||
u8 pipe_type;
|
||||
u8 pipe_dir;
|
||||
u16 mps;
|
||||
};
|
||||
|
||||
struct dwc2_qtd;
|
||||
|
||||
struct dwc2_hcd_urb {
|
||||
void *priv;
|
||||
struct dwc2_qtd *qtd;
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
void *setup_packet;
|
||||
dma_addr_t setup_dma;
|
||||
u32 length;
|
||||
u32 actual_length;
|
||||
int status;
|
||||
u32 error_count;
|
||||
u32 packet_count;
|
||||
u32 flags;
|
||||
u16 interval;
|
||||
ListItem_t free_list_entry;
|
||||
struct dwc2_hcd_pipe_info pipe_info;
|
||||
};
|
||||
|
||||
/* Phases for control transfers */
|
||||
enum dwc2_control_phase {
|
||||
DWC2_CONTROL_SETUP,
|
||||
DWC2_CONTROL_DATA,
|
||||
DWC2_CONTROL_STATUS,
|
||||
};
|
||||
|
||||
/* Transaction types */
|
||||
enum dwc2_transaction_type {
|
||||
DWC2_TRANSACTION_NONE,
|
||||
DWC2_TRANSACTION_PERIODIC,
|
||||
DWC2_TRANSACTION_NON_PERIODIC,
|
||||
DWC2_TRANSACTION_ALL,
|
||||
};
|
||||
|
||||
/* The number of elements per LS bitmap (per port on multi_tt) */
|
||||
#define DWC2_ELEMENTS_PER_LS_BITMAP DIV_ROUND_UP(DWC2_LS_SCHEDULE_SLICES, \
|
||||
BITS_PER_LONG)
|
||||
|
||||
/**
|
||||
* struct dwc2_tt - dwc2 data associated with a usb_tt
|
||||
*
|
||||
* @refcount: Number of Queue Heads (QHs) holding a reference.
|
||||
* @usb_tt: Pointer back to the official usb_tt.
|
||||
* @periodic_bitmaps: Bitmap for which parts of the 1ms frame are accounted
|
||||
* for already. Each is DWC2_ELEMENTS_PER_LS_BITMAP
|
||||
* elements (so sizeof(long) times that in bytes).
|
||||
*
|
||||
* This structure is stored in the hcpriv of the official usb_tt.
|
||||
*/
|
||||
struct dwc2_tt {
|
||||
int refcount;
|
||||
struct usb_tt *usb_tt;
|
||||
unsigned long periodic_bitmaps[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dwc2_hs_transfer_time - Info about a transfer on the high speed bus.
|
||||
*
|
||||
* @start_schedule_usecs: The start time on the main bus schedule. Note that
|
||||
* the main bus schedule is tightly packed and this
|
||||
* time should be interpreted as tightly packed (so
|
||||
* uFrame 0 starts at 0 us, uFrame 1 starts at 100 us
|
||||
* instead of 125 us).
|
||||
* @duration_us: How long this transfer goes.
|
||||
*/
|
||||
|
||||
struct dwc2_hs_transfer_time {
|
||||
u32 start_schedule_us;
|
||||
u16 duration_us;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dwc2_qh - Software queue head structure
|
||||
*
|
||||
* @hsotg: The HCD state structure for the DWC OTG controller
|
||||
* @ep_type: Endpoint type. One of the following values:
|
||||
* - USB_ENDPOINT_XFER_CONTROL
|
||||
* - USB_ENDPOINT_XFER_BULK
|
||||
* - USB_ENDPOINT_XFER_INT
|
||||
* - USB_ENDPOINT_XFER_ISOC
|
||||
* @ep_is_in: Endpoint direction
|
||||
* @maxp: Value from wMaxPacketSize field of Endpoint Descriptor
|
||||
* @dev_speed: Device speed. One of the following values:
|
||||
* - USB_SPEED_LOW
|
||||
* - USB_SPEED_FULL
|
||||
* - USB_SPEED_HIGH
|
||||
* @data_toggle: Determines the PID of the next data packet for
|
||||
* non-controltransfers. Ignored for control transfers.
|
||||
* One of the following values:
|
||||
* - DWC2_HC_PID_DATA0
|
||||
* - DWC2_HC_PID_DATA1
|
||||
* @ping_state: Ping state
|
||||
* @do_split: Full/low speed endpoint on high-speed hub requires split
|
||||
* @td_first: Index of first activated isochronous transfer descriptor
|
||||
* @td_last: Index of last activated isochronous transfer descriptor
|
||||
* @host_us: Bandwidth in microseconds per transfer as seen by host
|
||||
* @device_us: Bandwidth in microseconds per transfer as seen by device
|
||||
* @host_interval: Interval between transfers as seen by the host. If
|
||||
* the host is high speed and the device is low speed this
|
||||
* will be 8 times device interval.
|
||||
* @device_interval: Interval between transfers as seen by the device.
|
||||
* interval.
|
||||
* @next_active_frame: (Micro)frame _before_ we next need to put something on
|
||||
* the bus. We'll move the qh to active here. If the
|
||||
* host is in high speed mode this will be a uframe. If
|
||||
* the host is in low speed mode this will be a full frame.
|
||||
* @start_active_frame: If we are partway through a split transfer, this will be
|
||||
* what next_active_frame was when we started. Otherwise
|
||||
* it should always be the same as next_active_frame.
|
||||
* @num_hs_transfers: Number of transfers in hs_transfers.
|
||||
* Normally this is 1 but can be more than one for splits.
|
||||
* Always >= 1 unless the host is in low/full speed mode.
|
||||
* @hs_transfers: Transfers that are scheduled as seen by the high speed
|
||||
* bus. Not used if host is in low or full speed mode (but
|
||||
* note that it IS USED if the device is low or full speed
|
||||
* as long as the HOST is in high speed mode).
|
||||
* @ls_start_schedule_slice: Start time (in slices) on the low speed bus
|
||||
* schedule that's being used by this device. This
|
||||
* will be on the periodic_bitmap in a
|
||||
* "struct dwc2_tt". Not used if this device is high
|
||||
* speed. Note that this is in "schedule slice" which
|
||||
* is tightly packed.
|
||||
* @ls_duration_us: Duration on the low speed bus schedule.
|
||||
* @ntd: Actual number of transfer descriptors in a list
|
||||
* @dw_align_buf: Used instead of original buffer if its physical address
|
||||
* is not dword-aligned
|
||||
* @dw_align_buf_dma: DMA address for dw_align_buf
|
||||
* @qtd_list: List of QTDs for this QH
|
||||
* @channel: Host channel currently processing transfers for this QH
|
||||
* @qh_list_entry: Entry for QH in either the periodic or non-periodic
|
||||
* schedule
|
||||
* @desc_list: List of transfer descriptors
|
||||
* @desc_list_dma: Physical address of desc_list
|
||||
* @desc_list_sz: Size of descriptors list
|
||||
* @n_bytes: Xfer Bytes array. Each element corresponds to a transfer
|
||||
* descriptor and indicates original XferSize value for the
|
||||
* descriptor
|
||||
* @unreserve_timer: Timer for releasing periodic reservation.
|
||||
* @dwc2_tt: Pointer to our tt info (or NULL if no tt).
|
||||
* @ttport: Port number within our tt.
|
||||
* @tt_buffer_dirty True if clear_tt_buffer_complete is pending
|
||||
* @unreserve_pending: True if we planned to unreserve but haven't yet.
|
||||
* @schedule_low_speed: True if we have a low/full speed component (either the
|
||||
* host is in low/full speed mode or do_split).
|
||||
*
|
||||
* A Queue Head (QH) holds the static characteristics of an endpoint and
|
||||
* maintains a list of transfers (QTDs) for that endpoint. A QH structure may
|
||||
* be entered in either the non-periodic or periodic schedule.
|
||||
*/
|
||||
struct dwc2_qh {
|
||||
struct dwc2_hsotg *hsotg;
|
||||
u8 ep_type;
|
||||
u8 ep_is_in;
|
||||
u16 maxp;
|
||||
u8 dev_speed;
|
||||
u8 data_toggle;
|
||||
u8 ping_state;
|
||||
u8 do_split;
|
||||
u8 td_first;
|
||||
u8 td_last;
|
||||
u16 host_us;
|
||||
u16 device_us;
|
||||
u16 host_interval;
|
||||
u16 device_interval;
|
||||
u16 next_active_frame;
|
||||
u16 start_active_frame;
|
||||
s16 num_hs_transfers;
|
||||
struct dwc2_hs_transfer_time hs_transfers[DWC2_HS_SCHEDULE_UFRAMES];
|
||||
u32 ls_start_schedule_slice;
|
||||
u16 ntd;
|
||||
u8 *dw_align_buf;
|
||||
dma_addr_t dw_align_buf_dma;
|
||||
List_t qtd_list;
|
||||
struct dwc2_host_chan *channel;
|
||||
ListItem_t qh_list_entry;
|
||||
u32 *n_bytes;
|
||||
struct timer_list unreserve_timer;
|
||||
struct dwc2_tt *dwc_tt;
|
||||
int ttport;
|
||||
unsigned tt_buffer_dirty:1;
|
||||
unsigned unreserve_pending:1;
|
||||
unsigned schedule_low_speed:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dwc2_qtd - Software queue transfer descriptor (QTD)
|
||||
*
|
||||
* @control_phase: Current phase for control transfers (Setup, Data, or
|
||||
* Status)
|
||||
* @in_process: Indicates if this QTD is currently processed by HW
|
||||
* @data_toggle: Determines the PID of the next data packet for the
|
||||
* data phase of control transfers. Ignored for other
|
||||
* transfer types. One of the following values:
|
||||
* - DWC2_HC_PID_DATA0
|
||||
* - DWC2_HC_PID_DATA1
|
||||
* @complete_split: Keeps track of the current split type for FS/LS
|
||||
* endpoints on a HS Hub
|
||||
* @isoc_split_pos: Position of the ISOC split in full/low speed
|
||||
* @isoc_frame_index: Index of the next frame descriptor for an isochronous
|
||||
* transfer. A frame descriptor describes the buffer
|
||||
* position and length of the data to be transferred in the
|
||||
* next scheduled (micro)frame of an isochronous transfer.
|
||||
* It also holds status for that transaction. The frame
|
||||
* index starts at 0.
|
||||
* @isoc_split_offset: Position of the ISOC split in the buffer for the
|
||||
* current frame
|
||||
* @ssplit_out_xfer_count: How many bytes transferred during SSPLIT OUT
|
||||
* @error_count: Holds the number of bus errors that have occurred for
|
||||
* a transaction within this transfer
|
||||
* @n_desc: Number of DMA descriptors for this QTD
|
||||
* @isoc_frame_index_last: Last activated frame (packet) index, used in
|
||||
* descriptor DMA mode only
|
||||
* @urb: URB for this transfer
|
||||
* @qh: Queue head for this QTD
|
||||
* @qtd_list_entry: For linking to the QH's list of QTDs
|
||||
*
|
||||
* A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
|
||||
* interrupt, or isochronous transfer. A single QTD is created for each URB
|
||||
* (of one of these types) submitted to the HCD. The transfer associated with
|
||||
* a QTD may require one or multiple transactions.
|
||||
*
|
||||
* A QTD is linked to a Queue Head, which is entered in either the
|
||||
* non-periodic or periodic schedule for execution. When a QTD is chosen for
|
||||
* execution, some or all of its transactions may be executed. After
|
||||
* execution, the state of the QTD is updated. The QTD may be retired if all
|
||||
* its transactions are complete or if an error occurred. Otherwise, it
|
||||
* remains in the schedule so more transactions can be executed later.
|
||||
*/
|
||||
struct dwc2_qtd {
|
||||
enum dwc2_control_phase control_phase;
|
||||
u8 in_process;
|
||||
u8 data_toggle;
|
||||
u8 complete_split;
|
||||
u8 isoc_split_pos;
|
||||
u32 ssplit_out_xfer_count;
|
||||
u8 error_count;
|
||||
u8 n_desc;
|
||||
struct dwc2_hcd_urb *urb;
|
||||
struct dwc2_qh *qh;
|
||||
ListItem_t qtd_list_entry;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
struct hc_xfer_info {
|
||||
struct dwc2_hsotg *hsotg;
|
||||
struct dwc2_host_chan *chan;
|
||||
};
|
||||
#endif
|
||||
|
||||
u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg);
|
||||
|
||||
/* Gets the struct usb_hcd that contains a struct dwc2_hsotg */
|
||||
static inline struct usb_hcd *dwc2_hsotg_to_hcd(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
return (struct usb_hcd *)hsotg->priv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inline used to disable one channel interrupt. Channel interrupts are
|
||||
* disabled when the channel is halted or released by the interrupt handler.
|
||||
* There is no need to handle further interrupts of that type until the
|
||||
* channel is re-assigned. In fact, subsequent handling may cause crashes
|
||||
* because the channel structures are cleaned up when the channel is released.
|
||||
*/
|
||||
static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
|
||||
{
|
||||
u32 mask = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
|
||||
|
||||
mask &= ~intr;
|
||||
dwc2_writel(mask, hsotg->regs + HCINTMSK(chnum));
|
||||
}
|
||||
|
||||
void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan);
|
||||
void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
|
||||
enum dwc2_halt_status halt_status);
|
||||
void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_host_chan *chan);
|
||||
|
||||
/*
|
||||
* Reads HPRT0 in preparation to modify. It keeps the WC bits 0 so that if they
|
||||
* are read as 1, they won't clear when written back.
|
||||
*/
|
||||
static inline u32 dwc2_read_hprt0(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
|
||||
|
||||
hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
|
||||
return hprt0;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_get_ep_num(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->ep_num;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_get_pipe_type(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->pipe_type;
|
||||
}
|
||||
|
||||
static inline u16 dwc2_hcd_get_mps(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->mps;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_get_dev_addr(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->dev_addr;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_is_pipe_bulk(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->pipe_type == USB_ENDPOINT_XFER_BULK;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_is_pipe_control(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->pipe_type == USB_ENDPOINT_XFER_CONTROL;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_is_pipe_in(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return pipe->pipe_dir == USB_DIR_IN;
|
||||
}
|
||||
|
||||
static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe)
|
||||
{
|
||||
return !dwc2_hcd_is_pipe_in(pipe);
|
||||
}
|
||||
void dwc2_hcd_irq(struct dwc2_hsotg *hsotg);
|
||||
int dwc2_hcd_init(struct dwc2_hsotg *hsotg, struct usb_hcd *hcd);
|
||||
void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
|
||||
|
||||
/* Transaction Execution Functions */
|
||||
enum dwc2_transaction_type dwc2_hcd_select_transactions(
|
||||
struct dwc2_hsotg *hsotg);
|
||||
void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
|
||||
enum dwc2_transaction_type tr_type);
|
||||
|
||||
/* Schedule Queue Functions */
|
||||
/* Implemented in hcd_queue.c */
|
||||
struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_hcd_urb *urb,
|
||||
gfp_t mem_flags);
|
||||
void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||
int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||
void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||
void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||
int sched_csplit);
|
||||
|
||||
void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
|
||||
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
||||
struct dwc2_qh *qh);
|
||||
|
||||
/* Unlinks and frees a QTD */
|
||||
static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_qtd *qtd,
|
||||
struct dwc2_qh *qh)
|
||||
{
|
||||
list_del(&qtd->qtd_list_entry);
|
||||
list_add_tail(&qtd->qtd_list_entry, &hsotg->free_qtd_list);
|
||||
|
||||
qtd = NULL;
|
||||
}
|
||||
|
||||
/* Descriptor DMA support functions */
|
||||
void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_qh *qh);
|
||||
void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_host_chan *chan, int chnum,
|
||||
enum dwc2_halt_status halt_status);
|
||||
|
||||
int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||
gfp_t mem_flags);
|
||||
void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||
|
||||
/* Check if QH is non-periodic */
|
||||
#define dwc2_qh_is_non_per(_qh_ptr_) \
|
||||
((_qh_ptr_)->ep_type == USB_ENDPOINT_XFER_BULK || \
|
||||
(_qh_ptr_)->ep_type == USB_ENDPOINT_XFER_CONTROL)
|
||||
|
||||
#ifdef CONFIG_USB_DWC2_DEBUG_PERIODIC
|
||||
static inline bool dbg_hc(struct dwc2_host_chan *hc) { return true; }
|
||||
static inline bool dbg_qh(struct dwc2_qh *qh) { return true; }
|
||||
static inline bool dbg_urb(struct urb *urb) { return true; }
|
||||
static inline bool dbg_perio(void) { return true; }
|
||||
#else /* !CONFIG_USB_DWC2_DEBUG_PERIODIC */
|
||||
static inline bool dbg_hc(struct dwc2_host_chan *hc)
|
||||
{
|
||||
return hc->ep_type == USB_ENDPOINT_XFER_BULK ||
|
||||
hc->ep_type == USB_ENDPOINT_XFER_CONTROL;
|
||||
}
|
||||
|
||||
static inline bool dbg_qh(struct dwc2_qh *qh)
|
||||
{
|
||||
return qh->ep_type == USB_ENDPOINT_XFER_BULK ||
|
||||
qh->ep_type == USB_ENDPOINT_XFER_CONTROL;
|
||||
}
|
||||
|
||||
static inline bool dbg_urb(struct urb *urb)
|
||||
{
|
||||
return true;
|
||||
/*return usb_pipetype(urb->pipe) == PIPE_BULK ||
|
||||
usb_pipetype(urb->pipe) == PIPE_CONTROL;*/
|
||||
}
|
||||
|
||||
static inline bool dbg_perio(void) { return false; }
|
||||
#endif
|
||||
|
||||
/* High bandwidth multiplier as encoded in highspeed endpoint descriptors */
|
||||
#define dwc2_hb_mult(wmaxpacketsize) (1 + (((wmaxpacketsize) >> 11) & 0x03))
|
||||
|
||||
/* Packet size for any kind of endpoint descriptor */
|
||||
#define dwc2_max_packet(wmaxpacketsize) ((wmaxpacketsize) & 0x07ff)
|
||||
|
||||
/*
|
||||
* Returns true if frame1 index is greater than frame2 index. The comparison
|
||||
* is done modulo FRLISTEN_64_SIZE. This accounts for the rollover of the
|
||||
* frame number when the max index frame number is reached.
|
||||
*/
|
||||
static inline bool dwc2_frame_idx_num_gt(u16 fr_idx1, u16 fr_idx2)
|
||||
{
|
||||
u16 diff = fr_idx1 - fr_idx2;
|
||||
u16 sign = diff & (FRLISTEN_64_SIZE >> 1);
|
||||
|
||||
return diff && !sign;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if frame1 is less than or equal to frame2. The comparison is
|
||||
* done modulo HFNUM_MAX_FRNUM. This accounts for the rollover of the
|
||||
* frame number when the max frame number is reached.
|
||||
*/
|
||||
static inline int dwc2_frame_num_le(u16 frame1, u16 frame2)
|
||||
{
|
||||
return ((frame2 - frame1) & HFNUM_MAX_FRNUM) <= (HFNUM_MAX_FRNUM >> 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if frame1 is greater than frame2. The comparison is done
|
||||
* modulo HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
|
||||
* number when the max frame number is reached.
|
||||
*/
|
||||
static inline int dwc2_frame_num_gt(u16 frame1, u16 frame2)
|
||||
{
|
||||
return (frame1 != frame2) &&
|
||||
((frame1 - frame2) & HFNUM_MAX_FRNUM) < (HFNUM_MAX_FRNUM >> 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increments frame by the amount specified by inc. The addition is done
|
||||
* modulo HFNUM_MAX_FRNUM. Returns the incremented value.
|
||||
*/
|
||||
static inline u16 dwc2_frame_num_inc(u16 frame, u16 inc)
|
||||
{
|
||||
return (frame + inc) & HFNUM_MAX_FRNUM;
|
||||
}
|
||||
|
||||
static inline u16 dwc2_frame_num_dec(u16 frame, u16 dec)
|
||||
{
|
||||
return (frame + HFNUM_MAX_FRNUM + 1 - dec) & HFNUM_MAX_FRNUM;
|
||||
}
|
||||
|
||||
static inline u16 dwc2_full_frame_num(u16 frame)
|
||||
{
|
||||
return (frame & HFNUM_MAX_FRNUM) >> 3;
|
||||
}
|
||||
|
||||
static inline u16 dwc2_micro_frame_num(u16 frame)
|
||||
{
|
||||
return frame & 0x7;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the Core Interrupt Status register contents, ANDed with the Core
|
||||
* Interrupt Mask register contents
|
||||
*/
|
||||
static inline u32 dwc2_read_core_intr(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
return dwc2_readl(hsotg->regs + GINTSTS) &
|
||||
dwc2_readl(hsotg->regs + GINTMSK);
|
||||
}
|
||||
|
||||
static inline u32 dwc2_hcd_urb_get_status(struct dwc2_hcd_urb *dwc2_urb)
|
||||
{
|
||||
return dwc2_urb->status;
|
||||
}
|
||||
|
||||
static inline u32 dwc2_hcd_urb_get_actual_length(
|
||||
struct dwc2_hcd_urb *dwc2_urb)
|
||||
{
|
||||
return dwc2_urb->actual_length;
|
||||
}
|
||||
|
||||
static inline u32 dwc2_hcd_urb_get_error_count(struct dwc2_hcd_urb *dwc2_urb)
|
||||
{
|
||||
return dwc2_urb->error_count;
|
||||
}
|
||||
|
||||
static inline int dwc2_hcd_is_bandwidth_allocated(struct dwc2_hsotg *hsotg,
|
||||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct dwc2_qh *qh = (struct dwc2_qh *)ep->hcpriv;
|
||||
|
||||
if (qh && !list_item_empty(&qh->qh_list_entry))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u16 dwc2_hcd_get_ep_bandwidth(struct dwc2_hsotg *hsotg,
|
||||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct dwc2_qh *qh = (struct dwc2_qh *)ep->hcpriv;
|
||||
|
||||
if (!qh) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return qh->host_us;
|
||||
}
|
||||
|
||||
void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_host_chan *chan, int chnum,
|
||||
struct dwc2_qtd *qtd);
|
||||
|
||||
/* HCD Core API */
|
||||
|
||||
/**
|
||||
* dwc2_handle_hcd_intr() - Called on every hardware interrupt
|
||||
*
|
||||
* @hsotg: The DWC2 HCD
|
||||
*
|
||||
* Returns IRQ_HANDLED if interrupt is handled
|
||||
* Return IRQ_NONE if interrupt is not handled
|
||||
*/
|
||||
irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg);
|
||||
|
||||
/**
|
||||
* dwc2_hcd_stop() - Halts the DWC_otg host mode operation
|
||||
*
|
||||
* @hsotg: The DWC2 HCD
|
||||
*/
|
||||
void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
|
||||
|
||||
/**
|
||||
* dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
|
||||
* and 0 otherwise
|
||||
*
|
||||
* @hsotg: The DWC2 HCD
|
||||
*/
|
||||
int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
|
||||
|
||||
/* URB interface */
|
||||
|
||||
/* Transfer flags */
|
||||
#define URB_GIVEBACK_ASAP 0x1
|
||||
#define URB_SEND_ZERO_PACKET 0x2
|
||||
|
||||
/* Host driver callbacks */
|
||||
struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg,
|
||||
void *context, gfp_t mem_flags,
|
||||
int *ttport);
|
||||
|
||||
void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_tt *dwc_tt);
|
||||
int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
|
||||
void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
||||
int status);
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Macro to sample the remaining PHY clocks left in the current frame. This
|
||||
* may be used during debugging to determine the average time it takes to
|
||||
* execute sections of code. There are two possible sample points, "a" and
|
||||
* "b", so the _letter_ argument must be one of these values.
|
||||
*
|
||||
* To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
|
||||
* example, "cat /sys/devices/lm0/hcd_frrem".
|
||||
*/
|
||||
#define dwc2_sample_frrem(_hcd_, _qh_, _letter_) \
|
||||
do { \
|
||||
struct hfnum_data _hfnum_; \
|
||||
struct dwc2_qtd *_qtd_; \
|
||||
\
|
||||
_qtd_ = list_entry((_qh_)->qtd_list.next, struct dwc2_qtd, \
|
||||
qtd_list_entry); \
|
||||
if (usb_pipeint(_qtd_->urb->pipe) && \
|
||||
(_qh_)->start_active_frame != 0 && !_qtd_->complete_split) { \
|
||||
_hfnum_.d32 = dwc2_readl((_hcd_)->regs + HFNUM); \
|
||||
switch (_hfnum_.b.frnum & 0x7) { \
|
||||
case 7: \
|
||||
(_hcd_)->hfnum_7_samples_##_letter_++; \
|
||||
(_hcd_)->hfnum_7_frrem_accum_##_letter_ += \
|
||||
_hfnum_.b.frrem; \
|
||||
break; \
|
||||
case 0: \
|
||||
(_hcd_)->hfnum_0_samples_##_letter_++; \
|
||||
(_hcd_)->hfnum_0_frrem_accum_##_letter_ += \
|
||||
_hfnum_.b.frrem; \
|
||||
break; \
|
||||
default: \
|
||||
(_hcd_)->hfnum_other_samples_##_letter_++; \
|
||||
(_hcd_)->hfnum_other_frrem_accum_##_letter_ += \
|
||||
_hfnum_.b.frrem; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define dwc2_sample_frrem(_hcd_, _qh_, _letter_) do {} while (0)
|
||||
#endif
|
||||
|
||||
void dwc2_hcd_start_isr(struct dwc2_hsotg *hsotg);
|
||||
|
||||
#endif /* __DWC2_HCD_H__ */
|
1523
A27-STEPLDR/Src/usb/hcd_intr.c
Normal file
1523
A27-STEPLDR/Src/usb/hcd_intr.c
Normal file
File diff suppressed because it is too large
Load Diff
429
A27-STEPLDR/Src/usb/hcd_queue.c
Normal file
429
A27-STEPLDR/Src/usb/hcd_queue.c
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
* hcd_queue.c - DesignWare HS OTG Controller host queuing routines
|
||||
*
|
||||
* Copyright (C) 2004-2013 Synopsys, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the functions to manage Queue Heads and Queue
|
||||
* Transfer Descriptors for Host mode
|
||||
*/
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <asm/dma-mapping.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "hcd.h"
|
||||
|
||||
/* Wait this long before releasing periodic reservation */
|
||||
#define DWC2_UNRESERVE_DELAY (5)
|
||||
|
||||
#define swap(a, b) do {unsigned long tmp = (a); (a) = (b); (b) = tmp;} while(0)
|
||||
unsigned long gcd(unsigned long a, unsigned long b)
|
||||
{
|
||||
unsigned long r = a | b;
|
||||
|
||||
if (!a || !b)
|
||||
return r;
|
||||
|
||||
/* Isolate lsbit of r */
|
||||
r &= -r;
|
||||
|
||||
while (!(b & r))
|
||||
b >>= 1;
|
||||
if (b == r)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
while (!(a & r))
|
||||
a >>= 1;
|
||||
if (a == r)
|
||||
return r;
|
||||
if (a == b)
|
||||
return a;
|
||||
|
||||
if (a < b)
|
||||
swap(a, b);
|
||||
a -= b;
|
||||
a >>= 1;
|
||||
if (a & r)
|
||||
a += b;
|
||||
a >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_do_unreserve() - Actually release the periodic reservation
|
||||
*
|
||||
* This function actually releases the periodic bandwidth that was reserved
|
||||
* by the given qh.
|
||||
*
|
||||
* @hsotg: The HCD state structure for the DWC OTG controller
|
||||
* @qh: QH for the periodic transfer.
|
||||
*/
|
||||
static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
{
|
||||
assert_spin_locked(&hsotg->lock);
|
||||
|
||||
WARN_ON(!qh->unreserve_pending);
|
||||
|
||||
/* No more unreserve pending--we're doing it */
|
||||
qh->unreserve_pending = false;
|
||||
if (!list_item_empty(&qh->qh_list_entry)) {
|
||||
WARN_ON(!list_item_empty(&qh->qh_list_entry));
|
||||
list_del_init(&qh->qh_list_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_unreserve_timer_fn() - Timer function to release periodic reservation
|
||||
*
|
||||
* According to the kernel doc for usb_submit_urb() (specifically the part about
|
||||
* "Reserved Bandwidth Transfers"), we need to keep a reservation active as
|
||||
* long as a device driver keeps submitting. Since we're using HCD_BH to give
|
||||
* back the URB we need to give the driver a little bit of time before we
|
||||
* release the reservation. This worker is called after the appropriate
|
||||
* delay.
|
||||
*
|
||||
* @work: Pointer to a qh unreserve_work.
|
||||
*/
|
||||
/* static void dwc2_unreserve_timer_fn(unsigned long data)
|
||||
{
|
||||
} */
|
||||
|
||||
|
||||
/**
|
||||
* dwc2_qh_init() - Initializes a QH structure
|
||||
*
|
||||
* @hsotg: The HCD state structure for the DWC OTG controller
|
||||
* @qh: The QH to init
|
||||
* @urb: Holds the information about the device/endpoint needed to initialize
|
||||
* the QH
|
||||
* @mem_flags: Flags for allocating memory.
|
||||
*/
|
||||
static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||
struct dwc2_hcd_urb *urb, gfp_t mem_flags)
|
||||
{
|
||||
int dev_speed = dwc2_host_get_speed(hsotg, urb->priv);
|
||||
u8 ep_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
|
||||
bool ep_is_in = !!dwc2_hcd_is_pipe_in(&urb->pipe_info);
|
||||
u32 hprt = dwc2_readl(hsotg->regs + HPRT0);
|
||||
u32 prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
|
||||
bool do_split = (prtspd == HPRT0_SPD_HIGH_SPEED &&
|
||||
dev_speed != USB_SPEED_HIGH);
|
||||
int maxp = dwc2_hcd_get_mps(&urb->pipe_info);
|
||||
int bytecount = dwc2_hb_mult(maxp) * dwc2_max_packet(maxp);
|
||||
char *speed, *type;
|
||||
|
||||
/* Initialize QH */
|
||||
qh->hsotg = hsotg;
|
||||
qh->ep_type = ep_type;
|
||||
qh->ep_is_in = ep_is_in;
|
||||
|
||||
qh->data_toggle = DWC2_HC_PID_DATA0;
|
||||
qh->maxp = maxp;
|
||||
INIT_LIST_HEAD(&qh->qtd_list);
|
||||
INIT_LIST_ITEM(&qh->qh_list_entry);
|
||||
qh->qh_list_entry.pvOwner = (void *)qh;
|
||||
qh->do_split = do_split;
|
||||
qh->dev_speed = dev_speed;
|
||||
|
||||
switch (dev_speed) {
|
||||
case USB_SPEED_LOW:
|
||||
speed = "low";
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
speed = "full";
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
speed = "high";
|
||||
break;
|
||||
default:
|
||||
speed = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (qh->ep_type) {
|
||||
case USB_ENDPOINT_XFER_CONTROL:
|
||||
type = "control";
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
type = "bulk";
|
||||
break;
|
||||
default:
|
||||
type = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
USB_UNUSED(bytecount);
|
||||
USB_UNUSED(speed);
|
||||
USB_UNUSED(type);
|
||||
dwc2_sch_dbg(hsotg, "QH=%p Init %s, %s speed, %d bytes:\n", qh, type,
|
||||
speed, bytecount);
|
||||
dwc2_sch_dbg(hsotg, "QH=%p ...addr=%d, ep=%d, %s\n", qh,
|
||||
dwc2_hcd_get_dev_addr(&urb->pipe_info),
|
||||
dwc2_hcd_get_ep_num(&urb->pipe_info),
|
||||
ep_is_in ? "IN" : "OUT");
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hcd_qh_create() - Allocates and initializes a QH
|
||||
*
|
||||
* @hsotg: The HCD state structure for the DWC OTG controller
|
||||
* @urb: Holds the information about the device/endpoint needed
|
||||
* to initialize the QH
|
||||
* @atomic_alloc: Flag to do atomic allocation if needed
|
||||
*
|
||||
* Return: Pointer to the newly allocated QH, or NULL on error
|
||||
*/
|
||||
struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_hcd_urb *urb,
|
||||
gfp_t mem_flags)
|
||||
{
|
||||
struct dwc2_qh *qh;
|
||||
|
||||
if (!urb->priv)
|
||||
return NULL;
|
||||
|
||||
/* Allocate memory */
|
||||
qh = (struct dwc2_qh *)kzalloc(sizeof(*qh), mem_flags);
|
||||
if (!qh)
|
||||
return NULL;
|
||||
|
||||
dwc2_qh_init(hsotg, qh, urb, mem_flags);
|
||||
|
||||
/* if (hsotg->params.dma_desc_enable &&
|
||||
dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) {
|
||||
dwc2_hcd_qh_free(hsotg, qh);
|
||||
return NULL;
|
||||
} */
|
||||
|
||||
return qh;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hcd_qh_free() - Frees the QH
|
||||
*
|
||||
* @hsotg: HCD instance
|
||||
* @qh: The QH to free
|
||||
*
|
||||
* QH should already be removed from the list. QTD list should already be empty
|
||||
* if called from URB Dequeue.
|
||||
*
|
||||
* Must NOT be called with interrupt disabled or spinlock held
|
||||
*/
|
||||
void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
{
|
||||
/* Make sure any unreserve work is finished. */
|
||||
if (0) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
dwc2_do_unreserve(hsotg, qh);
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
}
|
||||
dwc2_host_put_tt_info(hsotg, qh->dwc_tt);
|
||||
|
||||
kfree(qh);
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hcd_qh_add() - Adds a QH to either the non periodic or periodic
|
||||
* schedule if it is not already in the schedule. If the QH is already in
|
||||
* the schedule, no action is taken.
|
||||
*
|
||||
* @hsotg: The HCD state structure for the DWC OTG controller
|
||||
* @qh: The QH to add
|
||||
*
|
||||
* Return: 0 if successful, negative error code otherwise
|
||||
*/
|
||||
int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
{
|
||||
u32 intr_mask;
|
||||
|
||||
if (dbg_qh(qh))
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
if (!list_item_empty(&qh->qh_list_entry))
|
||||
/* QH already in a schedule */
|
||||
return 0;
|
||||
|
||||
/* Add the new QH to the appropriate schedule */
|
||||
if (dwc2_qh_is_non_per(qh)) {
|
||||
/* Schedule right away */
|
||||
qh->start_active_frame = hsotg->frame_number;
|
||||
qh->next_active_frame = qh->start_active_frame;
|
||||
|
||||
/* Always start in inactive schedule */
|
||||
list_add_tail(&qh->qh_list_entry,
|
||||
&hsotg->non_periodic_sched_inactive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
|
||||
intr_mask |= GINTSTS_SOF;
|
||||
dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hcd_qh_unlink() - Removes a QH from either the non-periodic or periodic
|
||||
* schedule. Memory is not freed.
|
||||
*
|
||||
* @hsotg: The HCD state structure
|
||||
* @qh: QH to remove from schedule
|
||||
*/
|
||||
void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
||||
{
|
||||
u32 intr_mask;
|
||||
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
if (list_item_empty(&qh->qh_list_entry))
|
||||
/* QH is not in a schedule */
|
||||
return;
|
||||
|
||||
if (dwc2_qh_is_non_per(qh)) {
|
||||
if (hsotg->non_periodic_qh_ptr == &qh->qh_list_entry) {
|
||||
hsotg->non_periodic_qh_ptr = listGET_NEXT(hsotg->non_periodic_qh_ptr);
|
||||
}
|
||||
list_del_init(&qh->qh_list_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
|
||||
intr_mask &= ~GINTSTS_SOF;
|
||||
dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deactivates a QH. For non-periodic QHs, removes the QH from the active
|
||||
* non-periodic schedule. The QH is added to the inactive non-periodic
|
||||
* schedule if any QTDs are still attached to the QH.
|
||||
*
|
||||
* For periodic QHs, the QH is removed from the periodic queued schedule. If
|
||||
* there are any QTDs still attached to the QH, the QH is added to either the
|
||||
* periodic inactive schedule or the periodic ready schedule and its next
|
||||
* scheduled frame is calculated. The QH is placed in the ready schedule if
|
||||
* the scheduled frame has been reached already. Otherwise it's placed in the
|
||||
* inactive schedule. If there are no QTDs attached to the QH, the QH is
|
||||
* completely removed from the periodic schedule.
|
||||
*/
|
||||
void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||
int sched_next_periodic_split)
|
||||
{
|
||||
u16 old_frame = qh->next_active_frame;
|
||||
|
||||
dev_vdbg(hsotg->dev, "%s() ep_type:%d\n", __func__, qh->ep_type);
|
||||
|
||||
USB_UNUSED(old_frame);
|
||||
|
||||
if (dbg_qh(qh))
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
if (dwc2_qh_is_non_per(qh)) {
|
||||
dwc2_hcd_qh_unlink(hsotg, qh);
|
||||
if (!list_empty(&qh->qtd_list))
|
||||
/* Add back to inactive non-periodic schedule */
|
||||
dwc2_hcd_qh_add(hsotg, qh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hcd_qtd_init() - Initializes a QTD structure
|
||||
*
|
||||
* @qtd: The QTD to initialize
|
||||
* @urb: The associated URB
|
||||
*/
|
||||
void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
|
||||
{
|
||||
qtd->urb = urb;
|
||||
if (dwc2_hcd_get_pipe_type(&urb->pipe_info) ==
|
||||
USB_ENDPOINT_XFER_CONTROL) {
|
||||
/*
|
||||
* The only time the QTD data toggle is used is on the data
|
||||
* phase of control transfers. This phase always starts with
|
||||
* DATA1.
|
||||
*/
|
||||
qtd->data_toggle = DWC2_HC_PID_DATA1;
|
||||
qtd->control_phase = DWC2_CONTROL_SETUP;
|
||||
}
|
||||
|
||||
/* Start split */
|
||||
qtd->complete_split = 0;
|
||||
qtd->isoc_split_pos = DWC2_HCSPLT_XACTPOS_ALL;
|
||||
qtd->in_process = 0;
|
||||
|
||||
/* Store the qtd ptr in the urb to reference the QTD */
|
||||
urb->qtd = qtd;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH
|
||||
* Caller must hold driver lock.
|
||||
*
|
||||
* @hsotg: The DWC HCD structure
|
||||
* @qtd: The QTD to add
|
||||
* @qh: Queue head to add qtd to
|
||||
*
|
||||
* Return: 0 if successful, negative error code otherwise
|
||||
*
|
||||
* If the QH to which the QTD is added is not currently scheduled, it is placed
|
||||
* into the proper schedule based on its EP type.
|
||||
*/
|
||||
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
||||
struct dwc2_qh *qh)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (unlikely(!qh)) {
|
||||
dev_err(hsotg->dev, "%s: Invalid QH\n", __func__);
|
||||
retval = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
retval = dwc2_hcd_qh_add(hsotg, qh);
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
qtd->qh = qh;
|
||||
list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return retval;
|
||||
}
|
867
A27-STEPLDR/Src/usb/hw.h
Normal file
867
A27-STEPLDR/Src/usb/hw.h
Normal file
@ -0,0 +1,867 @@
|
||||
/*
|
||||
* hw.h - DesignWare HS OTG Controller hardware definitions
|
||||
*
|
||||
* Copyright 2004-2013 Synopsys, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __DWC2_HW_H__
|
||||
#define __DWC2_HW_H__
|
||||
|
||||
#define HSOTG_REG(x) (x)
|
||||
|
||||
#define GOTGCTL HSOTG_REG(0x000)
|
||||
#define GOTGCTL_CHIRPEN BIT(27)
|
||||
#define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22)
|
||||
#define GOTGCTL_MULT_VALID_BC_SHIFT 22
|
||||
#define GOTGCTL_OTGVER BIT(20)
|
||||
#define GOTGCTL_BSESVLD BIT(19)
|
||||
#define GOTGCTL_ASESVLD BIT(18)
|
||||
#define GOTGCTL_DBNC_SHORT BIT(17)
|
||||
#define GOTGCTL_CONID_B BIT(16)
|
||||
#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15)
|
||||
#define GOTGCTL_DEVHNPEN BIT(11)
|
||||
#define GOTGCTL_HSTSETHNPEN BIT(10)
|
||||
#define GOTGCTL_HNPREQ BIT(9)
|
||||
#define GOTGCTL_HSTNEGSCS BIT(8)
|
||||
#define GOTGCTL_SESREQ BIT(1)
|
||||
#define GOTGCTL_SESREQSCS BIT(0)
|
||||
|
||||
#define GOTGINT HSOTG_REG(0x004)
|
||||
#define GOTGINT_DBNCE_DONE BIT(19)
|
||||
#define GOTGINT_A_DEV_TOUT_CHG BIT(18)
|
||||
#define GOTGINT_HST_NEG_DET BIT(17)
|
||||
#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9)
|
||||
#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8)
|
||||
#define GOTGINT_SES_END_DET BIT(2)
|
||||
|
||||
#define GAHBCFG HSOTG_REG(0x008)
|
||||
#define GAHBCFG_AHB_SINGLE BIT(23)
|
||||
#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22)
|
||||
#define GAHBCFG_REM_MEM_SUPP BIT(21)
|
||||
#define GAHBCFG_P_TXF_EMP_LVL BIT(8)
|
||||
#define GAHBCFG_NP_TXF_EMP_LVL BIT(7)
|
||||
#define GAHBCFG_DMA_EN BIT(5)
|
||||
#define GAHBCFG_HBSTLEN_MASK (0xf << 1)
|
||||
#define GAHBCFG_HBSTLEN_SHIFT 1
|
||||
#define GAHBCFG_HBSTLEN_SINGLE 0
|
||||
#define GAHBCFG_HBSTLEN_INCR 1
|
||||
#define GAHBCFG_HBSTLEN_INCR4 3
|
||||
#define GAHBCFG_HBSTLEN_INCR8 5
|
||||
#define GAHBCFG_HBSTLEN_INCR16 7
|
||||
#define GAHBCFG_GLBL_INTR_EN BIT(0)
|
||||
#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \
|
||||
GAHBCFG_NP_TXF_EMP_LVL | \
|
||||
GAHBCFG_DMA_EN | \
|
||||
GAHBCFG_GLBL_INTR_EN)
|
||||
|
||||
#define GUSBCFG HSOTG_REG(0x00C)
|
||||
#define GUSBCFG_FORCEDEVMODE BIT(30)
|
||||
#define GUSBCFG_FORCEHOSTMODE BIT(29)
|
||||
#define GUSBCFG_TXENDDELAY BIT(28)
|
||||
#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27)
|
||||
#define GUSBCFG_ICUSBCAP BIT(26)
|
||||
#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25)
|
||||
#define GUSBCFG_INDICATORPASSTHROUGH BIT(24)
|
||||
#define GUSBCFG_INDICATORCOMPLEMENT BIT(23)
|
||||
#define GUSBCFG_TERMSELDLPULSE BIT(22)
|
||||
#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21)
|
||||
#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20)
|
||||
#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19)
|
||||
#define GUSBCFG_ULPI_AUTO_RES BIT(18)
|
||||
#define GUSBCFG_ULPI_FS_LS BIT(17)
|
||||
#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16)
|
||||
#define GUSBCFG_PHY_LP_CLK_SEL BIT(15)
|
||||
#define GUSBCFG_USBTRDTIM_MASK (0xf << 10)
|
||||
#define GUSBCFG_USBTRDTIM_SHIFT 10
|
||||
#define GUSBCFG_HNPCAP BIT(9)
|
||||
#define GUSBCFG_SRPCAP BIT(8)
|
||||
#define GUSBCFG_DDRSEL BIT(7)
|
||||
#define GUSBCFG_PHYSEL BIT(6)
|
||||
#define GUSBCFG_FSINTF BIT(5)
|
||||
#define GUSBCFG_ULPI_UTMI_SEL BIT(4)
|
||||
#define GUSBCFG_PHYIF16 BIT(3)
|
||||
#define GUSBCFG_PHYIF8 (0 << 3)
|
||||
#define GUSBCFG_TOUTCAL_MASK (0x7 << 0)
|
||||
#define GUSBCFG_TOUTCAL_SHIFT 0
|
||||
#define GUSBCFG_TOUTCAL_LIMIT 0x7
|
||||
#define GUSBCFG_TOUTCAL(_x) ((_x) << 0)
|
||||
|
||||
#define GRSTCTL HSOTG_REG(0x010)
|
||||
#define GRSTCTL_AHBIDLE BIT(31)
|
||||
#define GRSTCTL_DMAREQ BIT(30)
|
||||
#define GRSTCTL_TXFNUM_MASK (0x1f << 6)
|
||||
#define GRSTCTL_TXFNUM_SHIFT 6
|
||||
#define GRSTCTL_TXFNUM_LIMIT 0x1f
|
||||
#define GRSTCTL_TXFNUM(_x) ((_x) << 6)
|
||||
#define GRSTCTL_TXFFLSH BIT(5)
|
||||
#define GRSTCTL_RXFFLSH BIT(4)
|
||||
#define GRSTCTL_IN_TKNQ_FLSH BIT(3)
|
||||
#define GRSTCTL_FRMCNTRRST BIT(2)
|
||||
#define GRSTCTL_HSFTRST BIT(1)
|
||||
#define GRSTCTL_CSFTRST BIT(0)
|
||||
|
||||
#define GINTSTS HSOTG_REG(0x014)
|
||||
#define GINTMSK HSOTG_REG(0x018)
|
||||
#define GINTSTS_WKUPINT BIT(31)
|
||||
#define GINTSTS_SESSREQINT BIT(30)
|
||||
#define GINTSTS_DISCONNINT BIT(29)
|
||||
#define GINTSTS_CONIDSTSCHNG BIT(28)
|
||||
#define GINTSTS_LPMTRANRCVD BIT(27)
|
||||
#define GINTSTS_PTXFEMP BIT(26)
|
||||
#define GINTSTS_HCHINT BIT(25)
|
||||
#define GINTSTS_PRTINT BIT(24)
|
||||
#define GINTSTS_RESETDET BIT(23)
|
||||
#define GINTSTS_FET_SUSP BIT(22)
|
||||
#define GINTSTS_INCOMPL_IP BIT(21)
|
||||
#define GINTSTS_INCOMPL_SOOUT BIT(21)
|
||||
#define GINTSTS_INCOMPL_SOIN BIT(20)
|
||||
#define GINTSTS_OEPINT BIT(19)
|
||||
#define GINTSTS_IEPINT BIT(18)
|
||||
#define GINTSTS_EPMIS BIT(17)
|
||||
#define GINTSTS_RESTOREDONE BIT(16)
|
||||
#define GINTSTS_EOPF BIT(15)
|
||||
#define GINTSTS_ISOUTDROP BIT(14)
|
||||
#define GINTSTS_ENUMDONE BIT(13)
|
||||
#define GINTSTS_USBRST BIT(12)
|
||||
#define GINTSTS_USBSUSP BIT(11)
|
||||
#define GINTSTS_ERLYSUSP BIT(10)
|
||||
#define GINTSTS_I2CINT BIT(9)
|
||||
#define GINTSTS_ULPI_CK_INT BIT(8)
|
||||
#define GINTSTS_GOUTNAKEFF BIT(7)
|
||||
#define GINTSTS_GINNAKEFF BIT(6)
|
||||
#define GINTSTS_NPTXFEMP BIT(5)
|
||||
#define GINTSTS_RXFLVL BIT(4)
|
||||
#define GINTSTS_SOF BIT(3)
|
||||
#define GINTSTS_OTGINT BIT(2)
|
||||
#define GINTSTS_MODEMIS BIT(1)
|
||||
#define GINTSTS_CURMODE_HOST BIT(0)
|
||||
|
||||
#define GRXSTSR HSOTG_REG(0x01C)
|
||||
#define GRXSTSP HSOTG_REG(0x020)
|
||||
#define GRXSTS_FN_MASK (0x7f << 25)
|
||||
#define GRXSTS_FN_SHIFT 25
|
||||
#define GRXSTS_PKTSTS_MASK (0xf << 17)
|
||||
#define GRXSTS_PKTSTS_SHIFT 17
|
||||
#define GRXSTS_PKTSTS_GLOBALOUTNAK 1
|
||||
#define GRXSTS_PKTSTS_OUTRX 2
|
||||
#define GRXSTS_PKTSTS_HCHIN 2
|
||||
#define GRXSTS_PKTSTS_OUTDONE 3
|
||||
#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3
|
||||
#define GRXSTS_PKTSTS_SETUPDONE 4
|
||||
#define GRXSTS_PKTSTS_DATATOGGLEERR 5
|
||||
#define GRXSTS_PKTSTS_SETUPRX 6
|
||||
#define GRXSTS_PKTSTS_HCHHALTED 7
|
||||
#define GRXSTS_HCHNUM_MASK (0xf << 0)
|
||||
#define GRXSTS_HCHNUM_SHIFT 0
|
||||
#define GRXSTS_DPID_MASK (0x3 << 15)
|
||||
#define GRXSTS_DPID_SHIFT 15
|
||||
#define GRXSTS_BYTECNT_MASK (0x7ff << 4)
|
||||
#define GRXSTS_BYTECNT_SHIFT 4
|
||||
#define GRXSTS_EPNUM_MASK (0xf << 0)
|
||||
#define GRXSTS_EPNUM_SHIFT 0
|
||||
|
||||
#define GRXFSIZ HSOTG_REG(0x024)
|
||||
#define GRXFSIZ_DEPTH_MASK (0xffff << 0)
|
||||
#define GRXFSIZ_DEPTH_SHIFT 0
|
||||
|
||||
#define GNPTXFSIZ HSOTG_REG(0x028)
|
||||
/* Use FIFOSIZE_* constants to access this register */
|
||||
|
||||
#define GNPTXSTS HSOTG_REG(0x02C)
|
||||
#define GNPTXSTS_NP_TXQ_TOP_MASK (0x7f << 24)
|
||||
#define GNPTXSTS_NP_TXQ_TOP_SHIFT 24
|
||||
#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK (0xff << 16)
|
||||
#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT 16
|
||||
#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v) (((_v) >> 16) & 0xff)
|
||||
#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK (0xffff << 0)
|
||||
#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT 0
|
||||
#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v) (((_v) >> 0) & 0xffff)
|
||||
|
||||
#define GI2CCTL HSOTG_REG(0x0030)
|
||||
#define GI2CCTL_BSYDNE BIT(31)
|
||||
#define GI2CCTL_RW BIT(30)
|
||||
#define GI2CCTL_I2CDATSE0 BIT(28)
|
||||
#define GI2CCTL_I2CDEVADDR_MASK (0x3 << 26)
|
||||
#define GI2CCTL_I2CDEVADDR_SHIFT 26
|
||||
#define GI2CCTL_I2CSUSPCTL BIT(25)
|
||||
#define GI2CCTL_ACK BIT(24)
|
||||
#define GI2CCTL_I2CEN BIT(23)
|
||||
#define GI2CCTL_ADDR_MASK (0x7f << 16)
|
||||
#define GI2CCTL_ADDR_SHIFT 16
|
||||
#define GI2CCTL_REGADDR_MASK (0xff << 8)
|
||||
#define GI2CCTL_REGADDR_SHIFT 8
|
||||
#define GI2CCTL_RWDATA_MASK (0xff << 0)
|
||||
#define GI2CCTL_RWDATA_SHIFT 0
|
||||
|
||||
#define GPVNDCTL HSOTG_REG(0x0034)
|
||||
#define GGPIO HSOTG_REG(0x0038)
|
||||
#define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16)
|
||||
|
||||
#define GUID HSOTG_REG(0x003c)
|
||||
#define GSNPSID HSOTG_REG(0x0040)
|
||||
#define GHWCFG1 HSOTG_REG(0x0044)
|
||||
|
||||
#define GHWCFG2 HSOTG_REG(0x0048)
|
||||
#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31)
|
||||
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26)
|
||||
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26
|
||||
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
|
||||
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24
|
||||
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
|
||||
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22
|
||||
#define GHWCFG2_MULTI_PROC_INT BIT(20)
|
||||
#define GHWCFG2_DYNAMIC_FIFO BIT(19)
|
||||
#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18)
|
||||
#define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14)
|
||||
#define GHWCFG2_NUM_HOST_CHAN_SHIFT 14
|
||||
#define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10)
|
||||
#define GHWCFG2_NUM_DEV_EP_SHIFT 10
|
||||
#define GHWCFG2_FS_PHY_TYPE_MASK (0x3 << 8)
|
||||
#define GHWCFG2_FS_PHY_TYPE_SHIFT 8
|
||||
#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0
|
||||
#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1
|
||||
#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2
|
||||
#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3
|
||||
#define GHWCFG2_HS_PHY_TYPE_MASK (0x3 << 6)
|
||||
#define GHWCFG2_HS_PHY_TYPE_SHIFT 6
|
||||
#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
|
||||
#define GHWCFG2_HS_PHY_TYPE_UTMI 1
|
||||
#define GHWCFG2_HS_PHY_TYPE_ULPI 2
|
||||
#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
|
||||
#define GHWCFG2_POINT2POINT BIT(5)
|
||||
#define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3)
|
||||
#define GHWCFG2_ARCHITECTURE_SHIFT 3
|
||||
#define GHWCFG2_SLAVE_ONLY_ARCH 0
|
||||
#define GHWCFG2_EXT_DMA_ARCH 1
|
||||
#define GHWCFG2_INT_DMA_ARCH 2
|
||||
#define GHWCFG2_OP_MODE_MASK (0x7 << 0)
|
||||
#define GHWCFG2_OP_MODE_SHIFT 0
|
||||
#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0
|
||||
#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1
|
||||
#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2
|
||||
#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
|
||||
#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
|
||||
#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
|
||||
#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
|
||||
#define GHWCFG2_OP_MODE_UNDEFINED 7
|
||||
|
||||
#define GHWCFG3 HSOTG_REG(0x004c)
|
||||
#define GHWCFG3_DFIFO_DEPTH_MASK (0xffffUL << 16)
|
||||
#define GHWCFG3_DFIFO_DEPTH_SHIFT 16
|
||||
#define GHWCFG3_OTG_LPM_EN BIT(15)
|
||||
#define GHWCFG3_BC_SUPPORT BIT(14)
|
||||
#define GHWCFG3_OTG_ENABLE_HSIC BIT(13)
|
||||
#define GHWCFG3_ADP_SUPP BIT(12)
|
||||
#define GHWCFG3_SYNCH_RESET_TYPE BIT(11)
|
||||
#define GHWCFG3_OPTIONAL_FEATURES BIT(10)
|
||||
#define GHWCFG3_VENDOR_CTRL_IF BIT(9)
|
||||
#define GHWCFG3_I2C BIT(8)
|
||||
#define GHWCFG3_OTG_FUNC BIT(7)
|
||||
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
|
||||
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4
|
||||
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0)
|
||||
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0
|
||||
|
||||
#define GHWCFG4 HSOTG_REG(0x0050)
|
||||
#define GHWCFG4_DESC_DMA_DYN BIT(31)
|
||||
#define GHWCFG4_DESC_DMA BIT(30)
|
||||
#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
|
||||
#define GHWCFG4_NUM_IN_EPS_SHIFT 26
|
||||
#define GHWCFG4_DED_FIFO_EN BIT(25)
|
||||
#define GHWCFG4_DED_FIFO_SHIFT 25
|
||||
#define GHWCFG4_SESSION_END_FILT_EN BIT(24)
|
||||
#define GHWCFG4_B_VALID_FILT_EN BIT(23)
|
||||
#define GHWCFG4_A_VALID_FILT_EN BIT(22)
|
||||
#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21)
|
||||
#define GHWCFG4_IDDIG_FILT_EN BIT(20)
|
||||
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16)
|
||||
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
|
||||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
|
||||
#define GHWCFG4_XHIBER BIT(7)
|
||||
#define GHWCFG4_HIBER BIT(6)
|
||||
#define GHWCFG4_MIN_AHB_FREQ BIT(5)
|
||||
#define GHWCFG4_POWER_OPTIMIZ BIT(4)
|
||||
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0)
|
||||
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0
|
||||
|
||||
#define GLPMCFG HSOTG_REG(0x0054)
|
||||
#define GLPMCFG_INV_SEL_HSIC BIT(31)
|
||||
#define GLPMCFG_HSIC_CONNECT BIT(30)
|
||||
#define GLPMCFG_RETRY_COUNT_STS_MASK (0x7 << 25)
|
||||
#define GLPMCFG_RETRY_COUNT_STS_SHIFT 25
|
||||
#define GLPMCFG_SEND_LPM BIT(24)
|
||||
#define GLPMCFG_RETRY_COUNT_MASK (0x7 << 21)
|
||||
#define GLPMCFG_RETRY_COUNT_SHIFT 21
|
||||
#define GLPMCFG_LPM_CHAN_INDEX_MASK (0xf << 17)
|
||||
#define GLPMCFG_LPM_CHAN_INDEX_SHIFT 17
|
||||
#define GLPMCFG_SLEEP_STATE_RESUMEOK BIT(16)
|
||||
#define GLPMCFG_PRT_SLEEP_STS BIT(15)
|
||||
#define GLPMCFG_LPM_RESP_MASK (0x3 << 13)
|
||||
#define GLPMCFG_LPM_RESP_SHIFT 13
|
||||
#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8)
|
||||
#define GLPMCFG_HIRD_THRES_SHIFT 8
|
||||
#define GLPMCFG_HIRD_THRES_EN (0x10 << 8)
|
||||
#define GLPMCFG_EN_UTMI_SLEEP BIT(7)
|
||||
#define GLPMCFG_REM_WKUP_EN BIT(6)
|
||||
#define GLPMCFG_HIRD_MASK (0xf << 2)
|
||||
#define GLPMCFG_HIRD_SHIFT 2
|
||||
#define GLPMCFG_APPL_RESP BIT(1)
|
||||
#define GLPMCFG_LPM_CAP_EN BIT(0)
|
||||
|
||||
#define GPWRDN HSOTG_REG(0x0058)
|
||||
#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
|
||||
#define GPWRDN_MULT_VAL_ID_BC_SHIFT 24
|
||||
#define GPWRDN_ADP_INT BIT(23)
|
||||
#define GPWRDN_BSESSVLD BIT(22)
|
||||
#define GPWRDN_IDSTS BIT(21)
|
||||
#define GPWRDN_LINESTATE_MASK (0x3 << 19)
|
||||
#define GPWRDN_LINESTATE_SHIFT 19
|
||||
#define GPWRDN_STS_CHGINT_MSK BIT(18)
|
||||
#define GPWRDN_STS_CHGINT BIT(17)
|
||||
#define GPWRDN_SRP_DET_MSK BIT(16)
|
||||
#define GPWRDN_SRP_DET BIT(15)
|
||||
#define GPWRDN_CONNECT_DET_MSK BIT(14)
|
||||
#define GPWRDN_CONNECT_DET BIT(13)
|
||||
#define GPWRDN_DISCONN_DET_MSK BIT(12)
|
||||
#define GPWRDN_DISCONN_DET BIT(11)
|
||||
#define GPWRDN_RST_DET_MSK BIT(10)
|
||||
#define GPWRDN_RST_DET BIT(9)
|
||||
#define GPWRDN_LNSTSCHG_MSK BIT(8)
|
||||
#define GPWRDN_LNSTSCHG BIT(7)
|
||||
#define GPWRDN_DIS_VBUS BIT(6)
|
||||
#define GPWRDN_PWRDNSWTCH BIT(5)
|
||||
#define GPWRDN_PWRDNRSTN BIT(4)
|
||||
#define GPWRDN_PWRDNCLMP BIT(3)
|
||||
#define GPWRDN_RESTORE BIT(2)
|
||||
#define GPWRDN_PMUACTV BIT(1)
|
||||
#define GPWRDN_PMUINTSEL BIT(0)
|
||||
|
||||
#define GDFIFOCFG HSOTG_REG(0x005c)
|
||||
#define GDFIFOCFG_EPINFOBASE_MASK (0xffff << 16)
|
||||
#define GDFIFOCFG_EPINFOBASE_SHIFT 16
|
||||
#define GDFIFOCFG_GDFIFOCFG_MASK (0xffff << 0)
|
||||
#define GDFIFOCFG_GDFIFOCFG_SHIFT 0
|
||||
|
||||
#define ADPCTL HSOTG_REG(0x0060)
|
||||
#define ADPCTL_AR_MASK (0x3 << 27)
|
||||
#define ADPCTL_AR_SHIFT 27
|
||||
#define ADPCTL_ADP_TMOUT_INT_MSK BIT(26)
|
||||
#define ADPCTL_ADP_SNS_INT_MSK BIT(25)
|
||||
#define ADPCTL_ADP_PRB_INT_MSK BIT(24)
|
||||
#define ADPCTL_ADP_TMOUT_INT BIT(23)
|
||||
#define ADPCTL_ADP_SNS_INT BIT(22)
|
||||
#define ADPCTL_ADP_PRB_INT BIT(21)
|
||||
#define ADPCTL_ADPENA BIT(20)
|
||||
#define ADPCTL_ADPRES BIT(19)
|
||||
#define ADPCTL_ENASNS BIT(18)
|
||||
#define ADPCTL_ENAPRB BIT(17)
|
||||
#define ADPCTL_RTIM_MASK (0x7ff << 6)
|
||||
#define ADPCTL_RTIM_SHIFT 6
|
||||
#define ADPCTL_PRB_PER_MASK (0x3 << 4)
|
||||
#define ADPCTL_PRB_PER_SHIFT 4
|
||||
#define ADPCTL_PRB_DELTA_MASK (0x3 << 2)
|
||||
#define ADPCTL_PRB_DELTA_SHIFT 2
|
||||
#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0)
|
||||
#define ADPCTL_PRB_DSCHRG_SHIFT 0
|
||||
|
||||
#define HPTXFSIZ HSOTG_REG(0x100)
|
||||
/* Use FIFOSIZE_* constants to access this register */
|
||||
|
||||
#define DPTXFSIZN(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4))
|
||||
/* Use FIFOSIZE_* constants to access this register */
|
||||
|
||||
/* These apply to the GNPTXFSIZ, HPTXFSIZ and DPTXFSIZN registers */
|
||||
#define FIFOSIZE_DEPTH_MASK (0xffffUL << 16)
|
||||
#define FIFOSIZE_DEPTH_SHIFT 16
|
||||
#define FIFOSIZE_STARTADDR_MASK (0xffff << 0)
|
||||
#define FIFOSIZE_STARTADDR_SHIFT 0
|
||||
#define FIFOSIZE_DEPTH_GET(_x) (((_x) >> 16) & 0xffff)
|
||||
|
||||
/* Device mode registers */
|
||||
|
||||
#define DCFG HSOTG_REG(0x800)
|
||||
#define DCFG_DESCDMA_EN BIT(23)
|
||||
#define DCFG_EPMISCNT_MASK (0x1f << 18)
|
||||
#define DCFG_EPMISCNT_SHIFT 18
|
||||
#define DCFG_EPMISCNT_LIMIT 0x1f
|
||||
#define DCFG_EPMISCNT(_x) ((_x) << 18)
|
||||
#define DCFG_PERFRINT_MASK (0x3 << 11)
|
||||
#define DCFG_PERFRINT_SHIFT 11
|
||||
#define DCFG_PERFRINT_LIMIT 0x3
|
||||
#define DCFG_PERFRINT(_x) ((_x) << 11)
|
||||
#define DCFG_DEVADDR_MASK (0x7f << 4)
|
||||
#define DCFG_DEVADDR_SHIFT 4
|
||||
#define DCFG_DEVADDR_LIMIT 0x7f
|
||||
#define DCFG_DEVADDR(_x) ((_x) << 4)
|
||||
#define DCFG_NZ_STS_OUT_HSHK BIT(2)
|
||||
#define DCFG_DEVSPD_MASK (0x3 << 0)
|
||||
#define DCFG_DEVSPD_SHIFT 0
|
||||
#define DCFG_DEVSPD_HS 0
|
||||
#define DCFG_DEVSPD_FS 1
|
||||
#define DCFG_DEVSPD_LS 2
|
||||
#define DCFG_DEVSPD_FS48 3
|
||||
|
||||
#define DCTL HSOTG_REG(0x804)
|
||||
#define DCTL_PWRONPRGDONE BIT(11)
|
||||
#define DCTL_CGOUTNAK BIT(10)
|
||||
#define DCTL_SGOUTNAK BIT(9)
|
||||
#define DCTL_CGNPINNAK BIT(8)
|
||||
#define DCTL_SGNPINNAK BIT(7)
|
||||
#define DCTL_TSTCTL_MASK (0x7 << 4)
|
||||
#define DCTL_TSTCTL_SHIFT 4
|
||||
#define DCTL_GOUTNAKSTS BIT(3)
|
||||
#define DCTL_GNPINNAKSTS BIT(2)
|
||||
#define DCTL_SFTDISCON BIT(1)
|
||||
#define DCTL_RMTWKUPSIG BIT(0)
|
||||
|
||||
#define DSTS HSOTG_REG(0x808)
|
||||
#define DSTS_SOFFN_MASK (0x3fff << 8)
|
||||
#define DSTS_SOFFN_SHIFT 8
|
||||
#define DSTS_SOFFN_LIMIT 0x3fff
|
||||
#define DSTS_SOFFN(_x) ((_x) << 8)
|
||||
#define DSTS_ERRATICERR BIT(3)
|
||||
#define DSTS_ENUMSPD_MASK (0x3 << 1)
|
||||
#define DSTS_ENUMSPD_SHIFT 1
|
||||
#define DSTS_ENUMSPD_HS 0
|
||||
#define DSTS_ENUMSPD_FS 1
|
||||
#define DSTS_ENUMSPD_LS 2
|
||||
#define DSTS_ENUMSPD_FS48 3
|
||||
#define DSTS_SUSPSTS BIT(0)
|
||||
|
||||
#define DIEPMSK HSOTG_REG(0x810)
|
||||
#define DIEPMSK_NAKMSK BIT(13)
|
||||
#define DIEPMSK_BNAININTRMSK BIT(9)
|
||||
#define DIEPMSK_TXFIFOUNDRNMSK BIT(8)
|
||||
#define DIEPMSK_TXFIFOEMPTY BIT(7)
|
||||
#define DIEPMSK_INEPNAKEFFMSK BIT(6)
|
||||
#define DIEPMSK_INTKNEPMISMSK BIT(5)
|
||||
#define DIEPMSK_INTKNTXFEMPMSK BIT(4)
|
||||
#define DIEPMSK_TIMEOUTMSK BIT(3)
|
||||
#define DIEPMSK_AHBERRMSK BIT(2)
|
||||
#define DIEPMSK_EPDISBLDMSK BIT(1)
|
||||
#define DIEPMSK_XFERCOMPLMSK BIT(0)
|
||||
|
||||
#define DOEPMSK HSOTG_REG(0x814)
|
||||
#define DOEPMSK_BNAMSK BIT(9)
|
||||
#define DOEPMSK_BACK2BACKSETUP BIT(6)
|
||||
#define DOEPMSK_STSPHSERCVDMSK BIT(5)
|
||||
#define DOEPMSK_OUTTKNEPDISMSK BIT(4)
|
||||
#define DOEPMSK_SETUPMSK BIT(3)
|
||||
#define DOEPMSK_AHBERRMSK BIT(2)
|
||||
#define DOEPMSK_EPDISBLDMSK BIT(1)
|
||||
#define DOEPMSK_XFERCOMPLMSK BIT(0)
|
||||
|
||||
#define DAINT HSOTG_REG(0x818)
|
||||
#define DAINTMSK HSOTG_REG(0x81C)
|
||||
#define DAINT_OUTEP_SHIFT 16
|
||||
#define DAINT_OUTEP(_x) (1 << ((_x) + 16))
|
||||
#define DAINT_INEP(_x) (1 << (_x))
|
||||
|
||||
#define DTKNQR1 HSOTG_REG(0x820)
|
||||
#define DTKNQR2 HSOTG_REG(0x824)
|
||||
#define DTKNQR3 HSOTG_REG(0x830)
|
||||
#define DTKNQR4 HSOTG_REG(0x834)
|
||||
#define DIEPEMPMSK HSOTG_REG(0x834)
|
||||
|
||||
#define DVBUSDIS HSOTG_REG(0x828)
|
||||
#define DVBUSPULSE HSOTG_REG(0x82C)
|
||||
|
||||
#define DIEPCTL0 HSOTG_REG(0x900)
|
||||
#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20))
|
||||
|
||||
#define DOEPCTL0 HSOTG_REG(0xB00)
|
||||
#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20))
|
||||
|
||||
/* EP0 specialness:
|
||||
* bits[29..28] - reserved (no SetD0PID, SetD1PID)
|
||||
* bits[25..22] - should always be zero, this isn't a periodic endpoint
|
||||
* bits[10..0] - MPS setting different for EP0
|
||||
*/
|
||||
#define D0EPCTL_MPS_MASK (0x3 << 0)
|
||||
#define D0EPCTL_MPS_SHIFT 0
|
||||
#define D0EPCTL_MPS_64 0
|
||||
#define D0EPCTL_MPS_32 1
|
||||
#define D0EPCTL_MPS_16 2
|
||||
#define D0EPCTL_MPS_8 3
|
||||
|
||||
#define DXEPCTL_EPENA BIT(31)
|
||||
#define DXEPCTL_EPDIS BIT(30)
|
||||
#define DXEPCTL_SETD1PID BIT(29)
|
||||
#define DXEPCTL_SETODDFR BIT(29)
|
||||
#define DXEPCTL_SETD0PID BIT(28)
|
||||
#define DXEPCTL_SETEVENFR BIT(28)
|
||||
#define DXEPCTL_SNAK BIT(27)
|
||||
#define DXEPCTL_CNAK BIT(26)
|
||||
#define DXEPCTL_TXFNUM_MASK (0xf << 22)
|
||||
#define DXEPCTL_TXFNUM_SHIFT 22
|
||||
#define DXEPCTL_TXFNUM_LIMIT 0xf
|
||||
#define DXEPCTL_TXFNUM(_x) ((_x) << 22)
|
||||
#define DXEPCTL_STALL BIT(21)
|
||||
#define DXEPCTL_SNP BIT(20)
|
||||
#define DXEPCTL_EPTYPE_MASK (0x3 << 18)
|
||||
#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18)
|
||||
#define DXEPCTL_EPTYPE_ISO (0x1 << 18)
|
||||
#define DXEPCTL_EPTYPE_BULK (0x2 << 18)
|
||||
#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18)
|
||||
|
||||
#define DXEPCTL_NAKSTS BIT(17)
|
||||
#define DXEPCTL_DPID BIT(16)
|
||||
#define DXEPCTL_EOFRNUM BIT(16)
|
||||
#define DXEPCTL_USBACTEP BIT(15)
|
||||
#define DXEPCTL_NEXTEP_MASK (0xf << 11)
|
||||
#define DXEPCTL_NEXTEP_SHIFT 11
|
||||
#define DXEPCTL_NEXTEP_LIMIT 0xf
|
||||
#define DXEPCTL_NEXTEP(_x) ((_x) << 11)
|
||||
#define DXEPCTL_MPS_MASK (0x7ff << 0)
|
||||
#define DXEPCTL_MPS_SHIFT 0
|
||||
#define DXEPCTL_MPS_LIMIT 0x7ff
|
||||
#define DXEPCTL_MPS(_x) ((_x) << 0)
|
||||
|
||||
#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
|
||||
#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
|
||||
#define DXEPINT_SETUP_RCVD BIT(15)
|
||||
#define DXEPINT_NYETINTRPT BIT(14)
|
||||
#define DXEPINT_NAKINTRPT BIT(13)
|
||||
#define DXEPINT_BBLEERRINTRPT BIT(12)
|
||||
#define DXEPINT_PKTDRPSTS BIT(11)
|
||||
#define DXEPINT_BNAINTR BIT(9)
|
||||
#define DXEPINT_TXFIFOUNDRN BIT(8)
|
||||
#define DXEPINT_OUTPKTERR BIT(8)
|
||||
#define DXEPINT_TXFEMP BIT(7)
|
||||
#define DXEPINT_INEPNAKEFF BIT(6)
|
||||
#define DXEPINT_BACK2BACKSETUP BIT(6)
|
||||
#define DXEPINT_INTKNEPMIS BIT(5)
|
||||
#define DXEPINT_STSPHSERCVD BIT(5)
|
||||
#define DXEPINT_INTKNTXFEMP BIT(4)
|
||||
#define DXEPINT_OUTTKNEPDIS BIT(4)
|
||||
#define DXEPINT_TIMEOUT BIT(3)
|
||||
#define DXEPINT_SETUP BIT(3)
|
||||
#define DXEPINT_AHBERR BIT(2)
|
||||
#define DXEPINT_EPDISBLD BIT(1)
|
||||
#define DXEPINT_XFERCOMPL BIT(0)
|
||||
|
||||
#define DIEPTSIZ0 HSOTG_REG(0x910)
|
||||
#define DIEPTSIZ0_PKTCNT_MASK (0x3 << 19)
|
||||
#define DIEPTSIZ0_PKTCNT_SHIFT 19
|
||||
#define DIEPTSIZ0_PKTCNT_LIMIT 0x3
|
||||
#define DIEPTSIZ0_PKTCNT(_x) ((_x) << 19)
|
||||
#define DIEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
|
||||
#define DIEPTSIZ0_XFERSIZE_SHIFT 0
|
||||
#define DIEPTSIZ0_XFERSIZE_LIMIT 0x7f
|
||||
#define DIEPTSIZ0_XFERSIZE(_x) ((_x) << 0)
|
||||
|
||||
#define DOEPTSIZ0 HSOTG_REG(0xB10)
|
||||
#define DOEPTSIZ0_SUPCNT_MASK (0x3 << 29)
|
||||
#define DOEPTSIZ0_SUPCNT_SHIFT 29
|
||||
#define DOEPTSIZ0_SUPCNT_LIMIT 0x3
|
||||
#define DOEPTSIZ0_SUPCNT(_x) ((_x) << 29)
|
||||
#define DOEPTSIZ0_PKTCNT BIT(19)
|
||||
#define DOEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
|
||||
#define DOEPTSIZ0_XFERSIZE_SHIFT 0
|
||||
|
||||
#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20))
|
||||
#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20))
|
||||
#define DXEPTSIZ_MC_MASK (0x3 << 29)
|
||||
#define DXEPTSIZ_MC_SHIFT 29
|
||||
#define DXEPTSIZ_MC_LIMIT 0x3
|
||||
#define DXEPTSIZ_MC(_x) ((_x) << 29)
|
||||
#define DXEPTSIZ_PKTCNT_MASK (0x3ff << 19)
|
||||
#define DXEPTSIZ_PKTCNT_SHIFT 19
|
||||
#define DXEPTSIZ_PKTCNT_LIMIT 0x3ff
|
||||
#define DXEPTSIZ_PKTCNT_GET(_v) (((_v) >> 19) & 0x3ff)
|
||||
#define DXEPTSIZ_PKTCNT(_x) ((_x) << 19)
|
||||
#define DXEPTSIZ_XFERSIZE_MASK (0x7ffff << 0)
|
||||
#define DXEPTSIZ_XFERSIZE_SHIFT 0
|
||||
#define DXEPTSIZ_XFERSIZE_LIMIT 0x7ffff
|
||||
#define DXEPTSIZ_XFERSIZE_GET(_v) (((_v) >> 0) & 0x7ffff)
|
||||
#define DXEPTSIZ_XFERSIZE(_x) ((_x) << 0)
|
||||
|
||||
#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20))
|
||||
#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20))
|
||||
|
||||
#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20))
|
||||
|
||||
#define PCGCTL HSOTG_REG(0x0e00)
|
||||
#define PCGCTL_IF_DEV_MODE BIT(31)
|
||||
#define PCGCTL_P2HD_PRT_SPD_MASK (0x3 << 29)
|
||||
#define PCGCTL_P2HD_PRT_SPD_SHIFT 29
|
||||
#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3 << 27)
|
||||
#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27
|
||||
#define PCGCTL_MAC_DEV_ADDR_MASK (0x7f << 20)
|
||||
#define PCGCTL_MAC_DEV_ADDR_SHIFT 20
|
||||
#define PCGCTL_MAX_TERMSEL BIT(19)
|
||||
#define PCGCTL_MAX_XCVRSELECT_MASK (0x3 << 17)
|
||||
#define PCGCTL_MAX_XCVRSELECT_SHIFT 17
|
||||
#define PCGCTL_PORT_POWER BIT(16)
|
||||
#define PCGCTL_PRT_CLK_SEL_MASK (0x3 << 14)
|
||||
#define PCGCTL_PRT_CLK_SEL_SHIFT 14
|
||||
#define PCGCTL_ESS_REG_RESTORED BIT(13)
|
||||
#define PCGCTL_EXTND_HIBER_SWITCH BIT(12)
|
||||
#define PCGCTL_EXTND_HIBER_PWRCLMP BIT(11)
|
||||
#define PCGCTL_ENBL_EXTND_HIBER BIT(10)
|
||||
#define PCGCTL_RESTOREMODE BIT(9)
|
||||
#define PCGCTL_RESETAFTSUSP BIT(8)
|
||||
#define PCGCTL_DEEP_SLEEP BIT(7)
|
||||
#define PCGCTL_PHY_IN_SLEEP BIT(6)
|
||||
#define PCGCTL_ENBL_SLEEP_GATING BIT(5)
|
||||
#define PCGCTL_RSTPDWNMODULE BIT(3)
|
||||
#define PCGCTL_PWRCLMP BIT(2)
|
||||
#define PCGCTL_GATEHCLK BIT(1)
|
||||
#define PCGCTL_STOPPCLK BIT(0)
|
||||
|
||||
#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
|
||||
|
||||
/* Host Mode Registers */
|
||||
|
||||
#define HCFG HSOTG_REG(0x0400)
|
||||
#define HCFG_MODECHTIMEN BIT(31)
|
||||
#define HCFG_PERSCHEDENA BIT(26)
|
||||
#define HCFG_FRLISTEN_MASK (0x3 << 24)
|
||||
#define HCFG_FRLISTEN_SHIFT 24
|
||||
#define HCFG_FRLISTEN_8 (0 << 24)
|
||||
#define FRLISTEN_8_SIZE 8
|
||||
#define HCFG_FRLISTEN_16 BIT(24)
|
||||
#define FRLISTEN_16_SIZE 16
|
||||
#define HCFG_FRLISTEN_32 (2 << 24)
|
||||
#define FRLISTEN_32_SIZE 32
|
||||
#define HCFG_FRLISTEN_64 (3 << 24)
|
||||
#define FRLISTEN_64_SIZE 64
|
||||
#define HCFG_DESCDMA BIT(23)
|
||||
#define HCFG_RESVALID_MASK (0xff << 8)
|
||||
#define HCFG_RESVALID_SHIFT 8
|
||||
#define HCFG_ENA32KHZ BIT(7)
|
||||
#define HCFG_FSLSSUPP BIT(2)
|
||||
#define HCFG_FSLSPCLKSEL_MASK (0x3 << 0)
|
||||
#define HCFG_FSLSPCLKSEL_SHIFT 0
|
||||
#define HCFG_FSLSPCLKSEL_30_60_MHZ 0
|
||||
#define HCFG_FSLSPCLKSEL_48_MHZ 1
|
||||
#define HCFG_FSLSPCLKSEL_6_MHZ 2
|
||||
|
||||
#define HFIR HSOTG_REG(0x0404)
|
||||
#define HFIR_FRINT_MASK (0xffff << 0)
|
||||
#define HFIR_FRINT_SHIFT 0
|
||||
#define HFIR_RLDCTRL BIT(16)
|
||||
|
||||
#define HFNUM HSOTG_REG(0x0408)
|
||||
#define HFNUM_FRREM_MASK (0xffffUL << 16)
|
||||
#define HFNUM_FRREM_SHIFT 16
|
||||
#define HFNUM_FRNUM_MASK (0xffff << 0)
|
||||
#define HFNUM_FRNUM_SHIFT 0
|
||||
#define HFNUM_MAX_FRNUM 0x3fff
|
||||
|
||||
#define HPTXSTS HSOTG_REG(0x0410)
|
||||
#define TXSTS_QTOP_ODD BIT(31)
|
||||
#define TXSTS_QTOP_CHNEP_MASK (0xf << 27)
|
||||
#define TXSTS_QTOP_CHNEP_SHIFT 27
|
||||
#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
|
||||
#define TXSTS_QTOP_TOKEN_SHIFT 25
|
||||
#define TXSTS_QTOP_TERMINATE BIT(24)
|
||||
#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
|
||||
#define TXSTS_QSPCAVAIL_SHIFT 16
|
||||
#define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
|
||||
#define TXSTS_FSPCAVAIL_SHIFT 0
|
||||
|
||||
#define HAINT HSOTG_REG(0x0414)
|
||||
#define HAINTMSK HSOTG_REG(0x0418)
|
||||
#define HFLBADDR HSOTG_REG(0x041c)
|
||||
|
||||
#define HPRT0 HSOTG_REG(0x0440)
|
||||
#define HPRT0_SPD_MASK (0x3 << 17)
|
||||
#define HPRT0_SPD_SHIFT 17
|
||||
#define HPRT0_SPD_HIGH_SPEED 0
|
||||
#define HPRT0_SPD_FULL_SPEED 1
|
||||
#define HPRT0_SPD_LOW_SPEED 2
|
||||
#define HPRT0_TSTCTL_MASK (0xf << 13)
|
||||
#define HPRT0_TSTCTL_SHIFT 13
|
||||
#define HPRT0_PWR BIT(12)
|
||||
#define HPRT0_LNSTS_MASK (0x3 << 10)
|
||||
#define HPRT0_LNSTS_SHIFT 10
|
||||
#define HPRT0_RST BIT(8)
|
||||
#define HPRT0_SUSP BIT(7)
|
||||
#define HPRT0_RES BIT(6)
|
||||
#define HPRT0_OVRCURRCHG BIT(5)
|
||||
#define HPRT0_OVRCURRACT BIT(4)
|
||||
#define HPRT0_ENACHG BIT(3)
|
||||
#define HPRT0_ENA BIT(2)
|
||||
#define HPRT0_CONNDET BIT(1)
|
||||
#define HPRT0_CONNSTS BIT(0)
|
||||
|
||||
#define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch))
|
||||
#define HCCHAR_CHENA BIT(31)
|
||||
#define HCCHAR_CHDIS BIT(30)
|
||||
#define HCCHAR_ODDFRM BIT(29)
|
||||
#define HCCHAR_DEVADDR_MASK (0x7f << 22)
|
||||
#define HCCHAR_DEVADDR_SHIFT 22
|
||||
#define HCCHAR_MULTICNT_MASK (0x3 << 20)
|
||||
#define HCCHAR_MULTICNT_SHIFT 20
|
||||
#define HCCHAR_EPTYPE_MASK (0x3 << 18)
|
||||
#define HCCHAR_EPTYPE_SHIFT 18
|
||||
#define HCCHAR_LSPDDEV BIT(17)
|
||||
#define HCCHAR_EPDIR BIT(15)
|
||||
#define HCCHAR_EPNUM_MASK (0xf << 11)
|
||||
#define HCCHAR_EPNUM_SHIFT 11
|
||||
#define HCCHAR_MPS_MASK (0x7ff << 0)
|
||||
#define HCCHAR_MPS_SHIFT 0
|
||||
|
||||
#define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch))
|
||||
#define HCSPLT_SPLTENA BIT(31)
|
||||
#define HCSPLT_COMPSPLT BIT(16)
|
||||
#define HCSPLT_XACTPOS_MASK (0x3 << 14)
|
||||
#define HCSPLT_XACTPOS_SHIFT 14
|
||||
#define HCSPLT_XACTPOS_MID 0
|
||||
#define HCSPLT_XACTPOS_END 1
|
||||
#define HCSPLT_XACTPOS_BEGIN 2
|
||||
#define HCSPLT_XACTPOS_ALL 3
|
||||
#define HCSPLT_HUBADDR_MASK (0x7f << 7)
|
||||
#define HCSPLT_HUBADDR_SHIFT 7
|
||||
#define HCSPLT_PRTADDR_MASK (0x7f << 0)
|
||||
#define HCSPLT_PRTADDR_SHIFT 0
|
||||
|
||||
#define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch))
|
||||
#define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch))
|
||||
#define HCINTMSK_RESERVED14_31 (0x3ffff << 14)
|
||||
#define HCINTMSK_FRM_LIST_ROLL BIT(13)
|
||||
#define HCINTMSK_XCS_XACT BIT(12)
|
||||
#define HCINTMSK_BNA BIT(11)
|
||||
#define HCINTMSK_DATATGLERR BIT(10)
|
||||
#define HCINTMSK_FRMOVRUN BIT(9)
|
||||
#define HCINTMSK_BBLERR BIT(8)
|
||||
#define HCINTMSK_XACTERR BIT(7)
|
||||
#define HCINTMSK_NYET BIT(6)
|
||||
#define HCINTMSK_ACK BIT(5)
|
||||
#define HCINTMSK_NAK BIT(4)
|
||||
#define HCINTMSK_STALL BIT(3)
|
||||
#define HCINTMSK_AHBERR BIT(2)
|
||||
#define HCINTMSK_CHHLTD BIT(1)
|
||||
#define HCINTMSK_XFERCOMPL BIT(0)
|
||||
|
||||
#define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch))
|
||||
#define TSIZ_DOPNG BIT(31)
|
||||
#define TSIZ_SC_MC_PID_MASK (0x3 << 29)
|
||||
#define TSIZ_SC_MC_PID_SHIFT 29
|
||||
#define TSIZ_SC_MC_PID_DATA0 0
|
||||
#define TSIZ_SC_MC_PID_DATA2 1
|
||||
#define TSIZ_SC_MC_PID_DATA1 2
|
||||
#define TSIZ_SC_MC_PID_MDATA 3
|
||||
#define TSIZ_SC_MC_PID_SETUP 3
|
||||
#define TSIZ_PKTCNT_MASK (0x3ff << 19)
|
||||
#define TSIZ_PKTCNT_SHIFT 19
|
||||
#define TSIZ_NTD_MASK (0xff << 8)
|
||||
#define TSIZ_NTD_SHIFT 8
|
||||
#define TSIZ_SCHINFO_MASK (0xff << 0)
|
||||
#define TSIZ_SCHINFO_SHIFT 0
|
||||
#define TSIZ_XFERSIZE_MASK (0x7ffff << 0)
|
||||
#define TSIZ_XFERSIZE_SHIFT 0
|
||||
|
||||
#define HCDMA(_ch) HSOTG_REG(0x0514 + 0x20 * (_ch))
|
||||
|
||||
#define HCDMAB(_ch) HSOTG_REG(0x051c + 0x20 * (_ch))
|
||||
|
||||
#define HCFIFO(_ch) HSOTG_REG(0x1000 + 0x1000 * (_ch))
|
||||
|
||||
/**
|
||||
* struct dwc2_dma_desc - DMA descriptor structure,
|
||||
* used for both host and gadget modes
|
||||
*
|
||||
* @status: DMA descriptor status quadlet
|
||||
* @buf: DMA descriptor data buffer pointer
|
||||
*
|
||||
* DMA Descriptor structure contains two quadlets:
|
||||
* Status quadlet and Data buffer pointer.
|
||||
*/
|
||||
struct dwc2_dma_desc {
|
||||
u32 status;
|
||||
u32 buf;
|
||||
};//__packed
|
||||
|
||||
/* Host Mode DMA descriptor status quadlet */
|
||||
|
||||
#define HOST_DMA_A BIT(31)
|
||||
#define HOST_DMA_STS_MASK (0x3 << 28)
|
||||
#define HOST_DMA_STS_SHIFT 28
|
||||
#define HOST_DMA_STS_PKTERR BIT(28)
|
||||
#define HOST_DMA_EOL BIT(26)
|
||||
#define HOST_DMA_IOC BIT(25)
|
||||
#define HOST_DMA_SUP BIT(24)
|
||||
#define HOST_DMA_ALT_QTD BIT(23)
|
||||
#define HOST_DMA_QTD_OFFSET_MASK (0x3f << 17)
|
||||
#define HOST_DMA_QTD_OFFSET_SHIFT 17
|
||||
#define HOST_DMA_ISOC_NBYTES_MASK (0xfff << 0)
|
||||
#define HOST_DMA_ISOC_NBYTES_SHIFT 0
|
||||
#define HOST_DMA_NBYTES_MASK (0x1ffff << 0)
|
||||
#define HOST_DMA_NBYTES_SHIFT 0
|
||||
#define HOST_DMA_NBYTES_LIMIT 131071
|
||||
|
||||
/* Device Mode DMA descriptor status quadlet */
|
||||
|
||||
#define DEV_DMA_BUFF_STS_MASK (0x3 << 30)
|
||||
#define DEV_DMA_BUFF_STS_SHIFT 30
|
||||
#define DEV_DMA_BUFF_STS_HREADY 0
|
||||
#define DEV_DMA_BUFF_STS_DMABUSY 1
|
||||
#define DEV_DMA_BUFF_STS_DMADONE 2
|
||||
#define DEV_DMA_BUFF_STS_HBUSY 3UL
|
||||
#define DEV_DMA_STS_MASK (0x3 << 28)
|
||||
#define DEV_DMA_STS_SHIFT 28
|
||||
#define DEV_DMA_STS_SUCC 0
|
||||
#define DEV_DMA_STS_BUFF_FLUSH 1
|
||||
#define DEV_DMA_STS_BUFF_ERR 3
|
||||
#define DEV_DMA_L BIT(27)
|
||||
#define DEV_DMA_SHORT BIT(26)
|
||||
#define DEV_DMA_IOC BIT(25)
|
||||
#define DEV_DMA_SR BIT(24)
|
||||
#define DEV_DMA_MTRF BIT(23)
|
||||
#define DEV_DMA_ISOC_PID_MASK (0x3 << 23)
|
||||
#define DEV_DMA_ISOC_PID_SHIFT 23
|
||||
#define DEV_DMA_ISOC_PID_DATA0 0
|
||||
#define DEV_DMA_ISOC_PID_DATA2 1
|
||||
#define DEV_DMA_ISOC_PID_DATA1 2
|
||||
#define DEV_DMA_ISOC_PID_MDATA 3
|
||||
#define DEV_DMA_ISOC_FRNUM_MASK (0x7ff << 12)
|
||||
#define DEV_DMA_ISOC_FRNUM_SHIFT 12
|
||||
#define DEV_DMA_ISOC_TX_NBYTES_MASK (0xfff << 0)
|
||||
#define DEV_DMA_ISOC_TX_NBYTES_LIMIT 0xfff
|
||||
#define DEV_DMA_ISOC_RX_NBYTES_MASK (0x7ff << 0)
|
||||
#define DEV_DMA_ISOC_RX_NBYTES_LIMIT 0x7ff
|
||||
#define DEV_DMA_ISOC_NBYTES_SHIFT 0
|
||||
#define DEV_DMA_NBYTES_MASK (0xffff << 0)
|
||||
#define DEV_DMA_NBYTES_SHIFT 0
|
||||
#define DEV_DMA_NBYTES_LIMIT 0xffff
|
||||
|
||||
#define MAX_DMA_DESC_NUM_GENERIC 64
|
||||
#define MAX_DMA_DESC_NUM_HS_ISOC 256
|
||||
|
||||
#endif /* __DWC2_HW_H__ */
|
65
A27-STEPLDR/Src/usb/include/asm/dma-mapping.h
Normal file
65
A27-STEPLDR/Src/usb/include/asm/dma-mapping.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2007
|
||||
* Stelian Pop <stelian@popies.net>
|
||||
* Lead Tech Design <www.leadtechdesign.com>
|
||||
*/
|
||||
#ifndef __ASM_ARM_DMA_MAPPING_H
|
||||
#define __ASM_ARM_DMA_MAPPING_H
|
||||
|
||||
#include <linux/dma-direction.h>
|
||||
|
||||
#define dma_mapping_error(x, y) 0
|
||||
struct device;
|
||||
|
||||
static inline void *dma_alloc_coherent(struct device *dev, size_t len, dma_addr_t *handle, gfp_t flag)
|
||||
{
|
||||
(void)flag;
|
||||
//*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
|
||||
*handle = (unsigned long)malloc(len + ARCH_DMA_MINALIGN);
|
||||
return (void *)*handle;
|
||||
}
|
||||
|
||||
static inline void dma_free_coherent(struct device *dev, size_t size, void *addr, dma_addr_t handle)
|
||||
{
|
||||
free(addr);
|
||||
}
|
||||
|
||||
static inline void *dmam_alloc_coherent(struct device *dev, size_t len, dma_addr_t *handle, gfp_t flag)
|
||||
{
|
||||
(void)flag;
|
||||
(void)dev;
|
||||
*handle = (dma_addr_t)malloc(len + ARCH_DMA_MINALIGN);
|
||||
return (void *)*handle;
|
||||
}
|
||||
|
||||
static inline void dmam_free_coherent(struct device *dev, size_t len, void *vaddr, dma_addr_t handle)
|
||||
{
|
||||
free(vaddr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline unsigned long dma_map_single(volatile void *vaddr, size_t len,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
return (unsigned long)vaddr;
|
||||
}
|
||||
|
||||
static inline void dma_unmap_single(volatile void *vaddr, size_t len,
|
||||
unsigned long paddr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dma_sync_single_for_device(struct device *dev,
|
||||
dma_addr_t addr, size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dma_sync_single_for_cpu(struct device *dev,
|
||||
dma_addr_t addr, size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endif /* __ASM_ARM_DMA_MAPPING_H */
|
13
A27-STEPLDR/Src/usb/include/linux/dma-direction.h
Normal file
13
A27-STEPLDR/Src/usb/include/linux/dma-direction.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _LINUX_DMA_DIRECTION_H
|
||||
#define _LINUX_DMA_DIRECTION_H
|
||||
/*
|
||||
* These definitions mirror those in pci.h, so they can be used
|
||||
* interchangeably with their PCI_ counterparts.
|
||||
*/
|
||||
enum dma_data_direction {
|
||||
DMA_BIDIRECTIONAL = 0,
|
||||
DMA_TO_DEVICE = 1,
|
||||
DMA_FROM_DEVICE = 2,
|
||||
DMA_NONE = 3,
|
||||
};
|
||||
#endif
|
168
A27-STEPLDR/Src/usb/include/linux/errno.h
Normal file
168
A27-STEPLDR/Src/usb/include/linux/errno.h
Normal file
@ -0,0 +1,168 @@
|
||||
#ifndef _LINUX_ERRNO_H
|
||||
#define _LINUX_ERRNO_H
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
|
||||
#define ENOSYS 38 /* Invalid system call number */
|
||||
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
#define ECANCELED 125 /* Operation Canceled */
|
||||
#define ENOKEY 126 /* Required key not available */
|
||||
#define EKEYEXPIRED 127 /* Key has expired */
|
||||
#define EKEYREVOKED 128 /* Key has been revoked */
|
||||
#define EKEYREJECTED 129 /* Key was rejected by service */
|
||||
|
||||
/* for robust mutexes */
|
||||
#define EOWNERDEAD 130 /* Owner died */
|
||||
#define ENOTRECOVERABLE 131 /* State not recoverable */
|
||||
|
||||
#define ERFKILL 132 /* Operation not possible due to RF-kill */
|
||||
|
||||
#define EHWPOISON 133 /* Memory page has hardware error */
|
||||
|
||||
#define ERESTARTSYS 512
|
||||
#define ERESTARTNOINTR 513
|
||||
#define ERESTARTNOHAND 514 /* restart if no handler.. */
|
||||
#define ENOIOCTLCMD 515 /* No ioctl command */
|
||||
#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
|
||||
#define EPROBE_DEFER 517 /* Driver requests probe retry */
|
||||
#define EOPENSTALE 518 /* open found a stale dentry */
|
||||
|
||||
/* Defined for the NFSv3 protocol */
|
||||
#define EBADHANDLE 521 /* Illegal NFS file handle */
|
||||
#define ENOTSYNC 522 /* Update synchronization mismatch */
|
||||
#define EBADCOOKIE 523 /* Cookie is stale */
|
||||
#define ENOTSUPP 524 /* Operation is not supported */
|
||||
#define ETOOSMALL 525 /* Buffer or request is too small */
|
||||
#define ESERVERFAULT 526 /* An untranslatable error occurred */
|
||||
#define EBADTYPE 527 /* Type not supported by server */
|
||||
#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
|
||||
#define EIOCBQUEUED 529 /* iocb queued, will get completion event */
|
||||
#define ERECALLCONFLICT 530 /* conflict with recalled state */
|
||||
|
||||
#endif
|
981
A27-STEPLDR/Src/usb/include/linux/usb/ch9.h
Normal file
981
A27-STEPLDR/Src/usb/include/linux/usb/ch9.h
Normal file
@ -0,0 +1,981 @@
|
||||
/*
|
||||
* This file holds USB constants and structures that are needed for
|
||||
* USB device APIs. These are used by the USB device model, which is
|
||||
* defined in chapter 9 of the USB 2.0 specification and in the
|
||||
* Wireless USB 1.0 (spread around). Linux has several APIs in C that
|
||||
* need these:
|
||||
*
|
||||
* - the master/host side Linux-USB kernel driver API;
|
||||
* - the "usbfs" user space API; and
|
||||
* - the Linux "gadget" slave/device/peripheral side driver API.
|
||||
*
|
||||
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
|
||||
* act either as a USB master/host or as a USB slave/device. That means
|
||||
* the master and slave side APIs benefit from working well together.
|
||||
*
|
||||
* There's also "Wireless USB", using low power short range radios for
|
||||
* peripheral interconnection but otherwise building on the USB framework.
|
||||
*
|
||||
* Note all descriptors are declared '__attribute__((packed))' so that:
|
||||
*
|
||||
* [a] they never get padded, either internally (USB spec writers
|
||||
* probably handled that) or externally;
|
||||
*
|
||||
* [b] so that accessing bigger-than-a-bytes fields will never
|
||||
* generate bus errors on any platform, even when the location of
|
||||
* its descriptor inside a bundle isn't "naturally aligned", and
|
||||
*
|
||||
* [c] for consistency, removing all doubt even when it appears to
|
||||
* someone that the two other points are non-issues for that
|
||||
* particular descriptor type.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_CH9_H
|
||||
#define __LINUX_USB_CH9_H
|
||||
|
||||
//#include <linux/types.h> /* __u8 etc */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* CONTROL REQUEST SUPPORT */
|
||||
|
||||
/*
|
||||
* USB directions
|
||||
*
|
||||
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
|
||||
* It's also one of three fields in control requests bRequestType.
|
||||
*/
|
||||
#define USB_DIR_OUT 0 /* to device */
|
||||
#define USB_DIR_IN 0x80 /* to host */
|
||||
|
||||
/*
|
||||
* USB types, the second of three bRequestType fields
|
||||
*/
|
||||
#define USB_TYPE_MASK (0x03 << 5)
|
||||
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
/*
|
||||
* USB recipients, the third of three bRequestType fields
|
||||
*/
|
||||
#define USB_RECIP_MASK 0x1f
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
/* From Wireless USB 1.0 */
|
||||
#define USB_RECIP_PORT 0x04
|
||||
#define USB_RECIP_RPIPE 0x05
|
||||
|
||||
/*
|
||||
* Standard requests, for the bRequest field of a SETUP packet.
|
||||
*
|
||||
* These are qualified by the bRequestType field, so that for example
|
||||
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
|
||||
* by a GET_STATUS request.
|
||||
*/
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
#define USB_REQ_SET_SEL 0x30
|
||||
#define USB_REQ_SET_ISOCH_DELAY 0x31
|
||||
|
||||
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
|
||||
#define USB_REQ_GET_ENCRYPTION 0x0E
|
||||
#define USB_REQ_RPIPE_ABORT 0x0E
|
||||
#define USB_REQ_SET_HANDSHAKE 0x0F
|
||||
#define USB_REQ_RPIPE_RESET 0x0F
|
||||
#define USB_REQ_GET_HANDSHAKE 0x10
|
||||
#define USB_REQ_SET_CONNECTION 0x11
|
||||
#define USB_REQ_SET_SECURITY_DATA 0x12
|
||||
#define USB_REQ_GET_SECURITY_DATA 0x13
|
||||
#define USB_REQ_SET_WUSB_DATA 0x14
|
||||
#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
|
||||
#define USB_REQ_LOOPBACK_DATA_READ 0x16
|
||||
#define USB_REQ_SET_INTERFACE_DS 0x17
|
||||
|
||||
/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
|
||||
* used by hubs to put ports into a new L1 suspend state, except that it
|
||||
* forgot to define its number ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
|
||||
* are read as a bit array returned by USB_REQ_GET_STATUS. (So there
|
||||
* are at most sixteen features of each type.) Hubs may also support a
|
||||
* new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
|
||||
*/
|
||||
#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
|
||||
#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */
|
||||
#define USB_DEVICE_BATTERY 2 /* (wireless) */
|
||||
#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */
|
||||
#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/
|
||||
#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */
|
||||
#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
|
||||
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
|
||||
|
||||
/*
|
||||
* Test Mode Selectors
|
||||
* See USB 2.0 spec Table 9-7
|
||||
*/
|
||||
#define TEST_J 1
|
||||
#define TEST_K 2
|
||||
#define TEST_SE0_NAK 3
|
||||
#define TEST_PACKET 4
|
||||
#define TEST_FORCE_EN 5
|
||||
|
||||
/*
|
||||
* New Feature Selectors as added by USB 3.0
|
||||
* See USB 3.0 spec Table 9-6
|
||||
*/
|
||||
#define USB_DEVICE_U1_ENABLE 48 /* dev may initiate U1 transition */
|
||||
#define USB_DEVICE_U2_ENABLE 49 /* dev may initiate U2 transition */
|
||||
#define USB_DEVICE_LTM_ENABLE 50 /* dev may send LTM */
|
||||
#define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */
|
||||
|
||||
#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
|
||||
/*
|
||||
* Suspend Options, Table 9-7 USB 3.0 spec
|
||||
*/
|
||||
#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0))
|
||||
#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1))
|
||||
|
||||
#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
|
||||
|
||||
/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
|
||||
#define USB_DEV_STAT_U1_ENABLED 2 /* transition into U1 state */
|
||||
#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */
|
||||
#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */
|
||||
|
||||
/**
|
||||
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
||||
* @bRequestType: matches the USB bmRequestType field
|
||||
* @bRequest: matches the USB bRequest field
|
||||
* @wValue: matches the USB wValue field (le16 byte order)
|
||||
* @wIndex: matches the USB wIndex field (le16 byte order)
|
||||
* @wLength: matches the USB wLength field (le16 byte order)
|
||||
*
|
||||
* This structure is used to send control requests to a USB device. It matches
|
||||
* the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
|
||||
* USB spec for a fuller description of the different fields, and what they are
|
||||
* used for.
|
||||
*
|
||||
* Note that the driver for any interface can issue control requests.
|
||||
* For most devices, interfaces don't coordinate with each other, so
|
||||
* such requests may be made at any time.
|
||||
*/
|
||||
struct usb_ctrlrequest {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__le16 wValue;
|
||||
__le16 wIndex;
|
||||
__le16 wLength;
|
||||
} ;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
|
||||
* (rarely) accepted by SET_DESCRIPTOR.
|
||||
*
|
||||
* Note that all multi-byte values here are encoded in little endian
|
||||
* byte order "on the wire". Within the kernel and when exposed
|
||||
* through the Linux-USB APIs, they are not converted to cpu byte
|
||||
* order; it is the responsibility of the client code to do this.
|
||||
* The single exception is when device and configuration descriptors (but
|
||||
* not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
|
||||
* in this case the fields are converted to host endianness by the kernel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Descriptor types ... USB 2.0 spec table 9.5
|
||||
*/
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
#define USB_DT_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_DT_INTERFACE_POWER 0x08
|
||||
/* these are from a minor usb 2.0 revision (ECN) */
|
||||
#define USB_DT_OTG 0x09
|
||||
#define USB_DT_DEBUG 0x0a
|
||||
#define USB_DT_INTERFACE_ASSOCIATION 0x0b
|
||||
/* these are from the Wireless USB spec */
|
||||
#define USB_DT_SECURITY 0x0c
|
||||
#define USB_DT_KEY 0x0d
|
||||
#define USB_DT_ENCRYPTION_TYPE 0x0e
|
||||
#define USB_DT_BOS 0x0f
|
||||
#define USB_DT_DEVICE_CAPABILITY 0x10
|
||||
#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
|
||||
#define USB_DT_WIRE_ADAPTER 0x21
|
||||
#define USB_DT_RPIPE 0x22
|
||||
#define USB_DT_CS_RADIO_CONTROL 0x23
|
||||
/* From the T10 UAS specification */
|
||||
#define USB_DT_PIPE_USAGE 0x24
|
||||
/* From the USB 3.0 spec */
|
||||
#define USB_DT_SS_ENDPOINT_COMP 0x30
|
||||
/* From HID 1.11 spec */
|
||||
#define USB_DT_HID_REPORT 0x22
|
||||
|
||||
/* Conventional codes for class-specific descriptors. The convention is
|
||||
* defined in the USB "Common Class" Spec (3.11). Individual class specs
|
||||
* are authoritative for their usage, not the "common class" writeup.
|
||||
*/
|
||||
#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE)
|
||||
#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG)
|
||||
#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING)
|
||||
#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE)
|
||||
#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT)
|
||||
|
||||
/* All standard descriptors have these 2 fields at the beginning */
|
||||
struct usb_descriptor_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
} ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE: Device descriptor */
|
||||
struct usb_device_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__le16 idVendor;
|
||||
__le16 idProduct;
|
||||
__le16 bcdDevice;
|
||||
__u8 iManufacturer;
|
||||
__u8 iProduct;
|
||||
__u8 iSerialNumber;
|
||||
__u8 bNumConfigurations;
|
||||
} ;
|
||||
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
|
||||
|
||||
/*
|
||||
* Device and/or Interface Class codes
|
||||
* as found in bDeviceClass or bInterfaceClass
|
||||
* and defined by www.usb.org documents
|
||||
*/
|
||||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_COMM 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_PHYSICAL 5
|
||||
#define USB_CLASS_STILL_IMAGE 6
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_CDC_DATA 0x0a
|
||||
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
|
||||
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
|
||||
#define USB_CLASS_VIDEO 0x0e
|
||||
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
|
||||
#define USB_CLASS_MISC 0xef
|
||||
#define USB_CLASS_APP_SPEC 0xfe
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
#define USB_SUBCLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_CONFIG: Configuration descriptor information.
|
||||
*
|
||||
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
|
||||
* descriptor type is different. Highspeed-capable devices can look
|
||||
* different depending on what speed they're currently running. Only
|
||||
* devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
|
||||
* descriptors.
|
||||
*/
|
||||
struct usb_config_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 wTotalLength;
|
||||
__u8 bNumInterfaces;
|
||||
__u8 bConfigurationValue;
|
||||
__u8 iConfiguration;
|
||||
__u8 bmAttributes;
|
||||
__u8 bMaxPower;
|
||||
} ;
|
||||
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
|
||||
/* from config descriptor bmAttributes */
|
||||
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
|
||||
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
|
||||
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
|
||||
#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_STRING: String descriptor */
|
||||
struct usb_string_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 wData[1]; /* UTF-16LE encoded */
|
||||
} ;
|
||||
|
||||
/* note that "string" zero is special, it holds language codes that
|
||||
* the device supports, not Unicode characters.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_INTERFACE: Interface descriptor */
|
||||
struct usb_interface_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bInterfaceNumber;
|
||||
__u8 bAlternateSetting;
|
||||
__u8 bNumEndpoints;
|
||||
__u8 bInterfaceClass;
|
||||
__u8 bInterfaceSubClass;
|
||||
__u8 bInterfaceProtocol;
|
||||
__u8 iInterface;
|
||||
} ;
|
||||
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_ENDPOINT: Endpoint descriptor */
|
||||
struct usb_endpoint_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bmAttributes;
|
||||
__le16 wMaxPacketSize;
|
||||
__u8 bInterval;
|
||||
|
||||
/* NOTE: these two are _only_ in audio endpoints. */
|
||||
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
|
||||
__u8 bRefresh;
|
||||
__u8 bSynchAddress;
|
||||
} ;
|
||||
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
|
||||
/* Used to access common fields */
|
||||
struct usb_generic_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
};
|
||||
|
||||
struct usb_class_hid_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u16 bcdCDC;
|
||||
u8 bCountryCode;
|
||||
u8 bNumDescriptors; /* 0x01 */
|
||||
u8 bDescriptorType0;
|
||||
u16 wDescriptorLength0;
|
||||
/* optional descriptors are not supported. */
|
||||
};
|
||||
|
||||
struct usb_class_report_descriptor {
|
||||
u8 bLength; /* dummy */
|
||||
u8 bDescriptorType;
|
||||
u16 wLength;
|
||||
u8 bData[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoints
|
||||
*/
|
||||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
||||
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||
|
||||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
|
||||
|
||||
#define USB_ENDPOINT_MAXP_MASK 0x07ff
|
||||
#define USB_EP_MAXP_MULT_SHIFT 11
|
||||
#define USB_EP_MAXP_MULT_MASK (3 << USB_EP_MAXP_MULT_SHIFT)
|
||||
#define USB_EP_MAXP_MULT(m) \
|
||||
(((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT)
|
||||
|
||||
/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
|
||||
#define USB_ENDPOINT_INTRTYPE 0x30
|
||||
#define USB_ENDPOINT_INTR_PERIODIC (0 << 4)
|
||||
#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
|
||||
|
||||
#define USB_ENDPOINT_SYNCTYPE 0x0c
|
||||
#define USB_ENDPOINT_SYNC_NONE (0 << 2)
|
||||
#define USB_ENDPOINT_SYNC_ASYNC (1 << 2)
|
||||
#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2)
|
||||
#define USB_ENDPOINT_SYNC_SYNC (3 << 2)
|
||||
|
||||
#define USB_ENDPOINT_USAGE_MASK 0x30
|
||||
#define USB_ENDPOINT_USAGE_DATA 0x00
|
||||
#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
|
||||
#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_endpoint_num - get the endpoint's number
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns @epd's number: 0 to 15.
|
||||
*/
|
||||
static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_type - get the endpoint's transfer type
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
|
||||
* to @epd's transfer type.
|
||||
*/
|
||||
static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_dir_in - check if the endpoint has IN direction
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint is of type IN, otherwise it returns false.
|
||||
*/
|
||||
static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_dir_out - check if the endpoint has OUT direction
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint is of type OUT, otherwise it returns false.
|
||||
*/
|
||||
static inline int usb_endpoint_dir_out(
|
||||
const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint is of type bulk, otherwise it returns false.
|
||||
*/
|
||||
static inline int usb_endpoint_xfer_bulk(
|
||||
const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_BULK);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_xfer_control - check if the endpoint has control transfer type
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint is of type control, otherwise it returns false.
|
||||
*/
|
||||
static inline int usb_endpoint_xfer_control(
|
||||
const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint has bulk transfer type and IN direction,
|
||||
* otherwise it returns false.
|
||||
*/
|
||||
static inline int usb_endpoint_is_bulk_in(
|
||||
const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint has bulk transfer type and OUT direction,
|
||||
* otherwise it returns false.
|
||||
*/
|
||||
static inline int usb_endpoint_is_bulk_out(
|
||||
const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_maxp - get endpoint's max packet size
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns @epd's max packet
|
||||
*/
|
||||
static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return __le16_to_cpu(get_unaligned(&epd->wMaxPacketSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_maxp_mult - get endpoint's transactional opportunities
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Return @epd's wMaxPacketSize[12:11] + 1
|
||||
*/
|
||||
static inline int
|
||||
usb_endpoint_maxp_mult(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
int maxp = __le16_to_cpu(epd->wMaxPacketSize);
|
||||
|
||||
return USB_EP_MAXP_MULT(maxp) + 1;
|
||||
}
|
||||
|
||||
static inline int usb_endpoint_interrupt_type(
|
||||
const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
|
||||
struct usb_ss_ep_comp_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bMaxBurst;
|
||||
__u8 bmAttributes;
|
||||
__le16 wBytesPerInterval;
|
||||
} ;
|
||||
|
||||
#define USB_DT_SS_EP_COMP_SIZE 6
|
||||
|
||||
/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
|
||||
static inline int
|
||||
usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
|
||||
{
|
||||
int max_streams;
|
||||
|
||||
if (!comp)
|
||||
return 0;
|
||||
|
||||
max_streams = comp->bmAttributes & 0x1f;
|
||||
|
||||
if (!max_streams)
|
||||
return 0;
|
||||
|
||||
max_streams = 1 << max_streams;
|
||||
|
||||
return max_streams;
|
||||
}
|
||||
|
||||
/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
|
||||
#define USB_SS_MULT(p) (1 + ((p) & 0x3))
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
|
||||
struct usb_qualifier_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u8 bNumConfigurations;
|
||||
__u8 bRESERVED;
|
||||
} ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_OTG (from OTG 1.0a supplement) */
|
||||
struct usb_otg_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bmAttributes; /* support for HNP, SRP, etc */
|
||||
} ;
|
||||
|
||||
/* from usb_otg_descriptor.bmAttributes */
|
||||
#define USB_OTG_SRP (1 << 0)
|
||||
#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
|
||||
struct usb_debug_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
/* bulk endpoints with 8 byte maxpacket */
|
||||
__u8 bDebugInEndpoint;
|
||||
__u8 bDebugOutEndpoint;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
|
||||
struct usb_interface_assoc_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bFirstInterface;
|
||||
__u8 bInterfaceCount;
|
||||
__u8 bFunctionClass;
|
||||
__u8 bFunctionSubClass;
|
||||
__u8 bFunctionProtocol;
|
||||
__u8 iFunction;
|
||||
} ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_SECURITY: group of wireless security descriptors, including
|
||||
* encryption types available for setting up a CC/association.
|
||||
*/
|
||||
struct usb_security_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 wTotalLength;
|
||||
__u8 bNumEncryptionTypes;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys
|
||||
* may be retrieved.
|
||||
*/
|
||||
struct usb_key_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 tTKID[3];
|
||||
__u8 bReserved;
|
||||
__u8 bKeyData[0];
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */
|
||||
struct usb_encryption_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bEncryptionType;
|
||||
#define USB_ENC_TYPE_UNSECURE 0
|
||||
#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */
|
||||
#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */
|
||||
#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */
|
||||
__u8 bEncryptionValue; /* use in SET_ENCRYPTION */
|
||||
__u8 bAuthKeyIndex;
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_BOS: group of device-level capabilities */
|
||||
struct usb_bos_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 wTotalLength;
|
||||
__u8 bNumDeviceCaps;
|
||||
};
|
||||
|
||||
#define USB_DT_BOS_SIZE 5
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */
|
||||
struct usb_dev_cap_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
};
|
||||
|
||||
#define USB_CAP_TYPE_WIRELESS_USB 1
|
||||
|
||||
struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
|
||||
__u8 bmAttributes;
|
||||
#define USB_WIRELESS_P2P_DRD (1 << 1)
|
||||
#define USB_WIRELESS_BEACON_MASK (3 << 2)
|
||||
#define USB_WIRELESS_BEACON_SELF (1 << 2)
|
||||
#define USB_WIRELESS_BEACON_DIRECTED (2 << 2)
|
||||
#define USB_WIRELESS_BEACON_NONE (3 << 2)
|
||||
__le16 wPHYRates; /* bit rates, Mbps */
|
||||
#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */
|
||||
#define USB_WIRELESS_PHY_80 (1 << 1)
|
||||
#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */
|
||||
#define USB_WIRELESS_PHY_160 (1 << 3)
|
||||
#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */
|
||||
#define USB_WIRELESS_PHY_320 (1 << 5)
|
||||
#define USB_WIRELESS_PHY_400 (1 << 6)
|
||||
#define USB_WIRELESS_PHY_480 (1 << 7)
|
||||
__u8 bmTFITXPowerInfo; /* TFI power levels */
|
||||
__u8 bmFFITXPowerInfo; /* FFI power levels */
|
||||
__le16 bmBandGroup;
|
||||
__u8 bReserved;
|
||||
};
|
||||
|
||||
/* USB 2.0 Extension descriptor */
|
||||
#define USB_CAP_TYPE_EXT 2
|
||||
|
||||
struct usb_ext_cap_descriptor { /* Link Power Management */
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
__le32 bmAttributes;
|
||||
#define USB_LPM_SUPPORT (1 << 1) /* supports LPM */
|
||||
#define USB_BESL_SUPPORT (1 << 2) /* supports BESL */
|
||||
#define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/
|
||||
#define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */
|
||||
#define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8)
|
||||
#define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12)
|
||||
};
|
||||
|
||||
#define USB_DT_USB_EXT_CAP_SIZE 7
|
||||
|
||||
/*
|
||||
* SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
|
||||
* specific device level capabilities
|
||||
*/
|
||||
#define USB_SS_CAP_TYPE 3
|
||||
struct usb_ss_cap_descriptor { /* Link Power Management */
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
__u8 bmAttributes;
|
||||
#define USB_LTM_SUPPORT (1 << 1) /* supports LTM */
|
||||
__le16 wSpeedSupported;
|
||||
#define USB_LOW_SPEED_OPERATION (1) /* Low speed operation */
|
||||
#define USB_FULL_SPEED_OPERATION (1 << 1) /* Full speed operation */
|
||||
#define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */
|
||||
#define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */
|
||||
__u8 bFunctionalitySupport;
|
||||
__u8 bU1devExitLat;
|
||||
__le16 bU2DevExitLat;
|
||||
};
|
||||
|
||||
#define USB_DT_USB_SS_CAP_SIZE 10
|
||||
|
||||
/*
|
||||
* Container ID Capability descriptor: Defines the instance unique ID used to
|
||||
* identify the instance across all operating modes
|
||||
*/
|
||||
#define CONTAINER_ID_TYPE 4
|
||||
struct usb_ss_container_id_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
__u8 bReserved;
|
||||
__u8 ContainerID[16]; /* 128-bit number */
|
||||
};
|
||||
|
||||
#define USB_DT_USB_SS_CONTN_ID_SIZE 20
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with
|
||||
* each endpoint descriptor for a wireless device
|
||||
*/
|
||||
struct usb_wireless_ep_comp_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bMaxBurst;
|
||||
__u8 bMaxSequence;
|
||||
__le16 wMaxStreamDelay;
|
||||
__le16 wOverTheAirPacketSize;
|
||||
__u8 bOverTheAirInterval;
|
||||
__u8 bmCompAttributes;
|
||||
#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */
|
||||
#define USB_ENDPOINT_SWITCH_NO 0
|
||||
#define USB_ENDPOINT_SWITCH_SWITCH 1
|
||||
#define USB_ENDPOINT_SWITCH_SCALE 2
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
|
||||
* host and a device for connection set up, mutual authentication, and
|
||||
* exchanging short lived session keys. The handshake depends on a CC.
|
||||
*/
|
||||
struct usb_handshake {
|
||||
__u8 bMessageNumber;
|
||||
__u8 bStatus;
|
||||
__u8 tTKID[3];
|
||||
__u8 bReserved;
|
||||
__u8 CDID[16];
|
||||
__u8 nonce[16];
|
||||
__u8 MIC[8];
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
|
||||
* A CC may also be set up using non-wireless secure channels (including
|
||||
* wired USB!), and some devices may support CCs with multiple hosts.
|
||||
*/
|
||||
struct usb_connection_context {
|
||||
__u8 CHID[16]; /* persistent host id */
|
||||
__u8 CDID[16]; /* device id (unique w/in host context) */
|
||||
__u8 CK[16]; /* connection key */
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB 2.0 defines three speeds, here's how Linux identifies them */
|
||||
|
||||
enum usb_device_speed {
|
||||
USB_SPEED_UNKNOWN = 0, /* enumerating */
|
||||
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
|
||||
USB_SPEED_HIGH, /* usb 2.0 */
|
||||
USB_SPEED_WIRELESS, /* wireless (usb 2.5) */
|
||||
USB_SPEED_SUPER, /* usb 3.0 */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/**
|
||||
* usb_speed_string() - Returns human readable-name of the speed.
|
||||
* @speed: The speed to return human-readable name for. If it's not
|
||||
* any of the speeds defined in usb_device_speed enum, string for
|
||||
* USB_SPEED_UNKNOWN will be returned.
|
||||
*/
|
||||
extern const char *usb_speed_string(enum usb_device_speed speed);
|
||||
|
||||
#endif
|
||||
|
||||
enum usb_device_state {
|
||||
/* NOTATTACHED isn't in the USB spec, and this state acts
|
||||
* the same as ATTACHED ... but it's clearer this way.
|
||||
*/
|
||||
USB_STATE_NOTATTACHED = 0,
|
||||
|
||||
/* chapter 9 and authentication (wireless) device states */
|
||||
USB_STATE_ATTACHED,
|
||||
USB_STATE_POWERED, /* wired */
|
||||
USB_STATE_RECONNECTING, /* auth */
|
||||
USB_STATE_UNAUTHENTICATED, /* auth */
|
||||
USB_STATE_DEFAULT, /* limited function */
|
||||
USB_STATE_ADDRESS,
|
||||
USB_STATE_CONFIGURED, /* most functions */
|
||||
|
||||
USB_STATE_SUSPENDED
|
||||
|
||||
/* NOTE: there are actually four different SUSPENDED
|
||||
* states, returning to POWERED, DEFAULT, ADDRESS, or
|
||||
* CONFIGURED respectively when SOF tokens flow again.
|
||||
* At this level there's no difference between L1 and L2
|
||||
* suspend states. (L2 being original USB 1.1 suspend.)
|
||||
*/
|
||||
};
|
||||
|
||||
enum usb3_link_state {
|
||||
USB3_LPM_U0 = 0,
|
||||
USB3_LPM_U1,
|
||||
USB3_LPM_U2,
|
||||
USB3_LPM_U3
|
||||
};
|
||||
|
||||
/*
|
||||
* A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
|
||||
* 0xff means the parent hub will accept transitions to U1, but will not
|
||||
* initiate a transition.
|
||||
*
|
||||
* A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
|
||||
* U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved
|
||||
* values.
|
||||
*
|
||||
* A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
|
||||
* 0xff means the parent hub will accept transitions to U2, but will not
|
||||
* initiate a transition.
|
||||
*
|
||||
* A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
|
||||
* U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2
|
||||
* idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
|
||||
* 65.024ms.
|
||||
*/
|
||||
#define USB3_LPM_DISABLED 0x0
|
||||
#define USB3_LPM_U1_MAX_TIMEOUT 0x7F
|
||||
#define USB3_LPM_U2_MAX_TIMEOUT 0xFE
|
||||
#define USB3_LPM_DEVICE_INITIATED 0xFF
|
||||
|
||||
struct usb_set_sel_req {
|
||||
__u8 u1_sel;
|
||||
__u8 u1_pel;
|
||||
__le16 u2_sel;
|
||||
__le16 u2_pel;
|
||||
} ;
|
||||
|
||||
/*
|
||||
* The Set System Exit Latency control transfer provides one byte each for
|
||||
* U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each
|
||||
* are two bytes long.
|
||||
*/
|
||||
#define USB3_LPM_MAX_U1_SEL_PEL 0xFF
|
||||
#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* As per USB compliance update, a device that is actively drawing
|
||||
* more than 100mA from USB must report itself as bus-powered in
|
||||
* the GetStatus(DEVICE) call.
|
||||
* http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
|
||||
*/
|
||||
#define USB_SELF_POWER_VBUS_MAX_DRAW 100
|
||||
|
||||
/**
|
||||
* struct usb_string - wraps a C string and its USB id
|
||||
* @id:the (nonzero) ID for this string
|
||||
* @s:the string, in UTF-8 encoding
|
||||
*
|
||||
* If you're using usb_gadget_get_string(), use this to wrap a string
|
||||
* together with its ID.
|
||||
*/
|
||||
struct usb_string {
|
||||
u8 id;
|
||||
const char *s;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_USB_CH9_H */
|
327
A27-STEPLDR/Src/usb/include/linux/usb/composite.h
Normal file
327
A27-STEPLDR/Src/usb/include/linux/usb/composite.h
Normal file
@ -0,0 +1,327 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* composite.h -- framework for usb gadgets which are composite devices
|
||||
*
|
||||
* Copyright (C) 2006-2008 David Brownell
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_COMPOSITE_H
|
||||
#define __LINUX_USB_COMPOSITE_H
|
||||
|
||||
/*
|
||||
* This framework is an optional layer on top of the USB Gadget interface,
|
||||
* making it easier to build (a) Composite devices, supporting multiple
|
||||
* functions within any single configuration, and (b) Multi-configuration
|
||||
* devices, also supporting multiple functions but without necessarily
|
||||
* having more than one function per configuration.
|
||||
*
|
||||
* Example: a device with a single configuration supporting both network
|
||||
* link and mass storage functions is a composite device. Those functions
|
||||
* might alternatively be packaged in individual configurations, but in
|
||||
* the composite model the host can use both functions at the same time.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <usb/lin_gadget_compat.h>
|
||||
|
||||
/*
|
||||
* USB function drivers should return USB_GADGET_DELAYED_STATUS if they
|
||||
* wish to delay the data/status stages of the control transfer till they
|
||||
* are ready. The control transfer will then be kept from completing till
|
||||
* all the function drivers that requested for USB_GADGET_DELAYED_STAUS
|
||||
* invoke usb_composite_setup_continue().
|
||||
*/
|
||||
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
|
||||
|
||||
struct usb_configuration;
|
||||
|
||||
/**
|
||||
* struct usb_function - describes one function of a configuration
|
||||
* @name: For diagnostics, identifies the function.
|
||||
* @strings: tables of strings, keyed by identifiers assigned during bind()
|
||||
* and by language IDs provided in control requests
|
||||
* @descriptors: Table of full (or low) speed descriptors, using interface and
|
||||
* string identifiers assigned during @bind(). If this pointer is null,
|
||||
* the function will not be available at full speed (or at low speed).
|
||||
* @hs_descriptors: Table of high speed descriptors, using interface and
|
||||
* string identifiers assigned during @bind(). If this pointer is null,
|
||||
* the function will not be available at high speed.
|
||||
* @config: assigned when @usb_add_function() is called; this is the
|
||||
* configuration with which this function is associated.
|
||||
* @bind: Before the gadget can register, all of its functions bind() to the
|
||||
* available resources including string and interface identifiers used
|
||||
* in interface or class descriptors; endpoints; I/O buffers; and so on.
|
||||
* @unbind: Reverses @bind; called as a side effect of unregistering the
|
||||
* driver which added this function.
|
||||
* @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
|
||||
* initialize usb_ep.driver data at this time (when it is used).
|
||||
* Note that setting an interface to its current altsetting resets
|
||||
* interface state, and that all interfaces have a disabled state.
|
||||
* @get_alt: Returns the active altsetting. If this is not provided,
|
||||
* then only altsetting zero is supported.
|
||||
* @disable: (REQUIRED) Indicates the function should be disabled. Reasons
|
||||
* include host resetting or reconfiguring the gadget, and disconnection.
|
||||
* @setup: Used for interface-specific control requests.
|
||||
* @suspend: Notifies functions when the host stops sending USB traffic.
|
||||
* @resume: Notifies functions when the host restarts USB traffic.
|
||||
*
|
||||
* A single USB function uses one or more interfaces, and should in most
|
||||
* cases support operation at both full and high speeds. Each function is
|
||||
* associated by @usb_add_function() with a one configuration; that function
|
||||
* causes @bind() to be called so resources can be allocated as part of
|
||||
* setting up a gadget driver. Those resources include endpoints, which
|
||||
* should be allocated using @usb_ep_autoconfig().
|
||||
*
|
||||
* To support dual speed operation, a function driver provides descriptors
|
||||
* for both high and full speed operation. Except in rare cases that don't
|
||||
* involve bulk endpoints, each speed needs different endpoint descriptors.
|
||||
*
|
||||
* Function drivers choose their own strategies for managing instance data.
|
||||
* The simplest strategy just declares it "static', which means the function
|
||||
* can only be activated once. If the function needs to be exposed in more
|
||||
* than one configuration at a given speed, it needs to support multiple
|
||||
* usb_function structures (one for each configuration).
|
||||
*
|
||||
* A more complex strategy might encapsulate a @usb_function structure inside
|
||||
* a driver-specific instance structure to allows multiple activations. An
|
||||
* example of multiple activations might be a CDC ACM function that supports
|
||||
* two or more distinct instances within the same configuration, providing
|
||||
* several independent logical data links to a USB host.
|
||||
*/
|
||||
struct usb_function {
|
||||
const char *name;
|
||||
struct usb_descriptor_header **descriptors;
|
||||
struct usb_descriptor_header **hs_descriptors;
|
||||
|
||||
struct usb_configuration *config;
|
||||
|
||||
/* REVISIT: bind() functions can be marked __init, which
|
||||
* makes trouble for section mismatch analysis. See if
|
||||
* we can't restructure things to avoid mismatching.
|
||||
* Related: unbind() may kfree() but bind() won't...
|
||||
*/
|
||||
|
||||
/* configuration management: bind/unbind */
|
||||
int (*bind)(struct usb_configuration *,
|
||||
struct usb_function *);
|
||||
void (*unbind)(struct usb_configuration *,
|
||||
struct usb_function *);
|
||||
|
||||
/* runtime state management */
|
||||
int (*set_alt)(struct usb_function *,
|
||||
unsigned interface, unsigned alt);
|
||||
int (*get_alt)(struct usb_function *,
|
||||
unsigned interface);
|
||||
void (*disable)(struct usb_function *);
|
||||
int (*setup)(struct usb_function *,
|
||||
const struct usb_ctrlrequest *);
|
||||
void (*suspend)(struct usb_function *);
|
||||
void (*resume)(struct usb_function *);
|
||||
|
||||
/* private: */
|
||||
/* internals */
|
||||
struct list_head list;
|
||||
DECLARE_BITMAP(endpoints, 32);
|
||||
};
|
||||
|
||||
int usb_add_function(struct usb_configuration *, struct usb_function *);
|
||||
|
||||
int usb_function_deactivate(struct usb_function *);
|
||||
int usb_function_activate(struct usb_function *);
|
||||
|
||||
int usb_interface_id(struct usb_configuration *, struct usb_function *);
|
||||
|
||||
#define MAX_CONFIG_INTERFACES 16 /* arbitrary; max 255 */
|
||||
|
||||
/**
|
||||
* struct usb_configuration - represents one gadget configuration
|
||||
* @label: For diagnostics, describes the configuration.
|
||||
* @strings: Tables of strings, keyed by identifiers assigned during @bind()
|
||||
* and by language IDs provided in control requests.
|
||||
* @descriptors: Table of descriptors preceding all function descriptors.
|
||||
* Examples include OTG and vendor-specific descriptors.
|
||||
* @bind: Called from @usb_add_config() to allocate resources unique to this
|
||||
* configuration and to call @usb_add_function() for each function used.
|
||||
* @unbind: Reverses @bind; called as a side effect of unregistering the
|
||||
* driver which added this configuration.
|
||||
* @setup: Used to delegate control requests that aren't handled by standard
|
||||
* device infrastructure or directed at a specific interface.
|
||||
* @bConfigurationValue: Copied into configuration descriptor.
|
||||
* @iConfiguration: Copied into configuration descriptor.
|
||||
* @bmAttributes: Copied into configuration descriptor.
|
||||
* @bMaxPower: Copied into configuration descriptor.
|
||||
* @cdev: assigned by @usb_add_config() before calling @bind(); this is
|
||||
* the device associated with this configuration.
|
||||
*
|
||||
* Configurations are building blocks for gadget drivers structured around
|
||||
* function drivers. Simple USB gadgets require only one function and one
|
||||
* configuration, and handle dual-speed hardware by always providing the same
|
||||
* functionality. Slightly more complex gadgets may have more than one
|
||||
* single-function configuration at a given speed; or have configurations
|
||||
* that only work at one speed.
|
||||
*
|
||||
* Composite devices are, by definition, ones with configurations which
|
||||
* include more than one function.
|
||||
*
|
||||
* The lifecycle of a usb_configuration includes allocation, initialization
|
||||
* of the fields described above, and calling @usb_add_config() to set up
|
||||
* internal data and bind it to a specific device. The configuration's
|
||||
* @bind() method is then used to initialize all the functions and then
|
||||
* call @usb_add_function() for them.
|
||||
*
|
||||
* Those functions would normally be independant of each other, but that's
|
||||
* not mandatory. CDC WMC devices are an example where functions often
|
||||
* depend on other functions, with some functions subsidiary to others.
|
||||
* Such interdependency may be managed in any way, so long as all of the
|
||||
* descriptors complete by the time the composite driver returns from
|
||||
* its bind() routine.
|
||||
*/
|
||||
struct usb_configuration {
|
||||
const char *label;
|
||||
const struct usb_descriptor_header **descriptors;
|
||||
|
||||
/* REVISIT: bind() functions can be marked __init, which
|
||||
* makes trouble for section mismatch analysis. See if
|
||||
* we can't restructure things to avoid mismatching...
|
||||
*/
|
||||
|
||||
/* configuration management: bind/unbind */
|
||||
int (*bind)(struct usb_configuration *);
|
||||
void (*unbind)(struct usb_configuration *);
|
||||
int (*setup)(struct usb_configuration *,
|
||||
const struct usb_ctrlrequest *);
|
||||
|
||||
/* fields in the config descriptor */
|
||||
u8 bConfigurationValue;
|
||||
u8 iConfiguration;
|
||||
u8 bmAttributes;
|
||||
u8 bMaxPower;
|
||||
|
||||
struct usb_composite_dev *cdev;
|
||||
|
||||
/* private: */
|
||||
/* internals */
|
||||
struct list_head list;
|
||||
struct list_head functions;
|
||||
u8 next_interface_id;
|
||||
unsigned highspeed:1;
|
||||
unsigned fullspeed:1;
|
||||
struct usb_function *interface[MAX_CONFIG_INTERFACES];
|
||||
};
|
||||
|
||||
int usb_add_config(struct usb_composite_dev *,
|
||||
struct usb_configuration *);
|
||||
|
||||
/**
|
||||
* struct usb_composite_driver - groups configurations into a gadget
|
||||
* @name: For diagnostics, identifies the driver.
|
||||
* @dev: Template descriptor for the device, including default device
|
||||
* identifiers.
|
||||
* @strings: tables of strings, keyed by identifiers assigned during bind()
|
||||
* and language IDs provided in control requests
|
||||
* @bind: (REQUIRED) Used to allocate resources that are shared across the
|
||||
* whole device, such as string IDs, and add its configurations using
|
||||
* @usb_add_config(). This may fail by returning a negative errno
|
||||
* value; it should return zero on successful initialization.
|
||||
* @unbind: Reverses @bind(); called as a side effect of unregistering
|
||||
* this driver.
|
||||
* @disconnect: optional driver disconnect method
|
||||
* @suspend: Notifies when the host stops sending USB traffic,
|
||||
* after function notifications
|
||||
* @resume: Notifies configuration when the host restarts USB traffic,
|
||||
* before function notifications
|
||||
*
|
||||
* Devices default to reporting self powered operation. Devices which rely
|
||||
* on bus powered operation should report this in their @bind() method.
|
||||
*
|
||||
* Before returning from @bind, various fields in the template descriptor
|
||||
* may be overridden. These include the idVendor/idProduct/bcdDevice values
|
||||
* normally to bind the appropriate host side driver, and the three strings
|
||||
* (iManufacturer, iProduct, iSerialNumber) normally used to provide user
|
||||
* meaningful device identifiers. (The strings will not be defined unless
|
||||
* they are defined in @dev and @strings.) The correct ep0 maxpacket size
|
||||
* is also reported, as defined by the underlying controller driver.
|
||||
*/
|
||||
struct usb_composite_driver {
|
||||
const char *name;
|
||||
const struct usb_device_descriptor *dev;
|
||||
|
||||
/* REVISIT: bind() functions can be marked __init, which
|
||||
* makes trouble for section mismatch analysis. See if
|
||||
* we can't restructure things to avoid mismatching...
|
||||
*/
|
||||
|
||||
int (*bind)(struct usb_composite_dev *);
|
||||
int (*unbind)(struct usb_composite_dev *);
|
||||
|
||||
void (*disconnect)(struct usb_composite_dev *);
|
||||
|
||||
/* global suspend hooks */
|
||||
void (*suspend)(struct usb_composite_dev *);
|
||||
void (*resume)(struct usb_composite_dev *);
|
||||
};
|
||||
|
||||
extern int usb_composite_register(struct usb_composite_driver *);
|
||||
extern void usb_composite_unregister(struct usb_composite_driver *);
|
||||
|
||||
|
||||
/**
|
||||
* struct usb_composite_device - represents one composite usb gadget
|
||||
* @gadget: read-only, abstracts the gadget's usb peripheral controller
|
||||
* @req: used for control responses; buffer is pre-allocated
|
||||
* @bufsiz: size of buffer pre-allocated in @req
|
||||
* @config: the currently active configuration
|
||||
*
|
||||
* One of these devices is allocated and initialized before the
|
||||
* associated device driver's bind() is called.
|
||||
*
|
||||
* OPEN ISSUE: it appears that some WUSB devices will need to be
|
||||
* built by combining a normal (wired) gadget with a wireless one.
|
||||
* This revision of the gadget framework should probably try to make
|
||||
* sure doing that won't hurt too much.
|
||||
*
|
||||
* One notion for how to handle Wireless USB devices involves:
|
||||
* (a) a second gadget here, discovery mechanism TBD, but likely
|
||||
* needing separate "register/unregister WUSB gadget" calls;
|
||||
* (b) updates to usb_gadget to include flags "is it wireless",
|
||||
* "is it wired", plus (presumably in a wrapper structure)
|
||||
* bandgroup and PHY info;
|
||||
* (c) presumably a wireless_ep wrapping a usb_ep, and reporting
|
||||
* wireless-specific parameters like maxburst and maxsequence;
|
||||
* (d) configurations that are specific to wireless links;
|
||||
* (e) function drivers that understand wireless configs and will
|
||||
* support wireless for (additional) function instances;
|
||||
* (f) a function to support association setup (like CBAF), not
|
||||
* necessarily requiring a wireless adapter;
|
||||
* (g) composite device setup that can create one or more wireless
|
||||
* configs, including appropriate association setup support;
|
||||
* (h) more, TBD.
|
||||
*/
|
||||
struct usb_composite_dev {
|
||||
struct usb_request *req;
|
||||
unsigned bufsiz;
|
||||
|
||||
struct usb_configuration *config;
|
||||
|
||||
/* private: */
|
||||
/* internals */
|
||||
unsigned int suspended:1;
|
||||
struct usb_device_descriptor __aligned(CONFIG_SYS_CACHELINE_SIZE) desc;
|
||||
struct list_head configs;
|
||||
struct usb_composite_driver *driver;
|
||||
u8 next_string_id;
|
||||
|
||||
/* the gadget driver won't enable the data pullup
|
||||
* while the deactivation count is nonzero.
|
||||
*/
|
||||
unsigned deactivations;
|
||||
};
|
||||
|
||||
extern int usb_string_id(struct usb_composite_dev *c);
|
||||
extern int usb_string_ids_tab(struct usb_composite_dev *c,
|
||||
struct usb_string *str);
|
||||
extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
|
||||
|
||||
#endif /* __LINUX_USB_COMPOSITE_H */
|
441
A27-STEPLDR/Src/usb/include/linux/usb/gadget.h
Normal file
441
A27-STEPLDR/Src/usb/include/linux/usb/gadget.h
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* <linux/usb/gadget.h>
|
||||
*
|
||||
* We call the USB code inside a Linux-based peripheral device a "gadget"
|
||||
* driver, except for the hardware-specific bus glue. One USB host can
|
||||
* master many USB gadgets, but the gadgets are only slaved to one host.
|
||||
*
|
||||
*
|
||||
* (C) Copyright 2002-2004 by David Brownell
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software is licensed under the GNU GPL version 2.
|
||||
*
|
||||
* Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
|
||||
* Remy Bohmer <linux@bohmer.net>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_GADGET_H
|
||||
#define __LINUX_USB_GADGET_H
|
||||
/*
|
||||
#include <errno.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/list.h>*/
|
||||
#include "usb_os_adapter.h"
|
||||
#include <linux/errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct usb_ep;
|
||||
|
||||
/**
|
||||
* struct usb_request - describes one i/o request
|
||||
* @buf: Buffer used for data. Always provide this; some controllers
|
||||
* only use PIO, or don't use DMA for some endpoints.
|
||||
* @dma: DMA address corresponding to 'buf'. If you don't set this
|
||||
* field, and the usb controller needs one, it is responsible
|
||||
* for mapping and unmapping the buffer.
|
||||
* @stream_id: The stream id, when USB3.0 bulk streams are being used
|
||||
* @length: Length of that data
|
||||
* @no_interrupt: If true, hints that no completion irq is needed.
|
||||
* Helpful sometimes with deep request queues that are handled
|
||||
* directly by DMA controllers.
|
||||
* @zero: If true, when writing data, makes the last packet be "short"
|
||||
* by adding a zero length packet as needed;
|
||||
* @short_not_ok: When reading data, makes short packets be
|
||||
* treated as errors (queue stops advancing till cleanup).
|
||||
* @complete: Function called when request completes, so this request and
|
||||
* its buffer may be re-used.
|
||||
* Reads terminate with a short packet, or when the buffer fills,
|
||||
* whichever comes first. When writes terminate, some data bytes
|
||||
* will usually still be in flight (often in a hardware fifo).
|
||||
* Errors (for reads or writes) stop the queue from advancing
|
||||
* until the completion function returns, so that any transfers
|
||||
* invalidated by the error may first be dequeued.
|
||||
* @context: For use by the completion callback
|
||||
* @list: For use by the gadget driver.
|
||||
* @status: Reports completion code, zero or a negative errno.
|
||||
* Normally, faults block the transfer queue from advancing until
|
||||
* the completion callback returns.
|
||||
* Code "-ESHUTDOWN" indicates completion caused by device disconnect,
|
||||
* or when the driver disabled the endpoint.
|
||||
* @actual: Reports bytes transferred to/from the buffer. For reads (OUT
|
||||
* transfers) this may be less than the requested length. If the
|
||||
* short_not_ok flag is set, short reads are treated as errors
|
||||
* even when status otherwise indicates successful completion.
|
||||
* Note that for writes (IN transfers) some data bytes may still
|
||||
* reside in a device-side FIFO when the request is reported as
|
||||
* complete.
|
||||
*
|
||||
* These are allocated/freed through the endpoint they're used with. The
|
||||
* hardware's driver can add extra per-request data to the memory it returns,
|
||||
* which often avoids separate memory allocations (potential failures),
|
||||
* later when the request is queued.
|
||||
*
|
||||
* Request flags affect request handling, such as whether a zero length
|
||||
* packet is written (the "zero" flag), whether a short read should be
|
||||
* treated as an error (blocking request queue advance, the "short_not_ok"
|
||||
* flag), or hinting that an interrupt is not required (the "no_interrupt"
|
||||
* flag, for use with deep request queues).
|
||||
*
|
||||
* Bulk endpoints can use any size buffers, and can also be used for interrupt
|
||||
* transfers. interrupt-only endpoints can be much less functional.
|
||||
*
|
||||
* NOTE: this is analagous to 'struct urb' on the host side, except that
|
||||
* it's thinner and promotes more pre-allocation.
|
||||
*/
|
||||
|
||||
struct usb_request {
|
||||
void *buf;
|
||||
unsigned length;
|
||||
dma_addr_t dma;
|
||||
|
||||
unsigned stream_id:16;
|
||||
unsigned no_interrupt:1;
|
||||
unsigned zero:1;
|
||||
unsigned short_not_ok:1;
|
||||
|
||||
void (*complete)(struct usb_ep *ep,
|
||||
struct usb_request *req);
|
||||
void *context;
|
||||
|
||||
ListItem_t list;
|
||||
void* powner;
|
||||
|
||||
int status;
|
||||
unsigned actual;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* endpoint-specific parts of the api to the usb controller hardware.
|
||||
* unlike the urb model, (de)multiplexing layers are not required.
|
||||
* (so this api could slash overhead if used on the host side...)
|
||||
*
|
||||
* note that device side usb controllers commonly differ in how many
|
||||
* endpoints they support, as well as their capabilities.
|
||||
*/
|
||||
struct usb_ep_ops {
|
||||
int (*enable) (struct usb_ep *ep,
|
||||
const struct usb_endpoint_descriptor *desc);
|
||||
int (*disable) (struct usb_ep *ep);
|
||||
|
||||
struct usb_request *(*alloc_request) (struct usb_ep *ep,
|
||||
gfp_t gfp_flags);
|
||||
void (*free_request) (struct usb_ep *ep, struct usb_request *req);
|
||||
|
||||
int (*queue) (struct usb_ep *ep, struct usb_request *req,
|
||||
gfp_t gfp_flags);
|
||||
int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
|
||||
|
||||
int (*set_halt) (struct usb_ep *ep, int value);
|
||||
int (*set_wedge)(struct usb_ep *ep);
|
||||
int (*fifo_status) (struct usb_ep *ep);
|
||||
void (*fifo_flush) (struct usb_ep *ep);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct usb_ep - device side representation of USB endpoint
|
||||
* @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk"
|
||||
* @ops: Function pointers used to access hardware-specific operations.
|
||||
* @ep_list:the gadget's ep_list holds all of its endpoints
|
||||
* @maxpacket:The maximum packet size used on this endpoint. The initial
|
||||
* value can sometimes be reduced (hardware allowing), according to
|
||||
* the endpoint descriptor used to configure the endpoint.
|
||||
* @maxpacket_limit:The maximum packet size value which can be handled by this
|
||||
* endpoint. It's set once by UDC driver when endpoint is initialized, and
|
||||
* should not be changed. Should not be confused with maxpacket.
|
||||
* @max_streams: The maximum number of streams supported
|
||||
* by this EP (0 - 16, actual number is 2^n)
|
||||
* @maxburst: the maximum number of bursts supported by this EP (for usb3)
|
||||
* @driver_data:for use by the gadget driver. all other fields are
|
||||
* read-only to gadget drivers.
|
||||
* @desc: endpoint descriptor. This pointer is set before the endpoint is
|
||||
* enabled and remains valid until the endpoint is disabled.
|
||||
* @comp_desc: In case of SuperSpeed support, this is the endpoint companion
|
||||
* descriptor that is used to configure the endpoint
|
||||
*
|
||||
* the bus controller driver lists all the general purpose endpoints in
|
||||
* gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
|
||||
* and is accessed only in response to a driver setup() callback.
|
||||
*/
|
||||
struct usb_ep {
|
||||
void *driver_data;
|
||||
const char *name;
|
||||
const struct usb_ep_ops *ops;
|
||||
ListItem_t ep_list;
|
||||
void* powner;
|
||||
unsigned maxpacket:16;
|
||||
unsigned maxpacket_limit:16;
|
||||
unsigned max_streams:16;
|
||||
unsigned maxburst:5;
|
||||
const struct usb_endpoint_descriptor *desc;
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_ep_set_maxpacket_limit - set maximum packet size limit for endpoint
|
||||
* @ep:the endpoint being configured
|
||||
* @maxpacket_limit:value of maximum packet size limit
|
||||
*
|
||||
* This function shoud be used only in UDC drivers to initialize endpoint
|
||||
* (usually in probe function).
|
||||
*/
|
||||
static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep,
|
||||
unsigned maxpacket_limit)
|
||||
{
|
||||
ep->maxpacket_limit = maxpacket_limit;
|
||||
ep->maxpacket = maxpacket_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_enable - configure endpoint, making it usable
|
||||
* @ep:the endpoint being configured. may not be the endpoint named "ep0".
|
||||
* drivers discover endpoints through the ep_list of a usb_gadget.
|
||||
* @desc:descriptor for desired behavior. caller guarantees this pointer
|
||||
* remains valid until the endpoint is disabled; the data byte order
|
||||
* is little-endian (usb-standard).
|
||||
*
|
||||
* when configurations are set, or when interface settings change, the driver
|
||||
* will enable or disable the relevant endpoints. while it is enabled, an
|
||||
* endpoint may be used for i/o until the driver receives a disconnect() from
|
||||
* the host or until the endpoint is disabled.
|
||||
*
|
||||
* the ep0 implementation (which calls this routine) must ensure that the
|
||||
* hardware capabilities of each endpoint match the descriptor provided
|
||||
* for it. for example, an endpoint named "ep2in-bulk" would be usable
|
||||
* for interrupt transfers as well as bulk, but it likely couldn't be used
|
||||
* for iso transfers or for endpoint 14. some endpoints are fully
|
||||
* configurable, with more generic names like "ep-a". (remember that for
|
||||
* USB, "in" means "towards the USB master".)
|
||||
*
|
||||
* returns zero, or a negative error code.
|
||||
*/
|
||||
static inline int usb_ep_enable(struct usb_ep *ep,
|
||||
const struct usb_endpoint_descriptor *desc)
|
||||
{
|
||||
return ep->ops->enable(ep, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_disable - endpoint is no longer usable
|
||||
* @ep:the endpoint being unconfigured. may not be the endpoint named "ep0".
|
||||
*
|
||||
* no other task may be using this endpoint when this is called.
|
||||
* any pending and uncompleted requests will complete with status
|
||||
* indicating disconnect (-ESHUTDOWN) before this call returns.
|
||||
* gadget drivers must call usb_ep_enable() again before queueing
|
||||
* requests to the endpoint.
|
||||
*
|
||||
* returns zero, or a negative error code.
|
||||
*/
|
||||
static inline int usb_ep_disable(struct usb_ep *ep)
|
||||
{
|
||||
return ep->ops->disable(ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_alloc_request - allocate a request object to use with this endpoint
|
||||
* @ep:the endpoint to be used with with the request
|
||||
* @gfp_flags:GFP_* flags to use
|
||||
*
|
||||
* Request objects must be allocated with this call, since they normally
|
||||
* need controller-specific setup and may even need endpoint-specific
|
||||
* resources such as allocation of DMA descriptors.
|
||||
* Requests may be submitted with usb_ep_queue(), and receive a single
|
||||
* completion callback. Free requests with usb_ep_free_request(), when
|
||||
* they are no longer needed.
|
||||
*
|
||||
* Returns the request, or null if one could not be allocated.
|
||||
*/
|
||||
static inline struct usb_request *usb_ep_alloc_request(struct usb_ep *ep,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
return ep->ops->alloc_request(ep, gfp_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_free_request - frees a request object
|
||||
* @ep:the endpoint associated with the request
|
||||
* @req:the request being freed
|
||||
*
|
||||
* Reverses the effect of usb_ep_alloc_request().
|
||||
* Caller guarantees the request is not queued, and that it will
|
||||
* no longer be requeued (or otherwise used).
|
||||
*/
|
||||
static inline void usb_ep_free_request(struct usb_ep *ep,
|
||||
struct usb_request *req)
|
||||
{
|
||||
ep->ops->free_request(ep, req);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_queue - queues (submits) an I/O request to an endpoint.
|
||||
* @ep:the endpoint associated with the request
|
||||
* @req:the request being submitted
|
||||
* @gfp_flags: GFP_* flags to use in case the lower level driver couldn't
|
||||
* pre-allocate all necessary memory with the request.
|
||||
*
|
||||
* This tells the device controller to perform the specified request through
|
||||
* that endpoint (reading or writing a buffer). When the request completes,
|
||||
* including being canceled by usb_ep_dequeue(), the request's completion
|
||||
* routine is called to return the request to the driver. Any endpoint
|
||||
* (except control endpoints like ep0) may have more than one transfer
|
||||
* request queued; they complete in FIFO order. Once a gadget driver
|
||||
* submits a request, that request may not be examined or modified until it
|
||||
* is given back to that driver through the completion callback.
|
||||
*
|
||||
* Each request is turned into one or more packets. The controller driver
|
||||
* never merges adjacent requests into the same packet. OUT transfers
|
||||
* will sometimes use data that's already buffered in the hardware.
|
||||
* Drivers can rely on the fact that the first byte of the request's buffer
|
||||
* always corresponds to the first byte of some USB packet, for both
|
||||
* IN and OUT transfers.
|
||||
*
|
||||
* Bulk endpoints can queue any amount of data; the transfer is packetized
|
||||
* automatically. The last packet will be short if the request doesn't fill it
|
||||
* out completely. Zero length packets (ZLPs) should be avoided in portable
|
||||
* protocols since not all usb hardware can successfully handle zero length
|
||||
* packets. (ZLPs may be explicitly written, and may be implicitly written if
|
||||
* the request 'zero' flag is set.) Bulk endpoints may also be used
|
||||
* for interrupt transfers; but the reverse is not true, and some endpoints
|
||||
* won't support every interrupt transfer. (Such as 768 byte packets.)
|
||||
*
|
||||
* Interrupt-only endpoints are less functional than bulk endpoints, for
|
||||
* example by not supporting queueing or not handling buffers that are
|
||||
* larger than the endpoint's maxpacket size. They may also treat data
|
||||
* toggle differently.
|
||||
*
|
||||
* Control endpoints ... after getting a setup() callback, the driver queues
|
||||
* one response (even if it would be zero length). That enables the
|
||||
* status ack, after transfering data as specified in the response. Setup
|
||||
* functions may return negative error codes to generate protocol stalls.
|
||||
* (Note that some USB device controllers disallow protocol stall responses
|
||||
* in some cases.) When control responses are deferred (the response is
|
||||
* written after the setup callback returns), then usb_ep_set_halt() may be
|
||||
* used on ep0 to trigger protocol stalls.
|
||||
*
|
||||
* For periodic endpoints, like interrupt or isochronous ones, the usb host
|
||||
* arranges to poll once per interval, and the gadget driver usually will
|
||||
* have queued some data to transfer at that time.
|
||||
*
|
||||
* Returns zero, or a negative error code. Endpoints that are not enabled
|
||||
* report errors; errors will also be
|
||||
* reported when the usb peripheral is disconnected.
|
||||
*/
|
||||
static inline int usb_ep_queue(struct usb_ep *ep,
|
||||
struct usb_request *req, gfp_t gfp_flags)
|
||||
{
|
||||
return ep->ops->queue(ep, req, gfp_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_dequeue - dequeues (cancels, unlinks) an I/O request from an endpoint
|
||||
* @ep:the endpoint associated with the request
|
||||
* @req:the request being canceled
|
||||
*
|
||||
* if the request is still active on the endpoint, it is dequeued and its
|
||||
* completion routine is called (with status -ECONNRESET); else a negative
|
||||
* error code is returned.
|
||||
*
|
||||
* note that some hardware can't clear out write fifos (to unlink the request
|
||||
* at the head of the queue) except as part of disconnecting from usb. such
|
||||
* restrictions prevent drivers from supporting configuration changes,
|
||||
* even to configuration zero (a "chapter 9" requirement).
|
||||
*/
|
||||
static inline int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
return ep->ops->dequeue(ep, req);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_set_halt - sets the endpoint halt feature.
|
||||
* @ep: the non-isochronous endpoint being stalled
|
||||
*
|
||||
* Use this to stall an endpoint, perhaps as an error report.
|
||||
* Except for control endpoints,
|
||||
* the endpoint stays halted (will not stream any data) until the host
|
||||
* clears this feature; drivers may need to empty the endpoint's request
|
||||
* queue first, to make sure no inappropriate transfers happen.
|
||||
*
|
||||
* Note that while an endpoint CLEAR_FEATURE will be invisible to the
|
||||
* gadget driver, a SET_INTERFACE will not be. To reset endpoints for the
|
||||
* current altsetting, see usb_ep_clear_halt(). When switching altsettings,
|
||||
* it's simplest to use usb_ep_enable() or usb_ep_disable() for the endpoints.
|
||||
*
|
||||
* Returns zero, or a negative error code. On success, this call sets
|
||||
* underlying hardware state that blocks data transfers.
|
||||
* Attempts to halt IN endpoints will fail (returning -EAGAIN) if any
|
||||
* transfer requests are still queued, or if the controller hardware
|
||||
* (usually a FIFO) still holds bytes that the host hasn't collected.
|
||||
*/
|
||||
static inline int usb_ep_set_halt(struct usb_ep *ep)
|
||||
{
|
||||
return ep->ops->set_halt(ep, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_clear_halt - clears endpoint halt, and resets toggle
|
||||
* @ep:the bulk or interrupt endpoint being reset
|
||||
*
|
||||
* Use this when responding to the standard usb "set interface" request,
|
||||
* for endpoints that aren't reconfigured, after clearing any other state
|
||||
* in the endpoint's i/o queue.
|
||||
*
|
||||
* Returns zero, or a negative error code. On success, this call clears
|
||||
* the underlying hardware state reflecting endpoint halt and data toggle.
|
||||
* Note that some hardware can't support this request (like pxa2xx_udc),
|
||||
* and accordingly can't correctly implement interface altsettings.
|
||||
*/
|
||||
static inline int usb_ep_clear_halt(struct usb_ep *ep)
|
||||
{
|
||||
return ep->ops->set_halt(ep, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_fifo_status - returns number of bytes in fifo, or error
|
||||
* @ep: the endpoint whose fifo status is being checked.
|
||||
*
|
||||
* FIFO endpoints may have "unclaimed data" in them in certain cases,
|
||||
* such as after aborted transfers. Hosts may not have collected all
|
||||
* the IN data written by the gadget driver (and reported by a request
|
||||
* completion). The gadget driver may not have collected all the data
|
||||
* written OUT to it by the host. Drivers that need precise handling for
|
||||
* fault reporting or recovery may need to use this call.
|
||||
*
|
||||
* This returns the number of such bytes in the fifo, or a negative
|
||||
* errno if the endpoint doesn't use a FIFO or doesn't support such
|
||||
* precise handling.
|
||||
*/
|
||||
static inline int usb_ep_fifo_status(struct usb_ep *ep)
|
||||
{
|
||||
if (ep->ops->fifo_status)
|
||||
return ep->ops->fifo_status(ep);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_ep_fifo_flush - flushes contents of a fifo
|
||||
* @ep: the endpoint whose fifo is being flushed.
|
||||
*
|
||||
* This call may be used to flush the "unclaimed data" that may exist in
|
||||
* an endpoint fifo after abnormal transaction terminations. The call
|
||||
* must never be used except when endpoint is not being used for any
|
||||
* protocol translation.
|
||||
*/
|
||||
static inline void usb_ep_fifo_flush(struct usb_ep *ep)
|
||||
{
|
||||
if (ep->ops->fifo_flush)
|
||||
ep->ops->fifo_flush(ep);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* utility to simplify managing config descriptors */
|
||||
|
||||
/* write vector of descriptors into buffer */
|
||||
int usb_descriptor_fillbuf(void *, unsigned,
|
||||
const struct usb_descriptor_header **);
|
||||
#endif /* __LINUX_USB_GADGET_H */
|
37
A27-STEPLDR/Src/usb/include/linux/usb/otg.h
Normal file
37
A27-STEPLDR/Src/usb/include/linux/usb/otg.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/* include/linux/usb/otg.h
|
||||
*
|
||||
* Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* USB OTG (On The Go) defines
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_OTG_H
|
||||
#define __LINUX_USB_OTG_H
|
||||
|
||||
enum usb_dr_mode {
|
||||
USB_DR_MODE_UNKNOWN,
|
||||
USB_DR_MODE_HOST,
|
||||
USB_DR_MODE_PERIPHERAL,
|
||||
USB_DR_MODE_OTG,
|
||||
};
|
||||
|
||||
/**
|
||||
* usb_get_dr_mode() - Get dual role mode for given device
|
||||
* @node: Node offset to the given device
|
||||
*
|
||||
* The function gets phy interface string from property 'dr_mode',
|
||||
* and returns the correspondig enum usb_dr_mode
|
||||
*/
|
||||
enum usb_dr_mode usb_get_dr_mode(int node);
|
||||
|
||||
/**
|
||||
* usb_get_maximum_speed() - Get maximum speed for given device
|
||||
* @node: Node offset to the given device
|
||||
*
|
||||
* The function gets phy interface string from property 'maximum-speed',
|
||||
* and returns the correspondig enum usb_device_speed
|
||||
*/
|
||||
enum usb_device_speed usb_get_maximum_speed(int node);
|
||||
|
||||
#endif /* __LINUX_USB_OTG_H */
|
244
A27-STEPLDR/Src/usb/include/scsi.h
Normal file
244
A27-STEPLDR/Src/usb/include/scsi.h
Normal file
@ -0,0 +1,244 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*/
|
||||
#ifndef _SCSI_H
|
||||
#define _SCSI_H
|
||||
|
||||
struct scsi_cmd {
|
||||
unsigned char cmd[16]; /* command */
|
||||
/* for request sense */
|
||||
#pragma pack(ARCH_DMA_MINALIGN)
|
||||
unsigned char sense_buf[64];
|
||||
unsigned char status; /* SCSI Status */
|
||||
unsigned char target; /* Target ID */
|
||||
unsigned char lun; /* Target LUN */
|
||||
unsigned char cmdlen; /* command len */
|
||||
unsigned long datalen; /* Total data length */
|
||||
unsigned char * pdata; /* pointer to data */
|
||||
unsigned char msgout[12]; /* Messge out buffer (NOT USED) */
|
||||
unsigned char msgin[12]; /* Message in buffer */
|
||||
unsigned char sensecmdlen; /* Sense command len */
|
||||
unsigned long sensedatalen; /* Sense data len */
|
||||
unsigned char sensecmd[6]; /* Sense command */
|
||||
unsigned long contr_stat; /* Controller Status */
|
||||
unsigned long trans_bytes; /* tranfered bytes */
|
||||
|
||||
unsigned int priv;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
**
|
||||
** SCSI constants.
|
||||
**
|
||||
**-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
** Messages
|
||||
*/
|
||||
|
||||
#define M_COMPLETE (0x00)
|
||||
#define M_EXTENDED (0x01)
|
||||
#define M_SAVE_DP (0x02)
|
||||
#define M_RESTORE_DP (0x03)
|
||||
#define M_DISCONNECT (0x04)
|
||||
#define M_ID_ERROR (0x05)
|
||||
#define M_ABORT (0x06)
|
||||
#define M_REJECT (0x07)
|
||||
#define M_NOOP (0x08)
|
||||
#define M_PARITY (0x09)
|
||||
#define M_LCOMPLETE (0x0a)
|
||||
#define M_FCOMPLETE (0x0b)
|
||||
#define M_RESET (0x0c)
|
||||
#define M_ABORT_TAG (0x0d)
|
||||
#define M_CLEAR_QUEUE (0x0e)
|
||||
#define M_INIT_REC (0x0f)
|
||||
#define M_REL_REC (0x10)
|
||||
#define M_TERMINATE (0x11)
|
||||
#define M_SIMPLE_TAG (0x20)
|
||||
#define M_HEAD_TAG (0x21)
|
||||
#define M_ORDERED_TAG (0x22)
|
||||
#define M_IGN_RESIDUE (0x23)
|
||||
#define M_IDENTIFY (0x80)
|
||||
|
||||
#define M_X_MODIFY_DP (0x00)
|
||||
#define M_X_SYNC_REQ (0x01)
|
||||
#define M_X_WIDE_REQ (0x03)
|
||||
#define M_X_PPR_REQ (0x04)
|
||||
|
||||
|
||||
/*
|
||||
** Status
|
||||
*/
|
||||
|
||||
#define S_GOOD (0x00)
|
||||
#define S_CHECK_COND (0x02)
|
||||
#define S_COND_MET (0x04)
|
||||
#define S_BUSY (0x08)
|
||||
#define S_INT (0x10)
|
||||
#define S_INT_COND_MET (0x14)
|
||||
#define S_CONFLICT (0x18)
|
||||
#define S_TERMINATED (0x20)
|
||||
#define S_QUEUE_FULL (0x28)
|
||||
#define S_ILLEGAL (0xff)
|
||||
#define S_SENSE (0x80)
|
||||
|
||||
/*
|
||||
* Sense_keys
|
||||
*/
|
||||
|
||||
#define SENSE_NO_SENSE 0x0
|
||||
#define SENSE_RECOVERED_ERROR 0x1
|
||||
#define SENSE_NOT_READY 0x2
|
||||
#define SENSE_MEDIUM_ERROR 0x3
|
||||
#define SENSE_HARDWARE_ERROR 0x4
|
||||
#define SENSE_ILLEGAL_REQUEST 0x5
|
||||
#define SENSE_UNIT_ATTENTION 0x6
|
||||
#define SENSE_DATA_PROTECT 0x7
|
||||
#define SENSE_BLANK_CHECK 0x8
|
||||
#define SENSE_VENDOR_SPECIFIC 0x9
|
||||
#define SENSE_COPY_ABORTED 0xA
|
||||
#define SENSE_ABORTED_COMMAND 0xB
|
||||
#define SENSE_VOLUME_OVERFLOW 0xD
|
||||
#define SENSE_MISCOMPARE 0xE
|
||||
|
||||
|
||||
#define SCSI_CHANGE_DEF 0x40 /* Change Definition (Optional) */
|
||||
#define SCSI_COMPARE 0x39 /* Compare (O) */
|
||||
#define SCSI_COPY 0x18 /* Copy (O) */
|
||||
#define SCSI_COP_VERIFY 0x3A /* Copy and Verify (O) */
|
||||
#define SCSI_INQUIRY 0x12 /* Inquiry (MANDATORY) */
|
||||
#define SCSI_LOG_SELECT 0x4C /* Log Select (O) */
|
||||
#define SCSI_LOG_SENSE 0x4D /* Log Sense (O) */
|
||||
#define SCSI_MODE_SEL6 0x15 /* Mode Select 6-byte (Device Specific) */
|
||||
#define SCSI_MODE_SEL10 0x55 /* Mode Select 10-byte (Device Specific) */
|
||||
#define SCSI_MODE_SEN6 0x1A /* Mode Sense 6-byte (Device Specific) */
|
||||
#define SCSI_MODE_SEN10 0x5A /* Mode Sense 10-byte (Device Specific) */
|
||||
#define SCSI_READ_BUFF 0x3C /* Read Buffer (O) */
|
||||
#define SCSI_REQ_SENSE 0x03 /* Request Sense (MANDATORY) */
|
||||
#define SCSI_SEND_DIAG 0x1D /* Send Diagnostic (O) */
|
||||
#define SCSI_TST_U_RDY 0x00 /* Test Unit Ready (MANDATORY) */
|
||||
#define SCSI_WRITE_BUFF 0x3B /* Write Buffer (O) */
|
||||
/***************************************************************************
|
||||
* %%% Commands Unique to Direct Access Devices %%%
|
||||
***************************************************************************/
|
||||
#define SCSI_COMPARE 0x39 /* Compare (O) */
|
||||
#define SCSI_FORMAT 0x04 /* Format Unit (MANDATORY) */
|
||||
#define SCSI_LCK_UN_CAC 0x36 /* Lock Unlock Cache (O) */
|
||||
#define SCSI_PREFETCH 0x34 /* Prefetch (O) */
|
||||
#define SCSI_MED_REMOVL 0x1E /* Prevent/Allow medium Removal (O) */
|
||||
#define SCSI_READ6 0x08 /* Read 6-byte (MANDATORY) */
|
||||
#define SCSI_READ10 0x28 /* Read 10-byte (MANDATORY) */
|
||||
#define SCSI_READ16 0x48
|
||||
#define SCSI_RD_CAPAC 0x25 /* Read Capacity (MANDATORY) */
|
||||
#define SCSI_RD_CAPAC10 SCSI_RD_CAPAC /* Read Capacity (10) */
|
||||
#define SCSI_RD_CAPAC16 0x9e /* Read Capacity (16) */
|
||||
#define SCSI_RD_DEFECT 0x37 /* Read Defect Data (O) */
|
||||
#define SCSI_READ_LONG 0x3E /* Read Long (O) */
|
||||
#define SCSI_REASS_BLK 0x07 /* Reassign Blocks (O) */
|
||||
#define SCSI_RCV_DIAG 0x1C /* Receive Diagnostic Results (O) */
|
||||
#define SCSI_RELEASE 0x17 /* Release Unit (MANDATORY) */
|
||||
#define SCSI_REZERO 0x01 /* Rezero Unit (O) */
|
||||
#define SCSI_SRCH_DAT_E 0x31 /* Search Data Equal (O) */
|
||||
#define SCSI_SRCH_DAT_H 0x30 /* Search Data High (O) */
|
||||
#define SCSI_SRCH_DAT_L 0x32 /* Search Data Low (O) */
|
||||
#define SCSI_SEEK6 0x0B /* Seek 6-Byte (O) */
|
||||
#define SCSI_SEEK10 0x2B /* Seek 10-Byte (O) */
|
||||
#define SCSI_SEND_DIAG 0x1D /* Send Diagnostics (MANDATORY) */
|
||||
#define SCSI_SET_LIMIT 0x33 /* Set Limits (O) */
|
||||
#define SCSI_START_STP 0x1B /* Start/Stop Unit (O) */
|
||||
#define SCSI_SYNC_CACHE 0x35 /* Synchronize Cache (O) */
|
||||
#define SCSI_VERIFY 0x2F /* Verify (O) */
|
||||
#define SCSI_WRITE6 0x0A /* Write 6-Byte (MANDATORY) */
|
||||
#define SCSI_WRITE10 0x2A /* Write 10-Byte (MANDATORY) */
|
||||
#define SCSI_WRT_VERIFY 0x2E /* Write and Verify (O) */
|
||||
#define SCSI_WRITE_LONG 0x3F /* Write Long (O) */
|
||||
#define SCSI_WRITE_SAME 0x41 /* Write Same (O) */
|
||||
|
||||
/**
|
||||
* struct scsi_platdata - stores information about SCSI controller
|
||||
*
|
||||
* @base: Controller base address
|
||||
* @max_lun: Maximum number of logical units
|
||||
* @max_id: Maximum number of target ids
|
||||
*/
|
||||
struct scsi_platdata {
|
||||
unsigned long base;
|
||||
unsigned long max_lun;
|
||||
unsigned long max_id;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* Operations for SCSI */
|
||||
struct scsi_ops {
|
||||
/**
|
||||
* exec() - execute a command
|
||||
*
|
||||
* @dev: SCSI bus
|
||||
* @cmd: Command to execute
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int (*exec)(struct udevice *dev, struct scsi_cmd *cmd);
|
||||
|
||||
/**
|
||||
* bus_reset() - reset the bus
|
||||
*
|
||||
* @dev: SCSI bus to reset
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int (*bus_reset)(struct udevice *dev);
|
||||
};
|
||||
|
||||
#define scsi_get_ops(dev) ((struct scsi_ops *)(dev)->driver->ops)
|
||||
|
||||
extern struct scsi_ops scsi_ops;
|
||||
|
||||
/**
|
||||
* scsi_exec() - execute a command
|
||||
*
|
||||
* @dev: SCSI bus
|
||||
* @cmd: Command to execute
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int scsi_exec(struct udevice *dev, struct scsi_cmd *cmd);
|
||||
|
||||
/**
|
||||
* scsi_bus_reset() - reset the bus
|
||||
*
|
||||
* @dev: SCSI bus to reset
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int scsi_bus_reset(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* scsi_scan() - Scan all SCSI controllers for available devices
|
||||
*
|
||||
* @vebose: true to show information about each device found
|
||||
*/
|
||||
int scsi_scan(bool verbose);
|
||||
|
||||
/**
|
||||
* scsi_scan_dev() - scan a SCSI bus and create devices
|
||||
*
|
||||
* @dev: SCSI bus
|
||||
* @verbose: true to show information about each device found
|
||||
*/
|
||||
int scsi_scan_dev(struct udevice *dev, bool verbose);
|
||||
#endif
|
||||
|
||||
void scsi_low_level_init(int busdevfunc);
|
||||
void scsi_init(void);
|
||||
|
||||
#define SCSI_IDENTIFY 0xC0 /* not used */
|
||||
|
||||
/* Hardware errors */
|
||||
#define SCSI_SEL_TIME_OUT 0x00000101 /* Selection time out */
|
||||
#define SCSI_HNS_TIME_OUT 0x00000102 /* Handshake */
|
||||
#define SCSI_MA_TIME_OUT 0x00000103 /* Phase error */
|
||||
#define SCSI_UNEXP_DIS 0x00000104 /* unexpected disconnect */
|
||||
|
||||
#define SCSI_INT_STATE 0x00010000 /* unknown Interrupt number is stored in 16 LSB */
|
||||
|
||||
#endif /* _SCSI_H */
|
900
A27-STEPLDR/Src/usb/include/usb.h
Normal file
900
A27-STEPLDR/Src/usb/include/usb.h
Normal file
@ -0,0 +1,900 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* Adapted for U-Boot driver model
|
||||
* (C) Copyright 2015 Google, Inc
|
||||
* Note: Part of this code has been derived from linux
|
||||
*
|
||||
*/
|
||||
#ifndef _USB_H_
|
||||
#define _USB_H_
|
||||
|
||||
//#include <fdtdec.h>
|
||||
#include <usb_defs.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
//#include <asm/cache.h>
|
||||
//#include <part.h>
|
||||
|
||||
/*
|
||||
* The EHCI spec says that we must align to at least 32 bytes. However,
|
||||
* some platforms require larger alignment.
|
||||
*/
|
||||
#if ARCH_DMA_MINALIGN > 32
|
||||
#define USB_DMA_MINALIGN ARCH_DMA_MINALIGN
|
||||
#else
|
||||
#define USB_DMA_MINALIGN 32
|
||||
#endif
|
||||
|
||||
/* Everything is aribtrary */
|
||||
#define USB_ALTSETTINGALLOC 4
|
||||
#define USB_MAXALTSETTING 128 /* Hard limit */
|
||||
|
||||
#define USB_MAX_DEVICE 32
|
||||
#define USB_MAXCONFIG 8
|
||||
#define USB_MAXINTERFACES 8
|
||||
#define USB_MAXENDPOINTS 16
|
||||
#define USB_MAXCHILDREN 8 /* This is arbitrary */
|
||||
#define USB_MAX_HUB 16
|
||||
|
||||
#define USB_CNTL_TIMEOUT 10000 /* 100ms timeout */
|
||||
|
||||
/*
|
||||
* This is the timeout to allow for submitting an urb in ms. We allow more
|
||||
* time for a BULK device to react - some are slow.
|
||||
*/
|
||||
#define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000)
|
||||
|
||||
/* device request (setup) */
|
||||
struct devrequest {
|
||||
__u8 requesttype;
|
||||
__u8 request;
|
||||
__le16 value;
|
||||
__le16 index;
|
||||
__le16 length;
|
||||
};
|
||||
|
||||
/* Interface */
|
||||
struct usb_interface {
|
||||
struct usb_interface_descriptor desc;
|
||||
|
||||
__u8 no_of_ep;
|
||||
__u8 num_altsetting;
|
||||
__u8 act_altsetting;
|
||||
|
||||
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
|
||||
/*
|
||||
* Super Speed Device will have Super Speed Endpoint
|
||||
* Companion Descriptor (section 9.6.7 of usb 3.0 spec)
|
||||
* Revision 1.0 June 6th 2011
|
||||
*/
|
||||
struct usb_ss_ep_comp_descriptor ss_ep_comp_desc[USB_MAXENDPOINTS];
|
||||
};
|
||||
|
||||
/* Configuration information.. */
|
||||
struct usb_config {
|
||||
struct usb_config_descriptor desc;
|
||||
|
||||
__u8 no_of_if; /* number of interfaces */
|
||||
struct usb_interface if_desc[USB_MAXINTERFACES];
|
||||
};
|
||||
|
||||
enum {
|
||||
/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
|
||||
PACKET_SIZE_8 = 0,
|
||||
PACKET_SIZE_16 = 1,
|
||||
PACKET_SIZE_32 = 2,
|
||||
PACKET_SIZE_64 = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct usb_device - information about a USB device
|
||||
*
|
||||
* With driver model both UCLASS_USB (the USB controllers) and UCLASS_USB_HUB
|
||||
* (the hubs) have this as parent data. Hubs are children of controllers or
|
||||
* other hubs and there is always a single root hub for each controller.
|
||||
* Therefore struct usb_device can always be accessed with
|
||||
* dev_get_parent_priv(dev), where dev is a USB device.
|
||||
*
|
||||
* Pointers exist for obtaining both the device (could be any uclass) and
|
||||
* controller (UCLASS_USB) from this structure. The controller does not have
|
||||
* a struct usb_device since it is not a device.
|
||||
*/
|
||||
struct usb_device {
|
||||
int devnum; /* Device number on USB bus */
|
||||
int speed; /* full/low/high */
|
||||
char mf[32]; /* manufacturer */
|
||||
char prod[32]; /* product */
|
||||
char serial[32]; /* serial number */
|
||||
|
||||
struct usb_tt *tt;
|
||||
int ttport;
|
||||
|
||||
/* Maximum packet size; one of: PACKET_SIZE_* */
|
||||
int maxpacketsize;
|
||||
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
|
||||
unsigned int toggle[2];
|
||||
/* endpoint halts; one bit per endpoint # & direction;
|
||||
* [0] = IN, [1] = OUT
|
||||
*/
|
||||
unsigned int halted[2];
|
||||
int epmaxpacketin[16]; /* INput endpoint specific maximums */
|
||||
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
|
||||
|
||||
int configno; /* selected config number */
|
||||
/* Device Descriptor */
|
||||
struct usb_device_descriptor descriptor;
|
||||
struct usb_config config; /* config descriptor */
|
||||
|
||||
int have_langid; /* whether string_langid is valid yet */
|
||||
int string_langid; /* language ID for strings */
|
||||
int (*irq_handle)(struct usb_device *dev);
|
||||
unsigned long irq_status;
|
||||
int irq_act_len; /* transferred bytes */
|
||||
void *privptr;
|
||||
/*
|
||||
* Child devices - if this is a hub device
|
||||
* Each instance needs its own set of data structures.
|
||||
*/
|
||||
unsigned long status;
|
||||
unsigned long int_pending; /* 1 bit per ep, used by int_queue */
|
||||
int act_len; /* transferred bytes */
|
||||
int maxchild; /* Number of ports if hub */
|
||||
int portnr; /* Port number, 1=first */
|
||||
#ifndef CONFIG_DM_USB
|
||||
/* parent hub, or NULL if this is the root hub */
|
||||
struct usb_device *parent;
|
||||
struct usb_device *children[USB_MAXCHILDREN];
|
||||
void *controller; /* hardware controller private data */
|
||||
#endif
|
||||
/* slot_id - for xHCI enabled devices */
|
||||
unsigned int slot_id;
|
||||
#ifdef CONFIG_DM_USB
|
||||
struct udevice *dev; /* Pointer to associated device */
|
||||
struct udevice *controller_dev; /* Pointer to associated controller */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct int_queue;
|
||||
|
||||
/*
|
||||
* You can initialize platform's USB host or device
|
||||
* ports by passing this enum as an argument to
|
||||
* board_usb_init().
|
||||
*/
|
||||
enum usb_init_type {
|
||||
USB_INIT_HOST,
|
||||
USB_INIT_DEVICE
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* this is how the lowlevel part communicate with the outer world
|
||||
*/
|
||||
|
||||
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
|
||||
int usb_lowlevel_stop(int index);
|
||||
|
||||
#if defined(CONFIG_USB_MUSB_HOST) || defined(CONFIG_DM_USB)
|
||||
int usb_reset_root_port(struct usb_device *dev);
|
||||
#else
|
||||
#define usb_reset_root_port(dev)
|
||||
#endif
|
||||
|
||||
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int transfer_len, int *actual_length, int timeout);
|
||||
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||
int transfer_len, struct devrequest *setup, int timeout);
|
||||
|
||||
/* Defines */
|
||||
#define USB_UHCI_VEND_ID 0x8086
|
||||
#define USB_UHCI_DEV_ID 0x7112
|
||||
|
||||
/*
|
||||
* PXA25x can only act as USB device. There are drivers
|
||||
* which works with USB CDC gadgets implementations.
|
||||
* Some of them have common routines which can be used
|
||||
* in boards init functions e.g. udc_disconnect() used for
|
||||
* forced device disconnection from host.
|
||||
*/
|
||||
extern void udc_disconnect(void);
|
||||
|
||||
/*
|
||||
* board-specific hardware initialization, called by
|
||||
* usb drivers and u-boot commands
|
||||
*
|
||||
* @param index USB controller number
|
||||
* @param init initializes controller as USB host or device
|
||||
*/
|
||||
int board_usb_init(int index, enum usb_init_type init);
|
||||
|
||||
/*
|
||||
* can be used to clean up after failed USB initialization attempt
|
||||
* vide: board_usb_init()
|
||||
*
|
||||
* @param index USB controller number for selective cleanup
|
||||
* @param init usb_init_type passed to board_usb_init()
|
||||
*/
|
||||
int board_usb_cleanup(int index, enum usb_init_type init);
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
|
||||
#define USB_MAX_STOR_DEV 7
|
||||
int usb_stor_scan(int mode);
|
||||
int usb_stor_info(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HOST_ETHER
|
||||
|
||||
#define USB_MAX_ETH_DEV 5
|
||||
int usb_host_eth_scan(int mode);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_KEYBOARD
|
||||
|
||||
int drv_usb_kbd_init(void);
|
||||
int usb_kbd_deregister(int force);
|
||||
|
||||
#endif
|
||||
/* routines */
|
||||
int usb_init(void); /* initialize the USB Controller */
|
||||
int usb_stop(void); /* stop the USB Controller */
|
||||
int usb_detect_change(void); /* detect if a USB device has been (un)plugged */
|
||||
|
||||
|
||||
int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
|
||||
int usb_set_idle(struct usb_device *dev, int ifnum, int duration,
|
||||
int report_id);
|
||||
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
|
||||
unsigned char request, unsigned char requesttype,
|
||||
unsigned short value, unsigned short index,
|
||||
void *data, unsigned short size, int timeout);
|
||||
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
|
||||
void *data, int len, int *actual_length, int timeout);
|
||||
int usb_disable_asynch(int disable);
|
||||
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
|
||||
int usb_get_configuration_no(struct usb_device *dev, int cfgno,
|
||||
unsigned char *buffer, int length);
|
||||
int usb_get_configuration_len(struct usb_device *dev, int cfgno);
|
||||
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
|
||||
unsigned char id, void *buf, int size);
|
||||
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
|
||||
unsigned char type, unsigned char id, void *buf,
|
||||
int size);
|
||||
int usb_clear_halt(struct usb_device *dev, int pipe);
|
||||
int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
|
||||
int usb_set_interface(struct usb_device *dev, int interface, int alternate);
|
||||
int usb_get_port_status(struct usb_device *dev, int port, void *data);
|
||||
|
||||
/* big endian -> little endian conversion */
|
||||
/* some CPUs are already little endian e.g. the ARM920T */
|
||||
#define __swap_16(x) \
|
||||
({ unsigned short x_ = (unsigned short)x; \
|
||||
(unsigned short)( \
|
||||
((x_ & 0x00FFU) << 8) | ((x_ & 0xFF00U) >> 8)); \
|
||||
})
|
||||
#define __swap_32(x) \
|
||||
({ unsigned long x_ = (unsigned long)x; \
|
||||
(unsigned long)( \
|
||||
((x_ & 0x000000FFUL) << 24) | \
|
||||
((x_ & 0x0000FF00UL) << 8) | \
|
||||
((x_ & 0x00FF0000UL) >> 8) | \
|
||||
((x_ & 0xFF000000UL) >> 24)); \
|
||||
})
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
# define swap_16(x) (x)
|
||||
# define swap_32(x) (x)
|
||||
#else
|
||||
# define swap_16(x) __swap_16(x)
|
||||
# define swap_32(x) __swap_32(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Calling this entity a "pipe" is glorifying it. A USB pipe
|
||||
* is something embarrassingly simple: it basically consists
|
||||
* of the following information:
|
||||
* - device number (7 bits)
|
||||
* - endpoint number (4 bits)
|
||||
* - current Data0/1 state (1 bit)
|
||||
* - direction (1 bit)
|
||||
* - speed (2 bits)
|
||||
* - max packet size (2 bits: 8, 16, 32 or 64)
|
||||
* - pipe type (2 bits: control, interrupt, bulk, isochronous)
|
||||
*
|
||||
* That's 18 bits. Really. Nothing more. And the USB people have
|
||||
* documented these eighteen bits as some kind of glorious
|
||||
* virtual data structure.
|
||||
*
|
||||
* Let's not fall in that trap. We'll just encode it as a simple
|
||||
* unsigned int. The encoding is:
|
||||
*
|
||||
* - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64)
|
||||
* - direction: bit 7 (0 = Host-to-Device [Out],
|
||||
* (1 = Device-to-Host [In])
|
||||
* - device: bits 8-14
|
||||
* - endpoint: bits 15-18
|
||||
* - Data0/1: bit 19
|
||||
* - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt,
|
||||
* 10 = control, 11 = bulk)
|
||||
*
|
||||
* Why? Because it's arbitrary, and whatever encoding we select is really
|
||||
* up to us. This one happens to share a lot of bit positions with the UHCI
|
||||
* specification, so that much of the uhci driver can just mask the bits
|
||||
* appropriately.
|
||||
*/
|
||||
/* Create various pipes... */
|
||||
#define create_pipe(dev,endpoint) \
|
||||
(((dev)->devnum << 8) | ((endpoint) << 15) | \
|
||||
(dev)->maxpacketsize)
|
||||
#define default_pipe(dev) ((dev)->speed << 26)
|
||||
|
||||
#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \
|
||||
default_pipe(dev))
|
||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \
|
||||
default_pipe(dev) | \
|
||||
USB_DIR_IN)
|
||||
|
||||
/* The D0/D1 toggle bits */
|
||||
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
|
||||
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep))
|
||||
#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \
|
||||
((dev)->toggle[out] & \
|
||||
~(1 << ep)) | ((bit) << ep))
|
||||
|
||||
/* Endpoint halt control/status */
|
||||
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1)
|
||||
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
|
||||
#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
|
||||
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
|
||||
|
||||
#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \
|
||||
USB_PID_OUT)
|
||||
|
||||
//#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
|
||||
//#define usb_pipein(pipe) (((pipe) >> 7) & 1)
|
||||
|
||||
#define usb_pipein(pipe) ((pipe) & USB_DIR_IN)
|
||||
#define usb_pipeout(pipe) (!usb_pipein(pipe))
|
||||
|
||||
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
|
||||
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
|
||||
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
|
||||
#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
|
||||
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
|
||||
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
|
||||
#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
|
||||
#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
|
||||
#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
|
||||
|
||||
#define usb_pipe_ep_index(pipe) \
|
||||
usb_pipecontrol(pipe) ? (usb_pipeendpoint(pipe) * 2) : \
|
||||
((usb_pipeendpoint(pipe) * 2) - \
|
||||
(usb_pipein(pipe) ? 0 : 1))
|
||||
|
||||
/**
|
||||
* struct usb_device_id - identifies USB devices for probing and hotplugging
|
||||
* @match_flags: Bit mask controlling which of the other fields are used to
|
||||
* match against new devices. Any field except for driver_info may be
|
||||
* used, although some only make sense in conjunction with other fields.
|
||||
* This is usually set by a USB_DEVICE_*() macro, which sets all
|
||||
* other fields in this structure except for driver_info.
|
||||
* @idVendor: USB vendor ID for a device; numbers are assigned
|
||||
* by the USB forum to its members.
|
||||
* @idProduct: Vendor-assigned product ID.
|
||||
* @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
|
||||
* This is also used to identify individual product versions, for
|
||||
* a range consisting of a single device.
|
||||
* @bcdDevice_hi: High end of version number range. The range of product
|
||||
* versions is inclusive.
|
||||
* @bDeviceClass: Class of device; numbers are assigned
|
||||
* by the USB forum. Products may choose to implement classes,
|
||||
* or be vendor-specific. Device classes specify behavior of all
|
||||
* the interfaces on a device.
|
||||
* @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
|
||||
* @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
|
||||
* @bInterfaceClass: Class of interface; numbers are assigned
|
||||
* by the USB forum. Products may choose to implement classes,
|
||||
* or be vendor-specific. Interface classes specify behavior only
|
||||
* of a given interface; other interfaces may support other classes.
|
||||
* @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
|
||||
* @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
|
||||
* @bInterfaceNumber: Number of interface; composite devices may use
|
||||
* fixed interface numbers to differentiate between vendor-specific
|
||||
* interfaces.
|
||||
* @driver_info: Holds information used by the driver. Usually it holds
|
||||
* a pointer to a descriptor understood by the driver, or perhaps
|
||||
* device flags.
|
||||
*
|
||||
* In most cases, drivers will create a table of device IDs by using
|
||||
* USB_DEVICE(), or similar macros designed for that purpose.
|
||||
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
|
||||
* and provide it to the USB core through their usb_driver structure.
|
||||
*
|
||||
* See the usb_match_id() function for information about how matches are
|
||||
* performed. Briefly, you will normally use one of several macros to help
|
||||
* construct these entries. Each entry you provide will either identify
|
||||
* one or more specific products, or will identify a class of products
|
||||
* which have agreed to behave the same. You should put the more specific
|
||||
* matches towards the beginning of your table, so that driver_info can
|
||||
* record quirks of specific products.
|
||||
*/
|
||||
struct usb_device_id {
|
||||
/* which fields to match against? */
|
||||
u16 match_flags;
|
||||
|
||||
/* Used for product specific matches; range is inclusive */
|
||||
u16 idVendor;
|
||||
u16 idProduct;
|
||||
u16 bcdDevice_lo;
|
||||
u16 bcdDevice_hi;
|
||||
|
||||
/* Used for device class matches */
|
||||
u8 bDeviceClass;
|
||||
u8 bDeviceSubClass;
|
||||
u8 bDeviceProtocol;
|
||||
|
||||
/* Used for interface class matches */
|
||||
u8 bInterfaceClass;
|
||||
u8 bInterfaceSubClass;
|
||||
u8 bInterfaceProtocol;
|
||||
|
||||
/* Used for vendor-specific interface matches */
|
||||
u8 bInterfaceNumber;
|
||||
|
||||
/* not matched against */
|
||||
ulong driver_info;
|
||||
};
|
||||
|
||||
/* Some useful macros to use to create struct usb_device_id */
|
||||
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
|
||||
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
|
||||
#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
|
||||
#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
|
||||
#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
|
||||
#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
|
||||
#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
|
||||
#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
|
||||
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
|
||||
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
|
||||
#define USB_DEVICE_ID_MATCH_INT_NUMBER 0x0400
|
||||
|
||||
/* Match anything, indicates this is a valid entry even if everything is 0 */
|
||||
#define USB_DEVICE_ID_MATCH_NONE 0x0800
|
||||
#define USB_DEVICE_ID_MATCH_ALL 0x07ff
|
||||
|
||||
/**
|
||||
* struct usb_driver_entry - Matches a driver to its usb_device_ids
|
||||
* @driver: Driver to use
|
||||
* @match: List of match records for this driver, terminated by {}
|
||||
*/
|
||||
struct usb_driver_entry {
|
||||
struct driver *driver;
|
||||
const struct usb_device_id *match;
|
||||
};
|
||||
|
||||
#define USB_DEVICE_ID_MATCH_DEVICE \
|
||||
(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
|
||||
|
||||
/**
|
||||
* USB_DEVICE - macro used to describe a specific usb device
|
||||
* @vend: the 16 bit USB Vendor ID
|
||||
* @prod: the 16 bit USB Product ID
|
||||
*
|
||||
* This macro is used to create a struct usb_device_id that matches a
|
||||
* specific device.
|
||||
*/
|
||||
#define USB_DEVICE(vend, prod) \
|
||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
|
||||
.idVendor = (vend), \
|
||||
.idProduct = (prod)
|
||||
|
||||
#define U_BOOT_USB_DEVICE(__name, __match) \
|
||||
ll_entry_declare(struct usb_driver_entry, __name, usb_driver_entry) = {\
|
||||
.driver = llsym(struct driver, __name, driver), \
|
||||
.match = __match, \
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Hub Stuff
|
||||
*/
|
||||
struct usb_port_status {
|
||||
unsigned short wPortStatus;
|
||||
unsigned short wPortChange;
|
||||
};
|
||||
|
||||
struct usb_hub_status {
|
||||
unsigned short wHubStatus;
|
||||
unsigned short wHubChange;
|
||||
};
|
||||
|
||||
/*
|
||||
* Hub Device descriptor
|
||||
* USB Hub class device protocols
|
||||
*/
|
||||
#define USB_HUB_PR_FS 0 /* Full speed hub */
|
||||
#define USB_HUB_PR_HS_NO_TT 0 /* Hi-speed hub without TT */
|
||||
#define USB_HUB_PR_HS_SINGLE_TT 1 /* Hi-speed hub with single TT */
|
||||
#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */
|
||||
#define USB_HUB_PR_SS 3 /* Super speed hub */
|
||||
|
||||
/* Transaction Translator Think Times, in bits */
|
||||
#define HUB_TTTT_8_BITS 0x00
|
||||
#define HUB_TTTT_16_BITS 0x20
|
||||
#define HUB_TTTT_24_BITS 0x40
|
||||
#define HUB_TTTT_32_BITS 0x60
|
||||
|
||||
/* Hub descriptor */
|
||||
struct usb_hub_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bNbrPorts;
|
||||
unsigned short wHubCharacteristics;
|
||||
unsigned char bPwrOn2PwrGood;
|
||||
unsigned char bHubContrCurrent;
|
||||
/* 2.0 and 3.0 hubs differ here */
|
||||
union {
|
||||
struct {
|
||||
/* add 1 bit for hub status change; round to bytes */
|
||||
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
__u8 PortPowerCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
}hs;
|
||||
|
||||
struct {
|
||||
__u8 bHubHdrDecLat;
|
||||
__le16 wHubDelay;
|
||||
__le16 DeviceRemovable;
|
||||
}ss;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
struct usb_hub_device {
|
||||
struct usb_device *pusb_dev;
|
||||
struct usb_hub_descriptor desc;
|
||||
|
||||
ulong connect_timeout; /* Device connection timeout in ms */
|
||||
ulong query_delay; /* Device query delay in ms */
|
||||
int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */
|
||||
int hub_depth; /* USB 3.0 hub depth */
|
||||
struct usb_tt tt; /* Transaction Translator */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DM_USB
|
||||
/**
|
||||
* struct usb_platdata - Platform data about a USB controller
|
||||
*
|
||||
* Given a USB controller (UCLASS_USB) dev this is dev_get_platdata(dev)
|
||||
*/
|
||||
struct usb_platdata {
|
||||
enum usb_init_type init_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct usb_dev_platdata - Platform data about a USB device
|
||||
*
|
||||
* Given a USB device dev this structure is dev_get_parent_platdata(dev).
|
||||
* This is used by sandbox to provide emulation data also.
|
||||
*
|
||||
* @id: ID used to match this device
|
||||
* @devnum: Device address on the USB bus
|
||||
* @udev: usb-uclass internal use only do NOT use
|
||||
* @strings: List of descriptor strings (for sandbox emulation purposes)
|
||||
* @desc_list: List of descriptors (for sandbox emulation purposes)
|
||||
*/
|
||||
struct usb_dev_platdata {
|
||||
struct usb_device_id id;
|
||||
int devnum;
|
||||
/*
|
||||
* This pointer is used to pass the usb_device used in usb_scan_device,
|
||||
* to get the usb descriptors before the driver is known, to the
|
||||
* actual udevice once the driver is known and the udevice is created.
|
||||
* This will be NULL except during probe, do NOT use.
|
||||
*
|
||||
* This should eventually go away.
|
||||
*/
|
||||
struct usb_device *udev;
|
||||
|
||||
int configno;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct usb_bus_priv - information about the USB controller
|
||||
*
|
||||
* Given a USB controller (UCLASS_USB) 'dev', this is
|
||||
* dev_get_uclass_priv(dev).
|
||||
*
|
||||
* @next_addr: Next device address to allocate minus 1. Incremented by 1
|
||||
* each time a new device address is set, so this holds the
|
||||
* number of devices on the bus
|
||||
* @desc_before_addr: true if we can read a device descriptor before it
|
||||
* has been assigned an address. For XHCI this is not possible
|
||||
* so this will be false.
|
||||
* @companion: True if this is a companion controller to another USB
|
||||
* controller
|
||||
*/
|
||||
struct usb_bus_priv {
|
||||
int next_addr;
|
||||
bool desc_before_addr;
|
||||
bool companion;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct usb_emul_platdata - platform data about the USB emulator
|
||||
*
|
||||
* Given a USB emulator (UCLASS_USB_EMUL) 'dev', this is
|
||||
* dev_get_uclass_platdata(dev).
|
||||
*
|
||||
* @port1: USB emulator device port number on the parent hub
|
||||
*/
|
||||
struct usb_emul_platdata {
|
||||
int port1; /* Port number (numbered from 1) */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dm_usb_ops - USB controller operations
|
||||
*
|
||||
* This defines the operations supoorted on a USB controller. Common
|
||||
* arguments are:
|
||||
*
|
||||
* @bus: USB bus (i.e. controller), which is in UCLASS_USB.
|
||||
* @udev: USB device parent data. Controllers are not expected to need
|
||||
* this, since the device address on the bus is encoded in @pipe.
|
||||
* It is used for sandbox, and can be handy for debugging and
|
||||
* logging.
|
||||
* @pipe: An assortment of bitfields which provide address and packet
|
||||
* type information. See create_pipe() above for encoding
|
||||
* details
|
||||
* @buffer: A buffer to use for sending/receiving. This should be
|
||||
* DMA-aligned.
|
||||
* @length: Buffer length in bytes
|
||||
*/
|
||||
struct dm_usb_ops {
|
||||
/**
|
||||
* control() - Send a control message
|
||||
*
|
||||
* Most parameters are as above.
|
||||
*
|
||||
* @setup: Additional setup information required by the message
|
||||
*/
|
||||
int (*control)(struct udevice *bus, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length,
|
||||
struct devrequest *setup);
|
||||
/**
|
||||
* bulk() - Send a bulk message
|
||||
*
|
||||
* Parameters are as above.
|
||||
*/
|
||||
int (*bulk)(struct udevice *bus, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length);
|
||||
/**
|
||||
* interrupt() - Send an interrupt message
|
||||
*
|
||||
* Most parameters are as above.
|
||||
*
|
||||
* @interval: Interrupt interval
|
||||
*/
|
||||
int (*interrupt)(struct udevice *bus, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length,
|
||||
int interval);
|
||||
|
||||
/**
|
||||
* alloc_device() - Allocate a new device context (XHCI)
|
||||
*
|
||||
* Before sending packets to a new device on an XHCI bus, a device
|
||||
* context must be created. If this method is not NULL it will be
|
||||
* called before the device is enumerated (even before its descriptor
|
||||
* is read). This should be NULL for EHCI, which does not need this.
|
||||
*/
|
||||
int (*alloc_device)(struct udevice *bus, struct usb_device *udev);
|
||||
|
||||
/**
|
||||
* reset_root_port() - Reset usb root port
|
||||
*/
|
||||
int (*reset_root_port)(struct udevice *bus, struct usb_device *udev);
|
||||
|
||||
/**
|
||||
* get_max_xfer_size() - Get HCD's maximum transfer bytes
|
||||
*
|
||||
* The HCD may have limitation on the maximum bytes to be transferred
|
||||
* in a USB transfer. USB class driver needs to be aware of this.
|
||||
*/
|
||||
int (*get_max_xfer_size)(struct udevice *bus, size_t *size);
|
||||
};
|
||||
|
||||
#define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops)
|
||||
#define usb_get_emul_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops)
|
||||
|
||||
/**
|
||||
* usb_get_dev_index() - look up a device index number
|
||||
*
|
||||
* Look up devices using their index number (starting at 0). This works since
|
||||
* in U-Boot device addresses are allocated starting at 1 with no gaps.
|
||||
*
|
||||
* TODO(sjg@chromium.org): Remove this function when usb_ether.c is modified
|
||||
* to work better with driver model.
|
||||
*
|
||||
* @bus: USB bus to check
|
||||
* @index: Index number of device to find (0=first). This is just the
|
||||
* device address less 1.
|
||||
*/
|
||||
struct usb_device *usb_get_dev_index(struct udevice *bus, int index);
|
||||
|
||||
/**
|
||||
* usb_setup_device() - set up a device ready for use
|
||||
*
|
||||
* @dev: USB device pointer. This need not be a real device - it is
|
||||
* common for it to just be a local variable with its ->dev
|
||||
* member (i.e. @dev->dev) set to the parent device and
|
||||
* dev->portnr set to the port number on the hub (1=first)
|
||||
* @do_read: true to read the device descriptor before an address is set
|
||||
* (should be false for XHCI buses, true otherwise)
|
||||
* @parent: Parent device (either UCLASS_USB or UCLASS_USB_HUB)
|
||||
* @return 0 if OK, -ve on error */
|
||||
int usb_setup_device(struct usb_device *dev, bool do_read,
|
||||
struct usb_device *parent);
|
||||
|
||||
/**
|
||||
* usb_hub_is_root_hub() - Test whether a hub device is root hub or not
|
||||
*
|
||||
* @hub: USB hub device to test
|
||||
* @return: true if the hub device is root hub, false otherwise.
|
||||
*/
|
||||
bool usb_hub_is_root_hub(struct udevice *hub);
|
||||
|
||||
/**
|
||||
* usb_hub_scan() - Scan a hub and find its devices
|
||||
*
|
||||
* @hub: Hub device to scan
|
||||
*/
|
||||
int usb_hub_scan(struct udevice *hub);
|
||||
|
||||
/**
|
||||
* usb_scan_device() - Scan a device on a bus
|
||||
*
|
||||
* Scan a device on a bus. It has already been detected and is ready to
|
||||
* be enumerated. This may be either the root hub (@parent is a bus) or a
|
||||
* normal device (@parent is a hub)
|
||||
*
|
||||
* @parent: Parent device
|
||||
* @port: Hub port number (numbered from 1)
|
||||
* @speed: USB speed to use for this device
|
||||
* @devp: Returns pointer to device if all is well
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int usb_scan_device(struct udevice *parent, int port,
|
||||
enum usb_device_speed speed, struct udevice **devp);
|
||||
|
||||
/**
|
||||
* usb_get_bus() - Find the bus for a device
|
||||
*
|
||||
* Search up through parents to find the bus this device is connected to. This
|
||||
* will be a device with uclass UCLASS_USB.
|
||||
*
|
||||
* @dev: Device to check
|
||||
* @return The bus, or NULL if not found (this indicates a critical error in
|
||||
* the USB stack
|
||||
*/
|
||||
struct udevice *usb_get_bus(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* usb_select_config() - Set up a device ready for use
|
||||
*
|
||||
* This function assumes that the device already has an address and a driver
|
||||
* bound, and is ready to be set up.
|
||||
*
|
||||
* This re-reads the device and configuration descriptors and sets the
|
||||
* configuration
|
||||
*
|
||||
* @dev: Device to set up
|
||||
*/
|
||||
int usb_select_config(struct usb_device *dev);
|
||||
|
||||
/**
|
||||
* usb_child_pre_probe() - Pre-probe function for USB devices
|
||||
*
|
||||
* This is called on all children of hubs and USB controllers (i.e. UCLASS_USB
|
||||
* and UCLASS_USB_HUB) when a new device is about to be probed. It sets up the
|
||||
* device from the saved platform data and calls usb_select_config() to
|
||||
* finish set up.
|
||||
*
|
||||
* Once this is done, the device's normal driver can take over, knowing the
|
||||
* device is accessible on the USB bus.
|
||||
*
|
||||
* This function is for use only by the internal USB stack.
|
||||
*
|
||||
* @dev: Device to set up
|
||||
*/
|
||||
int usb_child_pre_probe(struct udevice *dev);
|
||||
|
||||
struct ehci_ctrl;
|
||||
|
||||
/**
|
||||
* usb_stor_reset() - Prepare to scan USB storage devices
|
||||
*
|
||||
* Empty the list of USB storage devices in preparation for scanning them.
|
||||
* This must be called before a USB scan.
|
||||
*/
|
||||
void usb_stor_reset(void);
|
||||
|
||||
#else /* !CONFIG_DM_USB */
|
||||
|
||||
struct usb_device *usb_get_dev_index(int index);
|
||||
|
||||
#endif
|
||||
|
||||
bool usb_device_has_child_on_port(struct usb_device *parent, int port);
|
||||
|
||||
int usb_hub_probe(struct usb_device *dev, int ifnum);
|
||||
void usb_hub_reset(void);
|
||||
|
||||
|
||||
/**
|
||||
* usb_alloc_new_device() - Allocate a new device
|
||||
*
|
||||
* @devp: returns a pointer of a new device structure. With driver model this
|
||||
* is a device pointer, but with legacy USB this pointer is
|
||||
* driver-specific.
|
||||
* @return 0 if OK, -ENOSPC if we have found out of room for new devices
|
||||
*/
|
||||
int usb_alloc_new_device(void *controller, struct usb_device **devp);
|
||||
|
||||
/**
|
||||
* usb_free_device() - Free a partially-inited device
|
||||
*
|
||||
* This is an internal function. It is used to reverse the action of
|
||||
* usb_alloc_new_device() when we hit a problem during init.
|
||||
*/
|
||||
void usb_free_device(void *controller);
|
||||
|
||||
int usb_new_device(struct usb_device *dev);
|
||||
|
||||
int usb_alloc_device(struct usb_device *dev);
|
||||
|
||||
/**
|
||||
* usb_get_max_xfer_size() - Get HCD's maximum transfer bytes
|
||||
*
|
||||
* The HCD may have limitation on the maximum bytes to be transferred
|
||||
* in a USB transfer. USB class driver needs to be aware of this.
|
||||
*
|
||||
* @dev: USB device
|
||||
* @size: maximum transfer bytes
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int usb_get_max_xfer_size(struct usb_device *dev, size_t *size);
|
||||
|
||||
/**
|
||||
* usb_show_tree() - show the USB device tree
|
||||
*
|
||||
* This shows a list of active USB devices along with basic information about
|
||||
* each.
|
||||
*/
|
||||
void usb_show_tree(void);
|
||||
|
||||
#define USB_DEV_PLUGED 0
|
||||
#define USB_DEV_UNPLUGED 1
|
||||
int usb_wait_dev_pluged(uint32_t timeout);
|
||||
|
||||
#endif /*_USB_H_ */
|
380
A27-STEPLDR/Src/usb/include/usb_defs.h
Normal file
380
A27-STEPLDR/Src/usb/include/usb_defs.h
Normal file
@ -0,0 +1,380 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* Note: Part of this code has been derived from linux
|
||||
*/
|
||||
#ifndef _USB_DEFS_H_
|
||||
#define _USB_DEFS_H_
|
||||
|
||||
/* USB constants */
|
||||
|
||||
/* Device and/or Interface Class codes */
|
||||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_COMM 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_DATA 10
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/* some HID sub classes */
|
||||
#define USB_SUB_HID_NONE 0
|
||||
#define USB_SUB_HID_BOOT 1
|
||||
|
||||
/* some UID Protocols */
|
||||
#define USB_PROT_HID_NONE 0
|
||||
#define USB_PROT_HID_KEYBOARD 1
|
||||
#define USB_PROT_HID_MOUSE 2
|
||||
|
||||
|
||||
/* Sub STORAGE Classes */
|
||||
#define US_SC_RBC 1 /* Typically, flash devices */
|
||||
#define US_SC_8020 2 /* CD-ROM */
|
||||
#define US_SC_QIC 3 /* QIC-157 Tapes */
|
||||
#define US_SC_UFI 4 /* Floppy */
|
||||
#define US_SC_8070 5 /* Removable media */
|
||||
#define US_SC_SCSI 6 /* Transparent */
|
||||
#define US_SC_MIN US_SC_RBC
|
||||
#define US_SC_MAX US_SC_SCSI
|
||||
|
||||
/* STORAGE Protocols */
|
||||
#define US_PR_CB 1 /* Control/Bulk w/o interrupt */
|
||||
#define US_PR_CBI 0 /* Control/Bulk/Interrupt */
|
||||
#define US_PR_BULK 0x50 /* bulk only */
|
||||
|
||||
/* USB types */
|
||||
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
/* USB recipients */
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
|
||||
/* USB directions */
|
||||
#define USB_DIR_OUT 0
|
||||
#define USB_DIR_IN 0x80
|
||||
|
||||
/*
|
||||
* bmRequestType: USB Device Requests, table 9.2 USB 2.0 spec.
|
||||
* (shifted) direction/type/recipient.
|
||||
*/
|
||||
#define DeviceRequest \
|
||||
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
|
||||
|
||||
#define DeviceOutRequest \
|
||||
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
|
||||
|
||||
#define InterfaceRequest \
|
||||
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||
|
||||
#define EndpointRequest \
|
||||
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||
|
||||
#define EndpointOutRequest \
|
||||
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||
|
||||
/* Descriptor types */
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
|
||||
#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
|
||||
#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
|
||||
#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a)
|
||||
|
||||
/* Descriptor sizes per descriptor type */
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
#define USB_DT_HID_SIZE 9
|
||||
|
||||
/* Endpoints */
|
||||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
||||
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||
|
||||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
|
||||
/* USB Packet IDs (PIDs) */
|
||||
#define USB_PID_UNDEF_0 0xf0
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_UNDEF_4 0xb4
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_UNDEF_6 0x96
|
||||
#define USB_PID_UNDEF_7 0x87
|
||||
#define USB_PID_UNDEF_8 0x78
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_UNDEF_F 0x0f
|
||||
|
||||
/* Standard requests */
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
/* HID requests */
|
||||
#define USB_REQ_GET_REPORT 0x01
|
||||
#define USB_REQ_GET_IDLE 0x02
|
||||
#define USB_REQ_GET_PROTOCOL 0x03
|
||||
#define USB_REQ_SET_REPORT 0x09
|
||||
#define USB_REQ_SET_IDLE 0x0A
|
||||
#define USB_REQ_SET_PROTOCOL 0x0B
|
||||
|
||||
/* Device features */
|
||||
#define USB_FEAT_HALT 0x00
|
||||
#define USB_FEAT_WAKEUP 0x01
|
||||
#define USB_FEAT_TEST 0x02
|
||||
|
||||
/* Test modes */
|
||||
#define USB_TEST_MODE_J 0x01
|
||||
#define USB_TEST_MODE_K 0x02
|
||||
#define USB_TEST_MODE_SE0_NAK 0x03
|
||||
#define USB_TEST_MODE_PACKET 0x04
|
||||
#define USB_TEST_MODE_FORCE_ENABLE 0x05
|
||||
|
||||
|
||||
/*
|
||||
* "pipe" definitions, use unsigned so we can compare reliably, since this
|
||||
* value is shifted up to bits 30/31.
|
||||
*/
|
||||
#define PIPE_ISOCHRONOUS 0U
|
||||
#define PIPE_INTERRUPT 1U
|
||||
#define PIPE_CONTROL 2U
|
||||
#define PIPE_BULK 3U
|
||||
#define PIPE_DEVEP_MASK 0x0007ff00
|
||||
|
||||
#define USB_ISOCHRONOUS 0
|
||||
#define USB_INTERRUPT 1
|
||||
#define USB_CONTROL 2
|
||||
#define USB_BULK 3
|
||||
|
||||
#define USB_PIPE_TYPE_SHIFT 30
|
||||
#define USB_PIPE_TYPE_MASK (3 << USB_PIPE_TYPE_SHIFT)
|
||||
|
||||
#define USB_PIPE_DEV_SHIFT 8
|
||||
#define USB_PIPE_DEV_MASK (0x7f << USB_PIPE_DEV_SHIFT)
|
||||
|
||||
#define USB_PIPE_EP_SHIFT 15
|
||||
#define USB_PIPE_EP_MASK (0xf << USB_PIPE_EP_SHIFT)
|
||||
|
||||
/* USB-status codes: */
|
||||
#define USB_ST_ACTIVE 0x1 /* TD is active */
|
||||
#define USB_ST_STALLED 0x2 /* TD is stalled */
|
||||
#define USB_ST_BUF_ERR 0x4 /* buffer error */
|
||||
#define USB_ST_BABBLE_DET 0x8 /* Babble detected */
|
||||
#define USB_ST_NAK_REC 0x10 /* NAK Received*/
|
||||
#define USB_ST_CRC_ERR 0x20 /* CRC/timeout Error */
|
||||
#define USB_ST_BIT_ERR 0x40 /* Bitstuff error */
|
||||
#define USB_ST_NOT_PROC 0x80000000L /* Not yet processed */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Hub defines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hub request types
|
||||
*/
|
||||
|
||||
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
||||
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
||||
|
||||
/*
|
||||
* Hub Class feature numbers
|
||||
*/
|
||||
#define C_HUB_LOCAL_POWER 0
|
||||
#define C_HUB_OVER_CURRENT 1
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
*/
|
||||
#define USB_PORT_FEAT_CONNECTION 0
|
||||
#define USB_PORT_FEAT_ENABLE 1
|
||||
#define USB_PORT_FEAT_SUSPEND 2
|
||||
#define USB_PORT_FEAT_OVER_CURRENT 3
|
||||
#define USB_PORT_FEAT_RESET 4
|
||||
#define USB_PORT_FEAT_POWER 8
|
||||
#define USB_PORT_FEAT_LOWSPEED 9
|
||||
#define USB_PORT_FEAT_HIGHSPEED 10
|
||||
#define USB_PORT_FEAT_C_CONNECTION 16
|
||||
#define USB_PORT_FEAT_C_ENABLE 17
|
||||
#define USB_PORT_FEAT_C_SUSPEND 18
|
||||
#define USB_PORT_FEAT_C_OVER_CURRENT 19
|
||||
#define USB_PORT_FEAT_C_RESET 20
|
||||
#define USB_PORT_FEAT_TEST 21
|
||||
|
||||
/*
|
||||
* Changes to Port feature numbers for Super speed,
|
||||
* from USB 3.0 spec Table 10-8
|
||||
*/
|
||||
#define USB_SS_PORT_FEAT_U1_TIMEOUT 23
|
||||
#define USB_SS_PORT_FEAT_U2_TIMEOUT 24
|
||||
#define USB_SS_PORT_FEAT_C_LINK_STATE 25
|
||||
#define USB_SS_PORT_FEAT_C_CONFIG_ERROR 26
|
||||
#define USB_SS_PORT_FEAT_BH_RESET 28
|
||||
#define USB_SS_PORT_FEAT_C_BH_RESET 29
|
||||
|
||||
/* wPortStatus bits */
|
||||
#define USB_PORT_STAT_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400 /* support for EHCI */
|
||||
#define USB_PORT_STAT_SUPER_SPEED 0x0600 /* faking support to XHCI */
|
||||
#define USB_PORT_STAT_SPEED_MASK \
|
||||
(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED)
|
||||
|
||||
/*
|
||||
* Changes to wPortStatus bit field in USB 3.0
|
||||
* See USB 3.0 spec Table 10-10
|
||||
*/
|
||||
#define USB_SS_PORT_STAT_LINK_STATE 0x01e0
|
||||
#define USB_SS_PORT_STAT_POWER 0x0200
|
||||
#define USB_SS_PORT_STAT_SPEED 0x1c00
|
||||
#define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000
|
||||
/* Bits that are the same from USB 2.0 */
|
||||
#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \
|
||||
USB_PORT_STAT_ENABLE | \
|
||||
USB_PORT_STAT_OVERCURRENT | \
|
||||
USB_PORT_STAT_RESET)
|
||||
|
||||
/* wPortChange bits */
|
||||
#define USB_PORT_STAT_C_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_C_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_C_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_C_RESET 0x0010
|
||||
|
||||
/*
|
||||
* Changes to wPortChange bit fields in USB 3.0
|
||||
* See USB 3.0 spec Table 10-12
|
||||
*/
|
||||
#define USB_SS_PORT_STAT_C_BH_RESET 0x0020
|
||||
#define USB_SS_PORT_STAT_C_LINK_STATE 0x0040
|
||||
#define USB_SS_PORT_STAT_C_CONFIG_ERROR 0x0080
|
||||
|
||||
/* wHubCharacteristics (masks) */
|
||||
#define HUB_CHAR_LPSM 0x0003
|
||||
#define HUB_CHAR_COMPOUND 0x0004
|
||||
#define HUB_CHAR_OCPM 0x0018
|
||||
#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */
|
||||
|
||||
/*
|
||||
* Hub Status & Hub Change bit masks
|
||||
*/
|
||||
#define HUB_STATUS_LOCAL_POWER 0x0001
|
||||
#define HUB_STATUS_OVERCURRENT 0x0002
|
||||
|
||||
#define HUB_CHANGE_LOCAL_POWER 0x0001
|
||||
#define HUB_CHANGE_OVERCURRENT 0x0002
|
||||
|
||||
/* Mask for wIndex in get/set port feature */
|
||||
#define USB_HUB_PORT_MASK 0xf
|
||||
|
||||
/* Hub class request codes */
|
||||
#define USB_REQ_SET_HUB_DEPTH 0x0c
|
||||
|
||||
/*
|
||||
* As of USB 2.0, full/low speed devices are segregated into trees.
|
||||
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
|
||||
* The other type grows from high speed hubs when they connect to
|
||||
* full/low speed devices using "Transaction Translators" (TTs).
|
||||
*/
|
||||
#if 0
|
||||
struct usb_tt {
|
||||
bool multi; /* true means one TT per port */
|
||||
unsigned think_time; /* think time in ns */
|
||||
};
|
||||
#else
|
||||
struct usb_device;
|
||||
struct usb_tt {
|
||||
struct usb_device *hub; /* upstream highspeed hub */
|
||||
int multi; /* true means one TT per port */
|
||||
unsigned think_time; /* think time in ns */
|
||||
void *hcpriv; /* HCD private data */
|
||||
|
||||
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
||||
spinlock_t lock;
|
||||
//struct list_head clear_list; /* of usb_tt_clear */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* CBI style
|
||||
*/
|
||||
|
||||
#define US_CBI_ADSC 0
|
||||
|
||||
/* Command Block Wrapper */
|
||||
struct umass_bbb_cbw {
|
||||
__u32 dCBWSignature;
|
||||
# define CBWSIGNATURE 0x43425355
|
||||
__u32 dCBWTag;
|
||||
__u32 dCBWDataTransferLength;
|
||||
__u8 bCBWFlags;
|
||||
# define CBWFLAGS_OUT 0x00
|
||||
# define CBWFLAGS_IN 0x80
|
||||
# define CBWFLAGS_SBZ 0x7f
|
||||
__u8 bCBWLUN;
|
||||
__u8 bCDBLength;
|
||||
# define CBWCDBLENGTH 16
|
||||
__u8 CBWCDB[CBWCDBLENGTH];
|
||||
};
|
||||
#define UMASS_BBB_CBW_SIZE 31
|
||||
|
||||
/* Command Status Wrapper */
|
||||
struct umass_bbb_csw {
|
||||
__u32 dCSWSignature;
|
||||
# define CSWSIGNATURE 0x53425355
|
||||
__u32 dCSWTag;
|
||||
__u32 dCSWDataResidue;
|
||||
__u8 bCSWStatus;
|
||||
# define CSWSTATUS_GOOD 0x0
|
||||
# define CSWSTATUS_FAILED 0x1
|
||||
# define CSWSTATUS_PHASE 0x2
|
||||
};
|
||||
#define UMASS_BBB_CSW_SIZE 13
|
||||
|
||||
/*
|
||||
* BULK only
|
||||
*/
|
||||
#define US_BBB_RESET 0xff
|
||||
#define US_BBB_GET_MAX_LUN 0xfe
|
||||
|
||||
#endif /*_USB_DEFS_H_ */
|
534
A27-STEPLDR/Src/usb/include/usbdescriptors.h
Normal file
534
A27-STEPLDR/Src/usb/include/usbdescriptors.h
Normal file
@ -0,0 +1,534 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Gerry Hamel, geh@ti.com, Texas Instruments
|
||||
*
|
||||
* Based on
|
||||
* linux/drivers/usbd/usb-function.h - USB Function
|
||||
*
|
||||
* Copyright (c) 2000, 2001, 2002 Lineo
|
||||
* Copyright (c) 2001 Hewlett Packard
|
||||
*
|
||||
* By:
|
||||
* Stuart Lynne <sl@lineo.com>,
|
||||
* Tom Rushworth <tbr@lineo.com>,
|
||||
* Bruce Balden <balden@lineo.com>
|
||||
*/
|
||||
|
||||
/* USB Descriptors - Create a complete description of all of the
|
||||
* function driver capabilities. These map directly to the USB descriptors.
|
||||
*
|
||||
* This heirarchy is created by the functions drivers and is passed to the
|
||||
* usb-device driver when the function driver is registered.
|
||||
*
|
||||
* device
|
||||
* configuration
|
||||
* interface
|
||||
* alternate
|
||||
* class
|
||||
* class
|
||||
* alternate
|
||||
* endpoint
|
||||
* endpoint
|
||||
* interface
|
||||
* alternate
|
||||
* endpoint
|
||||
* endpoint
|
||||
* configuration
|
||||
* interface
|
||||
* alternate
|
||||
* endpoint
|
||||
* endpoint
|
||||
*
|
||||
*
|
||||
* The configuration structures refer to the USB Configurations that will be
|
||||
* made available to a USB HOST during the enumeration process.
|
||||
*
|
||||
* The USB HOST will select a configuration and optionally an interface with
|
||||
* the usb set configuration and set interface commands.
|
||||
*
|
||||
* The selected interface (or the default interface if not specifically
|
||||
* selected) will define the list of endpoints that will be used.
|
||||
*
|
||||
* The configuration and interfaces are stored in an array that is indexed
|
||||
* by the specified configuratin or interface number minus one.
|
||||
*
|
||||
* A configuration number of zero is used to specify a return to the unconfigured
|
||||
* state.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __USBDESCRIPTORS_H__
|
||||
#define __USBDESCRIPTORS_H__
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
/*
|
||||
* communications class types
|
||||
*
|
||||
* c.f. CDC USB Class Definitions for Communications Devices
|
||||
* c.f. WMCD USB CDC Subclass Specification for Wireless Mobile Communications Devices
|
||||
*
|
||||
*/
|
||||
|
||||
#define CLASS_BCD_VERSION 0x0110
|
||||
|
||||
/* c.f. CDC 4.1 Table 14 */
|
||||
#define COMMUNICATIONS_DEVICE_CLASS 0x02
|
||||
|
||||
/* c.f. CDC 4.2 Table 15 */
|
||||
#define COMMUNICATIONS_INTERFACE_CLASS_CONTROL 0x02
|
||||
#define COMMUNICATIONS_INTERFACE_CLASS_DATA 0x0A
|
||||
#define COMMUNICATIONS_INTERFACE_CLASS_VENDOR 0x0FF
|
||||
|
||||
/* c.f. CDC 4.3 Table 16 */
|
||||
#define COMMUNICATIONS_NO_SUBCLASS 0x00
|
||||
#define COMMUNICATIONS_DLCM_SUBCLASS 0x01
|
||||
#define COMMUNICATIONS_ACM_SUBCLASS 0x02
|
||||
#define COMMUNICATIONS_TCM_SUBCLASS 0x03
|
||||
#define COMMUNICATIONS_MCCM_SUBCLASS 0x04
|
||||
#define COMMUNICATIONS_CCM_SUBCLASS 0x05
|
||||
#define COMMUNICATIONS_ENCM_SUBCLASS 0x06
|
||||
#define COMMUNICATIONS_ANCM_SUBCLASS 0x07
|
||||
|
||||
/* c.f. WMCD 5.1 */
|
||||
#define COMMUNICATIONS_WHCM_SUBCLASS 0x08
|
||||
#define COMMUNICATIONS_DMM_SUBCLASS 0x09
|
||||
#define COMMUNICATIONS_MDLM_SUBCLASS 0x0a
|
||||
#define COMMUNICATIONS_OBEX_SUBCLASS 0x0b
|
||||
|
||||
/* c.f. CDC 4.4 Table 17 */
|
||||
#define COMMUNICATIONS_NO_PROTOCOL 0x00
|
||||
#define COMMUNICATIONS_V25TER_PROTOCOL 0x01 /*Common AT Hayes compatible*/
|
||||
|
||||
/* c.f. CDC 4.5 Table 18 */
|
||||
#define DATA_INTERFACE_CLASS 0x0a
|
||||
|
||||
/* c.f. CDC 4.6 No Table */
|
||||
#define DATA_INTERFACE_SUBCLASS_NONE 0x00 /* No subclass pertinent */
|
||||
|
||||
/* c.f. CDC 4.7 Table 19 */
|
||||
#define DATA_INTERFACE_PROTOCOL_NONE 0x00 /* No class protcol required */
|
||||
|
||||
|
||||
/* c.f. CDC 5.2.3 Table 24 */
|
||||
#define CS_INTERFACE 0x24
|
||||
#define CS_ENDPOINT 0x25
|
||||
|
||||
/*
|
||||
* bDescriptorSubtypes
|
||||
*
|
||||
* c.f. CDC 5.2.3 Table 25
|
||||
* c.f. WMCD 5.3 Table 5.3
|
||||
*/
|
||||
|
||||
#define USB_ST_HEADER 0x00
|
||||
#define USB_ST_CMF 0x01
|
||||
#define USB_ST_ACMF 0x02
|
||||
#define USB_ST_DLMF 0x03
|
||||
#define USB_ST_TRF 0x04
|
||||
#define USB_ST_TCLF 0x05
|
||||
#define USB_ST_UF 0x06
|
||||
#define USB_ST_CSF 0x07
|
||||
#define USB_ST_TOMF 0x08
|
||||
#define USB_ST_USBTF 0x09
|
||||
#define USB_ST_NCT 0x0a
|
||||
#define USB_ST_PUF 0x0b
|
||||
#define USB_ST_EUF 0x0c
|
||||
#define USB_ST_MCMF 0x0d
|
||||
#define USB_ST_CCMF 0x0e
|
||||
#define USB_ST_ENF 0x0f
|
||||
#define USB_ST_ATMNF 0x10
|
||||
|
||||
#define USB_ST_WHCM 0x11
|
||||
#define USB_ST_MDLM 0x12
|
||||
#define USB_ST_MDLMD 0x13
|
||||
#define USB_ST_DMM 0x14
|
||||
#define USB_ST_OBEX 0x15
|
||||
#define USB_ST_CS 0x16
|
||||
#define USB_ST_CSD 0x17
|
||||
#define USB_ST_TCM 0x18
|
||||
|
||||
/* endpoint modifiers
|
||||
* static struct usb_endpoint_description function_default_A_1[] = {
|
||||
*
|
||||
* {this_endpoint: 0, attributes: CONTROL, max_size: 8, polling_interval: 0 },
|
||||
* {this_endpoint: 1, attributes: BULK, max_size: 64, polling_interval: 0, direction: IN},
|
||||
* {this_endpoint: 2, attributes: BULK, max_size: 64, polling_interval: 0, direction: OUT},
|
||||
* {this_endpoint: 3, attributes: INTERRUPT, max_size: 8, polling_interval: 0},
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define OUT 0x00
|
||||
#define IN 0x80
|
||||
|
||||
#define CONTROL 0x00
|
||||
#define ISOCHRONOUS 0x01
|
||||
#define BULK 0x02
|
||||
#define INTERRUPT 0x03
|
||||
|
||||
|
||||
/* configuration modifiers
|
||||
*/
|
||||
#define BMATTRIBUTE_RESERVED 0x80
|
||||
#define BMATTRIBUTE_SELF_POWERED 0x40
|
||||
|
||||
/*
|
||||
* standard usb descriptor structures
|
||||
*/
|
||||
|
||||
struct usb_endpoint_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType; /* 0x5 */
|
||||
u8 bEndpointAddress;
|
||||
u8 bmAttributes;
|
||||
u16 wMaxPacketSize;
|
||||
u8 bInterval;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_interface_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType; /* 0x04 */
|
||||
u8 bInterfaceNumber;
|
||||
u8 bAlternateSetting;
|
||||
u8 bNumEndpoints;
|
||||
u8 bInterfaceClass;
|
||||
u8 bInterfaceSubClass;
|
||||
u8 bInterfaceProtocol;
|
||||
u8 iInterface;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_configuration_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType; /* 0x2 */
|
||||
u16 wTotalLength;
|
||||
u8 bNumInterfaces;
|
||||
u8 bConfigurationValue;
|
||||
u8 iConfiguration;
|
||||
u8 bmAttributes;
|
||||
u8 bMaxPower;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_device_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType; /* 0x01 */
|
||||
u16 bcdUSB;
|
||||
u8 bDeviceClass;
|
||||
u8 bDeviceSubClass;
|
||||
u8 bDeviceProtocol;
|
||||
u8 bMaxPacketSize0;
|
||||
u16 idVendor;
|
||||
u16 idProduct;
|
||||
u16 bcdDevice;
|
||||
u8 iManufacturer;
|
||||
u8 iProduct;
|
||||
u8 iSerialNumber;
|
||||
u8 bNumConfigurations;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#if defined(CONFIG_USBD_HS)
|
||||
struct usb_qualifier_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
|
||||
u16 bcdUSB;
|
||||
u8 bDeviceClass;
|
||||
u8 bDeviceSubClass;
|
||||
u8 bDeviceProtocol;
|
||||
u8 bMaxPacketSize0;
|
||||
u8 bNumConfigurations;
|
||||
u8 breserved;
|
||||
} __attribute__ ((packed));
|
||||
#endif
|
||||
|
||||
struct usb_string_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType; /* 0x03 */
|
||||
u16 wData[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_generic_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*
|
||||
* communications class descriptor structures
|
||||
*
|
||||
* c.f. CDC 5.2 Table 25c
|
||||
*/
|
||||
|
||||
struct usb_class_function_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_function_descriptor_generic {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype;
|
||||
u8 bmCapabilities;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_header_function_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x00 */
|
||||
u16 bcdCDC;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_call_management_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x01 */
|
||||
u8 bmCapabilities;
|
||||
u8 bDataInterface;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_abstract_control_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x02 */
|
||||
u8 bmCapabilities;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_direct_line_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x03 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_telephone_ringer_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x04 */
|
||||
u8 bRingerVolSeps;
|
||||
u8 bNumRingerPatterns;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_telephone_call_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x05 */
|
||||
u8 bmCapabilities;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_union_function_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x06 */
|
||||
u8 bMasterInterface;
|
||||
/* u8 bSlaveInterface0[0]; */
|
||||
u8 bSlaveInterface0;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_country_selection_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x07 */
|
||||
u8 iCountryCodeRelDate;
|
||||
u16 wCountryCode0[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct usb_class_telephone_operational_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x08 */
|
||||
u8 bmCapabilities;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct usb_class_usb_terminal_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x09 */
|
||||
u8 bEntityId;
|
||||
u8 bInterfaceNo;
|
||||
u8 bOutInterfaceNo;
|
||||
u8 bmOptions;
|
||||
u8 bChild0[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_network_channel_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x0a */
|
||||
u8 bEntityId;
|
||||
u8 iName;
|
||||
u8 bChannelIndex;
|
||||
u8 bPhysicalInterface;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_protocol_unit_function_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x0b */
|
||||
u8 bEntityId;
|
||||
u8 bProtocol;
|
||||
u8 bChild0[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_extension_unit_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x0c */
|
||||
u8 bEntityId;
|
||||
u8 bExtensionCode;
|
||||
u8 iName;
|
||||
u8 bChild0[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_multi_channel_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x0d */
|
||||
u8 bmCapabilities;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_capi_control_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x0e */
|
||||
u8 bmCapabilities;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_ethernet_networking_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x0f */
|
||||
u8 iMACAddress;
|
||||
u32 bmEthernetStatistics;
|
||||
u16 wMaxSegmentSize;
|
||||
u16 wNumberMCFilters;
|
||||
u8 bNumberPowerFilters;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_atm_networking_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x10 */
|
||||
u8 iEndSystermIdentifier;
|
||||
u8 bmDataCapabilities;
|
||||
u8 bmATMDeviceStatistics;
|
||||
u16 wType2MaxSegmentSize;
|
||||
u16 wType3MaxSegmentSize;
|
||||
u16 wMaxVC;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct usb_class_mdlm_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x12 */
|
||||
u16 bcdVersion;
|
||||
u8 bGUID[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_mdlmd_descriptor {
|
||||
u8 bFunctionLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bDescriptorSubtype; /* 0x13 */
|
||||
u8 bGuidDescriptorType;
|
||||
u8 bDetailData[0];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* HID class descriptor structures
|
||||
*
|
||||
* c.f. HID 6.2.1
|
||||
*/
|
||||
|
||||
struct usb_class_hid_descriptor {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u16 bcdCDC;
|
||||
u8 bCountryCode;
|
||||
u8 bNumDescriptors; /* 0x01 */
|
||||
u8 bDescriptorType0;
|
||||
u16 wDescriptorLength0;
|
||||
/* optional descriptors are not supported. */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_class_report_descriptor {
|
||||
u8 bLength; /* dummy */
|
||||
u8 bDescriptorType;
|
||||
u16 wLength;
|
||||
u8 bData[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* descriptor union structures
|
||||
*/
|
||||
|
||||
struct usb_descriptor {
|
||||
union {
|
||||
struct usb_generic_descriptor generic;
|
||||
struct usb_endpoint_descriptor endpoint;
|
||||
struct usb_interface_descriptor interface;
|
||||
struct usb_configuration_descriptor configuration;
|
||||
struct usb_device_descriptor device;
|
||||
struct usb_string_descriptor string;
|
||||
} descriptor;
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_class_descriptor {
|
||||
union {
|
||||
struct usb_class_function_descriptor function;
|
||||
struct usb_class_function_descriptor_generic generic;
|
||||
struct usb_class_header_function_descriptor header_function;
|
||||
struct usb_class_call_management_descriptor call_management;
|
||||
struct usb_class_abstract_control_descriptor abstract_control;
|
||||
struct usb_class_direct_line_descriptor direct_line;
|
||||
struct usb_class_telephone_ringer_descriptor telephone_ringer;
|
||||
struct usb_class_telephone_operational_descriptor telephone_operational;
|
||||
struct usb_class_telephone_call_descriptor telephone_call;
|
||||
struct usb_class_union_function_descriptor union_function;
|
||||
struct usb_class_country_selection_descriptor country_selection;
|
||||
struct usb_class_usb_terminal_descriptor usb_terminal;
|
||||
struct usb_class_network_channel_descriptor network_channel;
|
||||
struct usb_class_extension_unit_descriptor extension_unit;
|
||||
struct usb_class_multi_channel_descriptor multi_channel;
|
||||
struct usb_class_capi_control_descriptor capi_control;
|
||||
struct usb_class_ethernet_networking_descriptor ethernet_networking;
|
||||
struct usb_class_atm_networking_descriptor atm_networking;
|
||||
struct usb_class_mdlm_descriptor mobile_direct;
|
||||
struct usb_class_mdlmd_descriptor mobile_direct_detail;
|
||||
struct usb_class_hid_descriptor hid;
|
||||
} descriptor;
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void print_device_descriptor(struct usb_device_descriptor *d)
|
||||
{
|
||||
serial_printf("usb device descriptor \n");
|
||||
serial_printf("\tbLength %2.2x\n", d->bLength);
|
||||
serial_printf("\tbDescriptorType %2.2x\n", d->bDescriptorType);
|
||||
serial_printf("\tbcdUSB %4.4x\n", d->bcdUSB);
|
||||
serial_printf("\tbDeviceClass %2.2x\n", d->bDeviceClass);
|
||||
serial_printf("\tbDeviceSubClass %2.2x\n", d->bDeviceSubClass);
|
||||
serial_printf("\tbDeviceProtocol %2.2x\n", d->bDeviceProtocol);
|
||||
serial_printf("\tbMaxPacketSize0 %2.2x\n", d->bMaxPacketSize0);
|
||||
serial_printf("\tidVendor %4.4x\n", d->idVendor);
|
||||
serial_printf("\tidProduct %4.4x\n", d->idProduct);
|
||||
serial_printf("\tbcdDevice %4.4x\n", d->bcdDevice);
|
||||
serial_printf("\tiManufacturer %2.2x\n", d->iManufacturer);
|
||||
serial_printf("\tiProduct %2.2x\n", d->iProduct);
|
||||
serial_printf("\tiSerialNumber %2.2x\n", d->iSerialNumber);
|
||||
serial_printf("\tbNumConfigurations %2.2x\n", d->bNumConfigurations);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* stubs */
|
||||
#define print_device_descriptor(d)
|
||||
|
||||
#endif /* DEBUG */
|
||||
#endif
|
777
A27-STEPLDR/Src/usb/include/usbdevice.h
Normal file
777
A27-STEPLDR/Src/usb/include/usbdevice.h
Normal file
@ -0,0 +1,777 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Gerry Hamel, geh@ti.com, Texas Instruments
|
||||
*
|
||||
* Based on linux/drivers/usbd/usbd.h
|
||||
*
|
||||
* Copyright (c) 2000, 2001, 2002 Lineo
|
||||
* Copyright (c) 2001 Hewlett Packard
|
||||
*
|
||||
* By:
|
||||
* Stuart Lynne <sl@lineo.com>,
|
||||
* Tom Rushworth <tbr@lineo.com>,
|
||||
* Bruce Balden <balden@lineo.com>
|
||||
*/
|
||||
|
||||
#ifndef __USBDCORE_H__
|
||||
#define __USBDCORE_H__
|
||||
|
||||
#include <common.h>
|
||||
#include "usbdescriptors.h"
|
||||
|
||||
|
||||
#define MAX_URBS_QUEUED 5
|
||||
|
||||
|
||||
#if 1
|
||||
#define usberr(fmt,args...) serial_printf("ERROR: %s(), %d: "fmt"\n",__FUNCTION__,__LINE__,##args)
|
||||
#else
|
||||
#define usberr(fmt,args...) do{}while(0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define usbdbg(fmt,args...) serial_printf("debug: %s(), %d: "fmt"\n",__FUNCTION__,__LINE__,##args)
|
||||
#else
|
||||
#define usbdbg(fmt,args...) do{}while(0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define usbinfo(fmt,args...) serial_printf("info: %s(), %d: "fmt"\n",__FUNCTION__,__LINE__,##args)
|
||||
#else
|
||||
#define usbinfo(fmt,args...) do{}while(0)
|
||||
#endif
|
||||
|
||||
#ifndef le16_to_cpu
|
||||
#define le16_to_cpu(x) (x)
|
||||
#endif
|
||||
|
||||
#ifndef inb
|
||||
#define inb(p) (*(volatile u8*)(p))
|
||||
#endif
|
||||
|
||||
#ifndef outb
|
||||
#define outb(val,p) (*(volatile u8*)(p) = (val))
|
||||
#endif
|
||||
|
||||
#ifndef inw
|
||||
#define inw(p) (*(volatile u16*)(p))
|
||||
#endif
|
||||
|
||||
#ifndef outw
|
||||
#define outw(val,p) (*(volatile u16*)(p) = (val))
|
||||
#endif
|
||||
|
||||
#ifndef inl
|
||||
#define inl(p) (*(volatile u32*)(p))
|
||||
#endif
|
||||
|
||||
#ifndef outl
|
||||
#define outl(val,p) (*(volatile u32*)(p) = (val))
|
||||
#endif
|
||||
|
||||
#ifndef insw
|
||||
#define insw(p,to,len) mmio_insw(p,to,len)
|
||||
#endif
|
||||
|
||||
#ifndef outsw
|
||||
#define outsw(p,from,len) mmio_outsw(p,from,len)
|
||||
#endif
|
||||
|
||||
#ifndef insb
|
||||
#define insb(p,to,len) mmio_insb(p,to,len)
|
||||
#endif
|
||||
|
||||
#ifndef mmio_insw
|
||||
#define mmio_insw(r,b,l) ({ int __i ; \
|
||||
u16 *__b2; \
|
||||
__b2 = (u16 *) b; \
|
||||
for (__i = 0; __i < l; __i++) { \
|
||||
*(__b2 + __i) = inw(r); \
|
||||
}; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef mmio_outsw
|
||||
#define mmio_outsw(r,b,l) ({ int __i; \
|
||||
u16 *__b2; \
|
||||
__b2 = (u16 *) b; \
|
||||
for (__i = 0; __i < l; __i++) { \
|
||||
outw( *(__b2 + __i), r); \
|
||||
} \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef mmio_insb
|
||||
#define mmio_insb(r,b,l) ({ int __i ; \
|
||||
u8 *__b2; \
|
||||
__b2 = (u8 *) b; \
|
||||
for (__i = 0; __i < l; __i++) { \
|
||||
*(__b2 + __i) = inb(r); \
|
||||
}; \
|
||||
})
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure member address manipulation macros.
|
||||
* These are used by client code (code using the urb_link routines), since
|
||||
* the urb_link structure is embedded in the client data structures.
|
||||
*
|
||||
* Note: a macro offsetof equivalent to member_offset is defined in stddef.h
|
||||
* but this is kept here for the sake of portability.
|
||||
*
|
||||
* p2surround returns a pointer to the surrounding structure given
|
||||
* type of the surrounding structure, the name memb of the structure
|
||||
* member pointed at by ptr. For example, if you have:
|
||||
*
|
||||
* struct foo {
|
||||
* int x;
|
||||
* float y;
|
||||
* char z;
|
||||
* } thingy;
|
||||
*
|
||||
* char *cp = &thingy.z;
|
||||
*
|
||||
* then
|
||||
*
|
||||
* &thingy == p2surround(struct foo, z, cp)
|
||||
*
|
||||
* Clear?
|
||||
*/
|
||||
#define _cv_(ptr) ((char*)(void*)(ptr))
|
||||
#define member_offset(type,memb) (_cv_(&(((type*)0)->memb))-(char*)0)
|
||||
#define p2surround(type,memb,ptr) ((type*)(void*)(_cv_(ptr)-member_offset(type,memb)))
|
||||
|
||||
struct urb;
|
||||
|
||||
struct usb_endpoint_instance;
|
||||
struct usb_interface_instance;
|
||||
struct usb_configuration_instance;
|
||||
struct usb_device_instance;
|
||||
struct usb_bus_instance;
|
||||
|
||||
/*
|
||||
* Device and/or Interface Class codes
|
||||
*/
|
||||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_COMM 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_PHYSICAL 5
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_DATA 10
|
||||
#define USB_CLASS_APP_SPEC 0xfe
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/*
|
||||
* USB types
|
||||
*/
|
||||
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
/*
|
||||
* USB recipients
|
||||
*/
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
|
||||
/*
|
||||
* USB directions
|
||||
*/
|
||||
#define USB_DIR_OUT 0
|
||||
#define USB_DIR_IN 0x80
|
||||
|
||||
/*
|
||||
* Descriptor types
|
||||
*/
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
|
||||
#if defined(CONFIG_USBD_HS)
|
||||
#define USB_DT_QUAL 0x06
|
||||
#endif
|
||||
|
||||
#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
|
||||
#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
|
||||
#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
|
||||
/*
|
||||
* Descriptor sizes per descriptor type
|
||||
*/
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
#define USB_DT_HID_SIZE 9
|
||||
|
||||
/*
|
||||
* Endpoints
|
||||
*/
|
||||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
||||
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||
|
||||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
|
||||
/*
|
||||
* USB Packet IDs (PIDs)
|
||||
*/
|
||||
#define USB_PID_UNDEF_0 0xf0
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
||||
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
||||
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
||||
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
||||
|
||||
/*
|
||||
* Standard requests
|
||||
*/
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
#define USBD_DEVICE_REQUESTS(x) (((unsigned int)x <= USB_REQ_SYNCH_FRAME) ? usbd_device_requests[x] : "UNKNOWN")
|
||||
|
||||
/*
|
||||
* HID requests
|
||||
*/
|
||||
#define USB_REQ_GET_REPORT 0x01
|
||||
#define USB_REQ_GET_IDLE 0x02
|
||||
#define USB_REQ_GET_PROTOCOL 0x03
|
||||
#define USB_REQ_SET_REPORT 0x09
|
||||
#define USB_REQ_SET_IDLE 0x0A
|
||||
#define USB_REQ_SET_PROTOCOL 0x0B
|
||||
|
||||
|
||||
/*
|
||||
* USB Spec Release number
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_USBD_HS)
|
||||
#define USB_BCD_VERSION 0x0200
|
||||
#else
|
||||
#define USB_BCD_VERSION 0x0110
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Device Requests (c.f Table 9-2)
|
||||
*/
|
||||
|
||||
#define USB_REQ_DIRECTION_MASK 0x80
|
||||
#define USB_REQ_TYPE_MASK 0x60
|
||||
#define USB_REQ_RECIPIENT_MASK 0x1f
|
||||
|
||||
#define USB_REQ_DEVICE2HOST 0x80
|
||||
#define USB_REQ_HOST2DEVICE 0x00
|
||||
|
||||
#define USB_REQ_TYPE_STANDARD 0x00
|
||||
#define USB_REQ_TYPE_CLASS 0x20
|
||||
#define USB_REQ_TYPE_VENDOR 0x40
|
||||
|
||||
#define USB_REQ_RECIPIENT_DEVICE 0x00
|
||||
#define USB_REQ_RECIPIENT_INTERFACE 0x01
|
||||
#define USB_REQ_RECIPIENT_ENDPOINT 0x02
|
||||
#define USB_REQ_RECIPIENT_OTHER 0x03
|
||||
|
||||
/*
|
||||
* get status bits
|
||||
*/
|
||||
|
||||
#define USB_STATUS_SELFPOWERED 0x01
|
||||
#define USB_STATUS_REMOTEWAKEUP 0x02
|
||||
|
||||
#define USB_STATUS_HALT 0x01
|
||||
|
||||
/*
|
||||
* descriptor types
|
||||
*/
|
||||
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE 0x01
|
||||
#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02
|
||||
#define USB_DESCRIPTOR_TYPE_STRING 0x03
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04
|
||||
#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08
|
||||
#define USB_DESCRIPTOR_TYPE_HID 0x21
|
||||
#define USB_DESCRIPTOR_TYPE_REPORT 0x22
|
||||
|
||||
#define USBD_DEVICE_DESCRIPTORS(x) (((unsigned int)x <= USB_DESCRIPTOR_TYPE_INTERFACE_POWER) ? \
|
||||
usbd_device_descriptors[x] : "UNKNOWN")
|
||||
|
||||
/*
|
||||
* standard feature selectors
|
||||
*/
|
||||
#define USB_ENDPOINT_HALT 0x00
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 0x01
|
||||
#define USB_TEST_MODE 0x02
|
||||
|
||||
|
||||
/* USB Requests
|
||||
*
|
||||
*/
|
||||
|
||||
struct usb_device_request {
|
||||
u8 bmRequestType;
|
||||
u8 bRequest;
|
||||
u16 wValue;
|
||||
u16 wIndex;
|
||||
u16 wLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* USB Status
|
||||
*
|
||||
*/
|
||||
typedef enum urb_send_status {
|
||||
SEND_IN_PROGRESS,
|
||||
SEND_FINISHED_OK,
|
||||
SEND_FINISHED_ERROR,
|
||||
RECV_READY,
|
||||
RECV_OK,
|
||||
RECV_ERROR
|
||||
} urb_send_status_t;
|
||||
|
||||
/*
|
||||
* Device State (c.f USB Spec 2.0 Figure 9-1)
|
||||
*
|
||||
* What state the usb device is in.
|
||||
*
|
||||
* Note the state does not change if the device is suspended, we simply set a
|
||||
* flag to show that it is suspended.
|
||||
*
|
||||
*/
|
||||
typedef enum usb_device_state {
|
||||
STATE_INIT, /* just initialized */
|
||||
STATE_CREATED, /* just created */
|
||||
STATE_ATTACHED, /* we are attached */
|
||||
STATE_POWERED, /* we have seen power indication (electrical bus signal) */
|
||||
STATE_DEFAULT, /* we been reset */
|
||||
STATE_ADDRESSED, /* we have been addressed (in default configuration) */
|
||||
STATE_CONFIGURED, /* we have seen a set configuration device command */
|
||||
STATE_UNKNOWN, /* destroyed */
|
||||
} usb_device_state_t;
|
||||
|
||||
#define USBD_DEVICE_STATE(x) (((unsigned int)x <= STATE_UNKNOWN) ? usbd_device_states[x] : "UNKNOWN")
|
||||
|
||||
/*
|
||||
* Device status
|
||||
*
|
||||
* Overall state
|
||||
*/
|
||||
typedef enum usb_device_status {
|
||||
USBD_OPENING, /* we are currently opening */
|
||||
USBD_OK, /* ok to use */
|
||||
USBD_SUSPENDED, /* we are currently suspended */
|
||||
USBD_CLOSING, /* we are currently closing */
|
||||
} usb_device_status_t;
|
||||
|
||||
#define USBD_DEVICE_STATUS(x) (((unsigned int)x <= USBD_CLOSING) ? usbd_device_status[x] : "UNKNOWN")
|
||||
|
||||
/*
|
||||
* Device Events
|
||||
*
|
||||
* These are defined in the USB Spec (c.f USB Spec 2.0 Figure 9-1).
|
||||
*
|
||||
* There are additional events defined to handle some extra actions we need
|
||||
* to have handled.
|
||||
*
|
||||
*/
|
||||
typedef enum usb_device_event {
|
||||
|
||||
DEVICE_UNKNOWN, /* bi - unknown event */
|
||||
DEVICE_INIT, /* bi - initialize */
|
||||
DEVICE_CREATE, /* bi - */
|
||||
DEVICE_HUB_CONFIGURED, /* bi - bus has been plugged int */
|
||||
DEVICE_RESET, /* bi - hub has powered our port */
|
||||
|
||||
DEVICE_ADDRESS_ASSIGNED, /* ep0 - set address setup received */
|
||||
DEVICE_CONFIGURED, /* ep0 - set configure setup received */
|
||||
DEVICE_SET_INTERFACE, /* ep0 - set interface setup received */
|
||||
|
||||
DEVICE_SET_FEATURE, /* ep0 - set feature setup received */
|
||||
DEVICE_CLEAR_FEATURE, /* ep0 - clear feature setup received */
|
||||
|
||||
DEVICE_DE_CONFIGURED, /* ep0 - set configure setup received for ?? */
|
||||
|
||||
DEVICE_BUS_INACTIVE, /* bi - bus in inactive (no SOF packets) */
|
||||
DEVICE_BUS_ACTIVITY, /* bi - bus is active again */
|
||||
|
||||
DEVICE_POWER_INTERRUPTION, /* bi - hub has depowered our port */
|
||||
DEVICE_HUB_RESET, /* bi - bus has been unplugged */
|
||||
DEVICE_DESTROY, /* bi - device instance should be destroyed */
|
||||
|
||||
DEVICE_HOTPLUG, /* bi - a hotplug event has occurred */
|
||||
|
||||
DEVICE_FUNCTION_PRIVATE, /* function - private */
|
||||
|
||||
} usb_device_event_t;
|
||||
|
||||
|
||||
typedef struct urb_link {
|
||||
struct urb_link *next;
|
||||
struct urb_link *prev;
|
||||
} urb_link;
|
||||
|
||||
/* USB Data structure - for passing data around.
|
||||
*
|
||||
* This is used for both sending and receiving data.
|
||||
*
|
||||
* The callback function is used to let the function driver know when
|
||||
* transmitted data has been sent.
|
||||
*
|
||||
* The callback function is set by the alloc_recv function when an urb is
|
||||
* allocated for receiving data for an endpoint and used to call the
|
||||
* function driver to inform it that data has arrived.
|
||||
*/
|
||||
|
||||
/* in linux we'd malloc this, but in u-boot we prefer static data */
|
||||
#define URB_BUF_SIZE 512
|
||||
|
||||
struct urb {
|
||||
|
||||
struct usb_endpoint_instance *endpoint;
|
||||
struct usb_device_instance *device;
|
||||
|
||||
struct usb_device_request device_request; /* contents of received SETUP packet */
|
||||
|
||||
struct urb_link link; /* embedded struct for circular doubly linked list of urbs */
|
||||
|
||||
u8* buffer;
|
||||
unsigned int buffer_length;
|
||||
unsigned int actual_length;
|
||||
|
||||
urb_send_status_t status;
|
||||
int data;
|
||||
|
||||
u16 buffer_data[URB_BUF_SIZE]; /* data received (OUT) or being sent (IN) */
|
||||
};
|
||||
|
||||
/* Endpoint configuration
|
||||
*
|
||||
* Per endpoint configuration data. Used to track which function driver owns
|
||||
* an endpoint.
|
||||
*
|
||||
*/
|
||||
struct usb_endpoint_instance {
|
||||
int endpoint_address; /* logical endpoint address */
|
||||
|
||||
/* control */
|
||||
int status; /* halted */
|
||||
int state; /* available for use by bus interface driver */
|
||||
|
||||
/* receive side */
|
||||
struct urb_link rcv; /* received urbs */
|
||||
struct urb_link rdy; /* empty urbs ready to receive */
|
||||
struct urb *rcv_urb; /* active urb */
|
||||
int rcv_attributes; /* copy of bmAttributes from endpoint descriptor */
|
||||
int rcv_packetSize; /* maximum packet size from endpoint descriptor */
|
||||
int rcv_transferSize; /* maximum transfer size from function driver */
|
||||
int rcv_queue;
|
||||
|
||||
/* transmit side */
|
||||
struct urb_link tx; /* urbs ready to transmit */
|
||||
struct urb_link done; /* transmitted urbs */
|
||||
struct urb *tx_urb; /* active urb */
|
||||
int tx_attributes; /* copy of bmAttributes from endpoint descriptor */
|
||||
int tx_packetSize; /* maximum packet size from endpoint descriptor */
|
||||
int tx_transferSize; /* maximum transfer size from function driver */
|
||||
int tx_queue;
|
||||
|
||||
int sent; /* data already sent */
|
||||
int last; /* data sent in last packet XXX do we need this */
|
||||
};
|
||||
|
||||
struct usb_alternate_instance {
|
||||
struct usb_interface_descriptor *interface_descriptor;
|
||||
|
||||
int endpoints;
|
||||
int *endpoint_transfersize_array;
|
||||
struct usb_endpoint_descriptor **endpoints_descriptor_array;
|
||||
};
|
||||
|
||||
struct usb_interface_instance {
|
||||
int alternates;
|
||||
struct usb_alternate_instance *alternates_instance_array;
|
||||
};
|
||||
|
||||
struct usb_configuration_instance {
|
||||
int interfaces;
|
||||
struct usb_configuration_descriptor *configuration_descriptor;
|
||||
struct usb_interface_instance *interface_instance_array;
|
||||
};
|
||||
|
||||
|
||||
/* USB Device Instance
|
||||
*
|
||||
* For each physical bus interface we create a logical device structure. This
|
||||
* tracks all of the required state to track the USB HOST's view of the device.
|
||||
*
|
||||
* Keep track of the device configuration for a real physical bus interface,
|
||||
* this includes the bus interface, multiple function drivers, the current
|
||||
* configuration and the current state.
|
||||
*
|
||||
* This will show:
|
||||
* the specific bus interface driver
|
||||
* the default endpoint 0 driver
|
||||
* the configured function driver
|
||||
* device state
|
||||
* device status
|
||||
* endpoint list
|
||||
*/
|
||||
|
||||
struct usb_device_instance {
|
||||
|
||||
/* generic */
|
||||
char *name;
|
||||
struct usb_device_descriptor *device_descriptor; /* per device descriptor */
|
||||
#if defined(CONFIG_USBD_HS)
|
||||
struct usb_qualifier_descriptor *qualifier_descriptor;
|
||||
#endif
|
||||
|
||||
void (*event) (struct usb_device_instance *device, usb_device_event_t event, int data);
|
||||
|
||||
/* Do cdc device specific control requests */
|
||||
int (*cdc_recv_setup)(struct usb_device_request *request, struct urb *urb);
|
||||
|
||||
/* bus interface */
|
||||
struct usb_bus_instance *bus; /* which bus interface driver */
|
||||
|
||||
/* configuration descriptors */
|
||||
int configurations;
|
||||
struct usb_configuration_instance *configuration_instance_array;
|
||||
|
||||
/* device state */
|
||||
usb_device_state_t device_state; /* current USB Device state */
|
||||
usb_device_state_t device_previous_state; /* current USB Device state */
|
||||
|
||||
u8 address; /* current address (zero is default) */
|
||||
u8 configuration; /* current show configuration (zero is default) */
|
||||
u8 interface; /* current interface (zero is default) */
|
||||
u8 alternate; /* alternate flag */
|
||||
|
||||
usb_device_status_t status; /* device status */
|
||||
|
||||
int urbs_queued; /* number of submitted urbs */
|
||||
|
||||
/* Shouldn't need to make this atomic, all we need is a change indicator */
|
||||
unsigned long usbd_rxtx_timestamp;
|
||||
unsigned long usbd_last_rxtx_timestamp;
|
||||
|
||||
};
|
||||
|
||||
/* Bus Interface configuration structure
|
||||
*
|
||||
* This is allocated for each configured instance of a bus interface driver.
|
||||
*
|
||||
* The privdata pointer may be used by the bus interface driver to store private
|
||||
* per instance state information.
|
||||
*/
|
||||
struct usb_bus_instance {
|
||||
|
||||
struct usb_device_instance *device;
|
||||
struct usb_endpoint_instance *endpoint_array; /* array of available configured endpoints */
|
||||
|
||||
int max_endpoints; /* maximimum number of rx enpoints */
|
||||
unsigned char maxpacketsize;
|
||||
|
||||
unsigned int serial_number;
|
||||
char *serial_number_str;
|
||||
void *privdata; /* private data for the bus interface */
|
||||
|
||||
};
|
||||
|
||||
extern char *usbd_device_events[];
|
||||
extern char *usbd_device_states[];
|
||||
extern char *usbd_device_status[];
|
||||
extern char *usbd_device_requests[];
|
||||
extern char *usbd_device_descriptors[];
|
||||
|
||||
void urb_link_init (urb_link * ul);
|
||||
void urb_detach (struct urb *urb);
|
||||
urb_link *first_urb_link (urb_link * hd);
|
||||
struct urb *first_urb (urb_link * hd);
|
||||
struct urb *first_urb_detached (urb_link * hd);
|
||||
void urb_append (urb_link * hd, struct urb *urb);
|
||||
|
||||
struct urb *usbd_alloc_urb (struct usb_device_instance *device, struct usb_endpoint_instance *endpoint);
|
||||
void usbd_dealloc_urb (struct urb *urb);
|
||||
|
||||
/*
|
||||
* usbd_device_event is used by bus interface drivers to tell the higher layers that
|
||||
* certain events have taken place.
|
||||
*/
|
||||
void usbd_device_event_irq (struct usb_device_instance *conf, usb_device_event_t, int);
|
||||
void usbd_device_event (struct usb_device_instance *conf, usb_device_event_t, int);
|
||||
|
||||
/* descriptors
|
||||
*
|
||||
* Various ways of finding descriptors based on the current device and any
|
||||
* possible configuration / interface / endpoint for it.
|
||||
*/
|
||||
struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct usb_device_instance *, int, int);
|
||||
struct usb_function_instance *usbd_device_function_instance (struct usb_device_instance *, unsigned int);
|
||||
struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *, int, int, int);
|
||||
struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *, int, int, int, int);
|
||||
struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance *, int, int, int, int);
|
||||
struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance *, int, int, int, int, int);
|
||||
struct usb_class_descriptor *usbd_device_class_descriptor_index (struct usb_device_instance *, int, int, int, int, int);
|
||||
struct usb_class_report_descriptor *usbd_device_class_report_descriptor_index( struct usb_device_instance *, int , int , int , int , int );
|
||||
struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *, int, int, int, int, int);
|
||||
int usbd_device_endpoint_transfersize (struct usb_device_instance *, int, int, int, int, int);
|
||||
struct usb_string_descriptor *usbd_get_string (u8);
|
||||
struct usb_device_descriptor *usbd_device_device_descriptor(struct
|
||||
usb_device_instance *, int);
|
||||
|
||||
#if defined(CONFIG_USBD_HS)
|
||||
/*
|
||||
* is_usbd_high_speed routine needs to be defined by specific gadget driver
|
||||
* It returns true if device enumerates at High speed
|
||||
* Retuns false otherwise
|
||||
*/
|
||||
int is_usbd_high_speed(void);
|
||||
#endif
|
||||
int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint);
|
||||
void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad);
|
||||
void usbd_tx_complete (struct usb_endpoint_instance *endpoint);
|
||||
|
||||
/* These are macros used in debugging */
|
||||
#ifdef DEBUG
|
||||
static inline void print_urb(struct urb *u)
|
||||
{
|
||||
serial_printf("urb %p\n", (u));
|
||||
serial_printf("\tendpoint %p\n", u->endpoint);
|
||||
serial_printf("\tdevice %p\n", u->device);
|
||||
serial_printf("\tbuffer %p\n", u->buffer);
|
||||
serial_printf("\tbuffer_length %d\n", u->buffer_length);
|
||||
serial_printf("\tactual_length %d\n", u->actual_length);
|
||||
serial_printf("\tstatus %d\n", u->status);
|
||||
serial_printf("\tdata %d\n", u->data);
|
||||
}
|
||||
|
||||
static inline void print_usb_device_request(struct usb_device_request *r)
|
||||
{
|
||||
serial_printf("usb request\n");
|
||||
serial_printf("\tbmRequestType 0x%2.2x\n", r->bmRequestType);
|
||||
if ((r->bmRequestType & USB_REQ_DIRECTION_MASK) == 0)
|
||||
serial_printf("\t\tDirection : To device\n");
|
||||
else
|
||||
serial_printf("\t\tDirection : To host\n");
|
||||
if ((r->bmRequestType & USB_TYPE_STANDARD) == USB_TYPE_STANDARD)
|
||||
serial_printf("\t\tType : Standard\n");
|
||||
if ((r->bmRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS)
|
||||
serial_printf("\t\tType : Standard\n");
|
||||
if ((r->bmRequestType & USB_TYPE_VENDOR) == USB_TYPE_VENDOR)
|
||||
serial_printf("\t\tType : Standard\n");
|
||||
if ((r->bmRequestType & USB_TYPE_RESERVED) == USB_TYPE_RESERVED)
|
||||
serial_printf("\t\tType : Standard\n");
|
||||
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
|
||||
USB_REQ_RECIPIENT_DEVICE)
|
||||
serial_printf("\t\tRecipient : Device\n");
|
||||
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
|
||||
USB_REQ_RECIPIENT_INTERFACE)
|
||||
serial_printf("\t\tRecipient : Interface\n");
|
||||
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
|
||||
USB_REQ_RECIPIENT_ENDPOINT)
|
||||
serial_printf("\t\tRecipient : Endpoint\n");
|
||||
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
|
||||
USB_REQ_RECIPIENT_OTHER)
|
||||
serial_printf("\t\tRecipient : Other\n");
|
||||
serial_printf("\tbRequest 0x%2.2x\n", r->bRequest);
|
||||
if (r->bRequest == USB_REQ_GET_STATUS)
|
||||
serial_printf("\t\tGET_STATUS\n");
|
||||
else if (r->bRequest == USB_REQ_SET_ADDRESS)
|
||||
serial_printf("\t\tSET_ADDRESS\n");
|
||||
else if (r->bRequest == USB_REQ_SET_FEATURE)
|
||||
serial_printf("\t\tSET_FEATURE\n");
|
||||
else if (r->bRequest == USB_REQ_GET_DESCRIPTOR)
|
||||
serial_printf("\t\tGET_DESCRIPTOR\n");
|
||||
else if (r->bRequest == USB_REQ_SET_CONFIGURATION)
|
||||
serial_printf("\t\tSET_CONFIGURATION\n");
|
||||
else if (r->bRequest == USB_REQ_SET_INTERFACE)
|
||||
serial_printf("\t\tUSB_REQ_SET_INTERFACE\n");
|
||||
else
|
||||
serial_printf("\tUNKNOWN %d\n", r->bRequest);
|
||||
serial_printf("\twValue 0x%4.4x\n", r->wValue);
|
||||
if (r->bRequest == USB_REQ_GET_DESCRIPTOR) {
|
||||
switch (r->wValue >> 8) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
serial_printf("\tDEVICE\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
serial_printf("\tCONFIGURATION\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_STRING:
|
||||
serial_printf("\tSTRING\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
serial_printf("\tINTERFACE\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_ENDPOINT:
|
||||
serial_printf("\tENDPOINT\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
serial_printf("\tDEVICE_QUALIFIER\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
|
||||
serial_printf("\tOTHER_SPEED_CONFIGURATION\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE_POWER:
|
||||
serial_printf("\tINTERFACE_POWER\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_HID:
|
||||
serial_printf("\tHID\n");
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_REPORT:
|
||||
serial_printf("\tREPORT\n");
|
||||
break;
|
||||
default:
|
||||
serial_printf("\tUNKNOWN TYPE\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
serial_printf("\twIndex 0x%4.4x\n", r->wIndex);
|
||||
serial_printf("\twLength 0x%4.4x\n", r->wLength);
|
||||
}
|
||||
#else
|
||||
/* stubs */
|
||||
#define print_urb(u)
|
||||
#define print_usb_device_request(r)
|
||||
#endif /* DEBUG */
|
||||
#endif
|
128
A27-STEPLDR/Src/usb/include/usbroothubdes.h
Normal file
128
A27-STEPLDR/Src/usb/include/usbroothubdes.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* USB virtual root hub descriptors
|
||||
*
|
||||
* (C) Copyright 2014
|
||||
* Stephen Warren swarren@wwwdotorg.org
|
||||
*
|
||||
* Based on ohci-hcd.c
|
||||
*/
|
||||
|
||||
#ifndef __USBROOTHUBDES_H__
|
||||
#define __USBROOTHUBDES_H__
|
||||
|
||||
/* Device descriptor */
|
||||
static __u8 root_hub_dev_des[] = {
|
||||
0x12, /* __u8 bLength; */
|
||||
0x01, /* __u8 bDescriptorType; Device */
|
||||
0x10, /* __u16 bcdUSB; v1.1 */
|
||||
0x01,
|
||||
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
|
||||
0x00, /* __u8 bDeviceSubClass; */
|
||||
0x00, /* __u8 bDeviceProtocol; */
|
||||
0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
|
||||
0x00, /* __u16 idVendor; */
|
||||
0x00,
|
||||
0x00, /* __u16 idProduct; */
|
||||
0x00,
|
||||
0x00, /* __u16 bcdDevice; */
|
||||
0x00,
|
||||
0x00, /* __u8 iManufacturer; */
|
||||
0x01, /* __u8 iProduct; */
|
||||
0x00, /* __u8 iSerialNumber; */
|
||||
0x01, /* __u8 bNumConfigurations; */
|
||||
};
|
||||
|
||||
/* Configuration descriptor */
|
||||
static __u8 root_hub_config_des[] = {
|
||||
0x09, /* __u8 bLength; */
|
||||
0x02, /* __u8 bDescriptorType; Configuration */
|
||||
0x19, /* __u16 wTotalLength; */
|
||||
0x00,
|
||||
0x01, /* __u8 bNumInterfaces; */
|
||||
0x01, /* __u8 bConfigurationValue; */
|
||||
0x00, /* __u8 iConfiguration; */
|
||||
0x40, /* __u8 bmAttributes;
|
||||
* Bit 7: Bus-powered
|
||||
* 6: Self-powered,
|
||||
* 5 Remote-wakwup,
|
||||
* 4..0: resvd
|
||||
*/
|
||||
0x00, /* __u8 MaxPower; */
|
||||
/* interface */
|
||||
0x09, /* __u8 if_bLength; */
|
||||
0x04, /* __u8 if_bDescriptorType; Interface */
|
||||
0x00, /* __u8 if_bInterfaceNumber; */
|
||||
0x00, /* __u8 if_bAlternateSetting; */
|
||||
0x01, /* __u8 if_bNumEndpoints; */
|
||||
0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
|
||||
0x00, /* __u8 if_bInterfaceSubClass; */
|
||||
0x00, /* __u8 if_bInterfaceProtocol; */
|
||||
0x00, /* __u8 if_iInterface; */
|
||||
/* endpoint */
|
||||
0x07, /* __u8 ep_bLength; */
|
||||
0x05, /* __u8 ep_bDescriptorType; Endpoint */
|
||||
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
|
||||
0x03, /* __u8 ep_bmAttributes; Interrupt */
|
||||
0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
|
||||
0x00,
|
||||
0xff, /* __u8 ep_bInterval; 255 ms */
|
||||
};
|
||||
|
||||
#ifdef WANT_USB_ROOT_HUB_HUB_DES
|
||||
static unsigned char root_hub_hub_des[] = {
|
||||
0x09, /* __u8 bLength; */
|
||||
0x29, /* __u8 bDescriptorType; Hub-descriptor */
|
||||
0x02, /* __u8 bNbrPorts; */
|
||||
0x00, /* __u16 wHubCharacteristics; */
|
||||
0x00,
|
||||
0x01, /* __u8 bPwrOn2pwrGood; 2ms */
|
||||
0x00, /* __u8 bHubContrCurrent; 0 mA */
|
||||
0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
|
||||
0xff, /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
|
||||
};
|
||||
#endif
|
||||
|
||||
static unsigned char root_hub_str_index0[] = {
|
||||
0x04, /* __u8 bLength; */
|
||||
0x03, /* __u8 bDescriptorType; String-descriptor */
|
||||
0x09, /* __u8 lang ID */
|
||||
0x04, /* __u8 lang ID */
|
||||
};
|
||||
|
||||
static unsigned char root_hub_str_index1[] = {
|
||||
32, /* __u8 bLength; */
|
||||
0x03, /* __u8 bDescriptorType; String-descriptor */
|
||||
'U', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'-', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'B', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'o', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'o', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
't', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
' ', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'R', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'o', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'o', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
't', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
' ', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'H', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'u', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
'b', /* __u8 Unicode */
|
||||
0, /* __u8 Unicode */
|
||||
};
|
||||
|
||||
#endif
|
382
A27-STEPLDR/Src/usb/params.c
Normal file
382
A27-STEPLDR/Src/usb/params.c
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2016 Synopsys, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <asm/dma-mapping.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "board.h"
|
||||
|
||||
/* static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->host_rx_fifo_size = 774;
|
||||
p->max_transfer_size = 65535;
|
||||
p->max_packet_count = 511;
|
||||
p->ahbcfg = 0x10;
|
||||
p->uframe_sched = false;
|
||||
}
|
||||
|
||||
static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
p->speed = DWC2_SPEED_PARAM_HIGH;
|
||||
p->host_rx_fifo_size = 512;
|
||||
p->host_nperio_tx_fifo_size = 512;
|
||||
p->host_perio_tx_fifo_size = 512;
|
||||
p->max_transfer_size = 65535;
|
||||
p->max_packet_count = 511;
|
||||
p->host_channels = 16;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
p->phy_utmi_width = 8;
|
||||
p->i2c_enable = false;
|
||||
p->reload_ctl = false;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
p->uframe_sched = false;
|
||||
p->change_speed_quirk = true;
|
||||
}
|
||||
|
||||
static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
p->host_rx_fifo_size = 525;
|
||||
p->host_nperio_tx_fifo_size = 128;
|
||||
p->host_perio_tx_fifo_size = 256;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
}
|
||||
|
||||
static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = 2;
|
||||
p->host_rx_fifo_size = 288;
|
||||
p->host_nperio_tx_fifo_size = 128;
|
||||
p->host_perio_tx_fifo_size = 96;
|
||||
p->max_transfer_size = 65535;
|
||||
p->max_packet_count = 511;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
}
|
||||
|
||||
static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
p->speed = DWC2_SPEED_PARAM_HIGH;
|
||||
p->host_rx_fifo_size = 512;
|
||||
p->host_nperio_tx_fifo_size = 500;
|
||||
p->host_perio_tx_fifo_size = 500;
|
||||
p->host_channels = 16;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
p->uframe_sched = false;
|
||||
}
|
||||
|
||||
static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT;
|
||||
}
|
||||
|
||||
static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
p->speed = DWC2_SPEED_PARAM_FULL;
|
||||
p->host_rx_fifo_size = 128;
|
||||
p->host_nperio_tx_fifo_size = 96;
|
||||
p->host_perio_tx_fifo_size = 96;
|
||||
p->max_packet_count = 256;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_FS;
|
||||
p->i2c_enable = false;
|
||||
p->uframe_sched = false;
|
||||
p->activate_stm_fs_transceiver = true;
|
||||
} */
|
||||
|
||||
static void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (hsotg->hw_params.op_mode) {
|
||||
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
|
||||
val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE;
|
||||
break;
|
||||
case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
|
||||
case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
|
||||
case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
|
||||
val = DWC2_CAP_PARAM_SRP_ONLY_CAPABLE;
|
||||
break;
|
||||
default:
|
||||
val = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
hsotg->params.otg_cap = val;
|
||||
}
|
||||
|
||||
static void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int val;
|
||||
u32 hs_phy_type = hsotg->hw_params.hs_phy_type;
|
||||
|
||||
val = DWC2_PHY_TYPE_PARAM_FS;
|
||||
if (hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED) {
|
||||
if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI ||
|
||||
hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)
|
||||
val = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
else
|
||||
val = DWC2_PHY_TYPE_PARAM_ULPI;
|
||||
}
|
||||
|
||||
if (dwc2_is_fs_iot(hsotg))
|
||||
hsotg->params.phy_type = DWC2_PHY_TYPE_PARAM_FS;
|
||||
|
||||
hsotg->params.phy_type = val;
|
||||
}
|
||||
|
||||
static void dwc2_set_param_speed(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS ?
|
||||
DWC2_SPEED_PARAM_FULL : DWC2_SPEED_PARAM_HIGH;
|
||||
|
||||
if (dwc2_is_fs_iot(hsotg))
|
||||
val = DWC2_SPEED_PARAM_FULL;
|
||||
|
||||
if (dwc2_is_hs_iot(hsotg))
|
||||
val = DWC2_SPEED_PARAM_HIGH;
|
||||
|
||||
hsotg->params.speed = val;
|
||||
}
|
||||
|
||||
static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = (hsotg->hw_params.utmi_phy_data_width ==
|
||||
GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16;
|
||||
|
||||
hsotg->params.phy_utmi_width = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_set_default_params() - Set all core parameters to their
|
||||
* auto-detected default values.
|
||||
*/
|
||||
static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_hw_params *hw = &hsotg->hw_params;
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
#ifdef USB_DMA
|
||||
bool dma_capable = !(hw->arch == GHWCFG2_SLAVE_ONLY_ARCH);
|
||||
#endif
|
||||
|
||||
dwc2_set_param_otg_cap(hsotg);
|
||||
dwc2_set_param_phy_type(hsotg);
|
||||
dwc2_set_param_speed(hsotg);
|
||||
dwc2_set_param_phy_utmi_width(hsotg);
|
||||
|
||||
p->enable_dynamic_fifo = hw->enable_dynamic_fifo;
|
||||
p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo;
|
||||
p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a);
|
||||
p->max_packet_count = hw->max_packet_count;
|
||||
p->max_transfer_size = hw->max_transfer_size;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT;
|
||||
|
||||
if ((hsotg->dr_mode == USB_DR_MODE_HOST) ||
|
||||
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
|
||||
p->host_channels = hw->host_channels;
|
||||
p->host_rx_fifo_size = hw->rx_fifo_size;
|
||||
p->host_nperio_tx_fifo_size = hw->host_nperio_tx_fifo_size;
|
||||
p->host_perio_tx_fifo_size = hw->host_perio_tx_fifo_size;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets host hardware parameters. Forces host mode if not currently in
|
||||
* host mode. Should be called immediately after a core soft reset in
|
||||
* order to get the reset values.
|
||||
*/
|
||||
static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_hw_params *hw = &hsotg->hw_params;
|
||||
u32 gnptxfsiz;
|
||||
u32 hptxfsiz;
|
||||
|
||||
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
|
||||
hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
|
||||
|
||||
hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
|
||||
FIFOSIZE_DEPTH_SHIFT;
|
||||
hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >>
|
||||
FIFOSIZE_DEPTH_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets device hardware parameters. Forces device mode if not
|
||||
* currently in device mode. Should be called immediately after a core
|
||||
* soft reset in order to get the reset values.
|
||||
*/
|
||||
static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_hw_params *hw = &hsotg->hw_params;
|
||||
u32 gnptxfsiz;
|
||||
|
||||
if (hsotg->dr_mode == USB_DR_MODE_HOST)
|
||||
return;
|
||||
|
||||
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
|
||||
|
||||
hw->dev_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
|
||||
FIFOSIZE_DEPTH_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* During device initialization, read various hardware configuration
|
||||
* registers and interpret the contents.
|
||||
*/
|
||||
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_hw_params *hw = &hsotg->hw_params;
|
||||
unsigned int width;
|
||||
u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4;
|
||||
u32 grxfsiz;
|
||||
|
||||
/*
|
||||
* Attempt to ensure this device is really a DWC_otg Controller.
|
||||
* Read and verify the GSNPSID register contents. The value should be
|
||||
* 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3",
|
||||
* as in "OTG version 2.xx" or "OTG version 3.xx".
|
||||
*/
|
||||
hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID);
|
||||
if ((hw->snpsid & 0xfffff000) != 0x4f542000 &&
|
||||
(hw->snpsid & 0xfffff000) != 0x4f543000 &&
|
||||
(hw->snpsid & 0xffff0000) != 0x55310000 &&
|
||||
(hw->snpsid & 0xffff0000) != 0x55320000) {
|
||||
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
|
||||
hw->snpsid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x (snpsid=%x)\n",
|
||||
hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
|
||||
hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
|
||||
|
||||
hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1);
|
||||
hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
|
||||
hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3);
|
||||
hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
|
||||
grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
|
||||
|
||||
/*
|
||||
* Host specific hardware parameters. Reading these parameters
|
||||
* requires the controller to be in host mode. The mode will
|
||||
* be forced, if necessary, to read these values.
|
||||
*/
|
||||
dwc2_get_host_hwparams(hsotg);
|
||||
dwc2_get_dev_hwparams(hsotg);
|
||||
|
||||
/* hwcfg1 */
|
||||
hw->dev_ep_dirs = hwcfg1;
|
||||
|
||||
/* hwcfg2 */
|
||||
hw->op_mode = (hwcfg2 & GHWCFG2_OP_MODE_MASK) >>
|
||||
GHWCFG2_OP_MODE_SHIFT;
|
||||
hw->arch = (hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >>
|
||||
GHWCFG2_ARCHITECTURE_SHIFT;
|
||||
hw->enable_dynamic_fifo = !!(hwcfg2 & GHWCFG2_DYNAMIC_FIFO);
|
||||
hw->host_channels = 1 + ((hwcfg2 & GHWCFG2_NUM_HOST_CHAN_MASK) >>
|
||||
GHWCFG2_NUM_HOST_CHAN_SHIFT);
|
||||
hw->hs_phy_type = (hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >>
|
||||
GHWCFG2_HS_PHY_TYPE_SHIFT;
|
||||
hw->fs_phy_type = (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
|
||||
GHWCFG2_FS_PHY_TYPE_SHIFT;
|
||||
hw->num_dev_ep = (hwcfg2 & GHWCFG2_NUM_DEV_EP_MASK) >>
|
||||
GHWCFG2_NUM_DEV_EP_SHIFT;
|
||||
hw->nperio_tx_q_depth =
|
||||
(hwcfg2 & GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK) >>
|
||||
GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT << 1;
|
||||
hw->host_perio_tx_q_depth =
|
||||
(hwcfg2 & GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK) >>
|
||||
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT << 1;
|
||||
hw->dev_token_q_depth =
|
||||
(hwcfg2 & GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK) >>
|
||||
GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT;
|
||||
|
||||
/* hwcfg3 */
|
||||
width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >>
|
||||
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
|
||||
hw->max_transfer_size = (1 << (width + 11)) - 1;
|
||||
width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >>
|
||||
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
|
||||
hw->max_packet_count = (1 << (width + 4)) - 1;
|
||||
hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >>
|
||||
GHWCFG3_DFIFO_DEPTH_SHIFT;
|
||||
|
||||
/* hwcfg4 */
|
||||
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
|
||||
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
|
||||
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
|
||||
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
|
||||
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
|
||||
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
|
||||
|
||||
/* fifo sizes */
|
||||
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
|
||||
GRXFSIZ_DEPTH_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dwc2_init_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
dwc2_set_default_params(hsotg);
|
||||
|
||||
return 0;
|
||||
}
|
176
A27-STEPLDR/Src/usb/platform.c
Normal file
176
A27-STEPLDR/Src/usb/platform.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* platform.c - DesignWare HS OTG Controller platform driver
|
||||
*
|
||||
* Copyright (C) Matthijs Kooijman <matthijs@stdin.nl>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <asm/dma-mapping.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include "core.h"
|
||||
#include "hcd.h"
|
||||
#include "amt630h.h"
|
||||
#include "aic.h"
|
||||
|
||||
static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
hsotg->dr_mode = USB_DR_MODE_HOST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//static QueueHandle_t usb_irq_queue;
|
||||
//static TaskHandle_t usb_irq_task;
|
||||
//static char first_irq = 1;
|
||||
|
||||
static void ark_usb_interrupt(void *param)
|
||||
{
|
||||
struct dwc2_hsotg *hsotg = (struct dwc2_hsotg *)param;
|
||||
//printf("ark_usb_interrupt\r\n");
|
||||
dwc2_handle_common_intr(hsotg->irq, param);
|
||||
dwc2_hcd_irq(hsotg);
|
||||
/*if (first_irq) {
|
||||
dwc2_hcd_irq(hsotg);
|
||||
first_irq = 0;
|
||||
} else {
|
||||
portDISABLE_INTERRUPTS();
|
||||
xQueueSendFromISR(usb_irq_queue, NULL, 0);
|
||||
}*/
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void usb_irq_task_proc(void *pvParameters)
|
||||
{
|
||||
struct dwc2_hsotg *hsotg = (struct dwc2_hsotg *)pvParameters;
|
||||
int ret = -1;
|
||||
|
||||
while(1) {
|
||||
ret = xQueueReceive(usb_irq_queue, NULL, portMAX_DELAY);
|
||||
|
||||
if (pdFALSE == ret) {
|
||||
continue;
|
||||
}
|
||||
//portENTER_CRITICAL();
|
||||
|
||||
dwc2_hcd_irq(hsotg);
|
||||
portENABLE_INTERRUPTS();
|
||||
//portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int dwc2_driver_init(struct dwc2_hsotg **dev, struct usb_hcd *hcd)
|
||||
{
|
||||
struct dwc2_hsotg *hsotg;
|
||||
int retval = -1;
|
||||
u32 size = sizeof(struct device);
|
||||
|
||||
hsotg = devm_kzalloc(NULL, sizeof(*hsotg), GFP_KERNEL);
|
||||
if (!hsotg)
|
||||
return -ENOMEM;
|
||||
|
||||
hsotg->dev = (struct device *)kzalloc(size, (__GFP_ZERO | GFP_KERNEL));
|
||||
if (NULL == hsotg->dev)
|
||||
goto error;
|
||||
|
||||
hsotg->phyif = GUSBCFG_PHYIF16;
|
||||
hsotg->regs = REGS_USB_BASE;
|
||||
|
||||
spin_lock_init(&(hsotg->lock));
|
||||
|
||||
hsotg->irq = USB_IRQn;
|
||||
retval = request_irq(hsotg->irq, 0, ark_usb_interrupt, (void*)hsotg);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
retval = dwc2_get_dr_mode(hsotg);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Reset before dwc2_get_hwparams() then it could get power-on real
|
||||
* reset value form registers.
|
||||
*/
|
||||
dwc2_core_reset_and_force_dr_mode(hsotg);
|
||||
|
||||
/* Detect config values from hardware */
|
||||
retval = dwc2_get_hwparams(hsotg);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
dwc2_force_dr_mode(hsotg);
|
||||
|
||||
retval = dwc2_init_params(hsotg);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
|
||||
//usb_irq_queue = xQueueCreate(1, 0);
|
||||
//xTaskCreate(usb_irq_task_proc, "usb_irq_proc", configMINIMAL_STACK_SIZE * 5, (void*)dev, configMAX_PRIORITIES, &usb_irq_task);
|
||||
retval = dwc2_hcd_init(hsotg, hcd);
|
||||
if (retval) {
|
||||
goto error;
|
||||
}
|
||||
hsotg->hcd_enabled = 1;
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
*dev = hsotg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (hsotg && hsotg->dev) {
|
||||
kfree(hsotg->dev);
|
||||
}
|
||||
if (hsotg) {
|
||||
kfree(hsotg);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int dwc2_driver_uninit(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
if (NULL == hsotg)
|
||||
return 0;
|
||||
if (hsotg->hcd_enabled)
|
||||
dwc2_hcd_remove(hsotg);
|
||||
|
||||
if (hsotg->dev)
|
||||
kfree(hsotg->dev);
|
||||
|
||||
kfree(hsotg);
|
||||
return 0;
|
||||
}
|
253
A27-STEPLDR/Src/usb/usb-compat.h
Normal file
253
A27-STEPLDR/Src/usb/usb-compat.h
Normal file
@ -0,0 +1,253 @@
|
||||
#ifndef __USB_COMPAT_H__
|
||||
#define __USB_COMPAT_H__
|
||||
|
||||
//#include <dm.h>
|
||||
#include "usb.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
struct usb_bus {
|
||||
int busnum; /* Bus number (in order of reg) */
|
||||
const char *bus_name; /* stable id (PCI slot_name etc) */
|
||||
u8 uses_dma; /* Does the host controller use DMA? */
|
||||
u8 uses_pio_for_control; /*
|
||||
* Does the host controller use PIO
|
||||
* for control transfers?
|
||||
*/
|
||||
u8 otg_port; /* 0, or number of OTG/HNP port */
|
||||
unsigned is_b_host:1; /* true during some HNP roleswitches */
|
||||
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
|
||||
unsigned no_stop_on_short:1; /*
|
||||
* Quirk: some controllers don't stop
|
||||
* the ep queue on a short transfer
|
||||
* with the URB_SHORT_NOT_OK flag set.
|
||||
*/
|
||||
unsigned no_sg_constraint:1; /* no sg constraint */
|
||||
unsigned sg_tablesize; /* 0 or largest number of sg list entries */
|
||||
|
||||
int devnum_next; /* Next open device number in
|
||||
* round-robin allocation */
|
||||
|
||||
int bandwidth_allocated; /* on this bus: how much of the time
|
||||
* reserved for periodic (intr/iso)
|
||||
* requests is used, on average?
|
||||
* Units: microseconds/frame.
|
||||
* Limits: Full/low speed reserve 90%,
|
||||
* while high speed reserves 80%.
|
||||
*/
|
||||
int bandwidth_int_reqs; /* number of Interrupt requests */
|
||||
int bandwidth_isoc_reqs; /* number of Isoc. requests */
|
||||
|
||||
unsigned resuming_ports; /* bit array: resuming root-hub ports */
|
||||
};
|
||||
|
||||
|
||||
struct usb_hcd {
|
||||
struct usb_bus self;
|
||||
int has_tt;
|
||||
void *hcd_priv;
|
||||
};
|
||||
|
||||
struct usb_host_endpoint {
|
||||
struct usb_endpoint_descriptor desc;
|
||||
List_t urb_list;
|
||||
void *hcpriv;
|
||||
};
|
||||
|
||||
/*
|
||||
* urb->transfer_flags:
|
||||
*
|
||||
* Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
|
||||
*/
|
||||
#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
|
||||
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
|
||||
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt*/
|
||||
|
||||
struct urb;
|
||||
|
||||
typedef void (*usb_complete_t)(struct urb *);
|
||||
|
||||
struct urb {
|
||||
void *hcpriv; /* private data for host controller */
|
||||
ListItem_t urb_list;
|
||||
int urb_complete;
|
||||
struct usb_device *dev; /* (in) pointer to associated device */
|
||||
struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
|
||||
unsigned int pipe; /* (in) pipe information */
|
||||
int status; /* (return) non-ISO status */
|
||||
unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
|
||||
void *transfer_buffer; /* (in) associated data buffer */
|
||||
dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
|
||||
u32 transfer_buffer_length; /* (in) data buffer length */
|
||||
u32 actual_length; /* (return) actual transfer length */
|
||||
unsigned char *setup_packet; /* (in) setup packet (control only) */
|
||||
dma_addr_t setup_dma;
|
||||
int start_frame; /* (modify) start frame (ISO) */
|
||||
void *context;
|
||||
usb_complete_t complete; /* (in) completion routine */
|
||||
int interval;
|
||||
|
||||
int error_count; /* (return) number of ISO errors */
|
||||
int number_of_packets; /* (in) number of ISO packets */
|
||||
};
|
||||
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
const char *product_desc; /* product/vendor string */
|
||||
size_t hcd_priv_size; /* size of private data */
|
||||
|
||||
/* irq handler */
|
||||
irqreturn_t (*irq) (struct usb_hcd *hcd);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */
|
||||
#define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
#define HCD_USB25 0x0030 /* Wireless USB 1.0 (USB 2.5)*/
|
||||
#define HCD_USB3 0x0040 /* USB 3.0 */
|
||||
#define HCD_USB31 0x0050 /* USB 3.1 */
|
||||
#define HCD_MASK 0x0070
|
||||
#define HCD_BH 0x0100 /* URB complete in BH context */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue)(struct usb_hcd *hcd,
|
||||
struct urb *urb, gfp_t mem_flags);
|
||||
int (*urb_dequeue)(struct usb_hcd *hcd,
|
||||
struct urb *urb, int status);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *ep);
|
||||
|
||||
/* (optional) reset any endpoint state such as sequence number
|
||||
and current window */
|
||||
void (*endpoint_reset)(struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *ep);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
};
|
||||
|
||||
#define usb_hcd_link_urb_to_ep(hcd, urb) do { \
|
||||
list_add_tail(&urb->urb_list, &urb->ep->urb_list); \
|
||||
} while(0)
|
||||
|
||||
#define usb_hcd_unlink_urb_from_ep(hcd, urb) list_del_init(&urb->urb_list)
|
||||
#define usb_hcd_check_unlink_urb(hdc, urb, status) 0
|
||||
|
||||
static inline void usb_hcd_giveback_urb(struct usb_hcd *hcd,
|
||||
struct urb *urb,
|
||||
int status)
|
||||
{
|
||||
urb->status = status;
|
||||
if (urb->complete)
|
||||
urb->complete(urb);
|
||||
}
|
||||
|
||||
static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
|
||||
struct urb *urb)
|
||||
{
|
||||
/* TODO: add cache invalidation here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd)
|
||||
{
|
||||
return &hcd->self;
|
||||
}
|
||||
|
||||
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
|
||||
{
|
||||
(void)hcd;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic bandwidth allocation constants/support
|
||||
*/
|
||||
#define FRAME_TIME_USECS 1000L
|
||||
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
|
||||
/* Trying not to use worst-case bit-stuffing
|
||||
* of (7/6 * 8 * bytecount) = 9.33 * bytecount */
|
||||
/* bytecount = data payload byte count */
|
||||
|
||||
#define NS_TO_US(ns) DIV_ROUND_UP(ns, 1000L)
|
||||
/* convert nanoseconds to microseconds, rounding up */
|
||||
|
||||
/*
|
||||
* Full/low speed bandwidth allocation constants/support.
|
||||
*/
|
||||
#define BW_HOST_DELAY 1000L /* nanoseconds */
|
||||
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
|
||||
/* 4 full-speed bit times (est.) */
|
||||
|
||||
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
|
||||
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
|
||||
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
|
||||
|
||||
/*
|
||||
* Ceiling [nano/micro]seconds (typical) for that many bytes at high speed
|
||||
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
|
||||
* to preallocate bandwidth)
|
||||
*/
|
||||
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
||||
#define HS_NSECS(bytes) (((55 * 8 * 2083) \
|
||||
+ (2083UL * (3 + BitTime(bytes))))/1000 \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \
|
||||
+ (2083UL * (3 + BitTime(bytes))))/1000 \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_USECS(bytes) NS_TO_US(HS_NSECS(bytes))
|
||||
#define HS_USECS_ISO(bytes) NS_TO_US(HS_NSECS_ISO(bytes))
|
||||
|
||||
#ifdef CONFIG_DM_USB
|
||||
static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
|
||||
{
|
||||
struct udevice *parent = udev->dev->parent;
|
||||
|
||||
/*
|
||||
* When called from usb-uclass.c: usb_scan_device() udev->dev points
|
||||
* to the parent udevice, not the actual udevice belonging to the
|
||||
* udev as the device is not instantiated yet.
|
||||
*
|
||||
* If dev is an usb-bus, then we are called from usb_scan_device() for
|
||||
* an usb-device plugged directly into the root port, return NULL.
|
||||
*/
|
||||
if (device_get_uclass_id(udev->dev) == UCLASS_USB)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If these 2 are not the same we are being called from
|
||||
* usb_scan_device() and udev itself is the parent.
|
||||
*/
|
||||
if (dev_get_parent_priv(udev->dev) != udev)
|
||||
return udev;
|
||||
|
||||
/* We are being called normally, use the parent pointer */
|
||||
if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
|
||||
return dev_get_parent_priv(parent);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static inline struct usb_device *usb_dev_get_parent(struct usb_device *dev)
|
||||
{
|
||||
return dev->parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_COMPAT_H__ */
|
1705
A27-STEPLDR/Src/usb/usb.c
Normal file
1705
A27-STEPLDR/Src/usb/usb.c
Normal file
File diff suppressed because it is too large
Load Diff
847
A27-STEPLDR/Src/usb/usb_massstorage.c
Normal file
847
A27-STEPLDR/Src/usb/usb_massstorage.c
Normal file
@ -0,0 +1,847 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONFIG_USB_STORAGE
|
||||
|
||||
#include "usb_os_adapter.h"
|
||||
#include "trace.h"
|
||||
#include <linux/usb/ch9.h>
|
||||
#include "scsi.h"
|
||||
#include "usb.h"
|
||||
#include "dwc2_compat.h"
|
||||
#include <linux/errno.h>
|
||||
#include "ark_dwc2.h"
|
||||
#include "usb_massstorage.h"
|
||||
#include "timer.h"
|
||||
#include "fs/ff.h"
|
||||
#include "fs/diskio.h"
|
||||
|
||||
/* direction table -- this indicates the direction of the data
|
||||
* transfer for each command code -- a 1 indicates input
|
||||
*/
|
||||
static const unsigned char us_direction[256/8] = {
|
||||
0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
|
||||
0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
|
||||
|
||||
#pragma pack(ARCH_DMA_MINALIGN)
|
||||
static struct scsi_cmd usb_ccb;
|
||||
static u32 CBWTag;
|
||||
|
||||
static int usb_max_devs; /* number of highest available usb device */
|
||||
|
||||
struct blk_desc usb_dev_desc[6];
|
||||
|
||||
struct us_data;
|
||||
typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
|
||||
typedef int (*trans_reset)(struct us_data *data);
|
||||
|
||||
#define USB_READY (1 << 0)
|
||||
struct us_data {
|
||||
struct usb_device *pusb_dev; /* this usb_device */
|
||||
unsigned int flags; /* from filter initially */
|
||||
unsigned char ifnum; /* interface number */
|
||||
unsigned char ep_in; /* in endpoint */
|
||||
unsigned char ep_out; /* out ....... */
|
||||
unsigned char ep_int; /* interrupt . */
|
||||
unsigned char subclass; /* as in overview */
|
||||
unsigned char protocol; /* .............. */
|
||||
unsigned char attention_done; /* force attn on first cmd */
|
||||
unsigned short ip_data; /* interrupt data */
|
||||
int action; /* what to do */
|
||||
int ip_wanted; /* needed */
|
||||
int *irq_handle; /* for USB int requests */
|
||||
unsigned int irqpipe; /* pipe for release_irq */
|
||||
unsigned char irqmaxp; /* max packed for irq Pipe */
|
||||
unsigned char irqinterval; /* Intervall for IRQ Pipe */
|
||||
struct scsi_cmd *srb; /* current srb */
|
||||
trans_reset transport_reset; /* reset routine */
|
||||
trans_cmnd transport; /* transport routine */
|
||||
unsigned short max_xfer_blk; /* maximum transfer blocks */
|
||||
};
|
||||
|
||||
static struct us_data usb_stor[USB_MAX_STOR_DEV];
|
||||
|
||||
#define USB_STOR_TRANSPORT_GOOD 0
|
||||
#define USB_STOR_TRANSPORT_FAILED -1
|
||||
#define USB_STOR_TRANSPORT_ERROR -2
|
||||
|
||||
static int usb_media_ready = 0;
|
||||
|
||||
/***********************************************************************
|
||||
* Data transfer routines
|
||||
***********************************************************************/
|
||||
|
||||
static unsigned int usb_get_max_lun(struct us_data *us)
|
||||
{
|
||||
int len;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
|
||||
len = usb_control_msg(us->pusb_dev,
|
||||
usb_rcvctrlpipe(us->pusb_dev, 0),
|
||||
US_BBB_GET_MAX_LUN,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||
0, us->ifnum,
|
||||
result, sizeof(char),
|
||||
USB_CNTL_TIMEOUT * 5);
|
||||
//debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
|
||||
return (len > 0) ? *result : 0;
|
||||
}
|
||||
|
||||
static int usb_stor_BBB_reset(struct us_data *us)
|
||||
{
|
||||
int result;
|
||||
unsigned int pipe;
|
||||
|
||||
/*
|
||||
* Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
|
||||
*
|
||||
* For Reset Recovery the host shall issue in the following order:
|
||||
* a) a Bulk-Only Mass Storage Reset
|
||||
* b) a Clear Feature HALT to the Bulk-In endpoint
|
||||
* c) a Clear Feature HALT to the Bulk-Out endpoint
|
||||
*
|
||||
* This is done in 3 steps.
|
||||
*
|
||||
* If the reset doesn't succeed, the device should be port reset.
|
||||
*
|
||||
* This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
|
||||
*/
|
||||
//debug("BBB_reset\n");
|
||||
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
|
||||
US_BBB_RESET,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
|
||||
|
||||
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
//debug("RESET:stall\n");
|
||||
return -1;
|
||||
}
|
||||
if (usb_media_ready == 0)
|
||||
return -1;
|
||||
|
||||
/* long wait for reset */
|
||||
mdelay(150);
|
||||
/* debug("BBB_reset result %d: status %lX reset\n",
|
||||
result, us->pusb_dev->status); */
|
||||
pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
|
||||
result = usb_clear_halt(us->pusb_dev, pipe);
|
||||
/* long wait for reset */
|
||||
mdelay(150);
|
||||
/* debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
|
||||
result, us->pusb_dev->status); */
|
||||
/* long wait for reset */
|
||||
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
|
||||
result = usb_clear_halt(us->pusb_dev, pipe);
|
||||
mdelay(150);
|
||||
/* debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
|
||||
result, us->pusb_dev->status);
|
||||
debug("BBB_reset done\n"); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the command for a BBB device. Note that the actual SCSI
|
||||
* command is copied into cbw.CBWCDB.
|
||||
*/
|
||||
static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
|
||||
{
|
||||
int result;
|
||||
int actlen;
|
||||
int dir_in;
|
||||
unsigned int pipe;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
|
||||
|
||||
dir_in = US_DIRECTION(srb->cmd[0]);
|
||||
|
||||
/* sanity checks */
|
||||
if (!(srb->cmdlen <= CBWCDBLENGTH)) {
|
||||
//debug("usb_stor_BBB_comdat:cmdlen too large\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* always OUT to the ep */
|
||||
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
|
||||
|
||||
cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
|
||||
cbw->dCBWTag = cpu_to_le32(CBWTag++);
|
||||
cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
|
||||
cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
|
||||
cbw->bCBWLUN = srb->lun;
|
||||
cbw->bCDBLength = srb->cmdlen;
|
||||
/* copy the command data into the CBW command data buffer */
|
||||
/* DST SRC LEN!!! */
|
||||
|
||||
memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
|
||||
&actlen, USB_CNTL_TIMEOUT * 5);
|
||||
if (result < 0)
|
||||
;//debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
#define USB_TRANSPORT_UNKNOWN_RETRY 5
|
||||
#define USB_TRANSPORT_NOT_READY_RETRY 10
|
||||
|
||||
/* clear a stall on an endpoint - special for BBB devices */
|
||||
static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, u8 endpt)
|
||||
{
|
||||
/* ENDPOINT_HALT = 0, so set value to 0 */
|
||||
return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
|
||||
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
|
||||
endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
|
||||
}
|
||||
|
||||
static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
|
||||
{
|
||||
int result, retry;
|
||||
int dir_in;
|
||||
int actlen, data_actlen;
|
||||
unsigned int pipe, pipein, pipeout;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
|
||||
|
||||
dir_in = US_DIRECTION(srb->cmd[0]);
|
||||
|
||||
/* COMMAND phase */
|
||||
//debug("COMMAND phase\n");
|
||||
result = usb_stor_BBB_comdat(srb, us);
|
||||
if (result < 0) {
|
||||
/* debug("failed to send CBW status %ld\n",
|
||||
us->pusb_dev->status); */
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
}
|
||||
if (!(us->flags & USB_READY))
|
||||
mdelay(5);
|
||||
pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
|
||||
pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
|
||||
/* DATA phase + error handling */
|
||||
data_actlen = 0;
|
||||
/* no data, go immediately to the STATUS phase */
|
||||
if (srb->datalen == 0)
|
||||
goto st;
|
||||
//debug("DATA phase\n");
|
||||
if (dir_in)
|
||||
pipe = pipein;
|
||||
else
|
||||
pipe = pipeout;
|
||||
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
|
||||
&data_actlen, USB_CNTL_TIMEOUT * 5);
|
||||
|
||||
/* special handling of STALL in DATA phase */
|
||||
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
//debug("DATA:stall\n");
|
||||
/* clear the STALL on the endpoint */
|
||||
result = usb_stor_BBB_clear_endpt_stall(us,
|
||||
dir_in ? us->ep_in : us->ep_out);
|
||||
if (result >= 0)
|
||||
/* continue on to STATUS phase */
|
||||
goto st;
|
||||
}
|
||||
if (result < 0) {
|
||||
/* debug("usb_bulk_msg error status %ld\n",
|
||||
us->pusb_dev->status); */
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
}
|
||||
|
||||
/* STATUS phase + error handling */
|
||||
char *tmpcsw;
|
||||
st:
|
||||
retry = 0;
|
||||
again:
|
||||
//debug("STATUS phase\n");
|
||||
tmpcsw = (char *)csw;
|
||||
tmpcsw[0] = 0x55;
|
||||
tmpcsw[1] = 0x53;
|
||||
tmpcsw[2] = 0x42;
|
||||
tmpcsw[3] = 0x43;
|
||||
tmpcsw[4] = 0x01;
|
||||
tmpcsw[5] = 0x00;
|
||||
tmpcsw[6] = 0x00;
|
||||
tmpcsw[7] = 0x00;
|
||||
tmpcsw[8] = 0x24;
|
||||
tmpcsw[9] = 0x00;
|
||||
tmpcsw[10] = 0x00;
|
||||
tmpcsw[11] = 0x00;
|
||||
tmpcsw[12] = 0x80;
|
||||
|
||||
|
||||
result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
|
||||
&actlen, USB_CNTL_TIMEOUT);
|
||||
|
||||
/* special handling of STALL in STATUS phase */
|
||||
if ((result < 0) && (retry < 1) &&
|
||||
(us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
//debug("STATUS:stall\n");
|
||||
/* clear the STALL on the endpoint */
|
||||
result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
|
||||
if (result >= 0 && (retry++ < 1))
|
||||
/* do a retry */
|
||||
goto again;
|
||||
}
|
||||
if (result < 0) {
|
||||
/* debug("usb_bulk_msg error status %ld\n",
|
||||
us->pusb_dev->status); */
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
}
|
||||
|
||||
/* misuse pipe to get the residue */
|
||||
pipe = le32_to_cpu(csw->dCSWDataResidue);
|
||||
if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
|
||||
pipe = srb->datalen - data_actlen;
|
||||
if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
|
||||
//debug("!CSWSIGNATURE\n");
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
|
||||
//debug("!Tag\n");
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
|
||||
//debug(">PHASE\n");
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
|
||||
//debug("=PHASE\n");
|
||||
usb_stor_BBB_reset(us);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else if (data_actlen > srb->datalen) {
|
||||
/* debug("transferred %dB instead of %ldB\n",
|
||||
data_actlen, srb->datalen); */
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
|
||||
//debug("FAILED\n");
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int usb_stor_irq(struct usb_device *dev)
|
||||
{
|
||||
struct us_data *us;
|
||||
us = (struct us_data *)dev->privptr;
|
||||
|
||||
if (us->ip_wanted)
|
||||
us->ip_wanted = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
|
||||
struct us_data *us)
|
||||
{
|
||||
unsigned short blk = 20;
|
||||
|
||||
us->max_xfer_blk = blk;
|
||||
}
|
||||
|
||||
static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
|
||||
{
|
||||
int retry, i;
|
||||
retry = 5;
|
||||
do {
|
||||
memset(&srb->cmd[0], 0, 12);
|
||||
srb->cmd[0] = SCSI_INQUIRY;
|
||||
srb->cmd[1] = srb->lun << 5;
|
||||
srb->cmd[4] = 36;
|
||||
srb->datalen = 36;
|
||||
srb->cmdlen = 12;
|
||||
i = ss->transport(srb, ss);
|
||||
//debug("inquiry returns %d\n", i);
|
||||
if (i == 0)
|
||||
break;
|
||||
} while (--retry);
|
||||
|
||||
if (!retry) {
|
||||
//printf("error in inquiry\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
|
||||
{
|
||||
char *ptr;
|
||||
int ret = -1;
|
||||
|
||||
ptr = (char *)srb->pdata;
|
||||
memset(&srb->cmd[0], 0, 12);
|
||||
srb->cmd[0] = SCSI_REQ_SENSE;
|
||||
srb->cmd[1] = srb->lun << 5;
|
||||
srb->cmd[4] = 18;
|
||||
srb->datalen = 18;
|
||||
srb->pdata = &srb->sense_buf[0];
|
||||
srb->cmdlen = 12;
|
||||
ret = ss->transport(srb, ss);
|
||||
/* debug("Request Sense returned %02X %02X %02X\n",
|
||||
srb->sense_buf[2], srb->sense_buf[12],
|
||||
srb->sense_buf[13]); */
|
||||
srb->pdata = (unsigned char *)ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
|
||||
{
|
||||
int retries = 10;
|
||||
int ret = -1;
|
||||
|
||||
do {
|
||||
memset(&srb->cmd[0], 0, 12);
|
||||
srb->cmd[0] = SCSI_TST_U_RDY;
|
||||
srb->cmd[1] = srb->lun << 5;
|
||||
srb->datalen = 0;
|
||||
srb->cmdlen = 12;
|
||||
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
|
||||
ss->flags |= USB_READY;
|
||||
return 0;
|
||||
}
|
||||
ret = usb_request_sense(srb, ss);
|
||||
if (ret != USB_STOR_TRANSPORT_GOOD)
|
||||
break;
|
||||
/*
|
||||
* Check the Key Code Qualifier, if it matches
|
||||
* "Not Ready - medium not present"
|
||||
* (the sense Key equals 0x2 and the ASC is 0x3a)
|
||||
* return immediately as the medium being absent won't change
|
||||
* unless there is a user action.
|
||||
*/
|
||||
if ((srb->sense_buf[2] == 0x02) &&
|
||||
(srb->sense_buf[12] == 0x3a))
|
||||
return -1;
|
||||
if (usb_media_ready == 0)
|
||||
break;
|
||||
mdelay(100);
|
||||
} while (retries--);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
|
||||
{
|
||||
int retry;
|
||||
/* XXX retries */
|
||||
retry = 3;
|
||||
do {
|
||||
memset(&srb->cmd[0], 0, 12);
|
||||
srb->cmd[0] = SCSI_RD_CAPAC;
|
||||
srb->cmd[1] = srb->lun << 5;
|
||||
srb->datalen = 8;
|
||||
srb->cmdlen = 12;
|
||||
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
||||
return 0;
|
||||
} while (retry--);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
|
||||
unsigned long start, unsigned short blocks)
|
||||
{
|
||||
memset(&srb->cmd[0], 0, 12);
|
||||
srb->cmd[0] = SCSI_READ10;
|
||||
srb->cmd[1] = srb->lun << 5;
|
||||
srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
|
||||
srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
|
||||
srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
|
||||
srb->cmd[5] = ((unsigned char) (start)) & 0xff;
|
||||
srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
|
||||
srb->cmd[8] = (unsigned char) blocks & 0xff;
|
||||
srb->cmdlen = 12;
|
||||
//debug("read10: start %lx blocks %x\n", start, blocks);
|
||||
return ss->transport(srb, ss);
|
||||
}
|
||||
|
||||
/* Probe to see if a new device is actually a Storage device */
|
||||
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
|
||||
struct us_data *ss)
|
||||
{
|
||||
struct usb_interface *iface;
|
||||
int i;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
unsigned int flags = 0;
|
||||
|
||||
/* let's examine the device now */
|
||||
iface = &dev->config.if_desc[ifnum];
|
||||
if (dev->descriptor.bDeviceClass != 0 ||
|
||||
iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
|
||||
iface->desc.bInterfaceSubClass < US_SC_MIN ||
|
||||
iface->desc.bInterfaceSubClass > US_SC_MAX) {
|
||||
//SendUartString("Not mass storage\r\n");
|
||||
/* if it's not a mass storage, we go no further */
|
||||
return 0;
|
||||
}
|
||||
memset(ss, 0, sizeof(struct us_data));
|
||||
usb_media_ready = 1;
|
||||
|
||||
/* At this point, we know we've got a live one */
|
||||
//debug("\n\nUSB Mass Storage device detected\n");
|
||||
|
||||
/* Initialize the us_data structure with some useful info */
|
||||
ss->flags = flags;
|
||||
ss->ifnum = ifnum;
|
||||
ss->pusb_dev = dev;
|
||||
ss->attention_done = 0;
|
||||
ss->subclass = iface->desc.bInterfaceSubClass;
|
||||
ss->protocol = iface->desc.bInterfaceProtocol;
|
||||
|
||||
/* set the handler pointers based on the protocol */
|
||||
//debug("Transport: ");
|
||||
switch (ss->protocol) {
|
||||
case US_PR_BULK:
|
||||
//debug("Bulk/Bulk/Bulk\n");
|
||||
ss->transport = usb_stor_BBB_transport;
|
||||
ss->transport_reset = usb_stor_BBB_reset;
|
||||
break;
|
||||
default:
|
||||
//printf("USB Storage Transport unknown / not yet implemented\n");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are expecting a minimum of 2 endpoints - in and out (bulk).
|
||||
* An optional interrupt is OK (necessary for CBI protocol).
|
||||
* We will ignore any others.
|
||||
*/
|
||||
for (i = 0; i < iface->desc.bNumEndpoints; i++) {
|
||||
ep_desc = &iface->ep_desc[i];
|
||||
/* is it an BULK endpoint? */
|
||||
if ((ep_desc->bmAttributes &
|
||||
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
|
||||
if (ep_desc->bEndpointAddress & USB_DIR_IN)
|
||||
ss->ep_in = ep_desc->bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
else
|
||||
ss->ep_out =
|
||||
ep_desc->bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
}
|
||||
|
||||
/* is it an interrupt endpoint? */
|
||||
if ((ep_desc->bmAttributes &
|
||||
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
|
||||
ss->ep_int = ep_desc->bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
ss->irqinterval = ep_desc->bInterval;
|
||||
}
|
||||
}
|
||||
/* debug("Endpoints In %d Out %d Int %d\n",
|
||||
ss->ep_in, ss->ep_out, ss->ep_int); */
|
||||
|
||||
/* Do some basic sanity checks, and bail if we find a problem */
|
||||
if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
|
||||
!ss->ep_in || !ss->ep_out ||
|
||||
(ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
|
||||
//debug("Problems with device\n");
|
||||
return 0;
|
||||
}
|
||||
/* set class specific stuff */
|
||||
/* We only handle certain protocols. Currently, these are
|
||||
* the only ones.
|
||||
* The SFF8070 accepts the requests used in u-boot
|
||||
*/
|
||||
if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
|
||||
ss->subclass != US_SC_8070) {
|
||||
//printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
|
||||
return 0;
|
||||
}
|
||||
if (ss->ep_int) {
|
||||
/* we had found an interrupt endpoint, prepare irq pipe
|
||||
* set up the IRQ pipe and handler
|
||||
*/
|
||||
ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
|
||||
ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
|
||||
ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
|
||||
dev->irq_handle = usb_stor_irq;
|
||||
}
|
||||
|
||||
/* Set the maximum transfer size per host controller setting */
|
||||
usb_stor_set_max_xfer_blk(dev, ss);
|
||||
|
||||
dev->privptr = (void *)ss;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
|
||||
struct blk_desc *dev_desc)
|
||||
{
|
||||
unsigned char perq, modi;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
|
||||
ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
|
||||
u32 capacity, blksz;
|
||||
struct scsi_cmd *pccb = &usb_ccb;
|
||||
memset(usb_stor_buf, 0, 36);
|
||||
pccb->pdata = usb_stor_buf;
|
||||
|
||||
dev_desc->target = dev->devnum;
|
||||
pccb->lun = dev_desc->lun;
|
||||
//debug(" address %d\n", dev_desc->target);
|
||||
|
||||
if (usb_inquiry(pccb, ss)) {
|
||||
//debug("%s: usb_inquiry() failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
perq = usb_stor_buf[0];
|
||||
modi = usb_stor_buf[1];
|
||||
|
||||
/*
|
||||
* Skip unknown devices (0x1f) and enclosure service devices (0x0d),
|
||||
* they would not respond to test_unit_ready .
|
||||
*/
|
||||
if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
|
||||
//debug("%s: unknown/unsupported device\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
if ((modi&0x80) == 0x80) {
|
||||
/* drive is removable */
|
||||
dev_desc->removable = 1;
|
||||
}
|
||||
memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
|
||||
memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
|
||||
memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
|
||||
dev_desc->vendor[8] = 0;
|
||||
dev_desc->product[16] = 0;
|
||||
dev_desc->revision[4] = 0;
|
||||
/* debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
|
||||
usb_stor_buf[3]); */
|
||||
if (usb_test_unit_ready(pccb, ss)) {
|
||||
/* printf("Device NOT ready\n"
|
||||
" Request Sense returned %02X %02X %02X\n",
|
||||
pccb->sense_buf[2], pccb->sense_buf[12],
|
||||
pccb->sense_buf[13]); */
|
||||
if (dev_desc->removable == 1)
|
||||
dev_desc->type = perq;
|
||||
return 0;
|
||||
}
|
||||
pccb->pdata = (unsigned char *)cap;
|
||||
memset(pccb->pdata, 0, 8);
|
||||
if (usb_read_capacity(pccb, ss) != 0) {
|
||||
//printf("READ_CAP ERROR\n");
|
||||
cap[0] = 2880;
|
||||
cap[1] = 0x200;
|
||||
}
|
||||
ss->flags &= ~USB_READY;
|
||||
//debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
|
||||
#if 0
|
||||
if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
|
||||
cap[0] >>= 16;
|
||||
|
||||
cap[0] = cpu_to_be32(cap[0]);
|
||||
cap[1] = cpu_to_be32(cap[1]);
|
||||
#endif
|
||||
|
||||
capacity = be32_to_cpu(cap[0]) + 1;
|
||||
blksz = be32_to_cpu(cap[1]);
|
||||
|
||||
dev_desc->lba = capacity;
|
||||
dev_desc->blksz = blksz;
|
||||
dev_desc->log2blksz = LOG2(dev_desc->blksz);
|
||||
dev_desc->type = perq;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, void *buffer)
|
||||
{
|
||||
lbaint_t start, blks;
|
||||
uintptr_t buf_addr;
|
||||
unsigned short smallblks;
|
||||
struct usb_device *udev;
|
||||
struct us_data *ss;
|
||||
int retry;
|
||||
struct scsi_cmd *srb = &usb_ccb;
|
||||
|
||||
if (blkcnt == 0)
|
||||
return 0;
|
||||
/* Setup device */
|
||||
udev = usb_dev_desc[block_dev->devnum].priv;
|
||||
if (!udev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ss = (struct us_data *)udev->privptr;
|
||||
usb_disable_asynch(1); /* asynch transfer not allowed */
|
||||
srb->lun = block_dev->lun;
|
||||
buf_addr = (uintptr_t)buffer;
|
||||
start = blknr;
|
||||
blks = blkcnt;
|
||||
|
||||
do {
|
||||
retry = 2;
|
||||
srb->pdata = (unsigned char *)buf_addr;
|
||||
if (blks > ss->max_xfer_blk)
|
||||
smallblks = ss->max_xfer_blk;
|
||||
else
|
||||
smallblks = (unsigned short) blks;
|
||||
retry_it:
|
||||
if (usb_media_ready == 0)
|
||||
break;
|
||||
/* if (smallblks == ss->max_xfer_blk)
|
||||
usb_show_progress(); */
|
||||
srb->datalen = block_dev->blksz * smallblks;
|
||||
srb->pdata = (unsigned char *)buf_addr;
|
||||
if (usb_read_10(srb, ss, start, smallblks)) {
|
||||
usb_request_sense(srb, ss);
|
||||
if (retry--)
|
||||
goto retry_it;
|
||||
blkcnt -= blks;
|
||||
break;
|
||||
}
|
||||
start += smallblks;
|
||||
blks -= smallblks;
|
||||
buf_addr += srb->datalen;
|
||||
} while (blks != 0);
|
||||
ss->flags &= ~USB_READY;
|
||||
|
||||
usb_disable_asynch(0);
|
||||
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
static int usb_stor_probe_device(struct usb_device *udev)
|
||||
{
|
||||
int lun, max_lun;
|
||||
int start;
|
||||
|
||||
if (udev == NULL)
|
||||
return -ENOENT; /* no more devices available */
|
||||
|
||||
//debug("\n\nProbing for storage\n");
|
||||
|
||||
/* We don't have space to even probe if we hit the maximum */
|
||||
if (usb_max_devs == USB_MAX_STOR_DEV) {
|
||||
/* printf("max USB Storage Device reached: %d stopping\n",
|
||||
usb_max_devs); */
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* OK, it's a storage device. Iterate over its LUNs and populate
|
||||
* usb_dev_desc'
|
||||
*/
|
||||
start = usb_max_devs;
|
||||
|
||||
max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
|
||||
for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
|
||||
lun++) {
|
||||
struct blk_desc *blkdev;
|
||||
|
||||
blkdev = &usb_dev_desc[usb_max_devs];
|
||||
memset(blkdev, '\0', sizeof(struct blk_desc));
|
||||
blkdev->if_type = IF_TYPE_USB;
|
||||
blkdev->devnum = usb_max_devs;
|
||||
blkdev->part_type = PART_TYPE_UNKNOWN;
|
||||
blkdev->target = 0xff;
|
||||
blkdev->type = DEV_TYPE_UNKNOWN;
|
||||
blkdev->block_read = usb_stor_read;
|
||||
//blkdev->block_write = usb_stor_write;
|
||||
blkdev->lun = lun;
|
||||
blkdev->priv = udev;
|
||||
|
||||
if (usb_stor_get_info(udev, &usb_stor[start],
|
||||
&usb_dev_desc[usb_max_devs]) == 1) {
|
||||
//debug("partype: %d\n", blkdev->part_type);
|
||||
//part_init(blkdev);
|
||||
//debug("partype: %d\n", blkdev->part_type);
|
||||
usb_max_devs++;
|
||||
//debug("%s: Found device %p\n", __func__, udev);
|
||||
/* blkdev->disk_priv = (void *)FF_USBDiskInit("/usb");
|
||||
if (NULL == blkdev->disk_priv) {
|
||||
printf("FF_USBDiskInit failed\r\n");
|
||||
continue;
|
||||
}
|
||||
mdelay(200);
|
||||
usb_disk_file_test(); */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb_stor_reset(void)
|
||||
{
|
||||
usb_max_devs = 0;
|
||||
CBWTag = 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* scan the usb and reports device info
|
||||
* to the user if mode = 1
|
||||
* returns current device or -1 if no
|
||||
*/
|
||||
int usb_stor_scan(int mode)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
if (mode == 1)
|
||||
SendUartString("scanning usb for storage devices... ");
|
||||
|
||||
usb_disable_asynch(1); /* asynch transfer not allowed */
|
||||
|
||||
usb_stor_reset();
|
||||
for (i = 0; i < USB_MAX_DEVICE; i++) {
|
||||
struct usb_device *dev;
|
||||
|
||||
dev = usb_get_dev_index(i); /* get device */
|
||||
//debug("i=%d\n", i);
|
||||
if (usb_stor_probe_device(dev))
|
||||
break;
|
||||
} /* for */
|
||||
|
||||
usb_disable_asynch(0); /* asynch transfer allowed */
|
||||
|
||||
if (usb_max_devs > 0) {
|
||||
SendUartString("Storage Device(s) found\r\n");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void usb_stor_disconnect()
|
||||
{
|
||||
usb_media_ready = 0;
|
||||
}
|
||||
|
||||
int USB_disk_initialize(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int USB_disk_read(void *buff, DWORD sector, BYTE count)
|
||||
{
|
||||
struct blk_desc *dev_desc = &usb_dev_desc[0];
|
||||
|
||||
return dev_desc->block_read(dev_desc, sector, count, buff);
|
||||
}
|
||||
|
||||
int USB_disk_ioctl(BYTE ctrl, void *buff)
|
||||
{
|
||||
struct blk_desc *dev_desc = &usb_dev_desc[0];
|
||||
|
||||
switch(ctrl)
|
||||
{
|
||||
case CTRL_SYNC:
|
||||
break;
|
||||
case GET_SECTOR_COUNT:
|
||||
*(DWORD*)buff = dev_desc->lba;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*(DWORD*)buff = 512;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
110
A27-STEPLDR/Src/usb/usb_massstorage.h
Normal file
110
A27-STEPLDR/Src/usb/usb_massstorage.h
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef __USB_MASS_STORAGE_H
|
||||
#define __USB_MASS_STORAGE_H
|
||||
|
||||
|
||||
/* Part types */
|
||||
#define PART_TYPE_UNKNOWN 0x00
|
||||
#define PART_TYPE_MAC 0x01
|
||||
#define PART_TYPE_DOS 0x02
|
||||
#define PART_TYPE_ISO 0x03
|
||||
#define PART_TYPE_AMIGA 0x04
|
||||
#define PART_TYPE_EFI 0x05
|
||||
|
||||
/* device types */
|
||||
#define DEV_TYPE_UNKNOWN 0xff /* not connected */
|
||||
#define DEV_TYPE_HARDDISK 0x00 /* harddisk */
|
||||
#define DEV_TYPE_TAPE 0x01 /* Tape */
|
||||
#define DEV_TYPE_CDROM 0x05 /* CD-ROM */
|
||||
#define DEV_TYPE_OPDISK 0x07 /* optical disk */
|
||||
|
||||
#define PART_NAME_LEN 32
|
||||
#define PART_TYPE_LEN 32
|
||||
#define MAX_SEARCH_PARTITIONS 64
|
||||
|
||||
typedef unsigned long lbaint_t;
|
||||
|
||||
typedef struct {
|
||||
u8 b[16];
|
||||
} efi_guid_t;
|
||||
|
||||
|
||||
/* Interface types: */
|
||||
enum if_type {
|
||||
IF_TYPE_UNKNOWN = 0,
|
||||
IF_TYPE_IDE,
|
||||
IF_TYPE_SCSI,
|
||||
IF_TYPE_ATAPI,
|
||||
IF_TYPE_USB,
|
||||
IF_TYPE_DOC,
|
||||
IF_TYPE_MMC,
|
||||
IF_TYPE_SD,
|
||||
IF_TYPE_SATA,
|
||||
IF_TYPE_HOST,
|
||||
IF_TYPE_NVME,
|
||||
IF_TYPE_EFI,
|
||||
|
||||
IF_TYPE_COUNT, /* Number of interface types */
|
||||
};
|
||||
|
||||
#define BLK_VEN_SIZE 40
|
||||
#define BLK_PRD_SIZE 20
|
||||
#define BLK_REV_SIZE 8
|
||||
|
||||
/*
|
||||
* Identifies the partition table type (ie. MBR vs GPT GUID) signature
|
||||
*/
|
||||
enum sig_type {
|
||||
SIG_TYPE_NONE,
|
||||
SIG_TYPE_MBR,
|
||||
SIG_TYPE_GUID,
|
||||
|
||||
SIG_TYPE_COUNT /* Number of signature types */
|
||||
};
|
||||
|
||||
/*
|
||||
* With driver model (CONFIG_BLK) this is uclass platform data, accessible
|
||||
* with dev_get_uclass_platdata(dev)
|
||||
*/
|
||||
struct blk_desc {
|
||||
/*
|
||||
* TODO: With driver model we should be able to use the parent
|
||||
* device's uclass instead.
|
||||
*/
|
||||
enum if_type if_type; /* type of the interface */
|
||||
int devnum; /* device number */
|
||||
unsigned char part_type; /* partition type */
|
||||
unsigned char target; /* target SCSI ID */
|
||||
unsigned char lun; /* target LUN */
|
||||
unsigned char hwpart; /* HW partition, e.g. for eMMC */
|
||||
unsigned char type; /* device type */
|
||||
unsigned char removable; /* removable device */
|
||||
lbaint_t lba; /* number of blocks */
|
||||
unsigned long blksz; /* block size */
|
||||
int log2blksz; /* for convenience: log2(blksz) */
|
||||
char vendor[BLK_VEN_SIZE + 1]; /* device vendor string */
|
||||
char product[BLK_PRD_SIZE + 1]; /* device product number */
|
||||
char revision[BLK_REV_SIZE + 1]; /* firmware revision */
|
||||
enum sig_type sig_type; /* Partition table signature type */
|
||||
union {
|
||||
u32 mbr_sig; /* MBR integer signature */
|
||||
efi_guid_t guid_sig; /* GPT GUID Signature */
|
||||
};
|
||||
|
||||
unsigned long (*block_read)(struct blk_desc *block_dev,
|
||||
lbaint_t start,
|
||||
lbaint_t blkcnt,
|
||||
void *buffer);
|
||||
unsigned long (*block_write)(struct blk_desc *block_dev,
|
||||
lbaint_t start,
|
||||
lbaint_t blkcnt,
|
||||
const void *buffer);
|
||||
unsigned long (*block_erase)(struct blk_desc *block_dev,
|
||||
lbaint_t start,
|
||||
lbaint_t blkcnt);
|
||||
void *priv; /* driver private struct pointer */
|
||||
void *disk_priv;
|
||||
};
|
||||
|
||||
extern struct blk_desc usb_dev_desc[6];
|
||||
|
||||
#endif
|
228
A27-STEPLDR/Src/usb/usb_os_adapter.c
Normal file
228
A27-STEPLDR/Src/usb/usb_os_adapter.c
Normal file
@ -0,0 +1,228 @@
|
||||
#include "usb_os_adapter.h"
|
||||
|
||||
void *kmem_cache_alloc(struct kmem_cache *obj, int flag)
|
||||
{
|
||||
(void)flag;
|
||||
return pvPortMalloc(obj->sz);
|
||||
}
|
||||
|
||||
void kmem_cache_free(struct kmem_cache *cachep, void *obj)
|
||||
{
|
||||
(void)cachep;
|
||||
vPortFree(obj);
|
||||
}
|
||||
|
||||
void kmem_cache_destroy(struct kmem_cache *cachep)
|
||||
{
|
||||
free(cachep);
|
||||
}
|
||||
|
||||
static void *kmalloc_array(size_t n, size_t size, gfp_t flags)
|
||||
{
|
||||
void* ptr = NULL;
|
||||
if (size != 0 && n > SIZE_MAX / size)
|
||||
return NULL;
|
||||
ptr = pvPortMalloc(n * size);
|
||||
|
||||
if (flags & __GFP_ZERO) {
|
||||
memset(ptr, 0, n * size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *kcalloc(size_t n, size_t size, gfp_t flags)
|
||||
{
|
||||
return kmalloc_array(n, size, flags | __GFP_ZERO);
|
||||
}
|
||||
|
||||
void *kmalloc(size_t size, int flags)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = pvPortMalloc(size);
|
||||
if (flags & __GFP_ZERO)
|
||||
memset(p, 0, size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *kzalloc(size_t size, gfp_t flags)
|
||||
{
|
||||
return kmalloc(size, flags | __GFP_ZERO);
|
||||
}
|
||||
|
||||
//struct device;
|
||||
void *devm_kzalloc(struct device *dev, size_t size, gfp_t flags)
|
||||
{
|
||||
return kmalloc(size, flags | __GFP_ZERO);
|
||||
}
|
||||
|
||||
|
||||
void kfree(void* addr)
|
||||
{
|
||||
vPortFree(addr);
|
||||
}
|
||||
|
||||
struct kmem_cache *get_mem(int element_sz)
|
||||
{
|
||||
struct kmem_cache *ret;
|
||||
|
||||
ret = pvPortMalloc(sizeof(struct kmem_cache));
|
||||
ret->sz = element_sz;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long _find_next_bit(const unsigned long *addr1,
|
||||
const unsigned long *addr2, unsigned long nbits,
|
||||
unsigned long start, unsigned long invert)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
if (unlikely(start >= nbits))
|
||||
return nbits;
|
||||
|
||||
tmp = addr1[start / BITS_PER_LONG];
|
||||
if (addr2)
|
||||
tmp &= addr2[start / BITS_PER_LONG];
|
||||
tmp ^= invert;
|
||||
|
||||
/* Handle 1st word. */
|
||||
tmp &= BITMAP_FIRST_WORD_MASK(start);
|
||||
start = round_down(start, BITS_PER_LONG);
|
||||
|
||||
while (!tmp) {
|
||||
start += BITS_PER_LONG;
|
||||
if (start >= nbits)
|
||||
return nbits;
|
||||
|
||||
tmp = addr1[start / BITS_PER_LONG];
|
||||
if (addr2)
|
||||
tmp &= addr2[start / BITS_PER_LONG];
|
||||
tmp ^= invert;
|
||||
}
|
||||
|
||||
return min(start + __ffs(tmp), nbits);
|
||||
}
|
||||
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
return _find_next_bit(addr, NULL, size, offset, 0UL);
|
||||
}
|
||||
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
return _find_next_bit(addr, NULL, size, offset, ~0UL);
|
||||
}
|
||||
|
||||
unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned int nr,
|
||||
unsigned long align_mask,
|
||||
unsigned long align_offset)
|
||||
{
|
||||
unsigned long index, end, i;
|
||||
again:
|
||||
index = find_next_zero_bit(map, size, start);
|
||||
|
||||
/* Align allocation */
|
||||
index = __ALIGN_MASK(index + align_offset, align_mask) - align_offset;
|
||||
|
||||
end = index + nr;
|
||||
if (end > size)
|
||||
return end;
|
||||
i = find_next_bit(map, end, index);
|
||||
if (i < end) {
|
||||
start = i + 1;
|
||||
goto again;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
bitmap_find_next_zero_area(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned int nr,
|
||||
unsigned long align_mask)
|
||||
{
|
||||
return bitmap_find_next_zero_area_off(map, size, start, nr, align_mask, 0);
|
||||
}
|
||||
|
||||
void bitmap_set(unsigned long *map, unsigned int start, int len)
|
||||
{
|
||||
unsigned long *p = map + BIT_WORD(start);
|
||||
const unsigned int size = start + len;
|
||||
int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
|
||||
unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
|
||||
|
||||
while (len - bits_to_set >= 0) {
|
||||
*p |= mask_to_set;
|
||||
len -= bits_to_set;
|
||||
bits_to_set = BITS_PER_LONG;
|
||||
mask_to_set = ~0UL;
|
||||
p++;
|
||||
}
|
||||
if (len) {
|
||||
mask_to_set &= BITMAP_LAST_WORD_MASK(size);
|
||||
*p |= mask_to_set;
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_clear(unsigned long *map, unsigned int start, int len)
|
||||
{
|
||||
unsigned long *p = map + BIT_WORD(start);
|
||||
const unsigned int size = start + len;
|
||||
int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
|
||||
unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
|
||||
|
||||
while (len - bits_to_clear >= 0) {
|
||||
*p &= ~mask_to_clear;
|
||||
len -= bits_to_clear;
|
||||
bits_to_clear = BITS_PER_LONG;
|
||||
mask_to_clear = ~0UL;
|
||||
p++;
|
||||
}
|
||||
if (len) {
|
||||
mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
|
||||
*p &= ~mask_to_clear;
|
||||
}
|
||||
}
|
||||
|
||||
void writesl(u32 addr, const void *buffer, unsigned int count)
|
||||
{
|
||||
if (count) {
|
||||
const u32 *buf = (u32 *)buffer;
|
||||
|
||||
do {
|
||||
writel(*buf++, addr);
|
||||
} while (--count);
|
||||
}
|
||||
}
|
||||
|
||||
void readsl(u32 addr, void *buffer, unsigned int count)
|
||||
{
|
||||
if (count) {
|
||||
u32 *buf = (u32 *)buffer;
|
||||
|
||||
do {
|
||||
u32 x = readl(addr);
|
||||
*buf++ = x;
|
||||
} while (--count);
|
||||
}
|
||||
}
|
||||
|
||||
void iowrite32_rep(u32 addr, const void *buffer, unsigned int count)
|
||||
{
|
||||
writesl(addr, buffer, count);
|
||||
}
|
||||
|
||||
void ioread32_rep(u32 addr, void *buffer, unsigned int count)
|
||||
{
|
||||
readsl(addr, buffer, count);
|
||||
}
|
||||
|
332
A27-STEPLDR/Src/usb/usb_os_adapter.h
Normal file
332
A27-STEPLDR/Src/usb/usb_os_adapter.h
Normal file
@ -0,0 +1,332 @@
|
||||
#ifndef _USB_OS_ADAPTER_H
|
||||
#define _USB_OS_ADAPTER_H
|
||||
|
||||
#include "os_adapt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define pr_err(...) TRACE_ERROR(__VA_ARGS__)
|
||||
#define WARN_ON_ONCE(condition) WARN_ON(condition)
|
||||
|
||||
#define USB_UNUSED(x) ((void) x)
|
||||
|
||||
typedef INT8 __s8;
|
||||
typedef UINT8 __u8;
|
||||
typedef INT16 __s16;
|
||||
typedef UINT16 __u16;
|
||||
typedef INT32 __s32;
|
||||
typedef UINT32 __u32;
|
||||
typedef long long __s64;
|
||||
typedef unsigned long long __u64;
|
||||
|
||||
typedef __u16 __le16;
|
||||
typedef __u16 __be16;
|
||||
//typedef __u32 __le32;
|
||||
typedef __u32 __be32;
|
||||
typedef __u64 __le64;
|
||||
typedef __u64 __be64;
|
||||
|
||||
typedef unsigned long ulong;
|
||||
typedef __u32 dev_t;
|
||||
|
||||
|
||||
#define __cpu_to_le16(x) (x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define __le16_to_cpu le16_to_cpu
|
||||
#define get_unaligned(x) (*x)
|
||||
|
||||
|
||||
void iowrite32_rep(u32 addr, const void *buffer, unsigned int count);
|
||||
void ioread32_rep(u32 addr, void *buffer, unsigned int count);
|
||||
unsigned long bitmap_find_next_zero_area(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned int nr,
|
||||
unsigned long align_mask);
|
||||
void bitmap_set(unsigned long *map, unsigned int start, int len);
|
||||
void bitmap_clear(unsigned long *map, unsigned int start, int len);
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(ListItem_t *item, List_t *list)
|
||||
{
|
||||
if (!listIS_CONTAINED_WITHIN(NULL, item))
|
||||
uxListRemove(item);
|
||||
vListInsertEnd(list, item);
|
||||
}
|
||||
|
||||
static inline void list_del_init(ListItem_t *item)
|
||||
{
|
||||
if (!listIS_CONTAINED_WITHIN(NULL, item))//maybe item has removed from list
|
||||
uxListRemove(item);
|
||||
//vListInitialiseItem(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(ListItem_t *item, List_t *list)
|
||||
{
|
||||
vListInsertEnd(list, item);
|
||||
}
|
||||
|
||||
static inline void INIT_LIST_HEAD(List_t *list)
|
||||
{
|
||||
vListInitialise(list);
|
||||
}
|
||||
|
||||
static inline void INIT_LIST_ITEM(ListItem_t *item)
|
||||
{
|
||||
vListInitialiseItem(item);
|
||||
}
|
||||
|
||||
#define list_for_each_entry_safe(pxListItem, nListItem, pvOwner, list) \
|
||||
for (pxListItem = listGET_HEAD_ENTRY(list), \
|
||||
nListItem = listGET_NEXT(pxListItem), \
|
||||
pvOwner = listGET_LIST_ITEM_OWNER(pxListItem); \
|
||||
pxListItem != listGET_END_MARKER(list); \
|
||||
pxListItem = nListItem, \
|
||||
nListItem = listGET_NEXT(pxListItem), \
|
||||
pvOwner = listGET_LIST_ITEM_OWNER(pxListItem))
|
||||
|
||||
#define list_for_each_safe(pxListItem, nListItem, list) \
|
||||
for (pxListItem = listGET_HEAD_ENTRY(list), \
|
||||
nListItem = listGET_NEXT(pxListItem); \
|
||||
pxListItem != listGET_END_MARKER(list); \
|
||||
pxListItem = nListItem, \
|
||||
nListItem = listGET_NEXT(pxListItem))
|
||||
|
||||
#define list_del(pxListItem) uxListRemove(pxListItem)
|
||||
#define list_empty(pxList) listLIST_IS_EMPTY(pxList)
|
||||
#define list_item_empty(pxListItem) ((pxListItem)->pxContainer == NULL)
|
||||
|
||||
#define __ARG_PLACEHOLDER_1 0,
|
||||
#define config_enabled(cfg) _config_enabled(cfg)
|
||||
#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
|
||||
#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
|
||||
#define ___config_enabled(__ignored, val, ...) val
|
||||
|
||||
/*
|
||||
* IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
|
||||
* 0 otherwise.
|
||||
*
|
||||
*/
|
||||
#define IS_ENABLED(option) \
|
||||
(config_enabled(option) || config_enabled(option##_MODULE))
|
||||
struct timer_list
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
struct unused {
|
||||
int a;
|
||||
};
|
||||
typedef struct unused unused_t;
|
||||
|
||||
|
||||
#define task_pid_nr(x) 0
|
||||
#define set_freezable(...) do { } while (0)
|
||||
#define try_to_freeze(...) 0
|
||||
#define set_current_state(...) do { } while (0)
|
||||
#define kthread_should_stop(...) 0
|
||||
#define schedule() do { } while (0)
|
||||
|
||||
#define setup_timer(timer, func, data) do {} while (0)
|
||||
#define del_timer_sync(timer) do {} while (0)
|
||||
#define schedule_work(work) do {} while (0)
|
||||
#define INIT_WORK(work, fun) do {} while (0)
|
||||
#define local_irq_save(flag) do {(void)flag;} while (0)
|
||||
#define local_irq_restore(flag) do {(void)flag;} while (0)
|
||||
|
||||
//#define local_irq_save(flag) do {portENTER_CRITICAL(); (void)flag;} while(0)
|
||||
//#define local_irq_restore(flag) do {portEXIT_CRITICAL(); (void)flag;} while(0)
|
||||
|
||||
|
||||
struct work_struct {
|
||||
int a;
|
||||
};
|
||||
|
||||
struct kmem_cache {
|
||||
int sz;
|
||||
};
|
||||
|
||||
typedef int wait_queue_head_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile unsigned int slock;
|
||||
} spinlock_t;
|
||||
|
||||
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||
{
|
||||
//TODO
|
||||
unsigned volatile long y;
|
||||
switch(size){
|
||||
case 1:
|
||||
y = (*(char *)ptr) & 0x000000ff;
|
||||
*((char *)ptr) = (char)x;
|
||||
break;
|
||||
case 2:
|
||||
y = (*(short *)ptr) & 0x0000ffff;
|
||||
*((short *)ptr) = (short)x;
|
||||
break;
|
||||
default: // 4
|
||||
y = (*(unsigned long *)ptr) & 0xffffffff;
|
||||
*((unsigned long *)ptr) = x;
|
||||
break;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
#define ARCH_SPIN_LOCK_UNLOCKED 1
|
||||
#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
|
||||
#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
|
||||
#define xchg(ptr,v) ((unsigned int)__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
|
||||
#define __xg(x) ((volatile long *)(x))
|
||||
|
||||
static inline void _raw_spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
xchg(&lock->slock, 1);
|
||||
}
|
||||
|
||||
static inline int _raw_spin_trylock(spinlock_t *lock)
|
||||
{
|
||||
return xchg(&lock->slock, 0) != 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline void _raw_spin_lock(spinlock_t *lock)
|
||||
{
|
||||
volatile int was_locked;
|
||||
do {
|
||||
was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
|
||||
} while(was_locked);
|
||||
}
|
||||
|
||||
#define SPINLOCK_MAGIC 0xdead4ead
|
||||
#define SPIN_LOCK_UNLOCKED ARCH_SPIN_LOCK_UNLOCKED
|
||||
#define spin_lock_init(x) do { (x)->slock = SPIN_LOCK_UNLOCKED; } while(0)
|
||||
#define spin_is_locked(x) arch_spin_is_locked(x)
|
||||
#define spin_unlock_wait(x) arch_spin_unlock_wait(x)
|
||||
#define _spin_trylock(lock) ({_raw_spin_trylock(lock) ? \
|
||||
1 : ({ 0;});})
|
||||
#define _spin_lock(lock) \
|
||||
do { \
|
||||
_raw_spin_lock(lock); \
|
||||
} while(0)
|
||||
|
||||
#define _spin_unlock(lock) \
|
||||
do { \
|
||||
_raw_spin_unlock(lock); \
|
||||
} while (0)
|
||||
|
||||
#define spin_lock(lock) _spin_lock(lock)
|
||||
#define spin_unlock(lock) _spin_unlock(lock)
|
||||
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
|
||||
|
||||
|
||||
#define spin_lock_irqsave(lock, flags) \
|
||||
do { \
|
||||
flags = __get_interrupt_state(); __disable_irq(); \
|
||||
} while (0)
|
||||
|
||||
#define spin_unlock_irqrestore(lock, flags) \
|
||||
do { \
|
||||
__set_interrupt_state(flags); \
|
||||
} while (0)
|
||||
|
||||
#define assert_spin_locked(lock) do {} while (0)
|
||||
|
||||
#define irqreturn_t int
|
||||
#define IRQ_NONE 0
|
||||
#define IRQ_HANDLED 1
|
||||
#define IRQ_WAKE_THREAD 2
|
||||
#define GFP_ATOMIC ((gfp_t) 0)
|
||||
#define GFP_KERNEL ((gfp_t) 0)
|
||||
#define GFP_NOFS ((gfp_t) 0)
|
||||
#define GFP_USER ((gfp_t) 0)
|
||||
#define __GFP_NOWARN ((gfp_t) 0)
|
||||
#define __GFP_ZERO ((gfp_t)0x8000u)
|
||||
#define UINT_MAX (~0U)
|
||||
|
||||
void *kmem_cache_alloc(struct kmem_cache *obj, int flag);
|
||||
void kmem_cache_free(struct kmem_cache *cachep, void *obj);
|
||||
void kmem_cache_destroy(struct kmem_cache *cachep);
|
||||
|
||||
void *kcalloc(size_t n, size_t size, gfp_t flags);
|
||||
void *kmalloc(size_t size, int flags);
|
||||
void *kzalloc(size_t size, gfp_t flags);
|
||||
void kfree(void* addr);
|
||||
struct device;
|
||||
void *devm_kzalloc(struct device *dev, size_t size, gfp_t flags);
|
||||
struct kmem_cache *get_mem(int element_sz);
|
||||
#define kmem_cache_create(a, sz, c, d, e) get_mem(sz)
|
||||
|
||||
|
||||
|
||||
#define min_t(type, x, y) (x < y ? x: y)
|
||||
#define max_t(type, x, y) (x > y ? x: y)
|
||||
#define msleep mdelay
|
||||
|
||||
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
|
||||
#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
|
||||
#define __round_mask(x, y) ((unsigned long)((y)-1))
|
||||
#define round_down(x, y) ((x) & ~(__round_mask((x), (y))))
|
||||
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||
|
||||
|
||||
//#define min(x,y) ((x) < (y) ? x : y)
|
||||
#define max(x,y) ((x) > (y) ? x : y)
|
||||
|
||||
|
||||
#define min3(x, y, z) min(min(x, y), z)
|
||||
#define max3(x, y, z) max(max(x, y), z)
|
||||
|
||||
#define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1))
|
||||
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||
|
||||
#define ALIGN(x,a) __ALIGN_MASK((x),(uintptr_t)(a)-1)
|
||||
//#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
|
||||
|
||||
|
||||
//typedef unsigned long uintptr_t;
|
||||
|
||||
#define PAD_COUNT(s, pad) (((s) - 1) / (pad) + 1)
|
||||
#define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad)
|
||||
#define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad) \
|
||||
char __##name[ROUND(PAD_SIZE((size) * sizeof(type), pad), align) \
|
||||
+ (align - 1)]; \
|
||||
\
|
||||
type *name = (type *)ALIGN((uintptr_t)__##name, align)
|
||||
#define ALLOC_ALIGN_BUFFER(type, name, size, align) \
|
||||
ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, 1)
|
||||
#define ALLOC_CACHE_ALIGN_BUFFER_PAD(type, name, size, pad) \
|
||||
ALLOC_ALIGN_BUFFER_PAD(type, name, size, ARCH_DMA_MINALIGN, pad)
|
||||
#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \
|
||||
ALLOC_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
|
||||
|
||||
#define be32_to_cpu(x) ((uint32_t)( \
|
||||
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
|
||||
|
||||
#define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \
|
||||
((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \
|
||||
((x & 0xffff0000) ? 16 : 0))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user