}
static void cdnsp_disable_port(struct cdnsp_device *pdev,
- __le32 __iomem *port_regs)
+ struct cdnsp_port *port)
{
- u32 temp = cdnsp_port_state_to_neutral(readl(port_regs));
+ u32 temp;
+
+ if (!port->exist)
+ return;
- writel(temp | PORT_PED, port_regs);
+ temp = cdnsp_port_state_to_neutral(readl(&port->regs->portsc));
+ writel(temp | PORT_PED, &port->regs->portsc);
}
static void cdnsp_clear_port_change_bit(struct cdnsp_device *pdev,
- __le32 __iomem *port_regs)
+ struct cdnsp_port *port)
{
- u32 portsc = readl(port_regs);
+ u32 portsc;
+
+ if (!port->exist)
+ return;
+ portsc = readl(&port->regs->portsc);
writel(cdnsp_port_state_to_neutral(portsc) |
- (portsc & PORT_CHANGE_BITS), port_regs);
+ (portsc & PORT_CHANGE_BITS), &port->regs->portsc);
}
static void cdnsp_set_apb_timeout_value(struct cdnsp_device *pdev)
struct usb_request *req,
int enable)
{
- if (pdev->active_port != &pdev->usb2_port || !pdev->gadget.lpm_capable)
+ if (pdev->active_port == &pdev->usb3_port || !pdev->gadget.lpm_capable)
return;
trace_cdnsp_lpm(enable);
break;
}
- if (speed >= USB_SPEED_SUPER) {
+ if (pdev->usb3_port.exist && speed >= USB_SPEED_SUPER) {
writel(temp, &pdev->port3x_regs->mode_addr);
cdnsp_set_link_state(pdev, &pdev->usb3_port.regs->portsc,
XDEV_RXDETECT);
} else {
- cdnsp_disable_port(pdev, &pdev->usb3_port.regs->portsc);
+ cdnsp_disable_port(pdev, &pdev->usb3_port);
}
- cdnsp_set_link_state(pdev, &pdev->usb2_port.regs->portsc,
- XDEV_RXDETECT);
+ if (pdev->usb2_port.exist) {
+ cdnsp_set_link_state(pdev, &pdev->usb2_port.regs->portsc,
+ XDEV_RXDETECT);
+ writel(PORT_REG6_L1_L0_HW_EN | fs_speed, &pdev->port20_regs->port_reg6);
+ }
+
+ if (pdev->eusb_port.exist)
+ cdnsp_set_link_state(pdev, &pdev->eusb_port.regs->portsc,
+ XDEV_RXDETECT);
cdnsp_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
- writel(PORT_REG6_L1_L0_HW_EN | fs_speed, &pdev->port20_regs->port_reg6);
ret = cdnsp_start(pdev);
if (ret) {
cdnsp_ep_dequeue(&pdev->eps[0], req);
}
- cdnsp_disable_port(pdev, &pdev->usb2_port.regs->portsc);
- cdnsp_disable_port(pdev, &pdev->usb3_port.regs->portsc);
+ cdnsp_disable_port(pdev, &pdev->usb2_port);
+ cdnsp_disable_port(pdev, &pdev->usb3_port);
+ cdnsp_disable_port(pdev, &pdev->eusb_port);
+
cdnsp_disable_slot(pdev);
cdnsp_halt(pdev);
temp = readl(&pdev->ir_set->irq_pending);
writel(IMAN_IE_CLEAR(temp), &pdev->ir_set->irq_pending);
- cdnsp_clear_port_change_bit(pdev, &pdev->usb2_port.regs->portsc);
- cdnsp_clear_port_change_bit(pdev, &pdev->usb3_port.regs->portsc);
+ cdnsp_clear_port_change_bit(pdev, &pdev->usb2_port);
+ cdnsp_clear_port_change_bit(pdev, &pdev->eusb_port);
+ cdnsp_clear_port_change_bit(pdev, &pdev->usb3_port);
/* Clear interrupt line */
temp = readl(&pdev->ir_set->irq_pending);
unsigned int link_state;
struct cdnsp_port usb2_port;
+ struct cdnsp_port eusb_port;
struct cdnsp_port usb3_port;
struct cdnsp_port *active_port;
u16 test_mode;
pdev->dcbaa, pdev->dcbaa->dma);
pdev->dcbaa = NULL;
-
- pdev->usb2_port.exist = 0;
- pdev->usb3_port.exist = 0;
- pdev->usb2_port.port_num = 0;
- pdev->usb3_port.port_num = 0;
+ memset(&pdev->usb2_port, 0, sizeof(struct cdnsp_port));
+ memset(&pdev->eusb_port, 0, sizeof(struct cdnsp_port));
+ memset(&pdev->usb3_port, 0, sizeof(struct cdnsp_port));
pdev->active_port = NULL;
}
port_offset = CDNSP_EXT_PORT_OFF(temp);
port_count = CDNSP_EXT_PORT_COUNT(temp);
+ if (port == &pdev->eusb_port) {
+ /*
+ * If controller has usb2 + eusb port then eusb is as
+ * second port
+ */
+ if (port_count == 2)
+ port_offset++;
+
+ if (port_count == 1 && pdev->usb2_port.exist)
+ return;
+ }
+
trace_cdnsp_port_info(addr, port_offset, port_count, port->maj_rev);
port->port_num = port_offset;
base = &pdev->cap_regs->hc_capbase;
offset = cdnsp_find_next_ext_cap(base, 0,
EXT_CAP_CFG_DEV_20PORT_CAP_ID);
- pdev->port20_regs = base + offset;
-
- offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
- pdev->port3x_regs = base + offset;
+ if (offset)
+ pdev->port20_regs = base + offset;
offset = 0;
- base = &pdev->cap_regs->hc_capbase;
/* Driver expects max 2 extended protocol capability. */
for (i = 0; i < 2; i++) {
cdnsp_add_in_port(pdev, &pdev->usb3_port,
base + offset);
- if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02 &&
- !pdev->usb2_port.port_num)
- cdnsp_add_in_port(pdev, &pdev->usb2_port,
- base + offset);
+ if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02) {
+ if (!pdev->usb2_port.port_num && pdev->port20_regs)
+ cdnsp_add_in_port(pdev, &pdev->usb2_port,
+ base + offset);
+
+ if (!pdev->eusb_port.port_num)
+ cdnsp_add_in_port(pdev, &pdev->eusb_port,
+ base + offset);
+ }
}
- if (!pdev->usb2_port.exist || !pdev->usb3_port.exist) {
- dev_err(pdev->dev, "Error: Only one port detected\n");
+ if (!pdev->usb2_port.exist && !pdev->eusb_port.exist &&
+ !pdev->usb3_port.exist) {
+ dev_err(pdev->dev, "Error: No port detected\n");
return -ENODEV;
}
- trace_cdnsp_init("Found USB 2.0 ports and USB 3.0 ports.");
+ if (pdev->usb2_port.exist) {
+ pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
+ (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
+ (pdev->usb2_port.port_num - 1));
+ trace_cdnsp_init("Found USB 2.0 port.");
+ }
- pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
- (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
- (pdev->usb2_port.port_num - 1));
+ if (pdev->eusb_port.exist) {
+ pdev->eusb_port.regs = (struct cdnsp_port_regs __iomem *)
+ (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
+ (pdev->eusb_port.port_num - 1));
+ trace_cdnsp_init("Found eUSB 2.0 port.");
+ }
+
+ if (pdev->usb3_port.exist) {
+ offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
+ pdev->port3x_regs = base + offset;
- pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
- (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
- (pdev->usb3_port.port_num - 1));
+ pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
+ (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
+ (pdev->usb3_port.port_num - 1));
+ trace_cdnsp_init("Found USB 3.x port.");
+ }
return 0;
}
*/
static void cdnsp_force_l0_go(struct cdnsp_device *pdev)
{
- if (pdev->active_port == &pdev->usb2_port && pdev->gadget.lpm_capable)
+ if (pdev->active_port != &pdev->usb3_port && pdev->gadget.lpm_capable)
cdnsp_set_link_state(pdev, &pdev->active_port->regs->portsc, XDEV_U0);
}
if (port_id == pdev->usb2_port.port_num) {
port = &pdev->usb2_port;
+ } else if (port_id == pdev->eusb_port.port_num) {
+ port = &pdev->eusb_port;
} else if (port_id == pdev->usb3_port.port_num) {
port = &pdev->usb3_port;
} else {
cdnsp_enable_slot(pdev);
}
- if (port_id == pdev->usb2_port.port_num)
+ if ((pdev->usb2_port.exist && port_id == pdev->usb2_port.port_num) ||
+ (pdev->eusb_port.exist && port_id == pdev->eusb_port.port_num))
cdnsp_set_usb2_hardware_lpm(pdev, NULL, 1);
else
writel(PORT_U1_TIMEOUT(1) | PORT_U2_TIMEOUT(1),
port_regs = pdev->active_port->regs;
- if (port_id == pdev->usb2_port.port_num)
+ if (port_id == pdev->usb2_port.port_num || port_id == pdev->eusb_port.port_num)
port2 = true;
new_event: