#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
#endif
+/*
+ * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt.
+ * Let's time out after 8 to have a little safety margin on top of that.
+ */
+#define HCHALT_TIMEOUT (8 * 1000)
+
static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
#define ALIGN_END_ADDR(type, ptr, size) \
return ret;
}
+static int ehci_shutdown(struct ehci_ctrl *ctrl)
+{
+ int i, ret = 0;
+ uint32_t cmd, reg;
+
+ if (!ctrl || !ctrl->hcor)
+ return -EINVAL;
+
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
+ cmd &= ~(CMD_PSE | CMD_ASE);
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+ ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0,
+ 100 * 1000);
+
+ if (!ret) {
+ for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) {
+ reg = ehci_readl(&ctrl->hcor->or_portsc[i]);
+ reg |= EHCI_PS_SUSP;
+ ehci_writel(&ctrl->hcor->or_portsc[i], reg);
+ }
+
+ cmd &= ~CMD_RUN;
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+ ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT,
+ HCHALT_TIMEOUT);
+ }
+
+ if (ret)
+ puts("EHCI failed to shut down host controller.\n");
+
+ return ret;
+}
+
static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
{
uint32_t delta, next;
}
break;
case USB_PORT_FEAT_TEST:
+ ehci_shutdown(ctrl);
reg &= ~(0xf << 16);
reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16;
ehci_writel(status_reg, reg);
int usb_lowlevel_stop(int index)
{
+ ehci_shutdown(&ehcic[index]);
return ehci_hcd_stop(index);
}
-int usb_lowlevel_init(int index, void **controller)
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
{
uint32_t reg;
uint32_t cmd;
struct QH *qh_list;
struct QH *periodic;
int i;
+ int rc;
- if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
- return -1;
+ rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor);
+ if (rc)
+ return rc;
+ if (init == USB_INIT_DEVICE)
+ goto done;
/* EHCI spec section 4.1 */
if (ehci_reset(index))
return -1;
#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
- if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
- return -1;
+ rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor);
+ if (rc)
+ return rc;
#endif
/* Set the high address word (aka segment) for 64-bit controller */
if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1)
- ehci_writel(ehcic[index].hcor->or_ctrldssegment, 0);
+ ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0);
qh_list = &ehcic[index].qh_list;
printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
ehcic[index].rootdev = 0;
-
+done:
*controller = &ehcic[index];
return 0;
}