struct dwc_otg_platform_data *pldata_otg;
struct dwc_otg_platform_data *pldata_host;
struct rkehci_platform_data *pldata_ehci;
- if (cpu_is_rk312x()) {
- pldata_otg = &usb20otg_pdata_rk3126;
- if (usb_to_uart_status)
- pldata_otg->dwc_otg_uart_mode(pldata_otg, PHY_UART_MODE);
- }
+
if (cpu_is_rk3288()) {
#ifdef CONFIG_RK_USB_UART
/* enable USB bypass UART function */
}
#endif
+ } else {
+ dwc_otg_device_t *otg_dev = g_otgdev;
+
+ if (!otg_dev)
+ return;
+
+ pldata_otg = otg_dev->pldata;
+ if (pldata_otg && pldata_otg->phy_power_down)
+ pldata_otg->phy_power_down(PHY_POWER_UP);
}
}
struct dwc_otg_platform_data *pldata_host;
struct rkehci_platform_data *pldata_ehci;
- if (cpu_is_rk312x()) {
- pldata_otg = &usb20otg_pdata_rk3126;
- usb_to_uart_status = pldata_otg->get_status(USB_STATUS_UARTMODE);
- pldata_otg->dwc_otg_uart_mode(pldata_otg, PHY_USB_MODE);
- }
if (cpu_is_rk3288()) {
#ifdef CONFIG_RK_USB_UART
/* disable USB bypass UART function */
RK3288_GRF_UOC1_CON0);
}
#endif
+ } else {
+ dwc_otg_device_t *otg_dev = g_otgdev;
+
+ if (!otg_dev)
+ return;
+
+ pldata_otg = otg_dev->pldata;
+ if (pldata_otg && pldata_otg->phy_power_down)
+ pldata_otg->phy_power_down(PHY_POWER_DOWN);
}
}
static void usb20otg_phy_suspend(void *pdata, int suspend)
{
struct dwc_otg_platform_data *usbpdata = pdata;
+
if (suspend) {
/* enable soft control */
- writel(UOC_HIWORD_UPDATE(0x55, 0x7f, 0),
+ writel(UOC_HIWORD_UPDATE(0x1d1, 0x1ff, 0),
RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
usbpdata->phy_status = 1;
} else {
gpio_set_value(control_usb->otg_gpios->gpio, 1);
}
}
-
+static void usb20otg_phy_power_down(int power_down)
+{
+ if (power_down == PHY_POWER_DOWN) {
+ if (control_usb->linestate_wakeup) {
+ /* enable otg0_linestate irq */
+ writel(UOC_HIWORD_UPDATE(0x3, 0x3, 14),
+ RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+ /* enable otg1_linestate irq */
+ writel(UOC_HIWORD_UPDATE(0x3, 0x3, 12),
+ RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+ }
+ } else if (power_down == PHY_POWER_UP) {
+ ;
+ }
+}
struct dwc_otg_platform_data usb20otg_pdata_rk3126 = {
.phyclk = NULL,
.ahbclk = NULL,
.power_enable = usb20otg_power_enable,
.dwc_otg_uart_mode = dwc_otg_uart_mode,
.bc_detect_cb = rk_battery_charger_detect_cb,
+ .phy_power_down = usb20otg_phy_power_down,
};
#endif
return IRQ_HANDLED;
}
+/********** Handler for linestate irq **********/
+static irqreturn_t otg0_linestate_irq_handler(int irq, void *dev_id)
+{
+ /*
+ * Here is a chip hwrdware bug, when disable/enable
+ * linestate irq bit the state machine will not reset
+ * So here have to add a delay to wait the linestate filter
+ * timer run out (linestate filter time had been set to 100us)
+ */
+ udelay(200);
+
+ /* clear and disable irq */
+ writel(UOC_HIWORD_UPDATE(0x2, 0x3, 12),
+ RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+
+
+ if (control_usb->usb_irq_wakeup) {
+ wake_lock_timeout(&control_usb->usb_wakelock,
+ WAKE_LOCK_TIMEOUT);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t otg1_linestate_irq_handler(int irq, void *dev_id)
+{
+ /*
+ * Here is a chip hwrdware bug, when disable/enable
+ * linestate irq bit the state machine will not reset
+ * So here have to add a delay to wait the linestate filter
+ * timer run out (linestate filter time had been set to 100us)
+ */
+ udelay(200);
+
+ /* clear and disable irq */
+ writel(UOC_HIWORD_UPDATE(0x2, 0x3, 14),
+ RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+
+
+ if (control_usb->usb_irq_wakeup) {
+ wake_lock_timeout(&control_usb->usb_wakelock,
+ WAKE_LOCK_TIMEOUT);
+ }
+
+ return IRQ_HANDLED;
+}
+
/************* register usb detection irqs **************/
static int otg_irq_detect_init(struct platform_device *pdev)
{
INIT_DELAYED_WORK(&control_usb->usb_det_wakeup_work, do_wakeup);
}
- /*register otg_bvalid irq */
+ /* register otg_bvalid irq */
irq = platform_get_irq_byname(pdev, "otg_bvalid");
if ((irq > 0) && control_usb->usb_irq_wakeup) {
ret = request_irq(irq, bvalid_irq_handler,
RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
}
}
- return ret;
+
+ if (!control_usb->linestate_wakeup)
+ return 0;
+
+ /* Set otg0&1_linestate_filter time to 100us */
+ writel(UOC_HIWORD_UPDATE(0x0, 0xf, 6), RK_GRF_VIRT + 0x1a0);
+
+ /* Register otg0_linestate irq */
+ irq = platform_get_irq_byname(pdev, "otg0_linestate");
+ if (irq > 0) {
+ ret = request_irq(irq, otg0_linestate_irq_handler,
+ 0, "otg0_linestate", NULL);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "request_irq %d failed!\n", irq);
+ } else {
+ /* Clear otg0_linestate irq */
+ writel(UOC_HIWORD_UPDATE(0x2, 0x3, 12),
+ RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+ }
+ }
+
+ /* Register otg1_linestate irq */
+ irq = platform_get_irq_byname(pdev, "otg1_linestate");
+ if (irq > 0) {
+ ret = request_irq(irq, otg1_linestate_irq_handler,
+ 0, "otg1_linestate", NULL);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "request_irq %d failed!\n", irq);
+ } else {
+ /* Clear otg1_linestate irq */
+ writel(UOC_HIWORD_UPDATE(0x2, 0x3, 14),
+ RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+ }
+ }
+ return 0;
}
/********** end of rk3126 usb detections **********/
"rockchip,remote_wakeup");
control_usb->usb_irq_wakeup = of_property_read_bool(np,
"rockchip,usb_irq_wakeup");
+ control_usb->linestate_wakeup = of_property_read_bool(np,
+ "rockchip,linestate_wakeup");
INIT_DELAYED_WORK(&control_usb->usb_charger_det_work,
usb_battery_charger_detect_work);