0, /* wHubCharacteristics */
10, /* bPwrOn2PwrGood */
0, /* bHubCntrCurrent */
- {}, /* Device removable */
- {} /* at most 7 ports! XXX */
+ { /* Device removable */
+ } /* at most 7 ports! XXX */
},
{
0x12, /* bLength */
tmp |= USBMODE_CM_HC;
#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
tmp |= USBMODE_BE;
+#else
+ tmp &= ~USBMODE_BE;
#endif
ehci_writel(reg_ptr, tmp);
}
static uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
{
- if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
+ int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams));
+
+ if (port < 0 || port >= max_ports) {
/* Printing the message would cause a scan failure! */
- debug("The request port(%u) is not configured\n", port);
+ debug("The request port(%u) exceeds maximum port number\n",
+ port);
return NULL;
}
{
int i, ret = 0;
uint32_t cmd, reg;
+ int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams));
if (!ctrl || !ctrl->hcor)
return -EINVAL;
cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
+ /* If not run, directly return */
+ if (!(cmd & CMD_RUN))
+ return 0;
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++) {
+ for (i = 0; i < max_ports; i++) {
reg = ehci_readl(&ctrl->hcor->or_portsc[i]);
reg |= EHCI_PS_SUSP;
ehci_writel(&ctrl->hcor->or_portsc[i], reg);
static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
{
uint32_t delta, next;
- uint32_t addr = (unsigned long)buf;
+ unsigned long addr = (unsigned long)buf;
int idx;
if (addr != ALIGN(addr, ARCH_DMA_MINALIGN))
idx = 0;
while (idx < QT_BUFFER_CNT) {
- td->qt_buffer[idx] = cpu_to_hc32(addr);
+ td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
td->qt_buffer_hi[idx] = 0;
next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1);
delta = next - addr;
static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
struct QH *qh)
{
- struct usb_device *ttdev;
- int parent_devnum;
+ uint8_t portnr = 0;
+ uint8_t hubaddr = 0;
if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL)
return;
- /*
- * For full / low speed devices we need to get the devnum and portnr of
- * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs
- * in the tree before that one!
- */
-#ifdef CONFIG_DM_USB
- /*
- * 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. So when searching
- * for the first usb-2 parent start with udev->dev not
- * udev->dev->parent .
- */
- struct udevice *parent;
- struct usb_device *uparent;
-
- ttdev = udev;
- parent = udev->dev;
- uparent = dev_get_parent_priv(parent);
-
- while (uparent->speed != USB_SPEED_HIGH) {
- struct udevice *dev = parent;
+ usb_find_usb2_hub_address_port(udev, &hubaddr, &portnr);
- if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
- printf("ehci: Error cannot find high-speed parent of usb-1 device\n");
- return;
- }
-
- ttdev = dev_get_parent_priv(dev);
- parent = dev->parent;
- uparent = dev_get_parent_priv(parent);
- }
- parent_devnum = uparent->devnum;
-#else
- ttdev = udev;
- while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH)
- ttdev = ttdev->parent;
- if (!ttdev->parent)
- return;
- parent_devnum = ttdev->parent->devnum;
-#endif
-
- qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) |
- QH_ENDPT2_HUBADDR(parent_devnum));
+ qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(portnr) |
+ QH_ENDPT2_HUBADDR(hubaddr));
}
static int
* qh_overlay.qt_next ...... 13-10 H
* - qh_overlay.qt_altnext
*/
- qh->qh_link = cpu_to_hc32((unsigned long)&ctrl->qh_list | QH_LINK_TYPE_QH);
+ qh->qh_link = cpu_to_hc32(virt_to_phys(&ctrl->qh_list) | QH_LINK_TYPE_QH);
c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe);
maxpacket = usb_maxpacket(dev, pipe);
endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
tdp = &qh->qh_overlay.qt_next;
-
if (req != NULL) {
/*
* Setup request qTD (3.5 in ehci-r10.pdf)
goto fail;
}
/* Update previous qTD! */
- *tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
+ *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
tdp = &qtd[qtd_counter++].qt_next;
toggle = 1;
}
goto fail;
}
/* Update previous qTD! */
- *tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
+ *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
tdp = &qtd[qtd_counter++].qt_next;
/*
* Data toggle has to be adjusted since the qTD transfer
QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
/* Update previous qTD! */
- *tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
+ *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
tdp = &qtd[qtd_counter++].qt_next;
}
- ctrl->qh_list.qh_link = cpu_to_hc32((unsigned long)qh | QH_LINK_TYPE_QH);
+ ctrl->qh_list.qh_link = cpu_to_hc32(virt_to_phys(qh) | QH_LINK_TYPE_QH);
/* Flush dcache */
flush_dcache_range((unsigned long)&ctrl->qh_list,
ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
/* Set async. queue head pointer. */
- ehci_writel(&ctrl->hcor->or_asynclistaddr, (unsigned long)&ctrl->qh_list);
+ ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(&ctrl->qh_list));
usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
return -1;
}
-const struct ehci_ops default_ehci_ops = {
+static const struct ehci_ops default_ehci_ops = {
.set_usb_mode = ehci_set_usbmode,
.get_port_speed = ehci_get_port_speed,
.powerup_fixup = ehci_powerup_fixup,
/* Set head of reclaim list */
memset(qh_list, 0, sizeof(*qh_list));
- qh_list->qh_link = cpu_to_hc32((unsigned long)qh_list | QH_LINK_TYPE_QH);
+ qh_list->qh_link = cpu_to_hc32(virt_to_phys(qh_list) | QH_LINK_TYPE_QH);
qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
QH_ENDPT1_EPS(USB_SPEED_HIGH));
qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
ALIGN_END_ADDR(struct QH, qh_list, 1));
/* Set async. queue head pointer. */
- ehci_writel(&ctrl->hcor->or_asynclistaddr, (unsigned long)qh_list);
+ ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(qh_list));
/*
* Set up periodic list
if (ret)
goto err;
+ if (ctrl->ops.init_after_reset) {
+ ret = ctrl->ops.init_after_reset(ctrl);
+ if (ret)
+ goto err;
+ }
+
ret = ehci_common_init(ctrl, tweaks);
if (ret)
goto err;