From: Hao Wu <hao.wu@xxxxxxxxx> This patch only modified Langwell OTG transceiver driver, and it needs host/client driver related patch to work. Main changes: - update to use intel_mid_otg common data structure. Signed-off-by: Hao Wu <hao.wu@xxxxxxxxx> Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx> --- drivers/usb/otg/langwell_otg.c | 1587 +++++++++++++++++++------------------- include/linux/usb/langwell_otg.h | 97 -- 2 files changed, 821 insertions(+), 863 deletions(-) diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c index 4378c64..c23471c 100644 --- a/drivers/usb/otg/langwell_otg.c +++ b/drivers/usb/otg/langwell_otg.c @@ -139,11 +139,11 @@ static struct list_head active_timers; static struct langwell_otg *the_transceiver; /* host/client notify transceiver when event affects HNP state */ -void langwell_update_transceiver() +void langwell_update_transceiver(void) { struct langwell_otg *lnw = the_transceiver; - dev_dbg(&lnw->pdev->dev, "transceiver is updated\n"); + dev_dbg(lnw->dev, "transceiver is updated\n"); if (!lnw->qwork) return ; @@ -175,137 +175,138 @@ static int langwell_otg_set_power(struct otg_transceiver *otg, } /* A-device drives vbus, controlled through PMIC CHRGCNTL register*/ -static void langwell_otg_drv_vbus(int on) +static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) { struct langwell_otg *lnw = the_transceiver; u8 r; - dev_dbg(&lnw->pdev->dev, "%s <--- %s\n", __func__, on ? "on" : "off"); + dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); /* FIXME: surely we should cache this on the first read. If not use readv to avoid two transactions */ if (intel_scu_ipc_ioread8(0x00, &r) < 0) { - dev_dbg(&lnw->pdev->dev, "Failed to read PMIC register 0xD2"); - return; + dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2"); + return -EBUSY; } if ((r & 0x03) != 0x02) { - dev_dbg(&lnw->pdev->dev, "not NEC PMIC attached\n"); - return; + dev_dbg(lnw->dev, "not NEC PMIC attached\n"); + return -EBUSY; } if (intel_scu_ipc_ioread8(0x20, &r) < 0) { - dev_dbg(&lnw->pdev->dev, "Failed to read PMIC register 0xD2"); - return; + dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2"); + return -EBUSY; } if ((r & 0x20) == 0) { - dev_dbg(&lnw->pdev->dev, "no battery attached\n"); - return; + dev_dbg(lnw->dev, "no battery attached\n"); + return -EBUSY; } /* Workaround for battery attachment issue */ if (r == 0x34) { - dev_dbg(&lnw->pdev->dev, "no battery attached on SH\n"); - return; + dev_dbg(lnw->dev, "no battery attached on SH\n"); + return -EBUSY; } - dev_dbg(&lnw->pdev->dev, "battery attached. 2 reg = %x\n", r); + dev_dbg(lnw->dev, "battery attached. 2 reg = %x\n", r); /* workaround: FW detect writing 0x20/0xc0 to d4 event. * this is only for NEC PMIC. */ - if (intel_scu_ipc_iowrite8(0xD4, on ? 0x20 : 0xC0)) - dev_dbg(&lnw->pdev->dev, "Failed to write PMIC.\n"); + if (intel_scu_ipc_iowrite8(0xD4, enabled ? 0x20 : 0xC0)) + dev_dbg(lnw->dev, "Failed to write PMIC.\n"); + + dev_dbg(lnw->dev, "%s --->\n", __func__); - dev_dbg(&lnw->pdev->dev, "%s --->\n", __func__); + return 0; } /* charge vbus or discharge vbus through a resistor to ground */ static void langwell_otg_chrg_vbus(int on) { - + struct langwell_otg *lnw = the_transceiver; u32 val; - val = readl(the_transceiver->regs + CI_OTGSC); + val = readl(lnw->iotg.base + CI_OTGSC); if (on) writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, - the_transceiver->regs + CI_OTGSC); + lnw->iotg.base + CI_OTGSC); else writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, - the_transceiver->regs + CI_OTGSC); - + lnw->iotg.base + CI_OTGSC); } /* Start SRP */ static int langwell_otg_start_srp(struct otg_transceiver *otg) { - struct langwell_otg *lnw = the_transceiver; - u32 val; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; - dev_dbg(&lnw->pdev->dev, "%s --->\n", __func__); + dev_dbg(lnw->dev, "%s --->\n", __func__); - val = readl(lnw->regs + CI_OTGSC); + val = readl(iotg->base + CI_OTGSC); - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, lnw->regs + CI_OTGSC); + writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, + iotg->base + CI_OTGSC); /* Check if the data plus is finished or not */ msleep(8); - val = readl(lnw->regs + CI_OTGSC); + val = readl(iotg->base + CI_OTGSC); if (val & (OTGSC_HADP | OTGSC_DP)) - dev_dbg(&lnw->pdev->dev, "DataLine SRP Error\n"); + dev_dbg(lnw->dev, "DataLine SRP Error\n"); /* Disable interrupt - b_sess_vld */ - val = readl(lnw->regs + CI_OTGSC); + val = readl(iotg->base + CI_OTGSC); val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); - writel(val, lnw->regs + CI_OTGSC); + writel(val, iotg->base + CI_OTGSC); /* Start VBus SRP, drive vbus to generate VBus pulse */ - langwell_otg_drv_vbus(1); + iotg->otg.set_vbus(&iotg->otg, true); msleep(15); - langwell_otg_drv_vbus(0); + iotg->otg.set_vbus(&iotg->otg, false); /* Enable interrupt - b_sess_vld*/ - val = readl(lnw->regs + CI_OTGSC); - dev_dbg(&lnw->pdev->dev, "After VBUS pulse OTGSC = %x\n", val); + val = readl(iotg->base + CI_OTGSC); + dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); + val |= (OTGSC_BSVIE | OTGSC_BSEIE); - writel(val, lnw->regs + CI_OTGSC); + writel(val, iotg->base + CI_OTGSC); /* If Vbus is valid, then update the hsm */ if (val & OTGSC_BSV) { - dev_dbg(&lnw->pdev->dev, "no b_sess_vld interrupt\n"); + dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); - lnw->hsm.b_sess_vld = 1; + lnw->iotg.hsm.b_sess_vld = 1; langwell_update_transceiver(); } - dev_dbg(&lnw->pdev->dev, "%s <---\n", __func__); + dev_dbg(lnw->dev, "%s <---\n", __func__); return 0; } - /* stop SOF via bus_suspend */ static void langwell_otg_loc_sof(int on) { struct langwell_otg *lnw = the_transceiver; - struct usb_hcd *hcd; - int err; + struct usb_hcd *hcd; + int err; - dev_dbg(&lnw->pdev->dev, - "%s ---> %s\n", __func__, on ? "suspend" : "resume"); + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); - hcd = bus_to_hcd(lnw->otg.host); + hcd = bus_to_hcd(lnw->iotg.otg.host); if (on) err = hcd->driver->bus_resume(hcd); else err = hcd->driver->bus_suspend(hcd); if (err) - dev_dbg(&lnw->pdev->dev, - "Fail to resume/suspend USB bus - %d\n", err); + dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); - dev_dbg(&lnw->pdev->dev, "%s <---\n", __func__); + dev_dbg(lnw->dev, "%s <---\n", __func__); } static int langwell_otg_check_otgsc(void) @@ -313,66 +314,67 @@ static int langwell_otg_check_otgsc(void) struct langwell_otg *lnw = the_transceiver; u32 otgsc, usbcfg; - dev_dbg(&lnw->pdev->dev, "check sync OTGSC and USBCFG registers\n"); + dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); - otgsc = readl(lnw->regs + CI_OTGSC); + otgsc = readl(lnw->iotg.base + CI_OTGSC); usbcfg = readl(lnw->usbcfg); - dev_dbg(&lnw->pdev->dev, "OTGSC = %08x, USBCFG = %08x\n", + dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", otgsc, usbcfg); - dev_dbg(&lnw->pdev->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); - dev_dbg(&lnw->pdev->dev, "USBCFG.VBUSVAL = %d\n", + dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); + dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", !!(usbcfg & USBCFG_VBUSVAL)); - dev_dbg(&lnw->pdev->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); - dev_dbg(&lnw->pdev->dev, "USBCFG.AVALID = %d\n", + dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); + dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", !!(usbcfg & USBCFG_AVALID)); - dev_dbg(&lnw->pdev->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); - dev_dbg(&lnw->pdev->dev, "USBCFG.BVALID = %d\n", + dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); + dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", !!(usbcfg & USBCFG_BVALID)); - dev_dbg(&lnw->pdev->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); - dev_dbg(&lnw->pdev->dev, "USBCFG.SESEND = %d\n", + dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); + dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", !!(usbcfg & USBCFG_SESEND)); /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { - dev_dbg(&lnw->pdev->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); + dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); goto err; } if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { - dev_dbg(&lnw->pdev->dev, "OTGSC.ASV != USBCFG.AVALID\n"); + dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); goto err; } if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { - dev_dbg(&lnw->pdev->dev, "OTGSC.BSV != USBCFG.BVALID\n"); + dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); goto err; } if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { - dev_dbg(&lnw->pdev->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); + dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); goto err; } - dev_dbg(&lnw->pdev->dev, "OTGSC and USBCFG are synced\n"); + dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); return 0; err: - dev_warn(&lnw->pdev->dev, "OTGSC isn't equal to USBCFG\n"); + dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); return -EPIPE; } static void langwell_otg_phy_low_power(int on) { - struct langwell_otg *lnw = the_transceiver; - u8 val, phcd; - int retval; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u8 val, phcd; + int retval; - dev_dbg(&lnw->pdev->dev, "%s ---> %s mode\n", + dev_dbg(lnw->dev, "%s ---> %s mode\n", __func__, on ? "Low power" : "Normal"); phcd = 0x40; - val = readb(lnw->regs + CI_HOSTPC1 + 2); + val = readb(iotg->base + CI_HOSTPC1 + 2); if (on) { /* Due to hardware issue, after set PHCD, sync will failed @@ -381,14 +383,15 @@ static void langwell_otg_phy_low_power(int on) * not touch PHCD bit */ retval = langwell_otg_check_otgsc(); if (retval) { - dev_dbg(&lnw->pdev->dev, "Skip PHCD programming..\n"); + dev_dbg(lnw->dev, "Skip PHCD programming..\n"); return ; } - writeb(val | phcd, lnw->regs + CI_HOSTPC1 + 2); + + writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); } else - writeb(val & ~phcd, lnw->regs + CI_HOSTPC1 + 2); + writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); - dev_dbg(&lnw->pdev->dev, "%s <--- done\n", __func__); + dev_dbg(lnw->dev, "%s <--- done\n", __func__); } /* After drv vbus, add 2 ms delay to set PHCD */ @@ -396,7 +399,7 @@ static void langwell_otg_phy_low_power_wait(int on) { struct langwell_otg *lnw = the_transceiver; - dev_dbg(&lnw->pdev->dev, "add 2ms delay before programing PHCD\n"); + dev_dbg(lnw->dev, "add 2ms delay before programing PHCD\n"); mdelay(2); langwell_otg_phy_low_power(on); @@ -405,58 +408,64 @@ static void langwell_otg_phy_low_power_wait(int on) /* Enable/Disable OTG interrupt */ static void langwell_otg_intr(int on) { - struct langwell_otg *lnw = the_transceiver; - u32 val; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; - dev_dbg(&lnw->pdev->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - val = readl(lnw->regs + CI_OTGSC); + val = readl(iotg->base + CI_OTGSC); + + /* OTGSC_INT_MASK doesn't contains 1msInt */ if (on) { val = val | (OTGSC_INT_MASK); - writel(val, lnw->regs + CI_OTGSC); + writel(val, iotg->base + CI_OTGSC); } else { val = val & ~(OTGSC_INT_MASK); - writel(val, lnw->regs + CI_OTGSC); + writel(val, iotg->base + CI_OTGSC); } - dev_dbg(&lnw->pdev->dev, "%s <---\n", __func__); + + dev_dbg(lnw->dev, "%s <---\n", __func__); } /* set HAAR: Hardware Assist Auto-Reset */ static void langwell_otg_HAAR(int on) { - struct langwell_otg *lnw = the_transceiver; - u32 val; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; - dev_dbg(&lnw->pdev->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - val = readl(lnw->regs + CI_OTGSC); + val = readl(iotg->base + CI_OTGSC); if (on) writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, - lnw->regs + CI_OTGSC); + iotg->base + CI_OTGSC); else writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, - lnw->regs + CI_OTGSC); + iotg->base + CI_OTGSC); - dev_dbg(&lnw->pdev->dev, "%s <---\n", __func__); + dev_dbg(lnw->dev, "%s <---\n", __func__); } /* set HABA: Hardware Assist B-Disconnect to A-Connect */ static void langwell_otg_HABA(int on) { - struct langwell_otg *lnw = the_transceiver; - u32 val; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; - dev_dbg(&lnw->pdev->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - val = readl(lnw->regs + CI_OTGSC); + val = readl(iotg->base + CI_OTGSC); if (on) writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, - lnw->regs + CI_OTGSC); + iotg->base + CI_OTGSC); else writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, - lnw->regs + CI_OTGSC); + iotg->base + CI_OTGSC); - dev_dbg(&lnw->pdev->dev, "%s <---\n", __func__); + dev_dbg(lnw->dev, "%s <---\n", __func__); } static int langwell_otg_check_se0_srp(int on) @@ -465,17 +474,17 @@ static int langwell_otg_check_se0_srp(int on) int delay_time = TB_SE0_SRP * 10; u32 val; - dev_dbg(&lnw->pdev->dev, "%s --->\n", __func__); + dev_dbg(lnw->dev, "%s --->\n", __func__); do { udelay(100); if (!delay_time--) break; - val = readl(lnw->regs + CI_PORTSC1); + val = readl(lnw->iotg.base + CI_PORTSC1); val &= PORTSC_LS; } while (!val); - dev_dbg(&lnw->pdev->dev, "%s <---\n", __func__); + dev_dbg(lnw->dev, "%s <---\n", __func__); return val; } @@ -494,15 +503,15 @@ void langwell_otg_nsf_msg(unsigned long indicator) case 4: case 6: case 7: - dev_warn(&lnw->pdev->dev, + dev_warn(lnw->dev, "OTG:NSF-%lu - deivce not responding\n", indicator); break; case 3: - dev_warn(&lnw->pdev->dev, + dev_warn(lnw->dev, "OTG:NSF-%lu - deivce not supported\n", indicator); break; default: - dev_warn(&lnw->pdev->dev, "Do not have this kind of NSF\n"); + dev_warn(lnw->dev, "Do not have this kind of NSF\n"); break; } } @@ -547,7 +556,7 @@ static void langwell_otg_timer_fn(unsigned long indicator) *(int *)indicator = 1; - dev_dbg(&lnw->pdev->dev, "kernel timer - timeout\n"); + dev_dbg(lnw->dev, "kernel timer - timeout\n"); langwell_update_transceiver(); } @@ -555,48 +564,49 @@ static void langwell_otg_timer_fn(unsigned long indicator) /* kernel timer used instead of HW based interrupt */ static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) { - struct langwell_otg *lnw = the_transceiver; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; unsigned long j = jiffies; unsigned long data, time; switch (timers) { case TA_WAIT_VRISE_TMR: - lnw->hsm.a_wait_vrise_tmout = 0; - data = (unsigned long)&lnw->hsm.a_wait_vrise_tmout; + iotg->hsm.a_wait_vrise_tmout = 0; + data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; time = TA_WAIT_VRISE; break; case TA_WAIT_BCON_TMR: - lnw->hsm.a_wait_bcon_tmout = 0; - data = (unsigned long)&lnw->hsm.a_wait_bcon_tmout; + iotg->hsm.a_wait_bcon_tmout = 0; + data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; time = TA_WAIT_BCON; break; case TA_AIDL_BDIS_TMR: - lnw->hsm.a_aidl_bdis_tmout = 0; - data = (unsigned long)&lnw->hsm.a_aidl_bdis_tmout; + iotg->hsm.a_aidl_bdis_tmout = 0; + data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; time = TA_AIDL_BDIS; break; case TB_ASE0_BRST_TMR: - lnw->hsm.b_ase0_brst_tmout = 0; - data = (unsigned long)&lnw->hsm.b_ase0_brst_tmout; + iotg->hsm.b_ase0_brst_tmout = 0; + data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; time = TB_ASE0_BRST; break; case TB_SRP_INIT_TMR: - lnw->hsm.b_srp_init_tmout = 0; - data = (unsigned long)&lnw->hsm.b_srp_init_tmout; + iotg->hsm.b_srp_init_tmout = 0; + data = (unsigned long)&iotg->hsm.b_srp_init_tmout; time = TB_SRP_INIT; break; case TB_SRP_FAIL_TMR: - lnw->hsm.b_srp_fail_tmout = 0; - data = (unsigned long)&lnw->hsm.b_srp_fail_tmout; + iotg->hsm.b_srp_fail_tmout = 0; + data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; time = TB_SRP_FAIL; break; case TB_BUS_SUSPEND_TMR: - lnw->hsm.b_bus_suspend_tmout = 0; - data = (unsigned long)&lnw->hsm.b_bus_suspend_tmout; + iotg->hsm.b_bus_suspend_tmout = 0; + data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; time = TB_BUS_SUSPEND; break; default: - dev_dbg(&lnw->pdev->dev, "unkown timer, cannot enable it\n"); + dev_dbg(lnw->dev, "unkown timer, cannot enable it\n"); return; } @@ -606,7 +616,7 @@ static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) add_timer(&lnw->hsm_timer); - dev_dbg(&lnw->pdev->dev, "add timer successfully\n"); + dev_dbg(lnw->dev, "add timer successfully\n"); } /* Add timer to timer list */ @@ -614,6 +624,7 @@ static void langwell_otg_add_timer(void *gtimer) { struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; struct langwell_otg_timer *tmp_timer; + struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; u32 val32; /* Check if the timer is already in the active list, @@ -627,8 +638,8 @@ static void langwell_otg_add_timer(void *gtimer) timer->count = timer->expires; if (list_empty(&active_timers)) { - val32 = readl(the_transceiver->regs + CI_OTGSC); - writel(val32 | OTGSC_1MSE, the_transceiver->regs + CI_OTGSC); + val32 = readl(iotg->base + CI_OTGSC); + writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); } list_add_tail(&timer->list, &active_timers); @@ -637,6 +648,7 @@ static void langwell_otg_add_timer(void *gtimer) /* Remove timer from the timer list; clear timeout status */ static void langwell_otg_del_timer(void *gtimer) { + struct langwell_otg *lnw = the_transceiver; struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; struct langwell_otg_timer *tmp_timer, *del_tmp; u32 val32; @@ -646,8 +658,8 @@ static void langwell_otg_del_timer(void *gtimer) list_del(&timer->list); if (list_empty(&active_timers)) { - val32 = readl(the_transceiver->regs + CI_OTGSC); - writel(val32 & ~OTGSC_1MSE, the_transceiver->regs + CI_OTGSC); + val32 = readl(lnw->iotg.base + CI_OTGSC); + writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); } } @@ -669,7 +681,7 @@ static int langwell_otg_tick_timer(u32 *int_sts) } if (list_empty(&active_timers)) { - dev_dbg(&lnw->pdev->dev, "tick timer: disable 1ms int\n"); + dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); *int_sts = *int_sts & ~OTGSC_1MSE; } return expired; @@ -681,105 +693,108 @@ static void reset_otg(void) int delay_time = 1000; u32 val; - dev_dbg(&lnw->pdev->dev, "reseting OTG controller ...\n"); - val = readl(lnw->regs + CI_USBCMD); - writel(val | USBCMD_RST, lnw->regs + CI_USBCMD); + dev_dbg(lnw->dev, "reseting OTG controller ...\n"); + val = readl(lnw->iotg.base + CI_USBCMD); + writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); do { udelay(100); if (!delay_time--) - dev_dbg(&lnw->pdev->dev, "reset timeout\n"); - val = readl(lnw->regs + CI_USBCMD); + dev_dbg(lnw->dev, "reset timeout\n"); + val = readl(lnw->iotg.base + CI_USBCMD); val &= USBCMD_RST; } while (val != 0); - dev_dbg(&lnw->pdev->dev, "reset done.\n"); + dev_dbg(lnw->dev, "reset done.\n"); } static void set_host_mode(void) { - u32 val; + struct langwell_otg *lnw = the_transceiver; + u32 val; reset_otg(); - val = readl(the_transceiver->regs + CI_USBMODE); + val = readl(lnw->iotg.base + CI_USBMODE); val = (val & (~USBMODE_CM)) | USBMODE_HOST; - writel(val, the_transceiver->regs + CI_USBMODE); + writel(val, lnw->iotg.base + CI_USBMODE); } static void set_client_mode(void) { - u32 val; + struct langwell_otg *lnw = the_transceiver; + u32 val; reset_otg(); - val = readl(the_transceiver->regs + CI_USBMODE); + val = readl(lnw->iotg.base + CI_USBMODE); val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; - writel(val, the_transceiver->regs + CI_USBMODE); + writel(val, lnw->iotg.base + CI_USBMODE); } static void init_hsm(void) { - struct langwell_otg *lnw = the_transceiver; - u32 val32; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val32; /* read OTGSC after reset */ - val32 = readl(lnw->regs + CI_OTGSC); - - dev_dbg(&lnw->pdev->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); + val32 = readl(lnw->iotg.base + CI_OTGSC); + dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); /* set init state */ if (val32 & OTGSC_ID) { - lnw->hsm.id = 1; - lnw->otg.default_a = 0; + iotg->hsm.id = 1; + iotg->otg.default_a = 0; set_client_mode(); - lnw->otg.state = OTG_STATE_B_IDLE; - langwell_otg_drv_vbus(0); + iotg->otg.state = OTG_STATE_B_IDLE; } else { - lnw->hsm.id = 0; - lnw->otg.default_a = 1; + iotg->hsm.id = 0; + iotg->otg.default_a = 1; set_host_mode(); - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; } /* set session indicator */ if (val32 & OTGSC_BSE) - lnw->hsm.b_sess_end = 1; + iotg->hsm.b_sess_end = 1; if (val32 & OTGSC_BSV) - lnw->hsm.b_sess_vld = 1; + iotg->hsm.b_sess_vld = 1; if (val32 & OTGSC_ASV) - lnw->hsm.a_sess_vld = 1; + iotg->hsm.a_sess_vld = 1; if (val32 & OTGSC_AVV) - lnw->hsm.a_vbus_vld = 1; + iotg->hsm.a_vbus_vld = 1; /* defautly power the bus */ - lnw->hsm.a_bus_req = 1; - lnw->hsm.a_bus_drop = 0; + iotg->hsm.a_bus_req = 1; + iotg->hsm.a_bus_drop = 0; /* defautly don't request bus as B device */ - lnw->hsm.b_bus_req = 0; + iotg->hsm.b_bus_req = 0; /* no system error */ - lnw->hsm.a_clr_err = 0; + iotg->hsm.a_clr_err = 0; langwell_otg_phy_low_power_wait(1); } static void update_hsm(void) { - struct langwell_otg *lnw = the_transceiver; - u32 val32; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val32; /* read OTGSC */ - val32 = readl(lnw->regs + CI_OTGSC); - dev_dbg(&lnw->pdev->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); - - lnw->hsm.id = !!(val32 & OTGSC_ID); - lnw->hsm.b_sess_end = !!(val32 & OTGSC_BSE); - lnw->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); - lnw->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); - lnw->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); + val32 = readl(lnw->iotg.base + CI_OTGSC); + dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); + + iotg->hsm.id = !!(val32 & OTGSC_ID); + iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); + iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); + iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); + iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); } static irqreturn_t otg_dummy_irq(int irq, void *_dev) { - void __iomem *reg_base = _dev; - u32 val; - u32 int_mask = 0; + struct langwell_otg *lnw = the_transceiver; + void __iomem *reg_base = _dev; + u32 val; + u32 int_mask = 0; val = readl(reg_base + CI_USBMODE); if ((val & USBMODE_CM) != USBMODE_DEVICE) @@ -794,13 +809,14 @@ static irqreturn_t otg_dummy_irq(int irq, void *_dev) /* clear hsm.b_conn here since host driver can't detect it * otg_dummy_irq called means B-disconnect happened. */ - if (the_transceiver->hsm.b_conn) { - the_transceiver->hsm.b_conn = 0; - if (spin_trylock(&the_transceiver->wq_lock)) { + if (lnw->iotg.hsm.b_conn) { + lnw->iotg.hsm.b_conn = 0; + if (spin_trylock(&lnw->wq_lock)) { langwell_update_transceiver(); - spin_unlock(&the_transceiver->wq_lock); + spin_unlock(&lnw->wq_lock); } } + /* Clear interrupts */ writel(int_mask, reg_base + CI_USBSTS); return IRQ_HANDLED; @@ -808,56 +824,52 @@ static irqreturn_t otg_dummy_irq(int irq, void *_dev) static irqreturn_t otg_irq(int irq, void *_dev) { - struct langwell_otg *lnw = _dev; - u32 int_sts, int_en; - u32 int_mask = 0; - int flag = 0; + struct langwell_otg *lnw = _dev; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 int_sts, int_en; + u32 int_mask = 0; + int flag = 0; - int_sts = readl(lnw->regs + CI_OTGSC); + int_sts = readl(lnw->iotg.base + CI_OTGSC); int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; int_mask = int_sts & int_en; if (int_mask == 0) return IRQ_NONE; if (int_mask & OTGSC_IDIS) { - dev_dbg(&lnw->pdev->dev, "%s: id change int\n", __func__); - lnw->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; - dev_dbg(&lnw->pdev->dev, "id = %d\n", lnw->hsm.id); + dev_dbg(lnw->dev, "%s: id change int\n", __func__); + iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; + dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); flag = 1; } if (int_mask & OTGSC_DPIS) { - dev_dbg(&lnw->pdev->dev, "%s: data pulse int\n", __func__); - lnw->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; - dev_dbg(&lnw->pdev->dev, - "data pulse = %d\n", lnw->hsm.a_srp_det); + dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); + iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; + dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); flag = 1; } if (int_mask & OTGSC_BSEIS) { - dev_dbg(&lnw->pdev->dev, "%s: b session end int\n", __func__); - lnw->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; - dev_dbg(&lnw->pdev->dev, - "b_sess_end = %d\n", lnw->hsm.b_sess_end); + dev_dbg(lnw->dev, "%s: b session end int\n", __func__); + iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; + dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); flag = 1; } if (int_mask & OTGSC_BSVIS) { - dev_dbg(&lnw->pdev->dev, "%s: b session valid int\n", __func__); - lnw->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; - dev_dbg(&lnw->pdev->dev, - "b_sess_vld = %d\n", lnw->hsm.b_sess_end); + dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); + iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; + dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); flag = 1; } if (int_mask & OTGSC_ASVIS) { - dev_dbg(&lnw->pdev->dev, "%s: a session valid int\n", __func__); - lnw->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; - dev_dbg(&lnw->pdev->dev, - "a_sess_vld = %d\n", lnw->hsm.a_sess_vld); + dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); + iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; + dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); flag = 1; } if (int_mask & OTGSC_AVVIS) { - dev_dbg(&lnw->pdev->dev, "%s: a vbus valid int\n", __func__); - lnw->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; - dev_dbg(&lnw->pdev->dev, - "a_vbus_vld = %d\n", lnw->hsm.a_vbus_vld); + dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); + iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; + dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); flag = 1; } @@ -867,7 +879,8 @@ static irqreturn_t otg_irq(int irq, void *_dev) flag = 1; } - writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, lnw->regs + CI_OTGSC); + writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, + lnw->iotg.base + CI_OTGSC); if (flag) langwell_update_transceiver(); @@ -876,63 +889,70 @@ static irqreturn_t otg_irq(int irq, void *_dev) static void langwell_otg_work(struct work_struct *work) { - struct langwell_otg *lnw; - int retval; + struct langwell_otg *lnw; + struct intel_mid_otg_xceiv *iotg; + int retval; + struct pci_dev *pdev; lnw = container_of(work, struct langwell_otg, work); + iotg = &lnw->iotg; + pdev = to_pci_dev(lnw->dev); - dev_dbg(&lnw->pdev->dev, "%s: old state = %s\n", __func__, - state_string(lnw->otg.state)); + dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, + state_string(iotg->otg.state)); - switch (lnw->otg.state) { + switch (iotg->otg.state) { case OTG_STATE_UNDEFINED: case OTG_STATE_B_IDLE: - if (!lnw->hsm.id) { + if (!iotg->hsm.id) { langwell_otg_del_timer(b_srp_init_tmr); del_timer_sync(&lnw->hsm_timer); - lnw->otg.default_a = 1; - lnw->hsm.a_srp_det = 0; + + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + langwell_otg_chrg_vbus(0); set_host_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_A_IDLE; + + iotg->otg.state = OTG_STATE_A_IDLE; langwell_update_transceiver(); - } else if (lnw->hsm.b_sess_vld) { + } else if (iotg->hsm.b_sess_vld) { langwell_otg_del_timer(b_srp_init_tmr); del_timer_sync(&lnw->hsm_timer); - lnw->hsm.b_sess_end = 0; - lnw->hsm.a_bus_suspend = 0; + iotg->hsm.b_sess_end = 0; + iotg->hsm.a_bus_suspend = 0; langwell_otg_chrg_vbus(0); - if (lnw->client_ops) { - lnw->client_ops->resume(lnw->pdev); - lnw->otg.state = OTG_STATE_B_PERIPHERAL; + + if (lnw->iotg.start_peripheral) { + lnw->iotg.start_peripheral(&lnw->iotg); + iotg->otg.state = OTG_STATE_B_PERIPHERAL; } else - dev_dbg(&lnw->pdev->dev, - "client driver not loaded.\n"); + dev_dbg(lnw->dev, "client driver not loaded\n"); - } else if (lnw->hsm.b_srp_init_tmout) { - lnw->hsm.b_srp_init_tmout = 0; - dev_warn(&lnw->pdev->dev, "SRP init timeout\n"); - } else if (lnw->hsm.b_srp_fail_tmout) { - lnw->hsm.b_srp_fail_tmout = 0; - lnw->hsm.b_bus_req = 0; + } else if (iotg->hsm.b_srp_init_tmout) { + iotg->hsm.b_srp_init_tmout = 0; + dev_warn(lnw->dev, "SRP init timeout\n"); + } else if (iotg->hsm.b_srp_fail_tmout) { + iotg->hsm.b_srp_fail_tmout = 0; + iotg->hsm.b_bus_req = 0; + + /* No silence failure */ langwell_otg_nsf_msg(6); - } else if (lnw->hsm.b_bus_req && - (lnw->hsm.b_sess_end)) { + } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { del_timer_sync(&lnw->hsm_timer); /* workaround for b_se0_srp detection */ retval = langwell_otg_check_se0_srp(0); if (retval) { - lnw->hsm.b_bus_req = 0; - dev_dbg(&lnw->pdev->dev, - "LS is not SE0, try again later\n"); + iotg->hsm.b_bus_req = 0; + dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); } else { /* clear the PHCD before start srp */ langwell_otg_phy_low_power(0); /* Start SRP */ langwell_otg_add_timer(b_srp_init_tmr); - langwell_otg_start_srp(&lnw->otg); + iotg->otg.start_srp(&iotg->otg); langwell_otg_del_timer(b_srp_init_tmr); langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); @@ -942,607 +962,645 @@ static void langwell_otg_work(struct work_struct *work) } break; case OTG_STATE_B_SRP_INIT: - if (!lnw->hsm.id) { - lnw->otg.default_a = 1; - lnw->hsm.a_srp_det = 0; - langwell_otg_drv_vbus(0); + if (!iotg->hsm.id) { + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); langwell_otg_chrg_vbus(0); set_host_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; langwell_update_transceiver(); - } else if (lnw->hsm.b_sess_vld) { + } else if (iotg->hsm.b_sess_vld) { langwell_otg_chrg_vbus(0); - if (lnw->client_ops) { - lnw->client_ops->resume(lnw->pdev); - lnw->otg.state = OTG_STATE_B_PERIPHERAL; + if (lnw->iotg.start_peripheral) { + lnw->iotg.start_peripheral(&lnw->iotg); + iotg->otg.state = OTG_STATE_B_PERIPHERAL; } else - dev_dbg(&lnw->pdev->dev, - "client driver not loaded.\n"); + dev_dbg(lnw->dev, "client driver not loaded\n"); } break; case OTG_STATE_B_PERIPHERAL: - if (!lnw->hsm.id) { - lnw->otg.default_a = 1; - lnw->hsm.a_srp_det = 0; + if (!iotg->hsm.id) { + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; langwell_otg_chrg_vbus(0); - if (lnw->client_ops) { - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); - } else - dev_dbg(&lnw->pdev->dev, + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, "client driver has been removed.\n"); set_host_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; langwell_update_transceiver(); - } else if (!lnw->hsm.b_sess_vld) { - lnw->hsm.b_hnp_enable = 0; + } else if (!iotg->hsm.b_sess_vld) { + iotg->hsm.b_hnp_enable = 0; - if (lnw->client_ops) { - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); - } else - dev_dbg(&lnw->pdev->dev, + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, "client driver has been removed.\n"); - lnw->otg.state = OTG_STATE_B_IDLE; - } else if (lnw->hsm.b_bus_req && lnw->otg.gadget - && lnw->otg.gadget->b_hnp_enable - && lnw->hsm.a_bus_suspend) { + iotg->otg.state = OTG_STATE_B_IDLE; + } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && + iotg->otg.gadget->b_hnp_enable && + iotg->hsm.a_bus_suspend) { - if (lnw->client_ops) { - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); - } else - dev_dbg(&lnw->pdev->dev, + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, "client driver has been removed.\n"); langwell_otg_HAAR(1); - lnw->hsm.a_conn = 0; + iotg->hsm.a_conn = 0; - if (lnw->host_ops) { - lnw->host_ops->probe(lnw->pdev, - lnw->host_ops->id_table); - lnw->otg.state = OTG_STATE_B_WAIT_ACON; + if (lnw->iotg.start_host) { + lnw->iotg.start_host(&lnw->iotg); + iotg->otg.state = OTG_STATE_B_WAIT_ACON; } else - dev_dbg(&lnw->pdev->dev, - "host driver not loaded.\n"); + dev_dbg(lnw->dev, + "host driver not loaded.\n"); - lnw->hsm.a_bus_resume = 0; + iotg->hsm.a_bus_resume = 0; langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); } break; case OTG_STATE_B_WAIT_ACON: - if (!lnw->hsm.id) { + if (!iotg->hsm.id) { /* delete hsm timer for b_ase0_brst_tmr */ del_timer_sync(&lnw->hsm_timer); - lnw->otg.default_a = 1; - lnw->hsm.a_srp_det = 0; + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; langwell_otg_chrg_vbus(0); langwell_otg_HAAR(0); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); + set_host_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; langwell_update_transceiver(); - } else if (!lnw->hsm.b_sess_vld) { + } else if (!iotg->hsm.b_sess_vld) { /* delete hsm timer for b_ase0_brst_tmr */ del_timer_sync(&lnw->hsm_timer); - lnw->hsm.b_hnp_enable = 0; - lnw->hsm.b_bus_req = 0; + iotg->hsm.b_hnp_enable = 0; + iotg->hsm.b_bus_req = 0; + langwell_otg_chrg_vbus(0); langwell_otg_HAAR(0); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); set_client_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_B_IDLE; - } else if (lnw->hsm.a_conn) { + iotg->otg.state = OTG_STATE_B_IDLE; + } else if (iotg->hsm.a_conn) { /* delete hsm timer for b_ase0_brst_tmr */ del_timer_sync(&lnw->hsm_timer); + langwell_otg_HAAR(0); - lnw->otg.state = OTG_STATE_B_HOST; + iotg->otg.state = OTG_STATE_B_HOST; langwell_update_transceiver(); - } else if (lnw->hsm.a_bus_resume || - lnw->hsm.b_ase0_brst_tmout) { + } else if (iotg->hsm.a_bus_resume || + iotg->hsm.b_ase0_brst_tmout) { /* delete hsm timer for b_ase0_brst_tmr */ del_timer_sync(&lnw->hsm_timer); + langwell_otg_HAAR(0); langwell_otg_nsf_msg(7); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - lnw->hsm.a_bus_suspend = 0; - lnw->hsm.b_bus_req = 0; + iotg->hsm.a_bus_suspend = 0; + iotg->hsm.b_bus_req = 0; - if (lnw->client_ops) - lnw->client_ops->resume(lnw->pdev); + if (lnw->iotg.start_peripheral) + lnw->iotg.start_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver not loaded.\n"); - lnw->otg.state = OTG_STATE_B_PERIPHERAL; + iotg->otg.state = OTG_STATE_B_PERIPHERAL; } break; case OTG_STATE_B_HOST: - if (!lnw->hsm.id) { - lnw->otg.default_a = 1; - lnw->hsm.a_srp_det = 0; + if (!iotg->hsm.id) { + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; langwell_otg_chrg_vbus(0); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); + set_host_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; langwell_update_transceiver(); - } else if (!lnw->hsm.b_sess_vld) { - lnw->hsm.b_hnp_enable = 0; - lnw->hsm.b_bus_req = 0; + } else if (!iotg->hsm.b_sess_vld) { + iotg->hsm.b_hnp_enable = 0; + iotg->hsm.b_bus_req = 0; + langwell_otg_chrg_vbus(0); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); set_client_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_B_IDLE; - } else if ((!lnw->hsm.b_bus_req) || - (!lnw->hsm.a_conn)) { - lnw->hsm.b_bus_req = 0; + iotg->otg.state = OTG_STATE_B_IDLE; + } else if ((!iotg->hsm.b_bus_req) || + (!iotg->hsm.a_conn)) { + iotg->hsm.b_bus_req = 0; langwell_otg_loc_sof(0); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - lnw->hsm.a_bus_suspend = 0; + iotg->hsm.a_bus_suspend = 0; - if (lnw->client_ops) - lnw->client_ops->resume(lnw->pdev); + if (lnw->iotg.start_peripheral) + lnw->iotg.start_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, - "client driver not loaded.\n"); + dev_dbg(lnw->dev, + "client driver not loaded.\n"); - lnw->otg.state = OTG_STATE_B_PERIPHERAL; + iotg->otg.state = OTG_STATE_B_PERIPHERAL; } break; case OTG_STATE_A_IDLE: - lnw->otg.default_a = 1; - if (lnw->hsm.id) { - lnw->otg.default_a = 0; - lnw->hsm.b_bus_req = 0; - lnw->hsm.vbus_srp_up = 0; + iotg->otg.default_a = 1; + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + iotg->hsm.vbus_srp_up = 0; + langwell_otg_chrg_vbus(0); set_client_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (!lnw->hsm.a_bus_drop && - (lnw->hsm.a_srp_det || lnw->hsm.a_bus_req)) { + } else if (!iotg->hsm.a_bus_drop && + (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { langwell_otg_phy_low_power(0); - langwell_otg_drv_vbus(1); - lnw->hsm.vbus_srp_up = 0; - lnw->hsm.a_wait_vrise_tmout = 0; + + /* Turn on VBus */ + iotg->otg.set_vbus(&iotg->otg, true); + + iotg->hsm.vbus_srp_up = 0; + iotg->hsm.a_wait_vrise_tmout = 0; langwell_otg_add_timer(a_wait_vrise_tmr); - lnw->otg.state = OTG_STATE_A_WAIT_VRISE; + iotg->otg.state = OTG_STATE_A_WAIT_VRISE; langwell_update_transceiver(); - } else if (!lnw->hsm.a_bus_drop && lnw->hsm.a_sess_vld) { - lnw->hsm.vbus_srp_up = 1; - } else if (!lnw->hsm.a_sess_vld && lnw->hsm.vbus_srp_up) { + } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { + iotg->hsm.vbus_srp_up = 1; + } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { msleep(10); langwell_otg_phy_low_power(0); - langwell_otg_drv_vbus(1); - lnw->hsm.a_srp_det = 1; - lnw->hsm.vbus_srp_up = 0; - lnw->hsm.a_wait_vrise_tmout = 0; + + /* Turn on VBus */ + iotg->otg.set_vbus(&iotg->otg, true); + iotg->hsm.a_srp_det = 1; + iotg->hsm.vbus_srp_up = 0; + iotg->hsm.a_wait_vrise_tmout = 0; langwell_otg_add_timer(a_wait_vrise_tmr); - lnw->otg.state = OTG_STATE_A_WAIT_VRISE; + iotg->otg.state = OTG_STATE_A_WAIT_VRISE; langwell_update_transceiver(); - } else if (!lnw->hsm.a_sess_vld && - !lnw->hsm.vbus_srp_up) { + } else if (!iotg->hsm.a_sess_vld && + !iotg->hsm.vbus_srp_up) { langwell_otg_phy_low_power(1); } break; case OTG_STATE_A_WAIT_VRISE: - if (lnw->hsm.id) { + if (iotg->hsm.id) { langwell_otg_del_timer(a_wait_vrise_tmr); - lnw->hsm.b_bus_req = 0; - lnw->otg.default_a = 0; - langwell_otg_drv_vbus(0); + iotg->hsm.b_bus_req = 0; + iotg->otg.default_a = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); set_client_mode(); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_B_IDLE; - } else if (lnw->hsm.a_vbus_vld) { + iotg->otg.state = OTG_STATE_B_IDLE; + } else if (iotg->hsm.a_vbus_vld) { langwell_otg_del_timer(a_wait_vrise_tmr); - lnw->hsm.b_conn = 0; - if (lnw->host_ops) - lnw->host_ops->probe(lnw->pdev, - lnw->host_ops->id_table); + iotg->hsm.b_conn = 0; + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); else { - dev_dbg(&lnw->pdev->dev, - "host driver not loaded.\n"); + dev_dbg(lnw->dev, "host driver not loaded.\n"); break; } langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - lnw->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (lnw->hsm.a_wait_vrise_tmout) { - lnw->hsm.b_conn = 0; - if (lnw->hsm.a_vbus_vld) { - if (lnw->host_ops) - lnw->host_ops->probe( - lnw->pdev, - lnw->host_ops->id_table); + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } else if (iotg->hsm.a_wait_vrise_tmout) { + iotg->hsm.b_conn = 0; + if (iotg->hsm.a_vbus_vld) { + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); else { - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver not loaded.\n"); break; } langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - lnw->otg.state = OTG_STATE_A_WAIT_BCON; + iotg->otg.state = OTG_STATE_A_WAIT_BCON; } else { - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_A_VBUS_ERR; + iotg->otg.state = OTG_STATE_A_VBUS_ERR; } } break; case OTG_STATE_A_WAIT_BCON: - if (lnw->hsm.id) { + if (iotg->hsm.id) { /* delete hsm timer for a_wait_bcon_tmr */ del_timer_sync(&lnw->hsm_timer); - lnw->otg.default_a = 0; - lnw->hsm.b_bus_req = 0; - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); set_client_mode(); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (!lnw->hsm.a_vbus_vld) { + } else if (!iotg->hsm.a_vbus_vld) { /* delete hsm timer for a_wait_bcon_tmr */ del_timer_sync(&lnw->hsm_timer); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (lnw->hsm.a_bus_drop || - (lnw->hsm.a_wait_bcon_tmout && - !lnw->hsm.a_bus_req)) { + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } else if (iotg->hsm.a_bus_drop || + (iotg->hsm.a_wait_bcon_tmout && + !iotg->hsm.a_bus_req)) { /* delete hsm timer for a_wait_bcon_tmr */ del_timer_sync(&lnw->hsm_timer); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (lnw->hsm.b_conn) { + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (iotg->hsm.b_conn) { /* delete hsm timer for a_wait_bcon_tmr */ del_timer_sync(&lnw->hsm_timer); - lnw->hsm.a_suspend_req = 0; - lnw->otg.state = OTG_STATE_A_HOST; - if (lnw->hsm.a_srp_det && - !lnw->otg.host->b_hnp_enable) { + iotg->hsm.a_suspend_req = 0; + iotg->otg.state = OTG_STATE_A_HOST; + if (iotg->hsm.a_srp_det && iotg->otg.host && + !iotg->otg.host->b_hnp_enable) { /* SRP capable peripheral-only device */ - lnw->hsm.a_bus_req = 1; - lnw->hsm.a_srp_det = 0; - } else if (!lnw->hsm.a_bus_req && - lnw->otg.host->b_hnp_enable) { + iotg->hsm.a_bus_req = 1; + iotg->hsm.a_srp_det = 0; + } else if (!iotg->hsm.a_bus_req && iotg->otg.host && + iotg->otg.host->b_hnp_enable) { /* It is not safe enough to do a fast * transistion from A_WAIT_BCON to * A_SUSPEND */ msleep(10000); - if (lnw->hsm.a_bus_req) + if (iotg->hsm.a_bus_req) break; - if (request_irq(lnw->pdev->irq, + if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, - driver_name, lnw->regs) != 0) { - dev_dbg(&lnw->pdev->dev, + driver_name, iotg->base) != 0) { + dev_dbg(lnw->dev, "request interrupt %d fail\n", - lnw->pdev->irq); + pdev->irq); } langwell_otg_HABA(1); - lnw->hsm.b_bus_resume = 0; - lnw->hsm.a_aidl_bdis_tmout = 0; + iotg->hsm.b_bus_resume = 0; + iotg->hsm.a_aidl_bdis_tmout = 0; langwell_otg_loc_sof(0); /* clear PHCD to enable HW timer */ langwell_otg_phy_low_power(0); langwell_otg_add_timer(a_aidl_bdis_tmr); - lnw->otg.state = OTG_STATE_A_SUSPEND; - } else if (!lnw->hsm.a_bus_req && - !lnw->otg.host->b_hnp_enable) { - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + iotg->otg.state = OTG_STATE_A_SUSPEND; + } else if (!iotg->hsm.a_bus_req && iotg->otg.host && + !iotg->otg.host->b_hnp_enable) { + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver removed.\n"); - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_WAIT_VFALL; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; } } break; case OTG_STATE_A_HOST: - if (lnw->hsm.id) { - lnw->otg.default_a = 0; - lnw->hsm.b_bus_req = 0; - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); set_client_mode(); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (lnw->hsm.a_bus_drop || - (!lnw->otg.host->b_hnp_enable && - !lnw->hsm.a_bus_req)) { - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + } else if (iotg->hsm.a_bus_drop || + (iotg->otg.host && + !iotg->otg.host->b_hnp_enable && + !iotg->hsm.a_bus_req)) { + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!lnw->hsm.a_vbus_vld) { - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (!iotg->hsm.a_vbus_vld) { + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (lnw->otg.host->b_hnp_enable - && !lnw->hsm.a_bus_req) { + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } else if (iotg->otg.host && + iotg->otg.host->b_hnp_enable && + !iotg->hsm.a_bus_req) { /* Set HABA to enable hardware assistance to signal * A-connect after receiver B-disconnect. Hardware * will then set client mode and enable URE, SLE and * PCE after the assistance. otg_dummy_irq is used to * clean these ints when client driver is not resumed. */ - if (request_irq(lnw->pdev->irq, - otg_dummy_irq, IRQF_SHARED, driver_name, - lnw->regs) != 0) { - dev_dbg(&lnw->pdev->dev, + if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, + driver_name, iotg->base) != 0) { + dev_dbg(lnw->dev, "request interrupt %d failed\n", - lnw->pdev->irq); + pdev->irq); } /* set HABA */ langwell_otg_HABA(1); - lnw->hsm.b_bus_resume = 0; - lnw->hsm.a_aidl_bdis_tmout = 0; + iotg->hsm.b_bus_resume = 0; + iotg->hsm.a_aidl_bdis_tmout = 0; langwell_otg_loc_sof(0); /* clear PHCD to enable HW timer */ langwell_otg_phy_low_power(0); langwell_otg_add_timer(a_aidl_bdis_tmr); - lnw->otg.state = OTG_STATE_A_SUSPEND; - } else if (!lnw->hsm.b_conn || !lnw->hsm.a_bus_req) { + iotg->otg.state = OTG_STATE_A_SUSPEND; + } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - lnw->otg.state = OTG_STATE_A_WAIT_BCON; + iotg->otg.state = OTG_STATE_A_WAIT_BCON; } break; case OTG_STATE_A_SUSPEND: - if (lnw->hsm.id) { + if (iotg->hsm.id) { langwell_otg_del_timer(a_aidl_bdis_tmr); langwell_otg_HABA(0); - free_irq(lnw->pdev->irq, lnw->regs); - lnw->otg.default_a = 0; - lnw->hsm.b_bus_req = 0; - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + free_irq(pdev->irq, iotg->base); + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); set_client_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (lnw->hsm.a_bus_req || - lnw->hsm.b_bus_resume) { + } else if (iotg->hsm.a_bus_req || + iotg->hsm.b_bus_resume) { langwell_otg_del_timer(a_aidl_bdis_tmr); langwell_otg_HABA(0); - free_irq(lnw->pdev->irq, lnw->regs); - lnw->hsm.a_suspend_req = 0; + free_irq(pdev->irq, iotg->base); + iotg->hsm.a_suspend_req = 0; langwell_otg_loc_sof(1); - lnw->otg.state = OTG_STATE_A_HOST; - } else if (lnw->hsm.a_aidl_bdis_tmout || - lnw->hsm.a_bus_drop) { + iotg->otg.state = OTG_STATE_A_HOST; + } else if (iotg->hsm.a_aidl_bdis_tmout || + iotg->hsm.a_bus_drop) { langwell_otg_del_timer(a_aidl_bdis_tmr); langwell_otg_HABA(0); - free_irq(lnw->pdev->irq, lnw->regs); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + free_irq(pdev->irq, iotg->base); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!lnw->hsm.b_conn && - lnw->otg.host->b_hnp_enable) { + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (!iotg->hsm.b_conn && iotg->otg.host && + iotg->otg.host->b_hnp_enable) { langwell_otg_del_timer(a_aidl_bdis_tmr); langwell_otg_HABA(0); - free_irq(lnw->pdev->irq, lnw->regs); + free_irq(pdev->irq, iotg->base); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - lnw->hsm.b_bus_suspend = 0; - lnw->hsm.b_bus_suspend_vld = 0; + iotg->hsm.b_bus_suspend = 0; + iotg->hsm.b_bus_suspend_vld = 0; /* msleep(200); */ - if (lnw->client_ops) - lnw->client_ops->resume(lnw->pdev); + if (lnw->iotg.start_peripheral) + lnw->iotg.start_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver not loaded.\n"); langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); - lnw->otg.state = OTG_STATE_A_PERIPHERAL; + iotg->otg.state = OTG_STATE_A_PERIPHERAL; break; - } else if (!lnw->hsm.a_vbus_vld) { + } else if (!iotg->hsm.a_vbus_vld) { langwell_otg_del_timer(a_aidl_bdis_tmr); langwell_otg_HABA(0); - free_irq(lnw->pdev->irq, lnw->regs); - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); + free_irq(pdev->irq, iotg->base); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "host driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_A_VBUS_ERR; + iotg->otg.state = OTG_STATE_A_VBUS_ERR; } break; case OTG_STATE_A_PERIPHERAL: - if (lnw->hsm.id) { + if (iotg->hsm.id) { /* delete hsm timer for b_bus_suspend_tmr */ del_timer_sync(&lnw->hsm_timer); - lnw->otg.default_a = 0; - lnw->hsm.b_bus_req = 0; - if (lnw->client_ops) - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); set_client_mode(); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (!lnw->hsm.a_vbus_vld) { + } else if (!iotg->hsm.a_vbus_vld) { /* delete hsm timer for b_bus_suspend_tmr */ del_timer_sync(&lnw->hsm_timer); - if (lnw->client_ops) - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver has been removed.\n"); - langwell_otg_drv_vbus(0); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); langwell_otg_phy_low_power_wait(1); - lnw->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (lnw->hsm.a_bus_drop) { + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } else if (iotg->hsm.a_bus_drop) { /* delete hsm timer for b_bus_suspend_tmr */ del_timer_sync(&lnw->hsm_timer); - if (lnw->client_ops) - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver has been removed.\n"); - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (lnw->hsm.b_bus_suspend) { + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (iotg->hsm.b_bus_suspend) { /* delete hsm timer for b_bus_suspend_tmr */ del_timer_sync(&lnw->hsm_timer); - if (lnw->client_ops) - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver has been removed.\n"); - if (lnw->host_ops) - lnw->host_ops->probe(lnw->pdev, - lnw->host_ops->id_table); + + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, - "host driver not loaded.\n"); + dev_dbg(lnw->dev, + "host driver not loaded.\n"); langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - lnw->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (lnw->hsm.b_bus_suspend_tmout) { + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } else if (iotg->hsm.b_bus_suspend_tmout) { u32 val; - val = readl(lnw->regs + CI_PORTSC1); + val = readl(lnw->iotg.base + CI_PORTSC1); if (!(val & PORTSC_SUSP)) break; - if (lnw->client_ops) - lnw->client_ops->suspend(lnw->pdev, - PMSG_FREEZE); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, + dev_dbg(lnw->dev, "client driver has been removed.\n"); - if (lnw->host_ops) - lnw->host_ops->probe(lnw->pdev, - lnw->host_ops->id_table); + + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); else - dev_dbg(&lnw->pdev->dev, - "host driver not loaded.\n"); + dev_dbg(lnw->dev, + "host driver not loaded.\n"); langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - lnw->otg.state = OTG_STATE_A_WAIT_BCON; + iotg->otg.state = OTG_STATE_A_WAIT_BCON; } break; case OTG_STATE_A_VBUS_ERR: - if (lnw->hsm.id) { - lnw->otg.default_a = 0; - lnw->hsm.a_clr_err = 0; - lnw->hsm.a_srp_det = 0; + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + iotg->hsm.a_clr_err = 0; + iotg->hsm.a_srp_det = 0; set_client_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (lnw->hsm.a_clr_err) { - lnw->hsm.a_clr_err = 0; - lnw->hsm.a_srp_det = 0; + } else if (iotg->hsm.a_clr_err) { + iotg->hsm.a_clr_err = 0; + iotg->hsm.a_srp_det = 0; reset_otg(); init_hsm(); - if (lnw->otg.state == OTG_STATE_A_IDLE) + if (iotg->otg.state == OTG_STATE_A_IDLE) langwell_update_transceiver(); } else { /* FW will clear PHCD bit when any VBus @@ -1551,30 +1609,32 @@ static void langwell_otg_work(struct work_struct *work) } break; case OTG_STATE_A_WAIT_VFALL: - if (lnw->hsm.id) { - lnw->otg.default_a = 0; + if (iotg->hsm.id) { + iotg->otg.default_a = 0; set_client_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; langwell_update_transceiver(); - } else if (lnw->hsm.a_bus_req) { - langwell_otg_drv_vbus(1); - lnw->hsm.a_wait_vrise_tmout = 0; + } else if (iotg->hsm.a_bus_req) { + + /* Turn on VBus */ + iotg->otg.set_vbus(&iotg->otg, true); + iotg->hsm.a_wait_vrise_tmout = 0; langwell_otg_add_timer(a_wait_vrise_tmr); - lnw->otg.state = OTG_STATE_A_WAIT_VRISE; - } else if (!lnw->hsm.a_sess_vld) { - lnw->hsm.a_srp_det = 0; + iotg->otg.state = OTG_STATE_A_WAIT_VRISE; + } else if (!iotg->hsm.a_sess_vld) { + iotg->hsm.a_srp_det = 0; set_host_mode(); langwell_otg_phy_low_power(1); - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; } break; default: ; } - dev_dbg(&lnw->pdev->dev, "%s: new state = %s\n", __func__, - state_string(lnw->otg.state)); + dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, + state_string(iotg->otg.state)); } static ssize_t @@ -1597,15 +1657,15 @@ show_registers(struct device *_dev, struct device_attribute *attr, char *buf) "HOSTPC1 = 0x%08x\n" "OTGSC = 0x%08x\n" "USBMODE = 0x%08x\n", - readl(lnw->regs + 0x30), - readl(lnw->regs + 0x34), - readl(lnw->regs + 0x38), - readl(lnw->regs + 0x48), - readl(lnw->regs + 0x74), - readl(lnw->regs + 0xb4), - readl(lnw->regs + 0xf4), - readl(lnw->regs + 0xf8) - ); + readl(lnw->iotg.base + 0x30), + readl(lnw->iotg.base + 0x34), + readl(lnw->iotg.base + 0x38), + readl(lnw->iotg.base + 0x48), + readl(lnw->iotg.base + 0x74), + readl(lnw->iotg.base + 0xb4), + readl(lnw->iotg.base + 0xf4), + readl(lnw->iotg.base + 0xf8) + ); size -= t; next += t; @@ -1616,18 +1676,19 @@ static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); static ssize_t show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) { - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + char *next; + unsigned size, t; next = buf; size = PAGE_SIZE; - if (lnw->otg.host) - lnw->hsm.a_set_b_hnp_en = lnw->otg.host->b_hnp_enable; + if (iotg->otg.host) + iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; - if (lnw->otg.gadget) - lnw->hsm.b_hnp_enable = lnw->otg.gadget->b_hnp_enable; + if (iotg->otg.gadget) + iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; t = scnprintf(next, size, "\n" @@ -1659,34 +1720,34 @@ show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) "b_bus_req = \t%d\n" "b_bus_suspend_tmout = \t%d\n" "b_bus_suspend_vld = \t%d\n", - state_string(lnw->otg.state), - lnw->hsm.a_bus_resume, - lnw->hsm.a_bus_suspend, - lnw->hsm.a_conn, - lnw->hsm.a_sess_vld, - lnw->hsm.a_srp_det, - lnw->hsm.a_vbus_vld, - lnw->hsm.b_bus_resume, - lnw->hsm.b_bus_suspend, - lnw->hsm.b_conn, - lnw->hsm.b_se0_srp, - lnw->hsm.b_sess_end, - lnw->hsm.b_sess_vld, - lnw->hsm.id, - lnw->hsm.a_set_b_hnp_en, - lnw->hsm.b_srp_done, - lnw->hsm.b_hnp_enable, - lnw->hsm.a_wait_vrise_tmout, - lnw->hsm.a_wait_bcon_tmout, - lnw->hsm.a_aidl_bdis_tmout, - lnw->hsm.b_ase0_brst_tmout, - lnw->hsm.a_bus_drop, - lnw->hsm.a_bus_req, - lnw->hsm.a_clr_err, - lnw->hsm.a_suspend_req, - lnw->hsm.b_bus_req, - lnw->hsm.b_bus_suspend_tmout, - lnw->hsm.b_bus_suspend_vld + state_string(iotg->otg.state), + iotg->hsm.a_bus_resume, + iotg->hsm.a_bus_suspend, + iotg->hsm.a_conn, + iotg->hsm.a_sess_vld, + iotg->hsm.a_srp_det, + iotg->hsm.a_vbus_vld, + iotg->hsm.b_bus_resume, + iotg->hsm.b_bus_suspend, + iotg->hsm.b_conn, + iotg->hsm.b_se0_srp, + iotg->hsm.b_sess_end, + iotg->hsm.b_sess_vld, + iotg->hsm.id, + iotg->hsm.a_set_b_hnp_en, + iotg->hsm.b_srp_done, + iotg->hsm.b_hnp_enable, + iotg->hsm.a_wait_vrise_tmout, + iotg->hsm.a_wait_bcon_tmout, + iotg->hsm.a_aidl_bdis_tmout, + iotg->hsm.b_ase0_brst_tmout, + iotg->hsm.a_bus_drop, + iotg->hsm.a_bus_req, + iotg->hsm.a_clr_err, + iotg->hsm.a_suspend_req, + iotg->hsm.b_bus_req, + iotg->hsm.b_bus_suspend_tmout, + iotg->hsm.b_bus_suspend_vld ); size -= t; next += t; @@ -1705,7 +1766,7 @@ get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) next = buf; size = PAGE_SIZE; - t = scnprintf(next, size, "%d", lnw->hsm.a_bus_req); + t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); size -= t; next += t; @@ -1716,22 +1777,23 @@ static ssize_t set_a_bus_req(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct langwell_otg *lnw = the_transceiver; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - if (!lnw->otg.default_a) + if (!iotg->otg.default_a) return -1; if (count > 2) return -1; if (buf[0] == '0') { - lnw->hsm.a_bus_req = 0; - dev_dbg(&lnw->pdev->dev, "User request: a_bus_req = 0\n"); + iotg->hsm.a_bus_req = 0; + dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); } else if (buf[0] == '1') { /* If a_bus_drop is TRUE, a_bus_req can't be set */ - if (lnw->hsm.a_bus_drop) + if (iotg->hsm.a_bus_drop) return -1; - lnw->hsm.a_bus_req = 1; - dev_dbg(&lnw->pdev->dev, "User request: a_bus_req = 1\n"); + iotg->hsm.a_bus_req = 1; + dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); } if (spin_trylock(&lnw->wq_lock)) { langwell_update_transceiver(); @@ -1751,7 +1813,7 @@ get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) next = buf; size = PAGE_SIZE; - t = scnprintf(next, size, "%d", lnw->hsm.a_bus_drop); + t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); size -= t; next += t; @@ -1762,21 +1824,22 @@ static ssize_t set_a_bus_drop(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct langwell_otg *lnw = the_transceiver; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - if (!lnw->otg.default_a) + if (!iotg->otg.default_a) return -1; if (count > 2) return -1; if (buf[0] == '0') { - lnw->hsm.a_bus_drop = 0; - dev_dbg(&lnw->pdev->dev, "User request: a_bus_drop = 0\n"); + iotg->hsm.a_bus_drop = 0; + dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); } else if (buf[0] == '1') { - lnw->hsm.a_bus_drop = 1; - lnw->hsm.a_bus_req = 0; - dev_dbg(&lnw->pdev->dev, "User request: a_bus_drop = 1\n"); - dev_dbg(&lnw->pdev->dev, "User request: and a_bus_req = 0\n"); + iotg->hsm.a_bus_drop = 1; + iotg->hsm.a_bus_req = 0; + dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); + dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); } if (spin_trylock(&lnw->wq_lock)) { langwell_update_transceiver(); @@ -1797,7 +1860,7 @@ get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) next = buf; size = PAGE_SIZE; - t = scnprintf(next, size, "%d", lnw->hsm.b_bus_req); + t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); size -= t; next += t; @@ -1808,20 +1871,21 @@ static ssize_t set_b_bus_req(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct langwell_otg *lnw = the_transceiver; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - if (lnw->otg.default_a) + if (iotg->otg.default_a) return -1; if (count > 2) return -1; if (buf[0] == '0') { - lnw->hsm.b_bus_req = 0; - dev_dbg(&lnw->pdev->dev, "User request: b_bus_req = 0\n"); + iotg->hsm.b_bus_req = 0; + dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); } else if (buf[0] == '1') { - lnw->hsm.b_bus_req = 1; - dev_dbg(&lnw->pdev->dev, "User request: b_bus_req = 1\n"); + iotg->hsm.b_bus_req = 1; + dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); } if (spin_trylock(&lnw->wq_lock)) { langwell_update_transceiver(); @@ -1835,16 +1899,17 @@ static ssize_t set_a_clr_err(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct langwell_otg *lnw = the_transceiver; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - if (!lnw->otg.default_a) + if (!iotg->otg.default_a) return -1; if (count > 2) return -1; if (buf[0] == '1') { - lnw->hsm.a_clr_err = 1; - dev_dbg(&lnw->pdev->dev, "User request: a_clr_err = 1\n"); + iotg->hsm.a_clr_err = 1; + dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); } if (spin_trylock(&lnw->wq_lock)) { langwell_update_transceiver(); @@ -1867,65 +1932,6 @@ static struct attribute_group debug_dev_attr_group = { .attrs = inputs_attrs, }; -int langwell_register_host(struct pci_driver *host_driver) -{ - struct langwell_otg *lnw = the_transceiver; - int ret = 0; - - lnw->host_ops = host_driver; - langwell_update_transceiver(); - dev_dbg(&lnw->pdev->dev, "host controller driver is registered\n"); - - return ret; -} -EXPORT_SYMBOL(langwell_register_host); - -void langwell_unregister_host(struct pci_driver *host_driver) -{ - struct langwell_otg *lnw = the_transceiver; - - if (lnw->host_ops) - lnw->host_ops->remove(lnw->pdev); - lnw->host_ops = NULL; - lnw->hsm.a_bus_drop = 1; - langwell_update_transceiver(); - dev_dbg(&lnw->pdev->dev, "host controller driver is unregistered\n"); -} -EXPORT_SYMBOL(langwell_unregister_host); - -int langwell_register_peripheral(struct pci_driver *client_driver) -{ - struct langwell_otg *lnw = the_transceiver; - int ret = 0; - - if (client_driver) - ret = client_driver->probe(lnw->pdev, - client_driver->id_table); - if (!ret) { - lnw->client_ops = client_driver; - langwell_update_transceiver(); - dev_dbg(&lnw->pdev->dev, - "client controller driver is registered\n"); - } - - return ret; -} -EXPORT_SYMBOL(langwell_register_peripheral); - -void langwell_unregister_peripheral(struct pci_driver *client_driver) -{ - struct langwell_otg *lnw = the_transceiver; - - if (lnw->client_ops) - lnw->client_ops->remove(lnw->pdev); - lnw->client_ops = NULL; - lnw->hsm.b_bus_req = 0; - langwell_update_transceiver(); - dev_dbg(&lnw->pdev->dev, - "client controller driver is unregistered\n"); -} -EXPORT_SYMBOL(langwell_unregister_peripheral); - static int langwell_otg_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -1933,7 +1939,7 @@ static int langwell_otg_probe(struct pci_dev *pdev, void __iomem *base = NULL; int retval; u32 val32; - struct langwell_otg *langwell; + struct langwell_otg *lnw; char qname[] = "langwell_otg_queue"; retval = 0; @@ -1943,12 +1949,12 @@ static int langwell_otg_probe(struct pci_dev *pdev, goto done; } - langwell = kzalloc(sizeof *langwell, GFP_KERNEL); - if (langwell == NULL) { + lnw = kzalloc(sizeof *lnw, GFP_KERNEL); + if (lnw == NULL) { retval = -ENOMEM; goto done; } - the_transceiver = langwell; + the_transceiver = lnw; /* control register: BAR 0 */ resource = pci_resource_start(pdev, 0); @@ -1957,20 +1963,20 @@ static int langwell_otg_probe(struct pci_dev *pdev, retval = -EBUSY; goto err; } - langwell->region = 1; + lnw->region = 1; base = ioremap_nocache(resource, len); if (base == NULL) { retval = -EFAULT; goto err; } - langwell->regs = base; + lnw->iotg.base = base; if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { retval = -EBUSY; goto err; } - langwell->cfg_region = 1; + lnw->cfg_region = 1; /* For the SCCB.USBCFG register */ base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); @@ -1978,7 +1984,7 @@ static int langwell_otg_probe(struct pci_dev *pdev, retval = -EFAULT; goto err; } - langwell->usbcfg = base; + lnw->usbcfg = base; if (!pdev->irq) { dev_dbg(&pdev->dev, "No IRQ.\n"); @@ -1986,25 +1992,27 @@ static int langwell_otg_probe(struct pci_dev *pdev, goto err; } - langwell->qwork = create_singlethread_workqueue(qname); - if (!langwell->qwork) { + lnw->qwork = create_singlethread_workqueue(qname); + if (!lnw->qwork) { dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); retval = -ENOMEM; goto err; } - INIT_WORK(&langwell->work, langwell_otg_work); + INIT_WORK(&lnw->work, langwell_otg_work); /* OTG common part */ - langwell->pdev = pdev; - langwell->otg.dev = &pdev->dev; - langwell->otg.label = driver_name; - langwell->otg.set_host = langwell_otg_set_host; - langwell->otg.set_peripheral = langwell_otg_set_peripheral; - langwell->otg.set_power = langwell_otg_set_power; - langwell->otg.start_srp = langwell_otg_start_srp; - langwell->otg.state = OTG_STATE_UNDEFINED; - if (otg_set_transceiver(&langwell->otg)) { - dev_dbg(&pdev->dev, "can't set transceiver\n"); + lnw->dev = &pdev->dev; + lnw->iotg.otg.dev = lnw->dev; + lnw->iotg.otg.label = driver_name; + lnw->iotg.otg.set_host = langwell_otg_set_host; + lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; + lnw->iotg.otg.set_power = langwell_otg_set_power; + lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; + lnw->iotg.otg.start_srp = langwell_otg_start_srp; + lnw->iotg.otg.state = OTG_STATE_UNDEFINED; + + if (otg_set_transceiver(&lnw->iotg.otg)) { + dev_dbg(lnw->dev, "can't set transceiver\n"); retval = -EBUSY; goto err; } @@ -2012,19 +2020,19 @@ static int langwell_otg_probe(struct pci_dev *pdev, reset_otg(); init_hsm(); - spin_lock_init(&langwell->lock); - spin_lock_init(&langwell->wq_lock); + spin_lock_init(&lnw->lock); + spin_lock_init(&lnw->wq_lock); INIT_LIST_HEAD(&active_timers); - retval = langwell_otg_init_timers(&langwell->hsm); + retval = langwell_otg_init_timers(&lnw->iotg.hsm); if (retval) { dev_dbg(&pdev->dev, "Failed to init timers\n"); goto err; } - init_timer(&langwell->hsm_timer); + init_timer(&lnw->hsm_timer); if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, langwell) != 0) { - dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); + driver_name, lnw) != 0) { + dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; goto err; } @@ -2032,29 +2040,29 @@ static int langwell_otg_probe(struct pci_dev *pdev, /* enable OTGSC int */ val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; - writel(val32, langwell->regs + CI_OTGSC); + writel(val32, lnw->iotg.base + CI_OTGSC); retval = device_create_file(&pdev->dev, &dev_attr_registers); if (retval < 0) { - dev_dbg(&pdev->dev, "Can't register sysfs attribute: %d\n", - retval); + dev_dbg(lnw->dev, + "Can't register sysfs attribute: %d\n", retval); goto err; } retval = device_create_file(&pdev->dev, &dev_attr_hsm); if (retval < 0) { - dev_dbg(&pdev->dev, "Can't hsm sysfs attribute: %d\n", retval); + dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); goto err; } retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); if (retval < 0) { - dev_dbg(&pdev->dev, "Can't register sysfs attr group: %d\n", - retval); + dev_dbg(lnw->dev, + "Can't register sysfs attr group: %d\n", retval); goto err; } - if (langwell->otg.state == OTG_STATE_A_IDLE) + if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) langwell_update_transceiver(); return 0; @@ -2068,28 +2076,26 @@ done: static void langwell_otg_remove(struct pci_dev *pdev) { - struct langwell_otg *langwell; - - langwell = the_transceiver; + struct langwell_otg *lnw = the_transceiver; - if (langwell->qwork) { - flush_workqueue(langwell->qwork); - destroy_workqueue(langwell->qwork); + if (lnw->qwork) { + flush_workqueue(lnw->qwork); + destroy_workqueue(lnw->qwork); } langwell_otg_free_timers(); /* disable OTGSC interrupt as OTGSC doesn't change in reset */ - writel(0, langwell->regs + CI_OTGSC); + writel(0, lnw->iotg.base + CI_OTGSC); if (pdev->irq) - free_irq(pdev->irq, langwell); - if (langwell->usbcfg) - iounmap(langwell->usbcfg); - if (langwell->cfg_region) + free_irq(pdev->irq, lnw); + if (lnw->usbcfg) + iounmap(lnw->usbcfg); + if (lnw->cfg_region) release_mem_region(USBCFG_ADDR, USBCFG_LEN); - if (langwell->regs) - iounmap(langwell->regs); - if (langwell->region) + if (lnw->iotg.base) + iounmap(lnw->iotg.base); + if (lnw->region) release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); @@ -2098,8 +2104,8 @@ static void langwell_otg_remove(struct pci_dev *pdev) sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); device_remove_file(&pdev->dev, &dev_attr_hsm); device_remove_file(&pdev->dev, &dev_attr_registers); - kfree(langwell); - langwell = NULL; + kfree(lnw); + lnw = NULL; } static void transceiver_suspend(struct pci_dev *pdev) @@ -2111,8 +2117,9 @@ static void transceiver_suspend(struct pci_dev *pdev) static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) { - struct langwell_otg *lnw = the_transceiver; - int ret = 0; + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + int ret = 0; /* Disbale OTG interrupts */ langwell_otg_intr(0); @@ -2126,9 +2133,9 @@ static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) lnw->qwork = NULL; /* start actions */ - switch (lnw->otg.state) { + switch (iotg->otg.state) { case OTG_STATE_A_WAIT_VFALL: - lnw->otg.state = OTG_STATE_A_IDLE; + iotg->otg.state = OTG_STATE_A_IDLE; case OTG_STATE_A_IDLE: case OTG_STATE_B_IDLE: case OTG_STATE_A_VBUS_ERR: @@ -2136,96 +2143,104 @@ static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) break; case OTG_STATE_A_WAIT_VRISE: langwell_otg_del_timer(a_wait_vrise_tmr); - lnw->hsm.a_srp_det = 0; + iotg->hsm.a_srp_det = 0; - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_IDLE; + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_A_WAIT_BCON: del_timer_sync(&lnw->hsm_timer); - if (lnw->host_ops) - lnw->host_ops->remove(pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else dev_dbg(&pdev->dev, "host driver has been removed.\n"); - lnw->hsm.a_srp_det = 0; - - langwell_otg_drv_vbus(0); + iotg->hsm.a_srp_det = 0; - lnw->otg.state = OTG_STATE_A_IDLE; + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_A_HOST: - if (lnw->host_ops) - lnw->host_ops->remove(pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else dev_dbg(&pdev->dev, "host driver has been removed.\n"); - lnw->hsm.a_srp_det = 0; + iotg->hsm.a_srp_det = 0; - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_IDLE; + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + + iotg->otg.state = OTG_STATE_A_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_A_SUSPEND: langwell_otg_del_timer(a_aidl_bdis_tmr); langwell_otg_HABA(0); - if (lnw->host_ops) - lnw->host_ops->remove(pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - lnw->hsm.a_srp_det = 0; + dev_dbg(lnw->dev, "host driver has been removed.\n"); + iotg->hsm.a_srp_det = 0; - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_IDLE; + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_A_PERIPHERAL: del_timer_sync(&lnw->hsm_timer); - if (lnw->client_ops) - lnw->client_ops->suspend(pdev, message); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else dev_dbg(&pdev->dev, "client driver has been removed.\n"); - lnw->hsm.a_srp_det = 0; + iotg->hsm.a_srp_det = 0; - langwell_otg_drv_vbus(0); - lnw->otg.state = OTG_STATE_A_IDLE; + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_B_HOST: - if (lnw->host_ops) - lnw->host_ops->remove(pdev); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else dev_dbg(&pdev->dev, "host driver has been removed.\n"); - lnw->hsm.b_bus_req = 0; - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->hsm.b_bus_req = 0; + iotg->otg.state = OTG_STATE_B_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_B_PERIPHERAL: - if (lnw->client_ops) - lnw->client_ops->suspend(pdev, message); + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); else dev_dbg(&pdev->dev, "client driver has been removed.\n"); - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->otg.state = OTG_STATE_B_IDLE; transceiver_suspend(pdev); break; case OTG_STATE_B_WAIT_ACON: /* delete hsm timer for b_ase0_brst_tmr */ del_timer_sync(&lnw->hsm_timer); + langwell_otg_HAAR(0); - if (lnw->host_ops) - lnw->host_ops->remove(pdev); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); else dev_dbg(&pdev->dev, "host driver has been removed.\n"); - lnw->hsm.b_bus_req = 0; - lnw->otg.state = OTG_STATE_B_IDLE; + iotg->hsm.b_bus_req = 0; + iotg->otg.state = OTG_STATE_B_IDLE; transceiver_suspend(pdev); break; default: - dev_dbg(&pdev->dev, "error state before suspend\n "); + dev_dbg(lnw->dev, "error state before suspend\n"); break; } diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h index a5a3744..5da7f59 100644 --- a/include/linux/usb/langwell_otg.h +++ b/include/linux/usb/langwell_otg.h @@ -17,21 +17,10 @@ * */ -#ifndef __LANGWELL_OTG_H__ -#define __LANGWELL_OTG_H__ +#ifndef __LANGWELL_OTG_H +#define __LANGWELL_OTG_H -/* notify transceiver driver about OTG events */ -extern void langwell_update_transceiver(void); -/* HCD register bus driver */ -extern int langwell_register_host(struct pci_driver *host_driver); -/* HCD unregister bus driver */ -extern void langwell_unregister_host(struct pci_driver *host_driver); -/* DCD register bus driver */ -extern int langwell_register_peripheral(struct pci_driver *client_driver); -/* DCD unregister bus driver */ -extern void langwell_unregister_peripheral(struct pci_driver *client_driver); -/* No silent failure, output warning message */ -extern void langwell_otg_nsf_msg(unsigned long message); +#include <linux/usb/intel_mid_otg.h> #define CI_USBCMD 0x30 # define USBCMD_RST BIT(1) @@ -94,53 +83,6 @@ extern void langwell_otg_nsf_msg(unsigned long message); #define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI) -struct otg_hsm { - /* Input */ - int a_bus_resume; - int a_bus_suspend; - int a_conn; - int a_sess_vld; - int a_srp_det; - int a_vbus_vld; - int b_bus_resume; - int b_bus_suspend; - int b_conn; - int b_se0_srp; - int b_sess_end; - int b_sess_vld; - int id; - - /* Internal variables */ - int a_set_b_hnp_en; - int b_srp_done; - int b_hnp_enable; - - /* Timeout indicator for timers */ - int a_wait_vrise_tmout; - int a_wait_bcon_tmout; - int a_aidl_bdis_tmout; - int b_ase0_brst_tmout; - int b_bus_suspend_tmout; - int b_srp_init_tmout; - int b_srp_fail_tmout; - - /* Informative variables */ - int a_bus_drop; - int a_bus_req; - int a_clr_err; - int a_suspend_req; - int b_bus_req; - - /* Output */ - int drv_vbus; - int loc_conn; - int loc_sof; - - /* Others */ - int b_bus_suspend_vld; - int vbus_srp_up; -}; - enum langwell_otg_timer_type { TA_WAIT_VRISE_TMR, TA_WAIT_BCON_TMR, @@ -170,25 +112,26 @@ struct langwell_otg_timer { }; struct langwell_otg { - struct otg_transceiver otg; - struct otg_hsm hsm; - void __iomem *regs; - void __iomem *usbcfg; /* SCCB USB config Reg */ - unsigned region; - unsigned cfg_region; - struct pci_driver *host_ops; - struct pci_driver *client_ops; - struct pci_dev *pdev; - struct work_struct work; - struct workqueue_struct *qwork; - struct timer_list hsm_timer; - spinlock_t lock; - spinlock_t wq_lock; + struct intel_mid_otg_xceiv iotg; + struct device *dev; + + void __iomem *usbcfg; /* SCCBUSB config Reg */ + + unsigned region; + unsigned cfg_region; + + struct work_struct work; + struct workqueue_struct *qwork; + struct timer_list hsm_timer; + + spinlock_t lock; + spinlock_t wq_lock; }; -static inline struct langwell_otg *otg_to_langwell(struct otg_transceiver *otg) +static inline +struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg) { - return container_of(otg, struct langwell_otg, otg); + return container_of(iotg, struct langwell_otg, iotg); } #endif /* __LANGWELL_OTG_H__ */ -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html