|
@@ -30,12 +30,17 @@
|
|
|
|
|
|
#include "ehci.h"
|
|
#include "ehci.h"
|
|
|
|
|
|
-int rootdev;
|
|
|
|
-struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
|
|
|
|
-volatile struct ehci_hcor *hcor;
|
|
|
|
|
|
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
|
|
|
|
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
|
|
|
|
+#endif
|
|
|
|
|
|
-static uint16_t portreset;
|
|
|
|
-DEFINE_ALIGN_BUFFER(struct QH, qh_list, 1, USB_DMA_MINALIGN);
|
|
|
|
|
|
+static struct ehci_ctrl {
|
|
|
|
+ struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
|
|
|
|
+ struct ehci_hcor *hcor;
|
|
|
|
+ int rootdev;
|
|
|
|
+ uint16_t portreset;
|
|
|
|
+ struct QH qh_list __attribute__((aligned(USB_DMA_MINALIGN)));
|
|
|
|
+} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
|
|
|
|
|
|
#define ALIGN_END_ADDR(type, ptr, size) \
|
|
#define ALIGN_END_ADDR(type, ptr, size) \
|
|
((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
|
|
((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
|
|
@@ -136,24 +141,25 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
-static int ehci_reset(void)
|
|
|
|
|
|
+static int ehci_reset(int index)
|
|
{
|
|
{
|
|
uint32_t cmd;
|
|
uint32_t cmd;
|
|
uint32_t tmp;
|
|
uint32_t tmp;
|
|
uint32_t *reg_ptr;
|
|
uint32_t *reg_ptr;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- cmd = ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
|
|
cmd = (cmd & ~CMD_RUN) | CMD_RESET;
|
|
cmd = (cmd & ~CMD_RUN) | CMD_RESET;
|
|
- ehci_writel(&hcor->or_usbcmd, cmd);
|
|
|
|
- ret = handshake((uint32_t *)&hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000);
|
|
|
|
|
|
+ ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd);
|
|
|
|
+ ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd,
|
|
|
|
+ CMD_RESET, 0, 250 * 1000);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
printf("EHCI fail to reset\n");
|
|
printf("EHCI fail to reset\n");
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
if (ehci_is_TDI()) {
|
|
if (ehci_is_TDI()) {
|
|
- reg_ptr = (uint32_t *)((u8 *)hcor + USBMODE);
|
|
|
|
|
|
+ reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE);
|
|
tmp = ehci_readl(reg_ptr);
|
|
tmp = ehci_readl(reg_ptr);
|
|
tmp |= USBMODE_CM_HC;
|
|
tmp |= USBMODE_CM_HC;
|
|
#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
|
|
#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
|
|
@@ -163,10 +169,10 @@ static int ehci_reset(void)
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
|
|
#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
|
|
- cmd = ehci_readl(&hcor->or_txfilltuning);
|
|
|
|
|
|
+ cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning);
|
|
cmd &= ~TXFIFO_THRESH_MASK;
|
|
cmd &= ~TXFIFO_THRESH_MASK;
|
|
cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH);
|
|
cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH);
|
|
- ehci_writel(&hcor->or_txfilltuning, cmd);
|
|
|
|
|
|
+ ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd);
|
|
#endif
|
|
#endif
|
|
out:
|
|
out:
|
|
return ret;
|
|
return ret;
|
|
@@ -212,7 +218,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
struct qTD *qtd;
|
|
struct qTD *qtd;
|
|
int qtd_count = 0;
|
|
int qtd_count = 0;
|
|
int qtd_counter = 0;
|
|
int qtd_counter = 0;
|
|
-
|
|
|
|
volatile struct qTD *vtd;
|
|
volatile struct qTD *vtd;
|
|
unsigned long ts;
|
|
unsigned long ts;
|
|
uint32_t *tdp;
|
|
uint32_t *tdp;
|
|
@@ -221,6 +226,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
uint32_t cmd;
|
|
uint32_t cmd;
|
|
int timeout;
|
|
int timeout;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
+ struct ehci_ctrl *ctrl = dev->controller;
|
|
|
|
|
|
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
|
|
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
|
|
buffer, length, req);
|
|
buffer, length, req);
|
|
@@ -311,7 +317,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
* qh_overlay.qt_next ...... 13-10 H
|
|
* qh_overlay.qt_next ...... 13-10 H
|
|
* - qh_overlay.qt_altnext
|
|
* - qh_overlay.qt_altnext
|
|
*/
|
|
*/
|
|
- qh->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
|
|
|
|
|
|
+ qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH);
|
|
c = usb_pipespeed(pipe) != USB_SPEED_HIGH && !usb_pipeendpoint(pipe);
|
|
c = usb_pipespeed(pipe) != USB_SPEED_HIGH && !usb_pipeendpoint(pipe);
|
|
maxpacket = usb_maxpacket(dev, pipe);
|
|
maxpacket = usb_maxpacket(dev, pipe);
|
|
endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
|
|
endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
|
|
@@ -445,27 +451,27 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
tdp = &qtd[qtd_counter++].qt_next;
|
|
tdp = &qtd[qtd_counter++].qt_next;
|
|
}
|
|
}
|
|
|
|
|
|
- qh_list->qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
|
|
|
|
|
|
+ ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
|
|
|
|
|
|
/* Flush dcache */
|
|
/* Flush dcache */
|
|
- flush_dcache_range((uint32_t)qh_list,
|
|
|
|
- ALIGN_END_ADDR(struct QH, qh_list, 1));
|
|
|
|
|
|
+ flush_dcache_range((uint32_t)&ctrl->qh_list,
|
|
|
|
+ ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
|
|
flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
|
|
flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
|
|
flush_dcache_range((uint32_t)qtd,
|
|
flush_dcache_range((uint32_t)qtd,
|
|
ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
|
|
ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
|
|
|
|
|
|
/* Set async. queue head pointer. */
|
|
/* Set async. queue head pointer. */
|
|
- ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list);
|
|
|
|
|
|
+ ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list);
|
|
|
|
|
|
- usbsts = ehci_readl(&hcor->or_usbsts);
|
|
|
|
- ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
|
|
|
|
|
|
+ usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
|
|
|
|
+ ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
|
|
|
|
|
|
/* Enable async. schedule. */
|
|
/* Enable async. schedule. */
|
|
- cmd = ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
|
|
cmd |= CMD_ASE;
|
|
cmd |= CMD_ASE;
|
|
- ehci_writel(&hcor->or_usbcmd, cmd);
|
|
|
|
|
|
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
|
|
|
|
|
|
- ret = handshake((uint32_t *)&hcor->or_usbsts, STS_ASS, STS_ASS,
|
|
|
|
|
|
+ ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
|
|
100 * 1000);
|
|
100 * 1000);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
printf("EHCI fail timeout STS_ASS set\n");
|
|
printf("EHCI fail timeout STS_ASS set\n");
|
|
@@ -478,8 +484,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
timeout = USB_TIMEOUT_MS(pipe);
|
|
timeout = USB_TIMEOUT_MS(pipe);
|
|
do {
|
|
do {
|
|
/* Invalidate dcache */
|
|
/* Invalidate dcache */
|
|
- invalidate_dcache_range((uint32_t)qh_list,
|
|
|
|
- ALIGN_END_ADDR(struct QH, qh_list, 1));
|
|
|
|
|
|
+ invalidate_dcache_range((uint32_t)&ctrl->qh_list,
|
|
|
|
+ ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
|
|
invalidate_dcache_range((uint32_t)qh,
|
|
invalidate_dcache_range((uint32_t)qh,
|
|
ALIGN_END_ADDR(struct QH, qh, 1));
|
|
ALIGN_END_ADDR(struct QH, qh, 1));
|
|
invalidate_dcache_range((uint32_t)qtd,
|
|
invalidate_dcache_range((uint32_t)qtd,
|
|
@@ -508,11 +514,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
printf("EHCI timed out on TD - token=%#x\n", token);
|
|
printf("EHCI timed out on TD - token=%#x\n", token);
|
|
|
|
|
|
/* Disable async schedule. */
|
|
/* Disable async schedule. */
|
|
- cmd = ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
|
|
cmd &= ~CMD_ASE;
|
|
cmd &= ~CMD_ASE;
|
|
- ehci_writel(&hcor->or_usbcmd, cmd);
|
|
|
|
|
|
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
|
|
|
|
|
|
- ret = handshake((uint32_t *)&hcor->or_usbsts, STS_ASS, 0,
|
|
|
|
|
|
+ ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0,
|
|
100 * 1000);
|
|
100 * 1000);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
printf("EHCI fail timeout STS_ASS reset\n");
|
|
printf("EHCI fail timeout STS_ASS reset\n");
|
|
@@ -551,9 +557,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
} else {
|
|
} else {
|
|
dev->act_len = 0;
|
|
dev->act_len = 0;
|
|
debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
|
|
debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
|
|
- dev->devnum, ehci_readl(&hcor->or_usbsts),
|
|
|
|
- ehci_readl(&hcor->or_portsc[0]),
|
|
|
|
- ehci_readl(&hcor->or_portsc[1]));
|
|
|
|
|
|
+ dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts),
|
|
|
|
+ ehci_readl(&ctrl->hcor->or_portsc[0]),
|
|
|
|
+ ehci_readl(&ctrl->hcor->or_portsc[1]));
|
|
}
|
|
}
|
|
|
|
|
|
free(qtd);
|
|
free(qtd);
|
|
@@ -584,13 +590,14 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
int len, srclen;
|
|
int len, srclen;
|
|
uint32_t reg;
|
|
uint32_t reg;
|
|
uint32_t *status_reg;
|
|
uint32_t *status_reg;
|
|
|
|
+ struct ehci_ctrl *ctrl = dev->controller;
|
|
|
|
|
|
if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
|
|
if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
|
|
printf("The request port(%d) is not configured\n",
|
|
printf("The request port(%d) is not configured\n",
|
|
le16_to_cpu(req->index) - 1);
|
|
le16_to_cpu(req->index) - 1);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
- status_reg = (uint32_t *)&hcor->or_portsc[
|
|
|
|
|
|
+ status_reg = (uint32_t *)&ctrl->hcor->or_portsc[
|
|
le16_to_cpu(req->index) - 1];
|
|
le16_to_cpu(req->index) - 1];
|
|
srclen = 0;
|
|
srclen = 0;
|
|
|
|
|
|
@@ -658,7 +665,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
break;
|
|
break;
|
|
case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
|
|
case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
|
|
debug("USB_REQ_SET_ADDRESS\n");
|
|
debug("USB_REQ_SET_ADDRESS\n");
|
|
- rootdev = le16_to_cpu(req->value);
|
|
|
|
|
|
+ ctrl->rootdev = le16_to_cpu(req->value);
|
|
break;
|
|
break;
|
|
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
|
|
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
|
|
debug("USB_REQ_SET_CONFIGURATION\n");
|
|
debug("USB_REQ_SET_CONFIGURATION\n");
|
|
@@ -708,7 +715,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
|
|
tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
|
|
if (reg & EHCI_PS_OCC)
|
|
if (reg & EHCI_PS_OCC)
|
|
tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
|
|
tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
|
|
- if (portreset & (1 << le16_to_cpu(req->index)))
|
|
|
|
|
|
+ if (ctrl->portreset & (1 << le16_to_cpu(req->index)))
|
|
tmpbuf[2] |= USB_PORT_STAT_C_RESET;
|
|
tmpbuf[2] |= USB_PORT_STAT_C_RESET;
|
|
|
|
|
|
srcptr = tmpbuf;
|
|
srcptr = tmpbuf;
|
|
@@ -723,7 +730,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
ehci_writel(status_reg, reg);
|
|
ehci_writel(status_reg, reg);
|
|
break;
|
|
break;
|
|
case USB_PORT_FEAT_POWER:
|
|
case USB_PORT_FEAT_POWER:
|
|
- if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams))) {
|
|
|
|
|
|
+ if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) {
|
|
reg |= EHCI_PS_PP;
|
|
reg |= EHCI_PS_PP;
|
|
ehci_writel(status_reg, reg);
|
|
ehci_writel(status_reg, reg);
|
|
}
|
|
}
|
|
@@ -760,7 +767,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
ret = handshake(status_reg, EHCI_PS_PR, 0,
|
|
ret = handshake(status_reg, EHCI_PS_PR, 0,
|
|
2 * 1000);
|
|
2 * 1000);
|
|
if (!ret)
|
|
if (!ret)
|
|
- portreset |=
|
|
|
|
|
|
+ ctrl->portreset |=
|
|
1 << le16_to_cpu(req->index);
|
|
1 << le16_to_cpu(req->index);
|
|
else
|
|
else
|
|
printf("port(%d) reset error\n",
|
|
printf("port(%d) reset error\n",
|
|
@@ -772,7 +779,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
goto unknown;
|
|
goto unknown;
|
|
}
|
|
}
|
|
/* unblock posted writes */
|
|
/* unblock posted writes */
|
|
- (void) ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ (void) ehci_readl(&ctrl->hcor->or_usbcmd);
|
|
break;
|
|
break;
|
|
case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
|
|
case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
|
|
reg = ehci_readl(status_reg);
|
|
reg = ehci_readl(status_reg);
|
|
@@ -784,7 +791,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
|
|
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
|
|
break;
|
|
break;
|
|
case USB_PORT_FEAT_POWER:
|
|
case USB_PORT_FEAT_POWER:
|
|
- if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams)))
|
|
|
|
|
|
+ if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams)))
|
|
reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
|
|
reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
|
|
case USB_PORT_FEAT_C_CONNECTION:
|
|
case USB_PORT_FEAT_C_CONNECTION:
|
|
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
|
|
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
|
|
@@ -793,7 +800,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
|
|
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
|
|
break;
|
|
break;
|
|
case USB_PORT_FEAT_C_RESET:
|
|
case USB_PORT_FEAT_C_RESET:
|
|
- portreset &= ~(1 << le16_to_cpu(req->index));
|
|
|
|
|
|
+ ctrl->portreset &= ~(1 << le16_to_cpu(req->index));
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
debug("unknown feature %x\n", le16_to_cpu(req->value));
|
|
debug("unknown feature %x\n", le16_to_cpu(req->value));
|
|
@@ -801,7 +808,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
}
|
|
}
|
|
ehci_writel(status_reg, reg);
|
|
ehci_writel(status_reg, reg);
|
|
/* unblock posted write */
|
|
/* unblock posted write */
|
|
- (void) ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ (void) ehci_readl(&ctrl->hcor->or_usbcmd);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
debug("Unknown request\n");
|
|
debug("Unknown request\n");
|
|
@@ -831,26 +838,29 @@ unknown:
|
|
|
|
|
|
int usb_lowlevel_stop(int index)
|
|
int usb_lowlevel_stop(int index)
|
|
{
|
|
{
|
|
- return ehci_hcd_stop();
|
|
|
|
|
|
+ return ehci_hcd_stop(index);
|
|
}
|
|
}
|
|
|
|
|
|
int usb_lowlevel_init(int index, void **controller)
|
|
int usb_lowlevel_init(int index, void **controller)
|
|
{
|
|
{
|
|
uint32_t reg;
|
|
uint32_t reg;
|
|
uint32_t cmd;
|
|
uint32_t cmd;
|
|
|
|
+ struct QH *qh_list;
|
|
|
|
|
|
- if (ehci_hcd_init())
|
|
|
|
|
|
+ if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
/* EHCI spec section 4.1 */
|
|
/* EHCI spec section 4.1 */
|
|
- if (ehci_reset())
|
|
|
|
|
|
+ if (ehci_reset(index))
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
|
|
#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
|
|
- if (ehci_hcd_init())
|
|
|
|
|
|
+ if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
|
|
return -1;
|
|
return -1;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+ qh_list = &ehcic[index].qh_list;
|
|
|
|
+
|
|
/* Set head of reclaim list */
|
|
/* Set head of reclaim list */
|
|
memset(qh_list, 0, sizeof(*qh_list));
|
|
memset(qh_list, 0, sizeof(*qh_list));
|
|
qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
|
|
qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
|
|
@@ -862,7 +872,7 @@ int usb_lowlevel_init(int index, void **controller)
|
|
qh_list->qh_overlay.qt_token =
|
|
qh_list->qh_overlay.qt_token =
|
|
cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED));
|
|
cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED));
|
|
|
|
|
|
- reg = ehci_readl(&hccr->cr_hcsparams);
|
|
|
|
|
|
+ reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams);
|
|
descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
|
|
descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
|
|
printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
|
|
printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
|
|
/* Port Indicators */
|
|
/* Port Indicators */
|
|
@@ -875,27 +885,28 @@ int usb_lowlevel_init(int index, void **controller)
|
|
| 0x01, &descriptor.hub.wHubCharacteristics);
|
|
| 0x01, &descriptor.hub.wHubCharacteristics);
|
|
|
|
|
|
/* Start the host controller. */
|
|
/* Start the host controller. */
|
|
- cmd = ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
|
|
/*
|
|
/*
|
|
* Philips, Intel, and maybe others need CMD_RUN before the
|
|
* Philips, Intel, and maybe others need CMD_RUN before the
|
|
* root hub will detect new devices (why?); NEC doesn't
|
|
* root hub will detect new devices (why?); NEC doesn't
|
|
*/
|
|
*/
|
|
cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
|
|
cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
|
|
cmd |= CMD_RUN;
|
|
cmd |= CMD_RUN;
|
|
- ehci_writel(&hcor->or_usbcmd, cmd);
|
|
|
|
|
|
+ ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd);
|
|
|
|
|
|
/* take control over the ports */
|
|
/* take control over the ports */
|
|
- cmd = ehci_readl(&hcor->or_configflag);
|
|
|
|
|
|
+ cmd = ehci_readl(&ehcic[index].hcor->or_configflag);
|
|
cmd |= FLAG_CF;
|
|
cmd |= FLAG_CF;
|
|
- ehci_writel(&hcor->or_configflag, cmd);
|
|
|
|
|
|
+ ehci_writel(&ehcic[index].hcor->or_configflag, cmd);
|
|
/* unblock posted write */
|
|
/* unblock posted write */
|
|
- cmd = ehci_readl(&hcor->or_usbcmd);
|
|
|
|
|
|
+ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
|
|
mdelay(5);
|
|
mdelay(5);
|
|
- reg = HC_VERSION(ehci_readl(&hccr->cr_capbase));
|
|
|
|
|
|
+ reg = HC_VERSION(ehci_readl(&ehcic[index].hccr->cr_capbase));
|
|
printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
|
|
printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
|
|
|
|
|
|
- rootdev = 0;
|
|
|
|
|
|
+ ehcic[index].rootdev = 0;
|
|
|
|
|
|
|
|
+ *controller = &ehcic[index];
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -915,14 +926,15 @@ int
|
|
submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|
int length, struct devrequest *setup)
|
|
int length, struct devrequest *setup)
|
|
{
|
|
{
|
|
|
|
+ struct ehci_ctrl *ctrl = dev->controller;
|
|
|
|
|
|
if (usb_pipetype(pipe) != PIPE_CONTROL) {
|
|
if (usb_pipetype(pipe) != PIPE_CONTROL) {
|
|
debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
|
|
debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- if (usb_pipedevice(pipe) == rootdev) {
|
|
|
|
- if (!rootdev)
|
|
|
|
|
|
+ if (usb_pipedevice(pipe) == ctrl->rootdev) {
|
|
|
|
+ if (!ctrl->rootdev)
|
|
dev->speed = USB_SPEED_HIGH;
|
|
dev->speed = USB_SPEED_HIGH;
|
|
return ehci_submit_root(dev, pipe, buffer, length, setup);
|
|
return ehci_submit_root(dev, pipe, buffer, length, setup);
|
|
}
|
|
}
|