cleaned up
This commit is contained in:
@@ -34,10 +34,11 @@
|
||||
#undef DEBUG
|
||||
#undef SHOW_INFO
|
||||
|
||||
char ehci_inited;
|
||||
static char ehci_inited;
|
||||
static int rootdev;
|
||||
|
||||
static uint16_t portreset, companion;
|
||||
static uint16_t portreset;
|
||||
static uint16_t companion;
|
||||
|
||||
struct descriptor {
|
||||
struct usb_hub_descriptor hub;
|
||||
@@ -49,26 +50,26 @@ struct descriptor {
|
||||
|
||||
static struct descriptor rom_descriptor = {
|
||||
{
|
||||
0x8, /* bDescLength */
|
||||
0x29, /* bDescriptorType: hub descriptor */
|
||||
0x8, /* bDescLength */
|
||||
0x29, /* bDescriptorType: hub descriptor */
|
||||
2, /* bNrPorts -- runtime modified */
|
||||
0, /* wHubCharacteristics */
|
||||
0xff, /* bPwrOn2PwrGood */
|
||||
0xff, /* bPwrOn2PwrGood */
|
||||
0, /* bHubCntrCurrent */
|
||||
{}, /* Device removable */
|
||||
{} /* at most 7 ports! XXX */
|
||||
},
|
||||
{
|
||||
0x12, /* bLength */
|
||||
0x12, /* bLength */
|
||||
1, /* bDescriptorType: UDESC_DEVICE */
|
||||
0x0002, /* bcdUSB: v2.0 */
|
||||
0x0002, /* bcdUSB: v2.0 */
|
||||
9, /* bDeviceClass: UDCLASS_HUB */
|
||||
0, /* bDeviceSubClass: UDSUBCLASS_HUB */
|
||||
1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */
|
||||
64, /* bMaxPacketSize: 64 bytes */
|
||||
0x0000, /* idVendor */
|
||||
0x0000, /* idProduct */
|
||||
0x0001, /* bcdDevice */
|
||||
0x0000, /* idVendor */
|
||||
0x0000, /* idProduct */
|
||||
0x0001, /* bcdDevice */
|
||||
1, /* iManufacturer */
|
||||
2, /* iProduct */
|
||||
0, /* iSerialNumber */
|
||||
@@ -81,11 +82,11 @@ static struct descriptor rom_descriptor = {
|
||||
1, /* bNumInterface */
|
||||
1, /* bConfigurationValue */
|
||||
0, /* iConfiguration */
|
||||
0x40, /* bmAttributes: UC_SELF_POWER */
|
||||
0x40, /* bmAttributes: UC_SELF_POWER */
|
||||
0 /* bMaxPower */
|
||||
},
|
||||
{
|
||||
0x9, /* bLength */
|
||||
0x9, /* bLength */
|
||||
4, /* bDescriptorType: UDESC_INTERFACE */
|
||||
0, /* bInterfaceNumber */
|
||||
0, /* bAlternateSetting */
|
||||
@@ -96,11 +97,11 @@ static struct descriptor rom_descriptor = {
|
||||
0 /* iInterface */
|
||||
},
|
||||
{
|
||||
0x7, /* bLength */
|
||||
0x7, /* bLength */
|
||||
5, /* bDescriptorType: UDESC_ENDPOINT */
|
||||
0x81, /* bEndpointAddress: UE_DIR_IN | EHCI_INTR_ENDPT */
|
||||
0x81, /* bEndpointAddress: UE_DIR_IN | EHCI_INTR_ENDPT */
|
||||
3, /* bmAttributes: UE_INTERRUPT */
|
||||
8, 0, /* wMaxPacketSize */
|
||||
8, 0, /* wMaxPacketSize */
|
||||
255 /* bInterval */
|
||||
},
|
||||
};
|
||||
@@ -143,7 +144,8 @@ struct pci_device_id ehci_usb_pci_table[] =
|
||||
}
|
||||
};
|
||||
|
||||
static struct ehci {
|
||||
static struct ehci
|
||||
{
|
||||
/* ------- common part -------- */
|
||||
long handle; /* PCI BIOS */
|
||||
const struct pci_device_id *ent;
|
||||
@@ -195,6 +197,7 @@ static void cache_qh(struct QH *qh, int flush)
|
||||
struct qTD *qtd;
|
||||
struct qTD *next;
|
||||
static struct qTD *first_qtd;
|
||||
|
||||
/* Walk the QH list and flush/invalidate all entries */
|
||||
while(1)
|
||||
{
|
||||
@@ -205,6 +208,7 @@ static void cache_qh(struct QH *qh, int flush)
|
||||
qh = (struct QH *)(swpl(qh->qh_link) + gehci.dma_offset);
|
||||
}
|
||||
qh = qh_addr(qh);
|
||||
|
||||
/* Save first qTD pointer, needed for invalidating pass on this QH */
|
||||
if (flush)
|
||||
{
|
||||
@@ -215,6 +219,7 @@ static void cache_qh(struct QH *qh, int flush)
|
||||
}
|
||||
else
|
||||
qtd = first_qtd;
|
||||
|
||||
/* Walk the qTD list and flush/invalidate all entries */
|
||||
while(1)
|
||||
{
|
||||
@@ -255,7 +260,7 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
|
||||
wait(1);
|
||||
usec--;
|
||||
}
|
||||
while(usec > 0);
|
||||
while (usec > 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -269,22 +274,24 @@ static int ehci_reset(void)
|
||||
uint32_t tmp;
|
||||
uint32_t *reg_ptr;
|
||||
int ret = 0;
|
||||
if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC)
|
||||
&& (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2))
|
||||
|
||||
if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC) && (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2))
|
||||
{
|
||||
debug("ehci_reset set 48MHz clock\r\n");
|
||||
pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator
|
||||
}
|
||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
debug("cmd: 0x%08x\r\n", cmd);
|
||||
debug("%s cmd: 0x%08x\r\n", __FUNCTION__, cmd);
|
||||
cmd |= CMD_RESET;
|
||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||
ret = handshake((uint32_t *)&gehci.hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000);
|
||||
ret = handshake((uint32_t *) &gehci.hcor->or_usbcmd, CMD_RESET, 0, 250);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
err("EHCI fail to reset");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ehci_is_TDI())
|
||||
{
|
||||
reg_ptr = (uint32_t *)((u8 *)gehci.hcor + USBMODE);
|
||||
@@ -307,6 +314,7 @@ static void *ehci_alloc(size_t sz, size_t align)
|
||||
p = gehci.qh;
|
||||
ntds = 0;
|
||||
break;
|
||||
|
||||
case sizeof(struct qTD):
|
||||
if (ntds == 3)
|
||||
{
|
||||
@@ -316,6 +324,7 @@ static void *ehci_alloc(size_t sz, size_t align)
|
||||
p = gehci.td[ntds];
|
||||
ntds++;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown allocation size\r\n");
|
||||
return NULL;
|
||||
@@ -326,11 +335,15 @@ static void *ehci_alloc(size_t sz, size_t align)
|
||||
|
||||
static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
|
||||
{
|
||||
uint32_t addr, delta, next;
|
||||
uint32_t addr;
|
||||
uint32_t delta;
|
||||
uint32_t next;
|
||||
int idx;
|
||||
|
||||
addr = (uint32_t)buf;
|
||||
idx = 0;
|
||||
while(idx < 5)
|
||||
|
||||
while (idx < 5)
|
||||
{
|
||||
td->qt_buffer[idx] = swpl(addr - gehci.dma_offset);
|
||||
next = (addr + 4096) & ~4095;
|
||||
@@ -341,6 +354,7 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
|
||||
addr = next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx == 5)
|
||||
{
|
||||
debug("out of buffer pointers (%u bytes left)\r\n", sz);
|
||||
@@ -360,27 +374,46 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
uint32_t c, toggle;
|
||||
uint32_t cmd;
|
||||
int ret = 0;
|
||||
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\r\n", dev, pipe, buffer, length, req);
|
||||
|
||||
debug("%s: dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\r\n", __FUNCTION__, dev, pipe, buffer, length, req);
|
||||
|
||||
if (req != NULL)
|
||||
debug("ehci_submit_async req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\r\n",
|
||||
req->request, req->request, req->requesttype, req->requesttype, swpw(req->value), swpw(req->value), swpw(req->index));
|
||||
req->request, req->request,
|
||||
req->requesttype, req->requesttype,
|
||||
swpw(req->value), swpw(req->value), swpw(req->index));
|
||||
|
||||
qh = ehci_alloc(sizeof(struct QH), 32);
|
||||
if (qh == NULL)
|
||||
{
|
||||
debug("unable to allocate QH\r\n");
|
||||
return -1;
|
||||
}
|
||||
qh->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||
qh->qh_link = swpl(((uint32_t) gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||
|
||||
c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0;
|
||||
endpt = (8 << 28) | (c << 27) | (usb_maxpacket(dev, pipe) << 16) | (0 << 15) | (1 << 14) | (usb_pipespeed(pipe) << 12) | (usb_pipeendpoint(pipe) << 8) | (0 << 7) | (usb_pipedevice(pipe) << 0);
|
||||
endpt = (8 << 28) |
|
||||
(c << 27) |
|
||||
(usb_maxpacket(dev, pipe) << 16) |
|
||||
(0 << 15) |
|
||||
(1 << 14) |
|
||||
(usb_pipespeed(pipe) << 12) |
|
||||
(usb_pipeendpoint(pipe) << 8) |
|
||||
(0 << 7) |
|
||||
(usb_pipedevice(pipe) << 0);
|
||||
qh->qh_endpt1 = swpl(endpt);
|
||||
endpt = (1 << 30) | (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
|
||||
endpt = (1 << 30) |
|
||||
(dev->portnr << 23) |
|
||||
(dev->parent->devnum << 16) |
|
||||
(0 << 8) |
|
||||
(0 << 0);
|
||||
qh->qh_endpt2 = swpl(endpt);
|
||||
qh->qh_overlay.qt_next = swpl(QT_NEXT_TERMINATE);
|
||||
qh->qh_overlay.qt_altnext = swpl(QT_NEXT_TERMINATE);
|
||||
td = NULL;
|
||||
tdp = &qh->qh_overlay.qt_next;
|
||||
toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
|
||||
|
||||
if (req != NULL)
|
||||
{
|
||||
td = ehci_alloc(sizeof(struct qTD), 32);
|
||||
@@ -403,6 +436,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
tdp = &td->qt_next;
|
||||
toggle = 1;
|
||||
}
|
||||
|
||||
if (length > 0 || req == NULL)
|
||||
{
|
||||
td = ehci_alloc(sizeof(struct qTD), 32);
|
||||
@@ -424,6 +458,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
*tdp = swpl((uint32_t)td - gehci.dma_offset);
|
||||
tdp = &td->qt_next;
|
||||
}
|
||||
|
||||
if (req != NULL)
|
||||
{
|
||||
td = ehci_alloc(sizeof(struct qTD), 32);
|
||||
@@ -439,6 +474,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
*tdp = swpl((uint32_t)td - gehci.dma_offset);
|
||||
tdp = &td->qt_next;
|
||||
}
|
||||
|
||||
gehci.qh_list->qh_link = swpl(((uint32_t)qh - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||
/* Flush dcache */
|
||||
ehci_flush_dcache(gehci.qh_list);
|
||||
@@ -448,6 +484,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
cmd |= CMD_ASE;
|
||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||
|
||||
ret = handshake((uint32_t *)&gehci.hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -479,6 +516,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
goto fail;
|
||||
}
|
||||
gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||
|
||||
token = swpl(qh->qh_overlay.qt_token);
|
||||
if (!(token & 0x80))
|
||||
{
|
||||
@@ -490,17 +528,21 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle);
|
||||
dev->status = 0;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
dev->status = USB_ST_STALLED;
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
case 0x20:
|
||||
dev->status = USB_ST_BUF_ERR;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
case 0x10:
|
||||
dev->status = USB_ST_BABBLE_DET;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->status = USB_ST_CRC_ERR;
|
||||
break;
|
||||
@@ -511,11 +553,12 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
{
|
||||
dev->act_len = 0;
|
||||
debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\r\n",
|
||||
dev->devnum, ehci_readl(&gehci.hcor->or_usbsts), ehci_readl(&gehci.hcor->or_portsc[0]), ehci_readl(&gehci.hcor->or_portsc[1]));
|
||||
dev->devnum, ehci_readl(&gehci.hcor->or_usbsts),
|
||||
ehci_readl(&gehci.hcor->or_portsc[0]), ehci_readl(&gehci.hcor->or_portsc[1]));
|
||||
}
|
||||
return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
|
||||
fail:
|
||||
td = (void *)swpl(qh->qh_overlay.qt_next);
|
||||
td = (void *) swpl(qh->qh_overlay.qt_next);
|
||||
if (td != (void *)QT_NEXT_TERMINATE)
|
||||
td = (struct qTD *)(gehci.dma_offset + (uint32_t)td);
|
||||
while(td != (void *)QT_NEXT_TERMINATE)
|
||||
@@ -530,9 +573,13 @@ fail:
|
||||
if (ehci_readl(&gehci.hcor->or_usbsts) & STS_HSE) /* Host System Error */
|
||||
{
|
||||
unsigned short status = pci_read_config_word(gehci.handle, PCISR);
|
||||
err("EHCI Host System Error, controller usb-%s disabled\r\n(SR:0x%04X%s%s%s%s%s%s)", gehci.slot_name, status & 0xFFFF,
|
||||
status & 0x8000 ? ", Parity error" : "", status & 0x4000 ? ", Signaled system error" : "", status & 0x2000 ? ", Received master abort" : "",
|
||||
status & 0x1000 ? ", Received target abort" : "", status & 0x800 ? ", Signaled target abort" : "", status & 0x100 ? ", Data parity error" : "");
|
||||
err("EHCI Host System Error, controller usb-%s disabled\r\n(SR:0x%04X%s%s%s%s%s%s)",
|
||||
gehci.slot_name, status & 0xFFFF, status & 0x8000 ? ", Parity error" : "",
|
||||
status & 0x4000 ? ", Signaled system error" : "",
|
||||
status & 0x2000 ? ", Received master abort" : "",
|
||||
status & 0x1000 ? ", Received target abort" : "",
|
||||
status & 0x800 ? ", Signaled target abort" : "",
|
||||
status & 0x100 ? ", Data parity error" : "");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -574,11 +621,13 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
srcptr = &gehci.descriptor->device;
|
||||
srclen = 0x12;
|
||||
break;
|
||||
|
||||
case USB_DT_CONFIG:
|
||||
debug("USB_DT_CONFIG config\r\n");
|
||||
srcptr = &gehci.descriptor->config;
|
||||
srclen = 0x19;
|
||||
break;
|
||||
|
||||
case USB_DT_STRING:
|
||||
debug("USB_DT_STRING config\r\n");
|
||||
switch(swpw(req->value) & 0xff)
|
||||
@@ -587,14 +636,17 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
srcptr = "\4\3\1\0";
|
||||
srclen = 4;
|
||||
break;
|
||||
|
||||
case 1: /* Vendor */
|
||||
srcptr = "\2\3";
|
||||
srclen = 2;
|
||||
break;
|
||||
|
||||
case 2: /* Product */
|
||||
srcptr = "\34\3E\0H\0C\0I\0 \0R\0o\0o\0t\0 \0H\0u\0b\0";
|
||||
srclen = 28;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown value DT_STRING %x\r\n",
|
||||
swpw(req->value));
|
||||
@@ -606,6 +658,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
goto unknown;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
|
||||
switch(swpw(req->value) >> 8)
|
||||
{
|
||||
@@ -614,28 +667,34 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
srcptr = &gehci.descriptor->hub;
|
||||
srclen = 0x8;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown value %x\r\n", swpw(req->value));
|
||||
goto unknown;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
|
||||
debug("USB_REQ_SET_ADDRESS\r\n");
|
||||
rootdev = swpw(req->value);
|
||||
break;
|
||||
|
||||
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
|
||||
debug("USB_REQ_SET_CONFIGURATION\r\n");
|
||||
/* Nothing to do */
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
|
||||
tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */
|
||||
tmpbuf[1] = 0;
|
||||
srcptr = tmpbuf;
|
||||
srclen = 2;
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
|
||||
memset(tmpbuf, 0, 4);
|
||||
reg = ehci_readl(status_reg);
|
||||
|
||||
if ((reg & EHCI_PS_PR) && (portreset & (1 << swpw(req->index))))
|
||||
{
|
||||
int ret;
|
||||
@@ -646,11 +705,12 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
if (!ret)
|
||||
{
|
||||
tmpbuf[0] |= USB_PORT_STAT_RESET;
|
||||
reg = ehci_readl(status_reg);
|
||||
reg = ehci_readl(status_reg);
|
||||
}
|
||||
else
|
||||
err("port(%d) reset error", swpw(req->index) - 1);
|
||||
}
|
||||
|
||||
if (reg & EHCI_PS_CS)
|
||||
tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
|
||||
if (reg & EHCI_PS_PE)
|
||||
@@ -665,14 +725,22 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
{
|
||||
switch((reg >> 26) & 3)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; break;
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
default: tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; break;
|
||||
default:
|
||||
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
||||
|
||||
if (reg & EHCI_PS_CSC)
|
||||
tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
|
||||
if (reg & EHCI_PS_PEC)
|
||||
@@ -681,9 +749,11 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
|
||||
if (portreset & (1 << swpw(req->index)))
|
||||
tmpbuf[2] |= USB_PORT_STAT_C_RESET;
|
||||
|
||||
srcptr = tmpbuf;
|
||||
srclen = 4;
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
|
||||
reg = ehci_readl(status_reg);
|
||||
reg &= ~EHCI_PS_CLEAR;
|
||||
@@ -693,6 +763,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
reg |= EHCI_PS_PE;
|
||||
ehci_writel(status_reg, reg);
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_POWER:
|
||||
if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams)))
|
||||
{
|
||||
@@ -700,6 +771,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
ehci_writel(status_reg, reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_RESET:
|
||||
if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && !ehci_is_TDI() && EHCI_PS_IS_LOWSPEED(reg))
|
||||
{
|
||||
@@ -723,13 +795,15 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
portreset |= (1 << swpw(req->index));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown feature %x\r\n", swpw(req->value));
|
||||
goto unknown;
|
||||
}
|
||||
/* unblock posted writes */
|
||||
(void)ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
(void) ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
break;
|
||||
|
||||
case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
|
||||
reg = ehci_readl(status_reg);
|
||||
switch(swpw(req->value))
|
||||
@@ -737,29 +811,35 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
case USB_PORT_FEAT_ENABLE:
|
||||
reg &= ~EHCI_PS_PE;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_POWER:
|
||||
if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams)))
|
||||
reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_OVER_CURRENT:
|
||||
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
portreset &= ~(1 << swpw(req->index));
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown feature %x\r\n", swpw(req->value));
|
||||
goto unknown;
|
||||
}
|
||||
ehci_writel(status_reg, reg);
|
||||
/* unblock posted write */
|
||||
(void)ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
(void) ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Unknown request\r\n");
|
||||
goto unknown;
|
||||
@@ -775,7 +855,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
return 0;
|
||||
unknown:
|
||||
debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\r\n",
|
||||
req->requesttype, req->request, swpw(req->value), swpw(req->index), swpw(req->length));
|
||||
req->requesttype, req->request, swpw(req->value), swpw(req->index), swpw(req->length));
|
||||
dev->act_len = 0;
|
||||
dev->status = USB_ST_STALLED;
|
||||
return -1;
|
||||
@@ -797,6 +877,7 @@ static int hc_interrupt(struct ehci *ehci)
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (companion & (1 << i))
|
||||
{
|
||||
/* Low speed device, give up ownership. */
|
||||
@@ -806,7 +887,8 @@ static int hc_interrupt(struct ehci *ehci)
|
||||
i--;
|
||||
}
|
||||
}
|
||||
ehci_writel(&ehci->hcor->or_usbsts, status);
|
||||
ehci_writel(&ehci->hcor->or_usbsts, status);
|
||||
|
||||
return(1); /* interrupt was from this card */
|
||||
}
|
||||
|
||||
@@ -823,11 +905,13 @@ static int handle_usb_interrupt(struct ehci *ehci)
|
||||
static void hc_free_buffers(struct ehci *ehci)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ehci->descriptor != NULL)
|
||||
{
|
||||
usb_free(ehci->descriptor);
|
||||
ehci->descriptor = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (ehci->td_unaligned[i] != NULL)
|
||||
@@ -836,11 +920,13 @@ static void hc_free_buffers(struct ehci *ehci)
|
||||
ehci->td_unaligned[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ehci->qh_unaligned != NULL)
|
||||
{
|
||||
usb_free(ehci->qh_unaligned);
|
||||
ehci->qh_unaligned = NULL;
|
||||
}
|
||||
|
||||
if (ehci->qh_list_unaligned != NULL)
|
||||
{
|
||||
usb_free(ehci->qh_list_unaligned);
|
||||
@@ -855,6 +941,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
uint32_t cmd;
|
||||
uint32_t usb_base_addr = 0xFFFFFFFF;
|
||||
struct pci_rd *pci_rsc_desc;
|
||||
|
||||
pci_rsc_desc = pci_get_resource(handle); /* USB EHCI */
|
||||
if (handle && (ent != NULL))
|
||||
{
|
||||
@@ -864,6 +951,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
}
|
||||
else if (!gehci.handle) /* for restart USB cmd */
|
||||
return(-1);
|
||||
|
||||
gehci.qh_list_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32);
|
||||
if (gehci.qh_list_unaligned == NULL)
|
||||
{
|
||||
@@ -871,9 +959,11 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
hc_free_buffers(&gehci);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
gehci.qh_list = (struct QH *)(((uint32_t)gehci.qh_list_unaligned + 31) & ~31);
|
||||
memset(gehci.qh_list, 0, sizeof(struct QH));
|
||||
gehci.qh_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32);
|
||||
|
||||
if (gehci.qh_unaligned == NULL)
|
||||
{
|
||||
debug("QHs malloc failed");
|
||||
@@ -882,6 +972,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
}
|
||||
gehci.qh = (struct QH *)(((uint32_t)gehci.qh_unaligned + 31) & ~31);
|
||||
memset(gehci.qh, 0, sizeof(struct QH));
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
gehci.td_unaligned[i] = (struct qTD *)usb_malloc(sizeof(struct qTD) + 32);
|
||||
@@ -894,6 +985,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
gehci.td[i] = (struct qTD *)(((uint32_t)gehci.td_unaligned[i] + 31) & ~31);
|
||||
memset(gehci.td[i], 0, sizeof(struct qTD));
|
||||
}
|
||||
|
||||
gehci.descriptor = (struct descriptor *)usb_malloc(sizeof(struct descriptor));
|
||||
if (gehci.descriptor == NULL)
|
||||
{
|
||||
@@ -902,6 +994,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
return(-1);
|
||||
}
|
||||
memcpy(gehci.descriptor, &rom_descriptor, sizeof(struct descriptor));
|
||||
|
||||
if ((long) pci_rsc_desc >= 0)
|
||||
{
|
||||
unsigned short flags;
|
||||
@@ -925,18 +1018,20 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
flags = pci_rsc_desc->flags;
|
||||
pci_rsc_desc = (struct pci_rd *)((uint32_t)pci_rsc_desc->next + (uint32_t)pci_rsc_desc);
|
||||
}
|
||||
while(!(flags & FLG_LAST));
|
||||
while (!(flags & FLG_LAST));
|
||||
}
|
||||
else
|
||||
{
|
||||
hc_free_buffers(&gehci);
|
||||
return(-1); /* get_resource error */
|
||||
}
|
||||
|
||||
if (usb_base_addr == 0xFFFFFFFF)
|
||||
{
|
||||
hc_free_buffers(&gehci);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (handle && (ent != NULL))
|
||||
{
|
||||
switch(ent->vendor)
|
||||
@@ -955,6 +1050,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
hc_free_buffers(&gehci);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Set head of reclaim list */
|
||||
gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||
gehci.qh_list->qh_endpt1 = swpl((1 << 15) | (USB_SPEED_HIGH << 12));
|
||||
@@ -967,6 +1063,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
reg = ehci_readl(&gehci.hccr->cr_hcsparams);
|
||||
gehci.descriptor->hub.bNbrPorts = HCS_N_PORTS(reg);
|
||||
info("Register %x NbrPorts %d", reg, gehci.descriptor->hub.bNbrPorts);
|
||||
|
||||
/* Port Indicators */
|
||||
if (HCS_INDICATOR(reg))
|
||||
gehci.descriptor->hub.wHubCharacteristics |= 0x80;
|
||||
@@ -1002,19 +1099,24 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
int ehci_usb_lowlevel_stop(void *priv)
|
||||
{
|
||||
uint32_t cmd;
|
||||
|
||||
if (priv);
|
||||
if (!ehci_inited)
|
||||
return(0);
|
||||
/* turn off interrupts */
|
||||
|
||||
/* turn off interrupts */
|
||||
ehci_writel(&gehci.hcor->or_usbintr, 0);
|
||||
pci_unhook_interrupt(gehci.handle);
|
||||
|
||||
/* stop the controller */
|
||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
cmd &= ~CMD_RUN;
|
||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||
|
||||
/* turn off all ports => todo */
|
||||
/* use the companions */
|
||||
ehci_writel(&gehci.hcor->or_configflag, 0);
|
||||
|
||||
/* unblock posted write */
|
||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
ehci_reset();
|
||||
@@ -1040,6 +1142,7 @@ int ehci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (usb_pipedevice(pipe) == rootdev)
|
||||
{
|
||||
if (rootdev == 0)
|
||||
|
||||
Reference in New Issue
Block a user