From b4b7ff4b08e691656c9d77c758fc355833128ac0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 20 Jan 2016 14:01:31 -0300 Subject: Linux-libre 4.4-gnu --- drivers/usb/dwc2/core.c | 478 +++++++------- drivers/usb/dwc2/core.h | 107 ++-- drivers/usb/dwc2/core_intr.c | 106 ++-- drivers/usb/dwc2/debugfs.c | 72 +-- drivers/usb/dwc2/gadget.c | 1422 ++++++++++++++++++++---------------------- drivers/usb/dwc2/hcd.c | 353 ++++++++--- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c | 10 +- drivers/usb/dwc2/hcd_intr.c | 152 +++-- drivers/usb/dwc2/hcd_queue.c | 21 +- drivers/usb/dwc2/hw.h | 1 + drivers/usb/dwc2/platform.c | 292 +++++++-- 12 files changed, 1717 insertions(+), 1312 deletions(-) (limited to 'drivers/usb/dwc2') diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index b00fe9539..ef73e498e 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -73,13 +73,13 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) /* Backup Host regs */ hr = &hsotg->hr_backup; - hr->hcfg = readl(hsotg->regs + HCFG); - hr->haintmsk = readl(hsotg->regs + HAINTMSK); + hr->hcfg = dwc2_readl(hsotg->regs + HCFG); + hr->haintmsk = dwc2_readl(hsotg->regs + HAINTMSK); for (i = 0; i < hsotg->core_params->host_channels; ++i) - hr->hcintmsk[i] = readl(hsotg->regs + HCINTMSK(i)); + hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i)); - hr->hprt0 = readl(hsotg->regs + HPRT0); - hr->hfir = readl(hsotg->regs + HFIR); + hr->hprt0 = dwc2_read_hprt0(hsotg); + hr->hfir = dwc2_readl(hsotg->regs + HFIR); hr->valid = true; return 0; @@ -108,14 +108,15 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) } hr->valid = false; - writel(hr->hcfg, hsotg->regs + HCFG); - writel(hr->haintmsk, hsotg->regs + HAINTMSK); + dwc2_writel(hr->hcfg, hsotg->regs + HCFG); + dwc2_writel(hr->haintmsk, hsotg->regs + HAINTMSK); for (i = 0; i < hsotg->core_params->host_channels; ++i) - writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i)); + dwc2_writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i)); - writel(hr->hprt0, hsotg->regs + HPRT0); - writel(hr->hfir, hsotg->regs + HFIR); + dwc2_writel(hr->hprt0, hsotg->regs + HPRT0); + dwc2_writel(hr->hfir, hsotg->regs + HFIR); + hsotg->frame_number = 0; return 0; } @@ -146,15 +147,15 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) /* Backup dev regs */ dr = &hsotg->dr_backup; - dr->dcfg = readl(hsotg->regs + DCFG); - dr->dctl = readl(hsotg->regs + DCTL); - dr->daintmsk = readl(hsotg->regs + DAINTMSK); - dr->diepmsk = readl(hsotg->regs + DIEPMSK); - dr->doepmsk = readl(hsotg->regs + DOEPMSK); + dr->dcfg = dwc2_readl(hsotg->regs + DCFG); + dr->dctl = dwc2_readl(hsotg->regs + DCTL); + dr->daintmsk = dwc2_readl(hsotg->regs + DAINTMSK); + dr->diepmsk = dwc2_readl(hsotg->regs + DIEPMSK); + dr->doepmsk = dwc2_readl(hsotg->regs + DOEPMSK); for (i = 0; i < hsotg->num_of_eps; i++) { /* Backup IN EPs */ - dr->diepctl[i] = readl(hsotg->regs + DIEPCTL(i)); + dr->diepctl[i] = dwc2_readl(hsotg->regs + DIEPCTL(i)); /* Ensure DATA PID is correctly configured */ if (dr->diepctl[i] & DXEPCTL_DPID) @@ -162,11 +163,11 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) else dr->diepctl[i] |= DXEPCTL_SETD0PID; - dr->dieptsiz[i] = readl(hsotg->regs + DIEPTSIZ(i)); - dr->diepdma[i] = readl(hsotg->regs + DIEPDMA(i)); + dr->dieptsiz[i] = dwc2_readl(hsotg->regs + DIEPTSIZ(i)); + dr->diepdma[i] = dwc2_readl(hsotg->regs + DIEPDMA(i)); /* Backup OUT EPs */ - dr->doepctl[i] = readl(hsotg->regs + DOEPCTL(i)); + dr->doepctl[i] = dwc2_readl(hsotg->regs + DOEPCTL(i)); /* Ensure DATA PID is correctly configured */ if (dr->doepctl[i] & DXEPCTL_DPID) @@ -174,8 +175,8 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) else dr->doepctl[i] |= DXEPCTL_SETD0PID; - dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i)); - dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i)); + dr->doeptsiz[i] = dwc2_readl(hsotg->regs + DOEPTSIZ(i)); + dr->doepdma[i] = dwc2_readl(hsotg->regs + DOEPDMA(i)); } dr->valid = true; return 0; @@ -205,28 +206,28 @@ static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) } dr->valid = false; - writel(dr->dcfg, hsotg->regs + DCFG); - writel(dr->dctl, hsotg->regs + DCTL); - writel(dr->daintmsk, hsotg->regs + DAINTMSK); - writel(dr->diepmsk, hsotg->regs + DIEPMSK); - writel(dr->doepmsk, hsotg->regs + DOEPMSK); + dwc2_writel(dr->dcfg, hsotg->regs + DCFG); + dwc2_writel(dr->dctl, hsotg->regs + DCTL); + dwc2_writel(dr->daintmsk, hsotg->regs + DAINTMSK); + dwc2_writel(dr->diepmsk, hsotg->regs + DIEPMSK); + dwc2_writel(dr->doepmsk, hsotg->regs + DOEPMSK); for (i = 0; i < hsotg->num_of_eps; i++) { /* Restore IN EPs */ - writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i)); - writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i)); - writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i)); + dwc2_writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i)); + dwc2_writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i)); + dwc2_writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i)); /* Restore OUT EPs */ - writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i)); - writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i)); - writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i)); + dwc2_writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i)); + dwc2_writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i)); + dwc2_writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i)); } /* Set the Power-On Programming done bit */ - dctl = readl(hsotg->regs + DCTL); + dctl = dwc2_readl(hsotg->regs + DCTL); dctl |= DCTL_PWRONPRGDONE; - writel(dctl, hsotg->regs + DCTL); + dwc2_writel(dctl, hsotg->regs + DCTL); return 0; } @@ -253,16 +254,16 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) /* Backup global regs */ gr = &hsotg->gr_backup; - gr->gotgctl = readl(hsotg->regs + GOTGCTL); - gr->gintmsk = readl(hsotg->regs + GINTMSK); - gr->gahbcfg = readl(hsotg->regs + GAHBCFG); - gr->gusbcfg = readl(hsotg->regs + GUSBCFG); - gr->grxfsiz = readl(hsotg->regs + GRXFSIZ); - gr->gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ); - gr->hptxfsiz = readl(hsotg->regs + HPTXFSIZ); - gr->gdfifocfg = readl(hsotg->regs + GDFIFOCFG); + gr->gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); + gr->gintmsk = dwc2_readl(hsotg->regs + GINTMSK); + gr->gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); + gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); + gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); + gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); + gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ); + gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG); for (i = 0; i < MAX_EPS_CHANNELS; i++) - gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i)); + gr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i)); gr->valid = true; return 0; @@ -291,17 +292,17 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) } gr->valid = false; - writel(0xffffffff, hsotg->regs + GINTSTS); - writel(gr->gotgctl, hsotg->regs + GOTGCTL); - writel(gr->gintmsk, hsotg->regs + GINTMSK); - writel(gr->gusbcfg, hsotg->regs + GUSBCFG); - writel(gr->gahbcfg, hsotg->regs + GAHBCFG); - writel(gr->grxfsiz, hsotg->regs + GRXFSIZ); - writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ); - writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ); - writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG); + dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); + dwc2_writel(gr->gotgctl, hsotg->regs + GOTGCTL); + dwc2_writel(gr->gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG); + dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ); + dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ); + dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ); + dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG); for (i = 0; i < MAX_EPS_CHANNELS; i++) - writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i)); + dwc2_writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i)); return 0; } @@ -320,17 +321,17 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore) if (!hsotg->core_params->hibernation) return -ENOTSUPP; - pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); pcgcctl &= ~PCGCTL_STOPPCLK; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); - pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); pcgcctl &= ~PCGCTL_PWRCLMP; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); - pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); pcgcctl &= ~PCGCTL_RSTPDWNMODULE; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); udelay(100); if (restore) { @@ -397,19 +398,25 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) } } + /* + * Clear any pending interrupts since dwc2 will not be able to + * clear them after entering hibernation. + */ + dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); + /* Put the controller in low power state */ - pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); pcgcctl |= PCGCTL_PWRCLMP; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); ndelay(20); pcgcctl |= PCGCTL_RSTPDWNMODULE; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); ndelay(20); pcgcctl |= PCGCTL_STOPPCLK; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); return ret; } @@ -425,10 +432,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) u32 intmsk; /* Clear any pending OTG Interrupts */ - writel(0xffffffff, hsotg->regs + GOTGINT); + dwc2_writel(0xffffffff, hsotg->regs + GOTGINT); /* Clear any pending interrupts */ - writel(0xffffffff, hsotg->regs + GINTSTS); + dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); /* Enable the interrupts in the GINTMSK */ intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; @@ -441,7 +448,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTSTS_SESSREQINT; - writel(intmsk, hsotg->regs + GINTMSK); + dwc2_writel(intmsk, hsotg->regs + GINTMSK); } /* @@ -464,10 +471,10 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) } dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val); - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg &= ~HCFG_FSLSPCLKSEL_MASK; hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT; - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); } /* @@ -485,7 +492,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Wait for AHB master IDLE state */ do { usleep_range(20000, 40000); - greset = readl(hsotg->regs + GRSTCTL); + greset = dwc2_readl(hsotg->regs + GRSTCTL); if (++count > 50) { dev_warn(hsotg->dev, "%s() HANG! AHB Idle GRSTCTL=%0x\n", @@ -497,10 +504,10 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Core Soft Reset */ count = 0; greset |= GRSTCTL_CSFTRST; - writel(greset, hsotg->regs + GRSTCTL); + dwc2_writel(greset, hsotg->regs + GRSTCTL); do { usleep_range(20000, 40000); - greset = readl(hsotg->regs + GRSTCTL); + greset = dwc2_readl(hsotg->regs + GRSTCTL); if (++count > 50) { dev_warn(hsotg->dev, "%s() HANG! Soft Reset GRSTCTL=%0x\n", @@ -510,20 +517,20 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) } while (greset & GRSTCTL_CSFTRST); if (hsotg->dr_mode == USB_DR_MODE_HOST) { - gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); gusbcfg &= ~GUSBCFG_FORCEDEVMODE; gusbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); } else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) { - gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); gusbcfg &= ~GUSBCFG_FORCEHOSTMODE; gusbcfg |= GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); } else if (hsotg->dr_mode == USB_DR_MODE_OTG) { - gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); gusbcfg &= ~GUSBCFG_FORCEHOSTMODE; gusbcfg &= ~GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); } /* @@ -546,9 +553,9 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) */ if (select_phy) { dev_dbg(hsotg->dev, "FS PHY selected\n"); - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg |= GUSBCFG_PHYSEL; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); /* Reset after a PHY select */ retval = dwc2_core_reset(hsotg); @@ -571,18 +578,18 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) dev_dbg(hsotg->dev, "FS PHY enabling I2C\n"); /* Program GUSBCFG.OtgUtmiFsSel to I2C */ - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); /* Program GI2CCTL.I2CEn */ - i2cctl = readl(hsotg->regs + GI2CCTL); + i2cctl = dwc2_readl(hsotg->regs + GI2CCTL); i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK; i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT; i2cctl &= ~GI2CCTL_I2CEN; - writel(i2cctl, hsotg->regs + GI2CCTL); + dwc2_writel(i2cctl, hsotg->regs + GI2CCTL); i2cctl |= GI2CCTL_I2CEN; - writel(i2cctl, hsotg->regs + GI2CCTL); + dwc2_writel(i2cctl, hsotg->regs + GI2CCTL); } return retval; @@ -596,7 +603,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) if (!select_phy) return 0; - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); /* * HS PHY parameters. These parameters are preserved during soft reset @@ -624,7 +631,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) break; } - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); /* Reset after setting the PHY parameters */ retval = dwc2_core_reset(hsotg); @@ -659,15 +666,15 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && hsotg->core_params->ulpi_fs_ls > 0) { dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg |= GUSBCFG_ULPI_FS_LS; usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); } else { - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg &= ~GUSBCFG_ULPI_FS_LS; usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); } return retval; @@ -675,7 +682,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) { - u32 ahbcfg = readl(hsotg->regs + GAHBCFG); + u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); switch (hsotg->hw_params.arch) { case GHWCFG2_EXT_DMA_ARCH: @@ -714,7 +721,7 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) if (hsotg->core_params->dma_enable > 0) ahbcfg |= GAHBCFG_DMA_EN; - writel(ahbcfg, hsotg->regs + GAHBCFG); + dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); return 0; } @@ -723,7 +730,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) { u32 usbcfg; - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP); switch (hsotg->hw_params.op_mode) { @@ -751,7 +758,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) break; } - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); } /** @@ -769,7 +776,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg); - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); /* Set ULPI External VBUS bit if needed */ usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV; @@ -782,7 +789,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) if (hsotg->core_params->ts_dline > 0) usbcfg |= GUSBCFG_TERMSELDLPULSE; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); /* Reset the Controller */ retval = dwc2_core_reset(hsotg); @@ -808,11 +815,11 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) dwc2_gusbcfg_init(hsotg); /* Program the GOTGCTL register */ - otgctl = readl(hsotg->regs + GOTGCTL); + otgctl = dwc2_readl(hsotg->regs + GOTGCTL); otgctl &= ~GOTGCTL_OTGVER; if (hsotg->core_params->otg_ver > 0) otgctl |= GOTGCTL_OTGVER; - writel(otgctl, hsotg->regs + GOTGCTL); + dwc2_writel(otgctl, hsotg->regs + GOTGCTL); dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->core_params->otg_ver); /* Clear the SRP success bit for FS-I2c */ @@ -848,16 +855,16 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s()\n", __func__); /* Disable all interrupts */ - writel(0, hsotg->regs + GINTMSK); - writel(0, hsotg->regs + HAINTMSK); + dwc2_writel(0, hsotg->regs + GINTMSK); + dwc2_writel(0, hsotg->regs + HAINTMSK); /* Enable the common interrupts */ dwc2_enable_common_interrupts(hsotg); /* Enable host mode interrupts without disturbing common interrupts */ - intmsk = readl(hsotg->regs + GINTMSK); + intmsk = dwc2_readl(hsotg->regs + GINTMSK); intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT; - writel(intmsk, hsotg->regs + GINTMSK); + dwc2_writel(intmsk, hsotg->regs + GINTMSK); } /** @@ -867,12 +874,12 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg) */ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg) { - u32 intmsk = readl(hsotg->regs + GINTMSK); + u32 intmsk = dwc2_readl(hsotg->regs + GINTMSK); /* Disable host mode interrupts without disturbing common interrupts */ intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT | - GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP); - writel(intmsk, hsotg->regs + GINTMSK); + GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT); + dwc2_writel(intmsk, hsotg->regs + GINTMSK); } /* @@ -952,36 +959,37 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) dwc2_calculate_dynamic_fifo(hsotg); /* Rx FIFO */ - grxfsiz = readl(hsotg->regs + GRXFSIZ); + grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz); grxfsiz &= ~GRXFSIZ_DEPTH_MASK; grxfsiz |= params->host_rx_fifo_size << GRXFSIZ_DEPTH_SHIFT & GRXFSIZ_DEPTH_MASK; - writel(grxfsiz, hsotg->regs + GRXFSIZ); - dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", readl(hsotg->regs + GRXFSIZ)); + dwc2_writel(grxfsiz, hsotg->regs + GRXFSIZ); + dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", + dwc2_readl(hsotg->regs + GRXFSIZ)); /* Non-periodic Tx FIFO */ dev_dbg(hsotg->dev, "initial gnptxfsiz=%08x\n", - readl(hsotg->regs + GNPTXFSIZ)); + dwc2_readl(hsotg->regs + GNPTXFSIZ)); nptxfsiz = params->host_nperio_tx_fifo_size << FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK; nptxfsiz |= params->host_rx_fifo_size << FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK; - writel(nptxfsiz, hsotg->regs + GNPTXFSIZ); + dwc2_writel(nptxfsiz, hsotg->regs + GNPTXFSIZ); dev_dbg(hsotg->dev, "new gnptxfsiz=%08x\n", - readl(hsotg->regs + GNPTXFSIZ)); + dwc2_readl(hsotg->regs + GNPTXFSIZ)); /* Periodic Tx FIFO */ dev_dbg(hsotg->dev, "initial hptxfsiz=%08x\n", - readl(hsotg->regs + HPTXFSIZ)); + dwc2_readl(hsotg->regs + HPTXFSIZ)); hptxfsiz = params->host_perio_tx_fifo_size << FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK; hptxfsiz |= (params->host_rx_fifo_size + params->host_nperio_tx_fifo_size) << FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK; - writel(hptxfsiz, hsotg->regs + HPTXFSIZ); + dwc2_writel(hptxfsiz, hsotg->regs + HPTXFSIZ); dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n", - readl(hsotg->regs + HPTXFSIZ)); + dwc2_readl(hsotg->regs + HPTXFSIZ)); if (hsotg->core_params->en_multiple_tx_fifo > 0 && hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) { @@ -989,14 +997,14 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) * Global DFIFOCFG calculation for Host mode - * include RxFIFO, NPTXFIFO and HPTXFIFO */ - dfifocfg = readl(hsotg->regs + GDFIFOCFG); + dfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG); dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK; dfifocfg |= (params->host_rx_fifo_size + params->host_nperio_tx_fifo_size + params->host_perio_tx_fifo_size) << GDFIFOCFG_EPINFOBASE_SHIFT & GDFIFOCFG_EPINFOBASE_MASK; - writel(dfifocfg, hsotg->regs + GDFIFOCFG); + dwc2_writel(dfifocfg, hsotg->regs + GDFIFOCFG); } } @@ -1017,14 +1025,14 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg); /* Restart the Phy Clock */ - writel(0, hsotg->regs + PCGCTL); + dwc2_writel(0, hsotg->regs + PCGCTL); /* Initialize Host Configuration Register */ dwc2_init_fs_ls_pclk_sel(hsotg); if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL) { - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg |= HCFG_FSLSSUPP; - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); } /* @@ -1033,9 +1041,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) * and its value must not be changed during runtime. */ if (hsotg->core_params->reload_ctl > 0) { - hfir = readl(hsotg->regs + HFIR); + hfir = dwc2_readl(hsotg->regs + HFIR); hfir |= HFIR_RLDCTRL; - writel(hfir, hsotg->regs + HFIR); + dwc2_writel(hfir, hsotg->regs + HFIR); } if (hsotg->core_params->dma_desc_enable > 0) { @@ -1051,9 +1059,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) "falling back to buffer DMA mode.\n"); hsotg->core_params->dma_desc_enable = 0; } else { - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg |= HCFG_DESCDMA; - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); } } @@ -1062,18 +1070,18 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) /* TODO - check this */ /* Clear Host Set HNP Enable in the OTG Control Register */ - otgctl = readl(hsotg->regs + GOTGCTL); + otgctl = dwc2_readl(hsotg->regs + GOTGCTL); otgctl &= ~GOTGCTL_HSTSETHNPEN; - writel(otgctl, hsotg->regs + GOTGCTL); + dwc2_writel(otgctl, hsotg->regs + GOTGCTL); /* Make sure the FIFOs are flushed */ dwc2_flush_tx_fifo(hsotg, 0x10 /* all TX FIFOs */); dwc2_flush_rx_fifo(hsotg); /* Clear Host Set HNP Enable in the OTG Control Register */ - otgctl = readl(hsotg->regs + GOTGCTL); + otgctl = dwc2_readl(hsotg->regs + GOTGCTL); otgctl &= ~GOTGCTL_HSTSETHNPEN; - writel(otgctl, hsotg->regs + GOTGCTL); + dwc2_writel(otgctl, hsotg->regs + GOTGCTL); if (hsotg->core_params->dma_desc_enable <= 0) { int num_channels, i; @@ -1082,25 +1090,25 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) /* Flush out any leftover queued requests */ num_channels = hsotg->core_params->host_channels; for (i = 0; i < num_channels; i++) { - hcchar = readl(hsotg->regs + HCCHAR(i)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); hcchar &= ~HCCHAR_CHENA; hcchar |= HCCHAR_CHDIS; hcchar &= ~HCCHAR_EPDIR; - writel(hcchar, hsotg->regs + HCCHAR(i)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); } /* Halt all channels to put them into a known state */ for (i = 0; i < num_channels; i++) { int count = 0; - hcchar = readl(hsotg->regs + HCCHAR(i)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS; hcchar &= ~HCCHAR_EPDIR; - writel(hcchar, hsotg->regs + HCCHAR(i)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); dev_dbg(hsotg->dev, "%s: Halt channel %d\n", __func__, i); do { - hcchar = readl(hsotg->regs + HCCHAR(i)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); if (++count > 1000) { dev_err(hsotg->dev, "Unable to clear enable on channel %d\n", @@ -1121,7 +1129,7 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) !!(hprt0 & HPRT0_PWR)); if (!(hprt0 & HPRT0_PWR)) { hprt0 |= HPRT0_PWR; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); } } @@ -1201,7 +1209,7 @@ static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg, break; } - writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); + dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk); } @@ -1238,7 +1246,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg, } } - writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); + dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk); } @@ -1259,16 +1267,16 @@ static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg, } /* Enable the top level host channel interrupt */ - intmsk = readl(hsotg->regs + HAINTMSK); + intmsk = dwc2_readl(hsotg->regs + HAINTMSK); intmsk |= 1 << chan->hc_num; - writel(intmsk, hsotg->regs + HAINTMSK); + dwc2_writel(intmsk, hsotg->regs + HAINTMSK); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "set HAINTMSK to %08x\n", intmsk); /* Make sure host channel interrupts are enabled */ - intmsk = readl(hsotg->regs + GINTMSK); + intmsk = dwc2_readl(hsotg->regs + GINTMSK); intmsk |= GINTSTS_HCHINT; - writel(intmsk, hsotg->regs + GINTMSK); + dwc2_writel(intmsk, hsotg->regs + GINTMSK); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "set GINTMSK to %08x\n", intmsk); } @@ -1297,7 +1305,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) /* Clear old interrupt conditions for this host channel */ hcintmsk = 0xffffffff; hcintmsk &= ~HCINTMSK_RESERVED14_31; - writel(hcintmsk, hsotg->regs + HCINT(hc_num)); + dwc2_writel(hcintmsk, hsotg->regs + HCINT(hc_num)); /* Enable channel interrupts required for this transfer */ dwc2_hc_enable_ints(hsotg, chan); @@ -1314,7 +1322,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) hcchar |= HCCHAR_LSPDDEV; hcchar |= chan->ep_type << HCCHAR_EPTYPE_SHIFT & HCCHAR_EPTYPE_MASK; hcchar |= chan->max_packet << HCCHAR_MPS_SHIFT & HCCHAR_MPS_MASK; - writel(hcchar, hsotg->regs + HCCHAR(hc_num)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(hc_num)); if (dbg_hc(chan)) { dev_vdbg(hsotg->dev, "set HCCHAR(%d) to %08x\n", hc_num, hcchar); @@ -1368,7 +1376,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) } } - writel(hcsplt, hsotg->regs + HCSPLT(hc_num)); + dwc2_writel(hcsplt, hsotg->regs + HCSPLT(hc_num)); } /** @@ -1420,14 +1428,14 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, u32 hcintmsk = HCINTMSK_CHHLTD; dev_vdbg(hsotg->dev, "dequeue/error\n"); - writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); + dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); /* * Make sure no other interrupts besides halt are currently * pending. Handling another interrupt could cause a crash due * to the QTD and QH state. */ - writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num)); + dwc2_writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num)); /* * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR @@ -1436,7 +1444,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, */ chan->halt_status = halt_status; - hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); if (!(hcchar & HCCHAR_CHENA)) { /* * The channel is either already halted or it hasn't @@ -1464,7 +1472,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, return; } - hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); /* No need to set the bit in DDMA for disabling the channel */ /* TODO check it everywhere channel is disabled */ @@ -1487,7 +1495,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL || chan->ep_type == USB_ENDPOINT_XFER_BULK) { dev_vdbg(hsotg->dev, "control/bulk\n"); - nptxsts = readl(hsotg->regs + GNPTXSTS); + nptxsts = dwc2_readl(hsotg->regs + GNPTXSTS); if ((nptxsts & TXSTS_QSPCAVAIL_MASK) == 0) { dev_vdbg(hsotg->dev, "Disabling channel\n"); hcchar &= ~HCCHAR_CHENA; @@ -1495,7 +1503,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, } else { if (dbg_perio()) dev_vdbg(hsotg->dev, "isoc/intr\n"); - hptxsts = readl(hsotg->regs + HPTXSTS); + hptxsts = dwc2_readl(hsotg->regs + HPTXSTS); if ((hptxsts & TXSTS_QSPCAVAIL_MASK) == 0 || hsotg->queuing_high_bandwidth) { if (dbg_perio()) @@ -1508,7 +1516,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, dev_vdbg(hsotg->dev, "DMA enabled\n"); } - writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); chan->halt_status = halt_status; if (hcchar & HCCHAR_CHENA) { @@ -1555,10 +1563,10 @@ void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) * Clear channel interrupt enables and any unhandled channel interrupt * conditions */ - writel(0, hsotg->regs + HCINTMSK(chan->hc_num)); + dwc2_writel(0, hsotg->regs + HCINTMSK(chan->hc_num)); hcintmsk = 0xffffffff; hcintmsk &= ~HCINTMSK_RESERVED14_31; - writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num)); + dwc2_writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num)); } /** @@ -1644,13 +1652,13 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, if (((unsigned long)data_buf & 0x3) == 0) { /* xfer_buf is DWORD aligned */ for (i = 0; i < dword_count; i++, data_buf++) - writel(*data_buf, data_fifo); + dwc2_writel(*data_buf, data_fifo); } else { /* xfer_buf is not DWORD aligned */ for (i = 0; i < dword_count; i++, data_buf++) { u32 data = data_buf[0] | data_buf[1] << 8 | data_buf[2] << 16 | data_buf[3] << 24; - writel(data, data_fifo); + dwc2_writel(data, data_fifo); } } @@ -1803,7 +1811,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, hctsiz |= num_packets << TSIZ_PKTCNT_SHIFT & TSIZ_PKTCNT_MASK; hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT & TSIZ_SC_MC_PID_MASK; - writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); + dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); if (dbg_hc(chan)) { dev_vdbg(hsotg->dev, "Wrote %08x to HCTSIZ(%d)\n", hctsiz, chan->hc_num); @@ -1831,7 +1839,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, } else { dma_addr = chan->xfer_dma; } - writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num)); + dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num)); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n", (unsigned long)dma_addr, chan->hc_num); @@ -1839,13 +1847,13 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, /* Start the split */ if (chan->do_split) { - u32 hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num)); + u32 hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num)); hcsplt |= HCSPLT_SPLTENA; - writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num)); + dwc2_writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num)); } - hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); hcchar &= ~HCCHAR_MULTICNT_MASK; hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT & HCCHAR_MULTICNT_MASK; @@ -1865,7 +1873,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, (hcchar & HCCHAR_MULTICNT_MASK) >> HCCHAR_MULTICNT_SHIFT); - writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar, chan->hc_num); @@ -1924,18 +1932,18 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " NTD: %d\n", chan->ntd - 1); } - writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); + dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); hc_dma = (u32)chan->desc_list_addr & HCDMA_DMA_ADDR_MASK; /* Always start from first descriptor */ hc_dma &= ~HCDMA_CTD_MASK; - writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num)); + dwc2_writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num)); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "Wrote %08x to HCDMA(%d)\n", hc_dma, chan->hc_num); - hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); hcchar &= ~HCCHAR_MULTICNT_MASK; hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT & HCCHAR_MULTICNT_MASK; @@ -1954,7 +1962,7 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg, (hcchar & HCCHAR_MULTICNT_MASK) >> HCCHAR_MULTICNT_SHIFT); - writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar, chan->hc_num); @@ -2011,7 +2019,7 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg, * transfer completes, the extra requests for the channel will * be flushed. */ - u32 hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); + u32 hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar); hcchar |= HCCHAR_CHENA; @@ -2019,7 +2027,7 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg, if (dbg_hc(chan)) dev_vdbg(hsotg->dev, " IN xfer: hcchar = 0x%08x\n", hcchar); - writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); chan->requests++; return 1; } @@ -2029,8 +2037,8 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg, if (chan->xfer_count < chan->xfer_len) { if (chan->ep_type == USB_ENDPOINT_XFER_INT || chan->ep_type == USB_ENDPOINT_XFER_ISOC) { - u32 hcchar = readl(hsotg->regs + - HCCHAR(chan->hc_num)); + u32 hcchar = dwc2_readl(hsotg->regs + + HCCHAR(chan->hc_num)); dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar); @@ -2066,12 +2074,12 @@ void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) hctsiz = TSIZ_DOPNG; hctsiz |= 1 << TSIZ_PKTCNT_SHIFT; - writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); + dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); - hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); hcchar |= HCCHAR_CHENA; hcchar &= ~HCCHAR_CHDIS; - writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); } /** @@ -2090,8 +2098,8 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) u32 hprt0; int clock = 60; /* default value */ - usbcfg = readl(hsotg->regs + GUSBCFG); - hprt0 = readl(hsotg->regs + HPRT0); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); + hprt0 = dwc2_readl(hsotg->regs + HPRT0); if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) && !(usbcfg & GUSBCFG_PHYIF16)) @@ -2147,7 +2155,7 @@ void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes) dev_vdbg(hsotg->dev, "%s(%p,%p,%d)\n", __func__, hsotg, dest, bytes); for (i = 0; i < word_count; i++, data_buf++) - *data_buf = readl(fifo); + *data_buf = dwc2_readl(fifo); } /** @@ -2167,56 +2175,56 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "Host Global Registers\n"); addr = hsotg->regs + HCFG; dev_dbg(hsotg->dev, "HCFG @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HFIR; dev_dbg(hsotg->dev, "HFIR @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HFNUM; dev_dbg(hsotg->dev, "HFNUM @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HPTXSTS; dev_dbg(hsotg->dev, "HPTXSTS @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HAINT; dev_dbg(hsotg->dev, "HAINT @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HAINTMSK; dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); if (hsotg->core_params->dma_desc_enable > 0) { addr = hsotg->regs + HFLBADDR; dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); } addr = hsotg->regs + HPRT0; dev_dbg(hsotg->dev, "HPRT0 @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); for (i = 0; i < hsotg->core_params->host_channels; i++) { dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i); addr = hsotg->regs + HCCHAR(i); dev_dbg(hsotg->dev, "HCCHAR @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HCSPLT(i); dev_dbg(hsotg->dev, "HCSPLT @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HCINT(i); dev_dbg(hsotg->dev, "HCINT @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HCINTMSK(i); dev_dbg(hsotg->dev, "HCINTMSK @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HCTSIZ(i); dev_dbg(hsotg->dev, "HCTSIZ @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HCDMA(i); dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); if (hsotg->core_params->dma_desc_enable > 0) { addr = hsotg->regs + HCDMAB(i); dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); } } #endif @@ -2238,80 +2246,80 @@ void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "Core Global Registers\n"); addr = hsotg->regs + GOTGCTL; dev_dbg(hsotg->dev, "GOTGCTL @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GOTGINT; dev_dbg(hsotg->dev, "GOTGINT @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GAHBCFG; dev_dbg(hsotg->dev, "GAHBCFG @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GUSBCFG; dev_dbg(hsotg->dev, "GUSBCFG @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GRSTCTL; dev_dbg(hsotg->dev, "GRSTCTL @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GINTSTS; dev_dbg(hsotg->dev, "GINTSTS @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GINTMSK; dev_dbg(hsotg->dev, "GINTMSK @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GRXSTSR; dev_dbg(hsotg->dev, "GRXSTSR @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GRXFSIZ; dev_dbg(hsotg->dev, "GRXFSIZ @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GNPTXFSIZ; dev_dbg(hsotg->dev, "GNPTXFSIZ @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GNPTXSTS; dev_dbg(hsotg->dev, "GNPTXSTS @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GI2CCTL; dev_dbg(hsotg->dev, "GI2CCTL @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GPVNDCTL; dev_dbg(hsotg->dev, "GPVNDCTL @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GGPIO; dev_dbg(hsotg->dev, "GGPIO @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GUID; dev_dbg(hsotg->dev, "GUID @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GSNPSID; dev_dbg(hsotg->dev, "GSNPSID @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GHWCFG1; dev_dbg(hsotg->dev, "GHWCFG1 @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GHWCFG2; dev_dbg(hsotg->dev, "GHWCFG2 @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GHWCFG3; dev_dbg(hsotg->dev, "GHWCFG3 @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GHWCFG4; dev_dbg(hsotg->dev, "GHWCFG4 @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GLPMCFG; dev_dbg(hsotg->dev, "GLPMCFG @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GPWRDN; dev_dbg(hsotg->dev, "GPWRDN @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + GDFIFOCFG; dev_dbg(hsotg->dev, "GDFIFOCFG @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + HPTXFSIZ; dev_dbg(hsotg->dev, "HPTXFSIZ @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); addr = hsotg->regs + PCGCTL; dev_dbg(hsotg->dev, "PCGCTL @0x%08lX : 0x%08X\n", - (unsigned long)addr, readl(addr)); + (unsigned long)addr, dwc2_readl(addr)); #endif } @@ -2330,15 +2338,15 @@ void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num) greset = GRSTCTL_TXFFLSH; greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK; - writel(greset, hsotg->regs + GRSTCTL); + dwc2_writel(greset, hsotg->regs + GRSTCTL); do { - greset = readl(hsotg->regs + GRSTCTL); + greset = dwc2_readl(hsotg->regs + GRSTCTL); if (++count > 10000) { dev_warn(hsotg->dev, "%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", __func__, greset, - readl(hsotg->regs + GNPTXSTS)); + dwc2_readl(hsotg->regs + GNPTXSTS)); break; } udelay(1); @@ -2361,10 +2369,10 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "%s()\n", __func__); greset = GRSTCTL_RXFFLSH; - writel(greset, hsotg->regs + GRSTCTL); + dwc2_writel(greset, hsotg->regs + GRSTCTL); do { - greset = readl(hsotg->regs + GRSTCTL); + greset = dwc2_readl(hsotg->regs + GRSTCTL); if (++count > 10000) { dev_warn(hsotg->dev, "%s() HANG! GRSTCTL=%0x\n", __func__, greset); @@ -3062,7 +3070,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) * 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3", * as in "OTG version 2.xx" or "OTG version 3.xx". */ - hw->snpsid = readl(hsotg->regs + GSNPSID); + hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID); if ((hw->snpsid & 0xfffff000) != 0x4f542000 && (hw->snpsid & 0xfffff000) != 0x4f543000) { dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", @@ -3074,11 +3082,11 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf, hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid); - hwcfg1 = readl(hsotg->regs + GHWCFG1); - hwcfg2 = readl(hsotg->regs + GHWCFG2); - hwcfg3 = readl(hsotg->regs + GHWCFG3); - hwcfg4 = readl(hsotg->regs + GHWCFG4); - grxfsiz = readl(hsotg->regs + GRXFSIZ); + hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1); + hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2); + hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3); + hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4); + grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1); dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2); @@ -3087,18 +3095,18 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz); /* Force host mode to get HPTXFSIZ / GNPTXFSIZ exact power on value */ - gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); gusbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); usleep_range(100000, 150000); - gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ); - hptxfsiz = readl(hsotg->regs + HPTXFSIZ); + gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); + hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ); dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz); dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz); - gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); gusbcfg &= ~GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); usleep_range(100000, 150000); /* hwcfg2 */ @@ -3233,7 +3241,7 @@ u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg) { - if (readl(hsotg->regs + GSNPSID) == 0xffffffff) + if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff) return false; else return true; @@ -3247,10 +3255,10 @@ bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg) */ void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg) { - u32 ahbcfg = readl(hsotg->regs + GAHBCFG); + u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); ahbcfg |= GAHBCFG_GLBL_INTR_EN; - writel(ahbcfg, hsotg->regs + GAHBCFG); + dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); } /** @@ -3261,10 +3269,10 @@ void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg) */ void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg) { - u32 ahbcfg = readl(hsotg->regs + GAHBCFG); + u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); ahbcfg &= ~GAHBCFG_GLBL_INTR_EN; - writel(ahbcfg, hsotg->regs + GAHBCFG); + dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); } MODULE_DESCRIPTION("DESIGNWARE HS OTG Core"); diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 0ed876209..a66d3cb62 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -44,22 +44,38 @@ #include #include "hw.h" -#ifdef DWC2_LOG_WRITES -static inline void do_write(u32 value, void *addr) +static inline u32 dwc2_readl(const void __iomem *addr) { - writel(value, addr); - pr_info("INFO:: wrote %08x to %p\n", value, addr); + u32 value = __raw_readl(addr); + + /* In order to preserve endianness __raw_* operation is used. Therefore + * a barrier is needed to ensure IO access is not re-ordered across + * reads or writes + */ + mb(); + return value; } -#undef writel -#define writel(v, a) do_write(v, a) +static inline void dwc2_writel(u32 value, void __iomem *addr) +{ + __raw_writel(value, addr); + + /* + * In order to preserve endianness __raw_* operation is used. Therefore + * a barrier is needed to ensure IO access is not re-ordered across + * reads or writes + */ + mb(); +#ifdef DWC2_LOG_WRITES + pr_info("INFO:: wrote %08x to %p\n", value, addr); #endif +} /* Maximum number of Endpoints/HostChannels */ #define MAX_EPS_CHANNELS 16 -/* s3c-hsotg declarations */ -static const char * const s3c_hsotg_supply_names[] = { +/* dwc2-hsotg declarations */ +static const char * const dwc2_hsotg_supply_names[] = { "vusb_d", /* digital USB supply, 1.2V */ "vusb_a", /* analog USB supply, 1.1V */ }; @@ -85,10 +101,10 @@ static const char * const s3c_hsotg_supply_names[] = { #define EP0_MPS_LIMIT 64 struct dwc2_hsotg; -struct s3c_hsotg_req; +struct dwc2_hsotg_req; /** - * struct s3c_hsotg_ep - driver endpoint definition. + * struct dwc2_hsotg_ep - driver endpoint definition. * @ep: The gadget layer representation of the endpoint. * @name: The driver generated name for the endpoint. * @queue: Queue of requests for this endpoint. @@ -127,11 +143,11 @@ struct s3c_hsotg_req; * as in shared-fifo mode periodic in acts like a single-frame packet * buffer than a fifo) */ -struct s3c_hsotg_ep { +struct dwc2_hsotg_ep { struct usb_ep ep; struct list_head queue; struct dwc2_hsotg *parent; - struct s3c_hsotg_req *req; + struct dwc2_hsotg_req *req; struct dentry *debugfs; unsigned long total_data; @@ -150,17 +166,18 @@ struct s3c_hsotg_ep { unsigned int periodic:1; unsigned int isochronous:1; unsigned int send_zlp:1; + unsigned int has_correct_parity:1; char name[10]; }; /** - * struct s3c_hsotg_req - data transfer request + * struct dwc2_hsotg_req - data transfer request * @req: The USB gadget request * @queue: The list of requests for the endpoint this is queued for. * @saved_req_buf: variable to save req.buf when bounce buffers are used. */ -struct s3c_hsotg_req { +struct dwc2_hsotg_req { struct usb_request req; struct list_head queue; void *saved_req_buf; @@ -562,6 +579,15 @@ struct dwc2_hregs_backup { * - USB_DR_MODE_PERIPHERAL * - USB_DR_MODE_HOST * - USB_DR_MODE_OTG + * @hcd_enabled Host mode sub-driver initialization indicator. + * @gadget_enabled Peripheral mode sub-driver initialization indicator. + * @ll_hw_enabled Status of low-level hardware resources. + * @phy: The otg phy transceiver structure for phy control. + * @uphy: The otg phy transceiver structure for old USB phy control. + * @plat: The platform specific configuration data. This can be removed once + * all SoCs support usb transceiver. + * @supplies: Definition of USB power supplies + * @phyif: PHY interface width * @lock: Spinlock that protects all the driver data structures * @priv: Stores a pointer to the struct usb_hcd * @queuing_high_bandwidth: True if multiple packets of a high-bandwidth @@ -654,12 +680,6 @@ struct dwc2_hregs_backup { * These are for peripheral mode: * * @driver: USB gadget driver - * @phy: The otg phy transceiver structure for phy control. - * @uphy: The otg phy transceiver structure for old USB phy control. - * @plat: The platform specific configuration data. This can be removed once - * all SoCs support usb transceiver. - * @supplies: Definition of USB power supplies - * @phyif: PHY interface width * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. * @num_of_eps: Number of available EPs (excluding EP0) * @debug_root: Root directrory for debugfs. @@ -672,7 +692,6 @@ struct dwc2_hregs_backup { * @ctrl_req: Request for EP0 control packets. * @ep0_state: EP0 control transfers state * @test_mode: USB test mode requested by the host - * @last_rst: Time of last reset * @eps: The endpoints being supplied to the gadget framework * @g_using_dma: Indicate if dma usage is enabled * @g_rx_fifo_sz: Contains rx fifo size value @@ -690,13 +709,15 @@ struct dwc2_hsotg { enum usb_dr_mode dr_mode; unsigned int hcd_enabled:1; unsigned int gadget_enabled:1; + unsigned int ll_hw_enabled:1; struct phy *phy; struct usb_phy *uphy; - struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)]; + struct dwc2_hsotg_plat *plat; + struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)]; + u32 phyif; spinlock_t lock; - struct mutex init_mutex; void *priv; int irq; struct clk *clk; @@ -748,6 +769,7 @@ struct dwc2_hsotg { u16 frame_usecs[8]; u16 frame_number; u16 periodic_qh_count; + bool bus_suspended; #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS #define FRAME_NUM_ARRAY_SIZE 1000 @@ -796,9 +818,6 @@ struct dwc2_hsotg { #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) /* Gadget structures */ struct usb_gadget_driver *driver; - struct s3c_hsotg_plat *plat; - - u32 phyif; int fifo_mem; unsigned int dedicated_fifos:1; unsigned char num_of_eps; @@ -814,9 +833,8 @@ struct dwc2_hsotg { struct usb_gadget gadget; unsigned int enabled:1; unsigned int connected:1; - unsigned long last_rst; - struct s3c_hsotg_ep *eps_in[MAX_EPS_CHANNELS]; - struct s3c_hsotg_ep *eps_out[MAX_EPS_CHANNELS]; + struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS]; + struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS]; u32 g_using_dma; u32 g_rx_fifo_sz; u32 g_np_g_tx_fifo_sz; @@ -1088,7 +1106,8 @@ extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); - +extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg); +extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg); /* * Dump core registers and SPRAM @@ -1104,30 +1123,30 @@ extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg); /* Gadget defines */ #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) -extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg); -extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2); -extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2); +extern int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg); +extern int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2); +extern int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2); extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq); -extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, +extern void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, bool reset); -extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg); -extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2); -extern int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); +extern void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); +extern void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); +extern int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); #define dwc2_is_device_connected(hsotg) (hsotg->connected) #else -static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2) +static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2) { return 0; } -static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2) +static inline int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2) { return 0; } -static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2) +static inline int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2) { return 0; } static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) { return 0; } -static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, +static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, bool reset) {} -static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} -static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} -static inline int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, +static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} +static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} +static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) { return 0; } #define dwc2_is_device_connected(hsotg) (0) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 927be1e8b..27daa4278 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -80,15 +80,15 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg) */ static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg) { - u32 hprt0 = readl(hsotg->regs + HPRT0); + u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0); if (hprt0 & HPRT0_ENACHG) { hprt0 &= ~HPRT0_ENA; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); } /* Clear interrupt */ - writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS); } /** @@ -102,7 +102,7 @@ static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg) dwc2_is_host_mode(hsotg) ? "Host" : "Device"); /* Clear interrupt */ - writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS); } /** @@ -117,8 +117,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) u32 gotgctl; u32 gintmsk; - gotgint = readl(hsotg->regs + GOTGINT); - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgint = dwc2_readl(hsotg->regs + GOTGINT); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint, dwc2_op_state_str(hsotg)); @@ -126,10 +126,10 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, " ++OTG Interrupt: Session End Detected++ (%s)\n", dwc2_op_state_str(hsotg)); - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); if (dwc2_is_device_mode(hsotg)) - s3c_hsotg_disconnect(hsotg); + dwc2_hsotg_disconnect(hsotg); if (hsotg->op_state == OTG_STATE_B_HOST) { hsotg->op_state = OTG_STATE_B_PERIPHERAL; @@ -152,15 +152,15 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) hsotg->lx_state = DWC2_L0; } - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); gotgctl &= ~GOTGCTL_DEVHNPEN; - writel(gotgctl, hsotg->regs + GOTGCTL); + dwc2_writel(gotgctl, hsotg->regs + GOTGCTL); } if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) { dev_dbg(hsotg->dev, " ++OTG Interrupt: Session Request Success Status Change++\n"); - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); if (gotgctl & GOTGCTL_SESREQSCS) { if (hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS @@ -168,9 +168,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) hsotg->srp_success = 1; } else { /* Clear Session Request */ - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); gotgctl &= ~GOTGCTL_SESREQ; - writel(gotgctl, hsotg->regs + GOTGCTL); + dwc2_writel(gotgctl, hsotg->regs + GOTGCTL); } } } @@ -180,7 +180,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) * Print statements during the HNP interrupt handling * can cause it to fail */ - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); /* * WA for 3.00a- HW is not setting cur_mode, even sometimes * this does not help @@ -200,9 +200,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) * interrupt does not get handled and Linux * complains loudly. */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk &= ~GINTSTS_SOF; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); /* * Call callback function with spin lock @@ -216,9 +216,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) hsotg->op_state = OTG_STATE_B_HOST; } } else { - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN); - writel(gotgctl, hsotg->regs + GOTGCTL); + dwc2_writel(gotgctl, hsotg->regs + GOTGCTL); dev_dbg(hsotg->dev, "HNP Failed\n"); dev_err(hsotg->dev, "Device Not Connected/Responding\n"); @@ -244,9 +244,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) hsotg->op_state = OTG_STATE_A_PERIPHERAL; } else { /* Need to disable SOF interrupt immediately */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk &= ~GINTSTS_SOF; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); spin_unlock(&hsotg->lock); dwc2_hcd_start(hsotg); spin_lock(&hsotg->lock); @@ -261,7 +261,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n"); /* Clear GOTGINT */ - writel(gotgint, hsotg->regs + GOTGINT); + dwc2_writel(gotgint, hsotg->regs + GOTGINT); } /** @@ -276,11 +276,11 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) */ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) { - u32 gintmsk = readl(hsotg->regs + GINTMSK); + u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK); /* Need to disable SOF interrupt immediately */ gintmsk &= ~GINTSTS_SOF; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++ (%s)\n", dwc2_is_host_mode(hsotg) ? "Host" : "Device"); @@ -297,7 +297,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) } /* Clear interrupt */ - writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS); } /** @@ -313,16 +313,28 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) */ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) { - dev_dbg(hsotg->dev, "++Session Request Interrupt++\n"); + int ret; + + dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n", + hsotg->lx_state); /* Clear interrupt */ - writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS); - /* - * Report disconnect if there is any previous session established - */ - if (dwc2_is_device_mode(hsotg)) - s3c_hsotg_disconnect(hsotg); + if (dwc2_is_device_mode(hsotg)) { + if (hsotg->lx_state == DWC2_L2) { + ret = dwc2_exit_hibernation(hsotg, true); + if (ret && (ret != -ENOTSUPP)) + dev_err(hsotg->dev, + "exit hibernation failed\n"); + } + + /* + * Report disconnect if there is any previous session + * established + */ + dwc2_hsotg_disconnect(hsotg); + } } /* @@ -339,13 +351,14 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state); if (dwc2_is_device_mode(hsotg)) { - dev_dbg(hsotg->dev, "DSTS=0x%0x\n", readl(hsotg->regs + DSTS)); + dev_dbg(hsotg->dev, "DSTS=0x%0x\n", + dwc2_readl(hsotg->regs + DSTS)); if (hsotg->lx_state == DWC2_L2) { - u32 dctl = readl(hsotg->regs + DCTL); + u32 dctl = dwc2_readl(hsotg->regs + DCTL); /* Clear Remote Wakeup Signaling */ dctl &= ~DCTL_RMTWKUPSIG; - writel(dctl, hsotg->regs + DCTL); + dwc2_writel(dctl, hsotg->regs + DCTL); ret = dwc2_exit_hibernation(hsotg, true); if (ret && (ret != -ENOTSUPP)) dev_err(hsotg->dev, "exit hibernation failed\n"); @@ -355,12 +368,16 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) /* Change to L0 state */ hsotg->lx_state = DWC2_L0; } else { + if (hsotg->core_params->hibernation) { + dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS); + return; + } if (hsotg->lx_state != DWC2_L1) { - u32 pcgcctl = readl(hsotg->regs + PCGCTL); + u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); /* Restart the Phy Clock */ pcgcctl &= ~PCGCTL_STOPPCLK; - writel(pcgcctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); mod_timer(&hsotg->wkp_timer, jiffies + msecs_to_jiffies(71)); } else { @@ -370,7 +387,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) } /* Clear interrupt */ - writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS); } /* @@ -386,10 +403,7 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg) if (hsotg->op_state == OTG_STATE_A_HOST) dwc2_hcd_disconnect(hsotg); - /* Change to L3 (OFF) state */ - hsotg->lx_state = DWC2_L3; - - writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS); } /* @@ -412,7 +426,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) * Check the Device status register to determine if the Suspend * state is active */ - dsts = readl(hsotg->regs + DSTS); + dsts = dwc2_readl(hsotg->regs + DSTS); dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts); dev_dbg(hsotg->dev, "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n", @@ -465,7 +479,7 @@ skip_power_saving: clear_int: /* Clear interrupt */ - writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS); } #define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \ @@ -483,9 +497,9 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg) u32 gahbcfg; u32 gintmsk_common = GINTMSK_COMMON; - gintsts = readl(hsotg->regs + GINTSTS); - gintmsk = readl(hsotg->regs + GINTMSK); - gahbcfg = readl(hsotg->regs + GAHBCFG); + gintsts = dwc2_readl(hsotg->regs + GINTSTS); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); + gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); /* If any common interrupts set */ if (gintsts & gintmsk_common) diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index ef2ee3d9a..55d91f24f 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c @@ -57,7 +57,7 @@ static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t testmode = 0; spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_set_test_mode(hsotg, testmode); + dwc2_hsotg_set_test_mode(hsotg, testmode); spin_unlock_irqrestore(&hsotg->lock, flags); return count; } @@ -76,7 +76,7 @@ static int testmode_show(struct seq_file *s, void *unused) int dctl; spin_lock_irqsave(&hsotg->lock, flags); - dctl = readl(hsotg->regs + DCTL); + dctl = dwc2_readl(hsotg->regs + DCTL); dctl &= DCTL_TSTCTL_MASK; dctl >>= DCTL_TSTCTL_SHIFT; spin_unlock_irqrestore(&hsotg->lock, flags); @@ -137,38 +137,38 @@ static int state_show(struct seq_file *seq, void *v) int idx; seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", - readl(regs + DCFG), - readl(regs + DCTL), - readl(regs + DSTS)); + dwc2_readl(regs + DCFG), + dwc2_readl(regs + DCTL), + dwc2_readl(regs + DSTS)); seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", - readl(regs + DIEPMSK), readl(regs + DOEPMSK)); + dwc2_readl(regs + DIEPMSK), dwc2_readl(regs + DOEPMSK)); seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", - readl(regs + GINTMSK), - readl(regs + GINTSTS)); + dwc2_readl(regs + GINTMSK), + dwc2_readl(regs + GINTSTS)); seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", - readl(regs + DAINTMSK), - readl(regs + DAINT)); + dwc2_readl(regs + DAINTMSK), + dwc2_readl(regs + DAINT)); seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", - readl(regs + GNPTXSTS), - readl(regs + GRXSTSR)); + dwc2_readl(regs + GNPTXSTS), + dwc2_readl(regs + GRXSTSR)); seq_puts(seq, "\nEndpoint status:\n"); for (idx = 0; idx < hsotg->num_of_eps; idx++) { u32 in, out; - in = readl(regs + DIEPCTL(idx)); - out = readl(regs + DOEPCTL(idx)); + in = dwc2_readl(regs + DIEPCTL(idx)); + out = dwc2_readl(regs + DOEPCTL(idx)); seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", idx, in, out); - in = readl(regs + DIEPTSIZ(idx)); - out = readl(regs + DOEPTSIZ(idx)); + in = dwc2_readl(regs + DIEPTSIZ(idx)); + out = dwc2_readl(regs + DOEPTSIZ(idx)); seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", in, out); @@ -208,9 +208,9 @@ static int fifo_show(struct seq_file *seq, void *v) int idx; seq_puts(seq, "Non-periodic FIFOs:\n"); - seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); + seq_printf(seq, "RXFIFO: Size %d\n", dwc2_readl(regs + GRXFSIZ)); - val = readl(regs + GNPTXFSIZ); + val = dwc2_readl(regs + GNPTXFSIZ); seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", val >> FIFOSIZE_DEPTH_SHIFT, val & FIFOSIZE_DEPTH_MASK); @@ -218,7 +218,7 @@ static int fifo_show(struct seq_file *seq, void *v) seq_puts(seq, "\nPeriodic TXFIFOs:\n"); for (idx = 1; idx < hsotg->num_of_eps; idx++) { - val = readl(regs + DPTXFSIZN(idx)); + val = dwc2_readl(regs + DPTXFSIZN(idx)); seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, val >> FIFOSIZE_DEPTH_SHIFT, @@ -256,9 +256,9 @@ static const char *decode_direction(int is_in) */ static int ep_show(struct seq_file *seq, void *v) { - struct s3c_hsotg_ep *ep = seq->private; + struct dwc2_hsotg_ep *ep = seq->private; struct dwc2_hsotg *hsotg = ep->parent; - struct s3c_hsotg_req *req; + struct dwc2_hsotg_req *req; void __iomem *regs = hsotg->regs; int index = ep->index; int show_limit = 15; @@ -270,20 +270,20 @@ static int ep_show(struct seq_file *seq, void *v) /* first show the register state */ seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", - readl(regs + DIEPCTL(index)), - readl(regs + DOEPCTL(index))); + dwc2_readl(regs + DIEPCTL(index)), + dwc2_readl(regs + DOEPCTL(index))); seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", - readl(regs + DIEPDMA(index)), - readl(regs + DOEPDMA(index))); + dwc2_readl(regs + DIEPDMA(index)), + dwc2_readl(regs + DOEPDMA(index))); seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", - readl(regs + DIEPINT(index)), - readl(regs + DOEPINT(index))); + dwc2_readl(regs + DIEPINT(index)), + dwc2_readl(regs + DOEPINT(index))); seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", - readl(regs + DIEPTSIZ(index)), - readl(regs + DOEPTSIZ(index))); + dwc2_readl(regs + DIEPTSIZ(index)), + dwc2_readl(regs + DOEPTSIZ(index))); seq_puts(seq, "\n"); seq_printf(seq, "mps %d\n", ep->ep.maxpacket); @@ -326,7 +326,7 @@ static const struct file_operations ep_fops = { }; /** - * s3c_hsotg_create_debug - create debugfs directory and files + * dwc2_hsotg_create_debug - create debugfs directory and files * @hsotg: The driver state * * Create the debugfs files to allow the user to get information @@ -334,7 +334,7 @@ static const struct file_operations ep_fops = { * with the same name as the device itself, in case we end up * with multiple blocks in future systems. */ -static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) { struct dentry *root; struct dentry *file; @@ -360,7 +360,7 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) /* Create one file for each out endpoint */ for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { - struct s3c_hsotg_ep *ep; + struct dwc2_hsotg_ep *ep; ep = hsotg->eps_out[epidx]; if (ep) { @@ -373,7 +373,7 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) } /* Create one file for each in endpoint. EP0 is handled with out eps */ for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) { - struct s3c_hsotg_ep *ep; + struct dwc2_hsotg_ep *ep; ep = hsotg->eps_in[epidx]; if (ep) { @@ -386,10 +386,10 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) } } #else -static inline void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) {} +static inline void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) {} #endif -/* s3c_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */ +/* dwc2_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */ #define dump_register(nm) \ { \ @@ -737,7 +737,7 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) } /* Add gadget debugfs nodes */ - s3c_hsotg_create_debug(hsotg); + dwc2_hsotg_create_debug(hsotg); hsotg->regset = devm_kzalloc(hsotg->dev, sizeof(*hsotg->regset), GFP_KERNEL); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 3ee5b4c77..0abf73c91 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -25,28 +25,24 @@ #include #include #include -#include -#include #include -#include #include #include #include -#include #include "core.h" #include "hw.h" /* conversion functions */ -static inline struct s3c_hsotg_req *our_req(struct usb_request *req) +static inline struct dwc2_hsotg_req *our_req(struct usb_request *req) { - return container_of(req, struct s3c_hsotg_req, req); + return container_of(req, struct dwc2_hsotg_req, req); } -static inline struct s3c_hsotg_ep *our_ep(struct usb_ep *ep) +static inline struct dwc2_hsotg_ep *our_ep(struct usb_ep *ep) { - return container_of(ep, struct s3c_hsotg_ep, ep); + return container_of(ep, struct dwc2_hsotg_ep, ep); } static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget) @@ -56,15 +52,15 @@ static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget) static inline void __orr32(void __iomem *ptr, u32 val) { - writel(readl(ptr) | val, ptr); + dwc2_writel(dwc2_readl(ptr) | val, ptr); } static inline void __bic32(void __iomem *ptr, u32 val) { - writel(readl(ptr) & ~val, ptr); + dwc2_writel(dwc2_readl(ptr) & ~val, ptr); } -static inline struct s3c_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg, +static inline struct dwc2_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg, u32 ep_index, u32 dir_in) { if (dir_in) @@ -74,7 +70,7 @@ static inline struct s3c_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg, } /* forward declaration of functions */ -static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg); +static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg); /** * using_dma - return the DMA status of the driver. @@ -101,41 +97,41 @@ static inline bool using_dma(struct dwc2_hsotg *hsotg) } /** - * s3c_hsotg_en_gsint - enable one or more of the general interrupt + * dwc2_hsotg_en_gsint - enable one or more of the general interrupt * @hsotg: The device state * @ints: A bitmask of the interrupts to enable */ -static void s3c_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints) +static void dwc2_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints) { - u32 gsintmsk = readl(hsotg->regs + GINTMSK); + u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK); u32 new_gsintmsk; new_gsintmsk = gsintmsk | ints; if (new_gsintmsk != gsintmsk) { dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk); - writel(new_gsintmsk, hsotg->regs + GINTMSK); + dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK); } } /** - * s3c_hsotg_disable_gsint - disable one or more of the general interrupt + * dwc2_hsotg_disable_gsint - disable one or more of the general interrupt * @hsotg: The device state * @ints: A bitmask of the interrupts to enable */ -static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints) +static void dwc2_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints) { - u32 gsintmsk = readl(hsotg->regs + GINTMSK); + u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK); u32 new_gsintmsk; new_gsintmsk = gsintmsk & ~ints; if (new_gsintmsk != gsintmsk) - writel(new_gsintmsk, hsotg->regs + GINTMSK); + dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK); } /** - * s3c_hsotg_ctrl_epint - enable/disable an endpoint irq + * dwc2_hsotg_ctrl_epint - enable/disable an endpoint irq * @hsotg: The device state * @ep: The endpoint index * @dir_in: True if direction is in. @@ -144,7 +140,7 @@ static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints) * Set or clear the mask for an individual endpoint's interrupt * request. */ -static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, +static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, unsigned int ep, unsigned int dir_in, unsigned int en) { @@ -156,20 +152,20 @@ static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, bit <<= 16; local_irq_save(flags); - daint = readl(hsotg->regs + DAINTMSK); + daint = dwc2_readl(hsotg->regs + DAINTMSK); if (en) daint |= bit; else daint &= ~bit; - writel(daint, hsotg->regs + DAINTMSK); + dwc2_writel(daint, hsotg->regs + DAINTMSK); local_irq_restore(flags); } /** - * s3c_hsotg_init_fifo - initialise non-periodic FIFOs + * dwc2_hsotg_init_fifo - initialise non-periodic FIFOs * @hsotg: The device instance. */ -static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg) { unsigned int ep; unsigned int addr; @@ -181,8 +177,8 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg) hsotg->fifo_map = 0; /* set RX/NPTX FIFO sizes */ - writel(hsotg->g_rx_fifo_sz, hsotg->regs + GRXFSIZ); - writel((hsotg->g_rx_fifo_sz << FIFOSIZE_STARTADDR_SHIFT) | + dwc2_writel(hsotg->g_rx_fifo_sz, hsotg->regs + GRXFSIZ); + dwc2_writel((hsotg->g_rx_fifo_sz << FIFOSIZE_STARTADDR_SHIFT) | (hsotg->g_np_g_tx_fifo_sz << FIFOSIZE_DEPTH_SHIFT), hsotg->regs + GNPTXFSIZ); @@ -210,7 +206,7 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg) "insufficient fifo memory"); addr += hsotg->g_tx_fifo_sz[ep]; - writel(val, hsotg->regs + DPTXFSIZN(ep)); + dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep)); } /* @@ -218,13 +214,13 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg) * all fifos are flushed before continuing */ - writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH | + dwc2_writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH, hsotg->regs + GRSTCTL); /* wait until the fifos are both flushed */ timeout = 100; while (1) { - val = readl(hsotg->regs + GRSTCTL); + val = dwc2_readl(hsotg->regs + GRSTCTL); if ((val & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) == 0) break; @@ -248,12 +244,12 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg) * * Allocate a new USB request structure appropriate for the specified endpoint */ -static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep, +static struct usb_request *dwc2_hsotg_ep_alloc_request(struct usb_ep *ep, gfp_t flags) { - struct s3c_hsotg_req *req; + struct dwc2_hsotg_req *req; - req = kzalloc(sizeof(struct s3c_hsotg_req), flags); + req = kzalloc(sizeof(struct dwc2_hsotg_req), flags); if (!req) return NULL; @@ -269,23 +265,23 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep, * Returns true if the endpoint is in periodic mode, meaning it is being * used for an Interrupt or ISO transfer. */ -static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep) +static inline int is_ep_periodic(struct dwc2_hsotg_ep *hs_ep) { return hs_ep->periodic; } /** - * s3c_hsotg_unmap_dma - unmap the DMA memory being used for the request + * dwc2_hsotg_unmap_dma - unmap the DMA memory being used for the request * @hsotg: The device state. * @hs_ep: The endpoint for the request * @hs_req: The request being processed. * - * This is the reverse of s3c_hsotg_map_dma(), called for the completion + * This is the reverse of dwc2_hsotg_map_dma(), called for the completion * of a request to ensure the buffer is ready for access by the caller. */ -static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, - struct s3c_hsotg_req *hs_req) +static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_req *hs_req) { struct usb_request *req = &hs_req->req; @@ -297,7 +293,7 @@ static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, } /** - * s3c_hsotg_write_fifo - write packet Data to the TxFIFO + * dwc2_hsotg_write_fifo - write packet Data to the TxFIFO * @hsotg: The controller state. * @hs_ep: The endpoint we're going to write for. * @hs_req: The request to write data for. @@ -312,12 +308,12 @@ static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, * * This routine is only needed for PIO */ -static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, - struct s3c_hsotg_req *hs_req) +static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_req *hs_req) { bool periodic = is_ep_periodic(hs_ep); - u32 gnptxsts = readl(hsotg->regs + GNPTXSTS); + u32 gnptxsts = dwc2_readl(hsotg->regs + GNPTXSTS); int buf_pos = hs_req->req.actual; int to_write = hs_ep->size_loaded; void *data; @@ -332,7 +328,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, return 0; if (periodic && !hsotg->dedicated_fifos) { - u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); + u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); int size_left; int size_done; @@ -348,7 +344,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, * previous data has been completely sent. */ if (hs_ep->fifo_load != 0) { - s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP); + dwc2_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP); return -ENOSPC; } @@ -369,11 +365,11 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, __func__, can_write); if (can_write <= 0) { - s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP); + dwc2_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP); return -ENOSPC; } } else if (hsotg->dedicated_fifos && hs_ep->index != 0) { - can_write = readl(hsotg->regs + DTXFSTS(hs_ep->index)); + can_write = dwc2_readl(hsotg->regs + DTXFSTS(hs_ep->index)); can_write &= 0xffff; can_write *= 4; @@ -383,7 +379,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, "%s: no queue slots available (0x%08x)\n", __func__, gnptxsts); - s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP); + dwc2_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP); return -ENOSPC; } @@ -414,7 +410,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, /* it's needed only when we do not use dedicated fifos */ if (!hsotg->dedicated_fifos) - s3c_hsotg_en_gsint(hsotg, + dwc2_hsotg_en_gsint(hsotg, periodic ? GINTSTS_PTXFEMP : GINTSTS_NPTXFEMP); } @@ -443,7 +439,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, /* it's needed only when we do not use dedicated fifos */ if (!hsotg->dedicated_fifos) - s3c_hsotg_en_gsint(hsotg, + dwc2_hsotg_en_gsint(hsotg, periodic ? GINTSTS_PTXFEMP : GINTSTS_NPTXFEMP); } @@ -475,7 +471,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg, * Return the maximum data that can be queued in one go on a given endpoint * so that transfers that are too long can be split. */ -static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) +static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep) { int index = hs_ep->index; unsigned maxsize; @@ -508,7 +504,7 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) } /** - * s3c_hsotg_start_req - start a USB request from an endpoint's queue + * dwc2_hsotg_start_req - start a USB request from an endpoint's queue * @hsotg: The controller state. * @hs_ep: The endpoint to process a request for * @hs_req: The request to start. @@ -517,9 +513,9 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) * Start the given request running by setting the endpoint registers * appropriately, and writing any data to the FIFOs. */ -static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, - struct s3c_hsotg_req *hs_req, +static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_req *hs_req, bool continuing) { struct usb_request *ureq = &hs_req->req; @@ -550,13 +546,13 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index); dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n", - __func__, readl(hsotg->regs + epctrl_reg), index, + __func__, dwc2_readl(hsotg->regs + epctrl_reg), index, hs_ep->dir_in ? "in" : "out"); /* If endpoint is stalled, we will restart request later */ - ctrl = readl(hsotg->regs + epctrl_reg); + ctrl = dwc2_readl(hsotg->regs + epctrl_reg); - if (ctrl & DXEPCTL_STALL) { + if (index && ctrl & DXEPCTL_STALL) { dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); return; } @@ -618,18 +614,18 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, hs_ep->req = hs_req; /* write size / packets */ - writel(epsize, hsotg->regs + epsize_reg); + dwc2_writel(epsize, hsotg->regs + epsize_reg); if (using_dma(hsotg) && !continuing) { unsigned int dma_reg; /* * write DMA address to control register, buffer already - * synced by s3c_hsotg_ep_queue(). + * synced by dwc2_hsotg_ep_queue(). */ dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index); - writel(ureq->dma, hsotg->regs + dma_reg); + dwc2_writel(ureq->dma, hsotg->regs + dma_reg); dev_dbg(hsotg->dev, "%s: %pad => 0x%08x\n", __func__, &ureq->dma, dma_reg); @@ -645,7 +641,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, ctrl |= DXEPCTL_CNAK; /* clear NAK set by core */ dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); - writel(ctrl, hsotg->regs + epctrl_reg); + dwc2_writel(ctrl, hsotg->regs + epctrl_reg); /* * set these, it seems that DMA support increments past the end @@ -659,7 +655,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, /* set these anyway, we may need them for non-periodic in */ hs_ep->fifo_load = 0; - s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); + dwc2_hsotg_write_fifo(hsotg, hs_ep, hs_req); } /* @@ -667,7 +663,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, * to debugging to see what is going on. */ if (dir_in) - writel(DIEPMSK_INTKNTXFEMPMSK, + dwc2_writel(DIEPMSK_INTKNTXFEMPMSK, hsotg->regs + DIEPINT(index)); /* @@ -676,20 +672,20 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, */ /* check ep is enabled */ - if (!(readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA)) + if (!(dwc2_readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA)) dev_dbg(hsotg->dev, "ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n", - index, readl(hsotg->regs + epctrl_reg)); + index, dwc2_readl(hsotg->regs + epctrl_reg)); dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n", - __func__, readl(hsotg->regs + epctrl_reg)); + __func__, dwc2_readl(hsotg->regs + epctrl_reg)); /* enable ep interrupts */ - s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1); + dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1); } /** - * s3c_hsotg_map_dma - map the DMA memory being used for the request + * dwc2_hsotg_map_dma - map the DMA memory being used for the request * @hsotg: The device state. * @hs_ep: The endpoint the request is on. * @req: The request being processed. @@ -700,11 +696,11 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg, * DMA memory, then we map the memory and mark our request to allow us to * cleanup on completion. */ -static int s3c_hsotg_map_dma(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, +static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, struct usb_request *req) { - struct s3c_hsotg_req *hs_req = our_req(req); + struct dwc2_hsotg_req *hs_req = our_req(req); int ret; /* if the length is zero, ignore the DMA data */ @@ -724,8 +720,8 @@ dma_error: return -EIO; } -static int s3c_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req) +static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req) { void *req_buf = hs_req->req.buf; @@ -755,8 +751,8 @@ static int s3c_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg, return 0; } -static void s3c_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req) +static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req) { /* If dma is not being used or buffer was aligned */ if (!using_dma(hsotg) || !hs_req->saved_req_buf) @@ -777,11 +773,11 @@ static void s3c_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg, hs_req->saved_req_buf = NULL; } -static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, +static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) { - struct s3c_hsotg_req *hs_req = our_req(req); - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_req *hs_req = our_req(req); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; bool first; int ret; @@ -802,13 +798,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, req->actual = 0; req->status = -EINPROGRESS; - ret = s3c_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req); + ret = dwc2_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req); if (ret) return ret; /* if we're using DMA, sync the buffers as necessary */ if (using_dma(hs)) { - ret = s3c_hsotg_map_dma(hs, hs_ep, req); + ret = dwc2_hsotg_map_dma(hs, hs_ep, req); if (ret) return ret; } @@ -817,51 +813,51 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, list_add_tail(&hs_req->queue, &hs_ep->queue); if (first) - s3c_hsotg_start_req(hs, hs_ep, hs_req, false); + dwc2_hsotg_start_req(hs, hs_ep, hs_req, false); return 0; } -static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, +static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; unsigned long flags = 0; int ret = 0; spin_lock_irqsave(&hs->lock, flags); - ret = s3c_hsotg_ep_queue(ep, req, gfp_flags); + ret = dwc2_hsotg_ep_queue(ep, req, gfp_flags); spin_unlock_irqrestore(&hs->lock, flags); return ret; } -static void s3c_hsotg_ep_free_request(struct usb_ep *ep, +static void dwc2_hsotg_ep_free_request(struct usb_ep *ep, struct usb_request *req) { - struct s3c_hsotg_req *hs_req = our_req(req); + struct dwc2_hsotg_req *hs_req = our_req(req); kfree(hs_req); } /** - * s3c_hsotg_complete_oursetup - setup completion callback + * dwc2_hsotg_complete_oursetup - setup completion callback * @ep: The endpoint the request was on. * @req: The request completed. * * Called on completion of any requests the driver itself * submitted that need cleaning up. */ -static void s3c_hsotg_complete_oursetup(struct usb_ep *ep, +static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep, struct usb_request *req) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; dev_dbg(hsotg->dev, "%s: ep %p, req %p\n", __func__, ep, req); - s3c_hsotg_ep_free_request(ep, req); + dwc2_hsotg_ep_free_request(ep, req); } /** @@ -872,10 +868,10 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep, * Convert the given wIndex into a pointer to an driver endpoint * structure, or return NULL if it is not a valid endpoint. */ -static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, +static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, u32 windex) { - struct s3c_hsotg_ep *ep; + struct dwc2_hsotg_ep *ep; int dir = (windex & USB_DIR_IN) ? 1 : 0; int idx = windex & 0x7F; @@ -894,14 +890,14 @@ static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, } /** - * s3c_hsotg_set_test_mode - Enable usb Test Modes + * dwc2_hsotg_set_test_mode - Enable usb Test Modes * @hsotg: The driver state. * @testmode: requested usb test mode * Enable usb Test Mode requested by the Host. */ -int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) +int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) { - int dctl = readl(hsotg->regs + DCTL); + int dctl = dwc2_readl(hsotg->regs + DCTL); dctl &= ~DCTL_TSTCTL_MASK; switch (testmode) { @@ -915,12 +911,12 @@ int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) default: return -EINVAL; } - writel(dctl, hsotg->regs + DCTL); + dwc2_writel(dctl, hsotg->regs + DCTL); return 0; } /** - * s3c_hsotg_send_reply - send reply to control request + * dwc2_hsotg_send_reply - send reply to control request * @hsotg: The device state * @ep: Endpoint 0 * @buff: Buffer for request @@ -929,8 +925,8 @@ int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) * Create a request and queue it on the given endpoint. This is useful as * an internal method of sending replies to certain control requests, etc. */ -static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *ep, +static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *ep, void *buff, int length) { @@ -939,7 +935,7 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "%s: buff %p, len %d\n", __func__, buff, length); - req = s3c_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC); + req = dwc2_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC); hsotg->ep0_reply = req; if (!req) { dev_warn(hsotg->dev, "%s: cannot alloc req\n", __func__); @@ -953,12 +949,12 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg, * STATUS stage. */ req->zero = 0; - req->complete = s3c_hsotg_complete_oursetup; + req->complete = dwc2_hsotg_complete_oursetup; if (length) memcpy(req->buf, buff, length); - ret = s3c_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC); + ret = dwc2_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC); if (ret) { dev_warn(hsotg->dev, "%s: cannot queue req\n", __func__); return ret; @@ -968,15 +964,15 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg, } /** - * s3c_hsotg_process_req_status - process request GET_STATUS + * dwc2_hsotg_process_req_status - process request GET_STATUS * @hsotg: The device state * @ctrl: USB control request */ -static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg, +static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg, struct usb_ctrlrequest *ctrl) { - struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0]; - struct s3c_hsotg_ep *ep; + struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; + struct dwc2_hsotg_ep *ep; __le16 reply; int ret; @@ -1013,7 +1009,7 @@ static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg, if (le16_to_cpu(ctrl->wLength) != 2) return -EINVAL; - ret = s3c_hsotg_send_reply(hsotg, ep0, &reply, 2); + ret = dwc2_hsotg_send_reply(hsotg, ep0, &reply, 2); if (ret) { dev_err(hsotg->dev, "%s: failed to send reply\n", __func__); return ret; @@ -1022,7 +1018,7 @@ static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg, return 1; } -static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); +static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value); /** * get_ep_head - return the first request on the endpoint @@ -1030,27 +1026,27 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); * * Get the first request on the endpoint. */ -static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) +static struct dwc2_hsotg_req *get_ep_head(struct dwc2_hsotg_ep *hs_ep) { if (list_empty(&hs_ep->queue)) return NULL; - return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); + return list_first_entry(&hs_ep->queue, struct dwc2_hsotg_req, queue); } /** - * s3c_hsotg_process_req_feature - process request {SET,CLEAR}_FEATURE + * dwc2_hsotg_process_req_feature - process request {SET,CLEAR}_FEATURE * @hsotg: The device state * @ctrl: USB control request */ -static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, +static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, struct usb_ctrlrequest *ctrl) { - struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0]; - struct s3c_hsotg_req *hs_req; + struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; + struct dwc2_hsotg_req *hs_req; bool restart; bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); - struct s3c_hsotg_ep *ep; + struct dwc2_hsotg_ep *ep; int ret; bool halted; u32 recip; @@ -1074,7 +1070,7 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, return -EINVAL; hsotg->test_mode = wIndex >> 8; - ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); + ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0); if (ret) { dev_err(hsotg->dev, "%s: failed to send reply\n", __func__); @@ -1098,9 +1094,9 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, case USB_ENDPOINT_HALT: halted = ep->halted; - s3c_hsotg_ep_sethalt(&ep->ep, set); + dwc2_hsotg_ep_sethalt(&ep->ep, set); - ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); + ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0); if (ret) { dev_err(hsotg->dev, "%s: failed to send reply\n", __func__); @@ -1134,7 +1130,7 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, restart = !list_empty(&ep->queue); if (restart) { hs_req = get_ep_head(ep); - s3c_hsotg_start_req(hsotg, ep, + dwc2_hsotg_start_req(hsotg, ep, hs_req, false); } } @@ -1152,17 +1148,17 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, return 1; } -static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg); +static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg); /** - * s3c_hsotg_stall_ep0 - stall ep0 + * dwc2_hsotg_stall_ep0 - stall ep0 * @hsotg: The device state * * Set stall for ep0 as response for setup request. */ -static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg) { - struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0]; + struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; u32 reg; u32 ctrl; @@ -1174,24 +1170,24 @@ static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg) * taken effect, so no need to clear later. */ - ctrl = readl(hsotg->regs + reg); + ctrl = dwc2_readl(hsotg->regs + reg); ctrl |= DXEPCTL_STALL; ctrl |= DXEPCTL_CNAK; - writel(ctrl, hsotg->regs + reg); + dwc2_writel(ctrl, hsotg->regs + reg); dev_dbg(hsotg->dev, "written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n", - ctrl, reg, readl(hsotg->regs + reg)); + ctrl, reg, dwc2_readl(hsotg->regs + reg)); /* * complete won't be called, so we enqueue * setup request here */ - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_enqueue_setup(hsotg); } /** - * s3c_hsotg_process_control - process a control request + * dwc2_hsotg_process_control - process a control request * @hsotg: The device state * @ctrl: The control request received * @@ -1199,16 +1195,17 @@ static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg) * needs to work out what to do next (and whether to pass it on to the * gadget driver). */ -static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg, +static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg, struct usb_ctrlrequest *ctrl) { - struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0]; + struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; int ret = 0; u32 dcfg; - dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n", - ctrl->bRequest, ctrl->bRequestType, - ctrl->wValue, ctrl->wLength); + dev_dbg(hsotg->dev, + "ctrl Type=%02x, Req=%02x, V=%04x, I=%04x, L=%04x\n", + ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, + ctrl->wIndex, ctrl->wLength); if (ctrl->wLength == 0) { ep0->dir_in = 1; @@ -1225,24 +1222,24 @@ static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg, switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: hsotg->connected = 1; - dcfg = readl(hsotg->regs + DCFG); + dcfg = dwc2_readl(hsotg->regs + DCFG); dcfg &= ~DCFG_DEVADDR_MASK; dcfg |= (le16_to_cpu(ctrl->wValue) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK; - writel(dcfg, hsotg->regs + DCFG); + dwc2_writel(dcfg, hsotg->regs + DCFG); dev_info(hsotg->dev, "new address %d\n", ctrl->wValue); - ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); + ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0); return; case USB_REQ_GET_STATUS: - ret = s3c_hsotg_process_req_status(hsotg, ctrl); + ret = dwc2_hsotg_process_req_status(hsotg, ctrl); break; case USB_REQ_CLEAR_FEATURE: case USB_REQ_SET_FEATURE: - ret = s3c_hsotg_process_req_feature(hsotg, ctrl); + ret = dwc2_hsotg_process_req_feature(hsotg, ctrl); break; } } @@ -1263,21 +1260,21 @@ static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg, */ if (ret < 0) - s3c_hsotg_stall_ep0(hsotg); + dwc2_hsotg_stall_ep0(hsotg); } /** - * s3c_hsotg_complete_setup - completion of a setup transfer + * dwc2_hsotg_complete_setup - completion of a setup transfer * @ep: The endpoint the request was on. * @req: The request completed. * * Called on completion of any requests the driver itself submitted for * EP0 setup packets */ -static void s3c_hsotg_complete_setup(struct usb_ep *ep, +static void dwc2_hsotg_complete_setup(struct usb_ep *ep, struct usb_request *req) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; if (req->status < 0) { @@ -1287,23 +1284,23 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep, spin_lock(&hsotg->lock); if (req->actual == 0) - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_enqueue_setup(hsotg); else - s3c_hsotg_process_control(hsotg, req->buf); + dwc2_hsotg_process_control(hsotg, req->buf); spin_unlock(&hsotg->lock); } /** - * s3c_hsotg_enqueue_setup - start a request for EP0 packets + * dwc2_hsotg_enqueue_setup - start a request for EP0 packets * @hsotg: The device state. * * Enqueue a request on EP0 if necessary to received any SETUP packets * received from the host. */ -static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg) { struct usb_request *req = hsotg->ctrl_req; - struct s3c_hsotg_req *hs_req = our_req(req); + struct dwc2_hsotg_req *hs_req = our_req(req); int ret; dev_dbg(hsotg->dev, "%s: queueing setup request\n", __func__); @@ -1311,7 +1308,7 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg) req->zero = 0; req->length = 8; req->buf = hsotg->ctrl_buff; - req->complete = s3c_hsotg_complete_setup; + req->complete = dwc2_hsotg_complete_setup; if (!list_empty(&hs_req->queue)) { dev_dbg(hsotg->dev, "%s already queued???\n", __func__); @@ -1322,7 +1319,7 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg) hsotg->eps_out[0]->send_zlp = 0; hsotg->ep0_state = DWC2_EP0_SETUP; - ret = s3c_hsotg_ep_queue(&hsotg->eps_out[0]->ep, req, GFP_ATOMIC); + ret = dwc2_hsotg_ep_queue(&hsotg->eps_out[0]->ep, req, GFP_ATOMIC); if (ret < 0) { dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret); /* @@ -1332,8 +1329,8 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg) } } -static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep) +static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep) { u32 ctrl; u8 index = hs_ep->index; @@ -1347,19 +1344,19 @@ static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n", index); - writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | - DXEPTSIZ_XFERSIZE(0), hsotg->regs + - epsiz_reg); + dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | + DXEPTSIZ_XFERSIZE(0), hsotg->regs + + epsiz_reg); - ctrl = readl(hsotg->regs + epctl_reg); + ctrl = dwc2_readl(hsotg->regs + epctl_reg); ctrl |= DXEPCTL_CNAK; /* clear NAK set by core */ ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */ ctrl |= DXEPCTL_USBACTEP; - writel(ctrl, hsotg->regs + epctl_reg); + dwc2_writel(ctrl, hsotg->regs + epctl_reg); } /** - * s3c_hsotg_complete_request - complete a request given to us + * dwc2_hsotg_complete_request - complete a request given to us * @hsotg: The device state. * @hs_ep: The endpoint the request was on. * @hs_req: The request to complete. @@ -1371,9 +1368,9 @@ static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg, * * Note, expects the ep to already be locked as appropriate. */ -static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, - struct s3c_hsotg_req *hs_req, +static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_req *hs_req, int result) { bool restart; @@ -1394,14 +1391,14 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg, if (hs_req->req.status == -EINPROGRESS) hs_req->req.status = result; - s3c_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req); + if (using_dma(hsotg)) + dwc2_hsotg_unmap_dma(hsotg, hs_ep, hs_req); + + dwc2_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req); hs_ep->req = NULL; list_del_init(&hs_req->queue); - if (using_dma(hsotg)) - s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req); - /* * call the complete request with the locks off, just in case the * request tries to queue more work for this endpoint. @@ -1423,13 +1420,13 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg, restart = !list_empty(&hs_ep->queue); if (restart) { hs_req = get_ep_head(hs_ep); - s3c_hsotg_start_req(hsotg, hs_ep, hs_req, false); + dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, false); } } } /** - * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint + * dwc2_hsotg_rx_data - receive data from the FIFO for an endpoint * @hsotg: The device state. * @ep_idx: The endpoint index for the data * @size: The size of data in the fifo, in bytes @@ -1438,10 +1435,10 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg, * endpoint, so sort out whether we need to read the data into a request * that has been made for that endpoint. */ -static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) +static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) { - struct s3c_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx]; - struct s3c_hsotg_req *hs_req = hs_ep->req; + struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx]; + struct dwc2_hsotg_req *hs_req = hs_ep->req; void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx); int to_read; int max_req; @@ -1449,7 +1446,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) if (!hs_req) { - u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); + u32 epctl = dwc2_readl(hsotg->regs + DOEPCTL(ep_idx)); int ptr; dev_dbg(hsotg->dev, @@ -1458,7 +1455,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) /* dump the data from the FIFO, we've nothing we can do */ for (ptr = 0; ptr < size; ptr += 4) - (void)readl(fifo); + (void)dwc2_readl(fifo); return; } @@ -1492,7 +1489,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) } /** - * s3c_hsotg_ep0_zlp - send/receive zero-length packet on control endpoint + * dwc2_hsotg_ep0_zlp - send/receive zero-length packet on control endpoint * @hsotg: The device instance * @dir_in: If IN zlp * @@ -1503,17 +1500,30 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) * currently believed that we do not need to wait for any space in * the TxFIFO. */ -static void s3c_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in) +static void dwc2_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in) { /* eps_out[0] is used in both directions */ hsotg->eps_out[0]->dir_in = dir_in; hsotg->ep0_state = dir_in ? DWC2_EP0_STATUS_IN : DWC2_EP0_STATUS_OUT; - s3c_hsotg_program_zlp(hsotg, hsotg->eps_out[0]); + dwc2_hsotg_program_zlp(hsotg, hsotg->eps_out[0]); +} + +static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg, + u32 epctl_reg) +{ + u32 ctrl; + + ctrl = dwc2_readl(hsotg->regs + epctl_reg); + if (ctrl & DXEPCTL_EOFRNUM) + ctrl |= DXEPCTL_SETEVENFR; + else + ctrl |= DXEPCTL_SETODDFR; + dwc2_writel(ctrl, hsotg->regs + epctl_reg); } /** - * s3c_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO + * dwc2_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO * @hsotg: The device instance * @epnum: The endpoint received from * @@ -1521,11 +1531,11 @@ static void s3c_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in) * transfer for an OUT endpoint has been completed, either by a short * packet or by the finish of a transfer. */ -static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) +static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) { - u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum)); - struct s3c_hsotg_ep *hs_ep = hsotg->eps_out[epnum]; - struct s3c_hsotg_req *hs_req = hs_ep->req; + u32 epsize = dwc2_readl(hsotg->regs + DOEPTSIZ(epnum)); + struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[epnum]; + struct dwc2_hsotg_req *hs_req = hs_ep->req; struct usb_request *req = &hs_req->req; unsigned size_left = DXEPTSIZ_XFERSIZE_GET(epsize); int result = 0; @@ -1537,8 +1547,8 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) if (epnum == 0 && hsotg->ep0_state == DWC2_EP0_STATUS_OUT) { dev_dbg(hsotg->dev, "zlp packet received\n"); - s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); + dwc2_hsotg_enqueue_setup(hsotg); return; } @@ -1562,7 +1572,7 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) /* if there is more request to do, schedule new transfer */ if (req->actual < req->length && size_left == 0) { - s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); + dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, true); return; } @@ -1578,24 +1588,34 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) if (epnum == 0 && hsotg->ep0_state == DWC2_EP0_DATA_OUT) { /* Move to STATUS IN */ - s3c_hsotg_ep0_zlp(hsotg, true); + dwc2_hsotg_ep0_zlp(hsotg, true); return; } - s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); + /* + * Slave mode OUT transfers do not go through XferComplete so + * adjust the ISOC parity here. + */ + if (!using_dma(hsotg)) { + hs_ep->has_correct_parity = 1; + if (hs_ep->isochronous && hs_ep->interval == 1) + dwc2_hsotg_change_ep_iso_parity(hsotg, DOEPCTL(epnum)); + } + + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result); } /** - * s3c_hsotg_read_frameno - read current frame number + * dwc2_hsotg_read_frameno - read current frame number * @hsotg: The device instance * * Return the current frame number */ -static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg) +static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg) { u32 dsts; - dsts = readl(hsotg->regs + DSTS); + dsts = dwc2_readl(hsotg->regs + DSTS); dsts &= DSTS_SOFFN_MASK; dsts >>= DSTS_SOFFN_SHIFT; @@ -1603,7 +1623,7 @@ static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg) } /** - * s3c_hsotg_handle_rx - RX FIFO has data + * dwc2_hsotg_handle_rx - RX FIFO has data * @hsotg: The device instance * * The IRQ handler has detected that the RX FIFO has some data in it @@ -1618,9 +1638,9 @@ static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg) * as the actual data should be sent to the memory directly and we turn * on the completion interrupts to get notifications of transfer completion. */ -static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg) { - u32 grxstsr = readl(hsotg->regs + GRXSTSP); + u32 grxstsr = dwc2_readl(hsotg->regs + GRXSTSP); u32 epnum, status, size; WARN_ON(using_dma(hsotg)); @@ -1641,55 +1661,55 @@ static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg) case GRXSTS_PKTSTS_OUTDONE: dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n", - s3c_hsotg_read_frameno(hsotg)); + dwc2_hsotg_read_frameno(hsotg)); if (!using_dma(hsotg)) - s3c_hsotg_handle_outdone(hsotg, epnum); + dwc2_hsotg_handle_outdone(hsotg, epnum); break; case GRXSTS_PKTSTS_SETUPDONE: dev_dbg(hsotg->dev, "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n", - s3c_hsotg_read_frameno(hsotg), - readl(hsotg->regs + DOEPCTL(0))); + dwc2_hsotg_read_frameno(hsotg), + dwc2_readl(hsotg->regs + DOEPCTL(0))); /* - * Call s3c_hsotg_handle_outdone here if it was not called from + * Call dwc2_hsotg_handle_outdone here if it was not called from * GRXSTS_PKTSTS_OUTDONE. That is, if the core didn't * generate GRXSTS_PKTSTS_OUTDONE for setup packet. */ if (hsotg->ep0_state == DWC2_EP0_SETUP) - s3c_hsotg_handle_outdone(hsotg, epnum); + dwc2_hsotg_handle_outdone(hsotg, epnum); break; case GRXSTS_PKTSTS_OUTRX: - s3c_hsotg_rx_data(hsotg, epnum, size); + dwc2_hsotg_rx_data(hsotg, epnum, size); break; case GRXSTS_PKTSTS_SETUPRX: dev_dbg(hsotg->dev, "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n", - s3c_hsotg_read_frameno(hsotg), - readl(hsotg->regs + DOEPCTL(0))); + dwc2_hsotg_read_frameno(hsotg), + dwc2_readl(hsotg->regs + DOEPCTL(0))); WARN_ON(hsotg->ep0_state != DWC2_EP0_SETUP); - s3c_hsotg_rx_data(hsotg, epnum, size); + dwc2_hsotg_rx_data(hsotg, epnum, size); break; default: dev_warn(hsotg->dev, "%s: unknown status %08x\n", __func__, grxstsr); - s3c_hsotg_dump(hsotg); + dwc2_hsotg_dump(hsotg); break; } } /** - * s3c_hsotg_ep0_mps - turn max packet size into register setting + * dwc2_hsotg_ep0_mps - turn max packet size into register setting * @mps: The maximum packet size in bytes. */ -static u32 s3c_hsotg_ep0_mps(unsigned int mps) +static u32 dwc2_hsotg_ep0_mps(unsigned int mps) { switch (mps) { case 64: @@ -1708,7 +1728,7 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps) } /** - * s3c_hsotg_set_ep_maxpacket - set endpoint's max-packet field + * dwc2_hsotg_set_ep_maxpacket - set endpoint's max-packet field * @hsotg: The driver state. * @ep: The index number of the endpoint * @mps: The maximum packet size in bytes @@ -1716,10 +1736,10 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps) * Configure the maximum packet size for the given endpoint, updating * the hardware control registers to reflect this. */ -static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg, +static void dwc2_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg, unsigned int ep, unsigned int mps, unsigned int dir_in) { - struct s3c_hsotg_ep *hs_ep; + struct dwc2_hsotg_ep *hs_ep; void __iomem *regs = hsotg->regs; u32 mpsval; u32 mcval; @@ -1731,7 +1751,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg, if (ep == 0) { /* EP0 is a special case */ - mpsval = s3c_hsotg_ep0_mps(mps); + mpsval = dwc2_hsotg_ep0_mps(mps); if (mpsval > 3) goto bad_mps; hs_ep->ep.maxpacket = mps; @@ -1748,15 +1768,15 @@ static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg, } if (dir_in) { - reg = readl(regs + DIEPCTL(ep)); + reg = dwc2_readl(regs + DIEPCTL(ep)); reg &= ~DXEPCTL_MPS_MASK; reg |= mpsval; - writel(reg, regs + DIEPCTL(ep)); + dwc2_writel(reg, regs + DIEPCTL(ep)); } else { - reg = readl(regs + DOEPCTL(ep)); + reg = dwc2_readl(regs + DOEPCTL(ep)); reg &= ~DXEPCTL_MPS_MASK; reg |= mpsval; - writel(reg, regs + DOEPCTL(ep)); + dwc2_writel(reg, regs + DOEPCTL(ep)); } return; @@ -1766,23 +1786,23 @@ bad_mps: } /** - * s3c_hsotg_txfifo_flush - flush Tx FIFO + * dwc2_hsotg_txfifo_flush - flush Tx FIFO * @hsotg: The driver state * @idx: The index for the endpoint (0..15) */ -static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx) +static void dwc2_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx) { int timeout; int val; - writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH, - hsotg->regs + GRSTCTL); + dwc2_writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH, + hsotg->regs + GRSTCTL); /* wait until the fifo is flushed */ timeout = 100; while (1) { - val = readl(hsotg->regs + GRSTCTL); + val = dwc2_readl(hsotg->regs + GRSTCTL); if ((val & (GRSTCTL_TXFFLSH)) == 0) break; @@ -1799,17 +1819,17 @@ static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx) } /** - * s3c_hsotg_trytx - check to see if anything needs transmitting + * dwc2_hsotg_trytx - check to see if anything needs transmitting * @hsotg: The driver state * @hs_ep: The driver endpoint to check. * * Check to see if there is a request that has data to send, and if so * make an attempt to write data into the FIFO. */ -static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep) +static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep) { - struct s3c_hsotg_req *hs_req = hs_ep->req; + struct dwc2_hsotg_req *hs_req = hs_ep->req; if (!hs_ep->dir_in || !hs_req) { /** @@ -1817,7 +1837,7 @@ static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg, * for endpoints, excepting ep0 */ if (hs_ep->index != 0) - s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, + dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); return 0; } @@ -1825,25 +1845,25 @@ static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg, if (hs_req->req.actual < hs_req->req.length) { dev_dbg(hsotg->dev, "trying to write more for ep%d\n", hs_ep->index); - return s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); + return dwc2_hsotg_write_fifo(hsotg, hs_ep, hs_req); } return 0; } /** - * s3c_hsotg_complete_in - complete IN transfer + * dwc2_hsotg_complete_in - complete IN transfer * @hsotg: The device state. * @hs_ep: The endpoint that has just completed. * * An IN transfer has been completed, update the transfer's state and then * call the relevant completion routines. */ -static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep) +static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep) { - struct s3c_hsotg_req *hs_req = hs_ep->req; - u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); + struct dwc2_hsotg_req *hs_req = hs_ep->req; + u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); int size_left, size_done; if (!hs_req) { @@ -1854,19 +1874,19 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg, /* Finish ZLP handling for IN EP0 transactions */ if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_STATUS_IN) { dev_dbg(hsotg->dev, "zlp packet sent\n"); - s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); if (hsotg->test_mode) { int ret; - ret = s3c_hsotg_set_test_mode(hsotg, hsotg->test_mode); + ret = dwc2_hsotg_set_test_mode(hsotg, hsotg->test_mode); if (ret < 0) { dev_dbg(hsotg->dev, "Invalid Test #%d\n", hsotg->test_mode); - s3c_hsotg_stall_ep0(hsotg); + dwc2_hsotg_stall_ep0(hsotg); return; } } - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_enqueue_setup(hsotg); return; } @@ -1895,13 +1915,13 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg, if (!size_left && hs_req->req.actual < hs_req->req.length) { dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); - s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); + dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, true); return; } /* Zlp for all endpoints, for ep0 only in DATA IN stage */ if (hs_ep->send_zlp) { - s3c_hsotg_program_zlp(hsotg, hs_ep); + dwc2_hsotg_program_zlp(hsotg, hs_ep); hs_ep->send_zlp = 0; /* transfer will be completed on next complete interrupt */ return; @@ -1909,36 +1929,36 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg, if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_DATA_IN) { /* Move to STATUS OUT */ - s3c_hsotg_ep0_zlp(hsotg, false); + dwc2_hsotg_ep0_zlp(hsotg, false); return; } - s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); } /** - * s3c_hsotg_epint - handle an in/out endpoint interrupt + * dwc2_hsotg_epint - handle an in/out endpoint interrupt * @hsotg: The driver state * @idx: The index for the endpoint (0..15) * @dir_in: Set if this is an IN endpoint * * Process and clear any interrupt pending for an individual endpoint */ -static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, +static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, int dir_in) { - struct s3c_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in); + struct dwc2_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in); u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx); u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx); u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx); u32 ints; u32 ctrl; - ints = readl(hsotg->regs + epint_reg); - ctrl = readl(hsotg->regs + epctl_reg); + ints = dwc2_readl(hsotg->regs + epint_reg); + ctrl = dwc2_readl(hsotg->regs + epctl_reg); /* Clear endpoint interrupts */ - writel(ints, hsotg->regs + epint_reg); + dwc2_writel(ints, hsotg->regs + epint_reg); if (!hs_ep) { dev_err(hsotg->dev, "%s:Interrupt for unconfigured ep%d(%s)\n", @@ -1954,35 +1974,31 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, ints &= ~DXEPINT_XFERCOMPL; if (ints & DXEPINT_XFERCOMPL) { - if (hs_ep->isochronous && hs_ep->interval == 1) { - if (ctrl & DXEPCTL_EOFRNUM) - ctrl |= DXEPCTL_SETEVENFR; - else - ctrl |= DXEPCTL_SETODDFR; - writel(ctrl, hsotg->regs + epctl_reg); - } + hs_ep->has_correct_parity = 1; + if (hs_ep->isochronous && hs_ep->interval == 1) + dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg); dev_dbg(hsotg->dev, "%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n", - __func__, readl(hsotg->regs + epctl_reg), - readl(hsotg->regs + epsiz_reg)); + __func__, dwc2_readl(hsotg->regs + epctl_reg), + dwc2_readl(hsotg->regs + epsiz_reg)); /* * we get OutDone from the FIFO, so we only need to look * at completing IN requests here */ if (dir_in) { - s3c_hsotg_complete_in(hsotg, hs_ep); + dwc2_hsotg_complete_in(hsotg, hs_ep); if (idx == 0 && !hs_ep->req) - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_enqueue_setup(hsotg); } else if (using_dma(hsotg)) { /* * We're using DMA, we need to fire an OutDone here * as we ignore the RXFIFO. */ - s3c_hsotg_handle_outdone(hsotg, idx); + dwc2_hsotg_handle_outdone(hsotg, idx); } } @@ -1990,16 +2006,16 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); if (dir_in) { - int epctl = readl(hsotg->regs + epctl_reg); + int epctl = dwc2_readl(hsotg->regs + epctl_reg); - s3c_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index); + dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index); if ((epctl & DXEPCTL_STALL) && (epctl & DXEPCTL_EPTYPE_BULK)) { - int dctl = readl(hsotg->regs + DCTL); + int dctl = dwc2_readl(hsotg->regs + DCTL); dctl |= DCTL_CGNPINNAK; - writel(dctl, hsotg->regs + DCTL); + dwc2_writel(dctl, hsotg->regs + DCTL); } } } @@ -2021,7 +2037,7 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, if (dir_in) WARN_ON_ONCE(1); else - s3c_hsotg_handle_outdone(hsotg, 0); + dwc2_hsotg_handle_outdone(hsotg, 0); } } @@ -2047,21 +2063,21 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); if (!using_dma(hsotg)) - s3c_hsotg_trytx(hsotg, hs_ep); + dwc2_hsotg_trytx(hsotg, hs_ep); } } } /** - * s3c_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done) + * dwc2_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done) * @hsotg: The device state. * * Handle updating the device settings after the enumeration phase has * been completed. */ -static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg) { - u32 dsts = readl(hsotg->regs + DSTS); + u32 dsts = dwc2_readl(hsotg->regs + DSTS); int ep0_mps = 0, ep_mps = 8; /* @@ -2113,23 +2129,23 @@ static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg) if (ep0_mps) { int i; /* Initialize ep0 for both in and out directions */ - s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 1); - s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 0); + dwc2_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 1); + dwc2_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 0); for (i = 1; i < hsotg->num_of_eps; i++) { if (hsotg->eps_in[i]) - s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 1); + dwc2_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 1); if (hsotg->eps_out[i]) - s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 0); + dwc2_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 0); } } /* ensure after enumeration our EP0 is active */ - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_enqueue_setup(hsotg); dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + DIEPCTL0), - readl(hsotg->regs + DOEPCTL0)); + dwc2_readl(hsotg->regs + DIEPCTL0), + dwc2_readl(hsotg->regs + DOEPCTL0)); } /** @@ -2142,34 +2158,34 @@ static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg) * completed with the given result code. */ static void kill_all_requests(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *ep, + struct dwc2_hsotg_ep *ep, int result) { - struct s3c_hsotg_req *req, *treq; + struct dwc2_hsotg_req *req, *treq; unsigned size; ep->req = NULL; list_for_each_entry_safe(req, treq, &ep->queue, queue) - s3c_hsotg_complete_request(hsotg, ep, req, + dwc2_hsotg_complete_request(hsotg, ep, req, result); if (!hsotg->dedicated_fifos) return; - size = (readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4; + size = (dwc2_readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4; if (size < ep->fifo_size) - s3c_hsotg_txfifo_flush(hsotg, ep->fifo_index); + dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); } /** - * s3c_hsotg_disconnect - disconnect service + * dwc2_hsotg_disconnect - disconnect service * @hsotg: The device state. * * The device has been disconnected. Remove all current * transactions and signal the gadget driver that this * has happened. */ -void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg) +void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg) { unsigned ep; @@ -2189,16 +2205,17 @@ void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg) } call_gadget(hsotg, disconnect); + hsotg->lx_state = DWC2_L3; } /** - * s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler + * dwc2_hsotg_irq_fifoempty - TX FIFO empty interrupt handler * @hsotg: The device state: * @periodic: True if this is a periodic FIFO interrupt */ -static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) +static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) { - struct s3c_hsotg_ep *ep; + struct dwc2_hsotg_ep *ep; int epno, ret; /* look through for any more data to transmit */ @@ -2215,7 +2232,7 @@ static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) (!periodic && ep->periodic)) continue; - ret = s3c_hsotg_trytx(hsotg, ep); + ret = dwc2_hsotg_trytx(hsotg, ep); if (ret < 0) break; } @@ -2227,12 +2244,12 @@ static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) GINTSTS_RXFLVL) /** - * s3c_hsotg_corereset - issue softreset to the core + * dwc2_hsotg_corereset - issue softreset to the core * @hsotg: The device state * * Issue a soft reset to the core, and await the core finishing it. */ -static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg) +static int dwc2_hsotg_corereset(struct dwc2_hsotg *hsotg) { int timeout; u32 grstctl; @@ -2240,11 +2257,11 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "resetting core\n"); /* issue soft reset */ - writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL); + dwc2_writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL); timeout = 10000; do { - grstctl = readl(hsotg->regs + GRSTCTL); + grstctl = dwc2_readl(hsotg->regs + GRSTCTL); } while ((grstctl & GRSTCTL_CSFTRST) && timeout-- > 0); if (grstctl & GRSTCTL_CSFTRST) { @@ -2255,7 +2272,7 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg) timeout = 10000; while (1) { - u32 grstctl = readl(hsotg->regs + GRSTCTL); + u32 grstctl = dwc2_readl(hsotg->regs + GRSTCTL); if (timeout-- < 0) { dev_info(hsotg->dev, @@ -2275,18 +2292,23 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg) } /** - * s3c_hsotg_core_init - issue softreset to the core + * dwc2_hsotg_core_init - issue softreset to the core * @hsotg: The device state * * Issue a soft reset to the core, and await the core finishing it. */ -void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, +void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, bool is_usb_reset) { + u32 intmsk; u32 val; + /* Kill any ep0 requests as controller will be reinitialized */ + kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); + if (!is_usb_reset) - s3c_hsotg_corereset(hsotg); + if (dwc2_hsotg_corereset(hsotg)) + return; /* * we must now enable ep0 ready for host detection and then @@ -2295,39 +2317,42 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, /* set the PLL on, remove the HNP/SRP and set the PHY */ val = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5; - writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) | + dwc2_writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) | (val << GUSBCFG_USBTRDTIM_SHIFT), hsotg->regs + GUSBCFG); - s3c_hsotg_init_fifo(hsotg); + dwc2_hsotg_init_fifo(hsotg); if (!is_usb_reset) __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON); - writel(DCFG_EPMISCNT(1) | DCFG_DEVSPD_HS, hsotg->regs + DCFG); + dwc2_writel(DCFG_EPMISCNT(1) | DCFG_DEVSPD_HS, hsotg->regs + DCFG); /* Clear any pending OTG interrupts */ - writel(0xffffffff, hsotg->regs + GOTGINT); + dwc2_writel(0xffffffff, hsotg->regs + GOTGINT); /* Clear any pending interrupts */ - writel(0xffffffff, hsotg->regs + GINTSTS); - - writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT | + dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); + intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT | GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF | - GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST | - GINTSTS_RESETDET | GINTSTS_ENUMDONE | - GINTSTS_OTGINT | GINTSTS_USBSUSP | - GINTSTS_WKUPINT, - hsotg->regs + GINTMSK); + GINTSTS_USBRST | GINTSTS_RESETDET | + GINTSTS_ENUMDONE | GINTSTS_OTGINT | + GINTSTS_USBSUSP | GINTSTS_WKUPINT | + GINTSTS_INCOMPL_SOIN | GINTSTS_INCOMPL_SOOUT; + + if (hsotg->core_params->external_id_pin_ctl <= 0) + intmsk |= GINTSTS_CONIDSTSCHNG; + + dwc2_writel(intmsk, hsotg->regs + GINTMSK); if (using_dma(hsotg)) - writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN | - (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT), - hsotg->regs + GAHBCFG); + dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN | + (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT), + hsotg->regs + GAHBCFG); else - writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NP_TXF_EMP_LVL | - GAHBCFG_P_TXF_EMP_LVL) : 0) | - GAHBCFG_GLBL_INTR_EN, - hsotg->regs + GAHBCFG); + dwc2_writel(((hsotg->dedicated_fifos) ? + (GAHBCFG_NP_TXF_EMP_LVL | + GAHBCFG_P_TXF_EMP_LVL) : 0) | + GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG); /* * If INTknTXFEmpMsk is enabled, it's important to disable ep interrupts @@ -2335,7 +2360,7 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, * interrupts. */ - writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ? + dwc2_writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ? DIEPMSK_TXFIFOEMPTY | DIEPMSK_INTKNTXFEMPMSK : 0) | DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK | DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK | @@ -2346,20 +2371,20 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, * don't need XferCompl, we get that from RXFIFO in slave mode. In * DMA mode we may need this. */ - writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK | + dwc2_writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK | DIEPMSK_TIMEOUTMSK) : 0) | DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK | DOEPMSK_SETUPMSK, hsotg->regs + DOEPMSK); - writel(0, hsotg->regs + DAINTMSK); + dwc2_writel(0, hsotg->regs + DAINTMSK); dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + DIEPCTL0), - readl(hsotg->regs + DOEPCTL0)); + dwc2_readl(hsotg->regs + DIEPCTL0), + dwc2_readl(hsotg->regs + DOEPCTL0)); /* enable in and out endpoint interrupts */ - s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT); + dwc2_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT); /* * Enable the RXFIFO when in slave mode, as this is how we collect @@ -2367,11 +2392,11 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, * things we cannot process, so do not use it. */ if (!using_dma(hsotg)) - s3c_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL); + dwc2_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL); /* Enable interrupts for EP0 in and out */ - s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); - s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); + dwc2_hsotg_ctrl_epint(hsotg, 0, 0, 1); + dwc2_hsotg_ctrl_epint(hsotg, 0, 1, 1); if (!is_usb_reset) { __orr32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE); @@ -2379,7 +2404,7 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, __bic32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE); } - dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL)); + dev_dbg(hsotg->dev, "DCTL=0x%08x\n", dwc2_readl(hsotg->regs + DCTL)); /* * DxEPCTL_USBActEp says RO in manual, but seems to be set by @@ -2387,23 +2412,23 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, */ /* set to read 1 8byte packet */ - writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | + dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(8), hsotg->regs + DOEPTSIZ0); - writel(s3c_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) | + dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) | DXEPCTL_CNAK | DXEPCTL_EPENA | DXEPCTL_USBACTEP, hsotg->regs + DOEPCTL0); /* enable, but don't activate EP0in */ - writel(s3c_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) | + dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) | DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0); - s3c_hsotg_enqueue_setup(hsotg); + dwc2_hsotg_enqueue_setup(hsotg); dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + DIEPCTL0), - readl(hsotg->regs + DOEPCTL0)); + dwc2_readl(hsotg->regs + DIEPCTL0), + dwc2_readl(hsotg->regs + DOEPCTL0)); /* clear global NAKs */ val = DCTL_CGOUTNAK | DCTL_CGNPINNAK; @@ -2414,27 +2439,27 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, /* must be at-least 3ms to allow bus to see disconnect */ mdelay(3); - hsotg->last_rst = jiffies; + hsotg->lx_state = DWC2_L0; } -static void s3c_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) { /* set the soft-disconnect bit */ __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON); } -void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) +void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) { /* remove the soft-disconnect and let's go */ __bic32(hsotg->regs + DCTL, DCTL_SFTDISCON); } /** - * s3c_hsotg_irq - handle device interrupt + * dwc2_hsotg_irq - handle device interrupt * @irq: The IRQ number triggered * @pw: The pw value when registered the handler. */ -static irqreturn_t s3c_hsotg_irq(int irq, void *pw) +static irqreturn_t dwc2_hsotg_irq(int irq, void *pw) { struct dwc2_hsotg *hsotg = pw; int retry_count = 8; @@ -2443,49 +2468,18 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) spin_lock(&hsotg->lock); irq_retry: - gintsts = readl(hsotg->regs + GINTSTS); - gintmsk = readl(hsotg->regs + GINTMSK); + gintsts = dwc2_readl(hsotg->regs + GINTSTS); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n", __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count); gintsts &= gintmsk; - if (gintsts & GINTSTS_ENUMDONE) { - writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS); - - s3c_hsotg_irq_enumdone(hsotg); - } - - if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) { - u32 daint = readl(hsotg->regs + DAINT); - u32 daintmsk = readl(hsotg->regs + DAINTMSK); - u32 daint_out, daint_in; - int ep; - - daint &= daintmsk; - daint_out = daint >> DAINT_OUTEP_SHIFT; - daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT); - - dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); - - for (ep = 0; ep < hsotg->num_of_eps && daint_out; - ep++, daint_out >>= 1) { - if (daint_out & 1) - s3c_hsotg_epint(hsotg, ep, 0); - } - - for (ep = 0; ep < hsotg->num_of_eps && daint_in; - ep++, daint_in >>= 1) { - if (daint_in & 1) - s3c_hsotg_epint(hsotg, ep, 1); - } - } - if (gintsts & GINTSTS_RESETDET) { dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__); - writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS); /* This event must be used only if controller is suspended */ if (hsotg->lx_state == DWC2_L2) { @@ -2496,27 +2490,50 @@ irq_retry: if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) { - u32 usb_status = readl(hsotg->regs + GOTGCTL); + u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL); + u32 connected = hsotg->connected; dev_dbg(hsotg->dev, "%s: USBRst\n", __func__); dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", - readl(hsotg->regs + GNPTXSTS)); + dwc2_readl(hsotg->regs + GNPTXSTS)); - writel(GINTSTS_USBRST, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS); /* Report disconnection if it is not already done. */ - s3c_hsotg_disconnect(hsotg); + dwc2_hsotg_disconnect(hsotg); + + if (usb_status & GOTGCTL_BSESVLD && connected) + dwc2_hsotg_core_init_disconnected(hsotg, true); + } - if (usb_status & GOTGCTL_BSESVLD) { - if (time_after(jiffies, hsotg->last_rst + - msecs_to_jiffies(200))) { + if (gintsts & GINTSTS_ENUMDONE) { + dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS); - kill_all_requests(hsotg, hsotg->eps_out[0], - -ECONNRESET); + dwc2_hsotg_irq_enumdone(hsotg); + } - hsotg->lx_state = DWC2_L0; - s3c_hsotg_core_init_disconnected(hsotg, true); - } + if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) { + u32 daint = dwc2_readl(hsotg->regs + DAINT); + u32 daintmsk = dwc2_readl(hsotg->regs + DAINTMSK); + u32 daint_out, daint_in; + int ep; + + daint &= daintmsk; + daint_out = daint >> DAINT_OUTEP_SHIFT; + daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT); + + dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); + + for (ep = 0; ep < hsotg->num_of_eps && daint_out; + ep++, daint_out >>= 1) { + if (daint_out & 1) + dwc2_hsotg_epint(hsotg, ep, 0); + } + + for (ep = 0; ep < hsotg->num_of_eps && daint_in; + ep++, daint_in >>= 1) { + if (daint_in & 1) + dwc2_hsotg_epint(hsotg, ep, 1); } } @@ -2531,8 +2548,8 @@ irq_retry: * it needs re-enabling */ - s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP); - s3c_hsotg_irq_fifoempty(hsotg, false); + dwc2_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP); + dwc2_hsotg_irq_fifoempty(hsotg, false); } if (gintsts & GINTSTS_PTXFEMP) { @@ -2540,23 +2557,23 @@ irq_retry: /* See note in GINTSTS_NPTxFEmp */ - s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP); - s3c_hsotg_irq_fifoempty(hsotg, true); + dwc2_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP); + dwc2_hsotg_irq_fifoempty(hsotg, true); } if (gintsts & GINTSTS_RXFLVL) { /* * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, - * we need to retry s3c_hsotg_handle_rx if this is still + * we need to retry dwc2_hsotg_handle_rx if this is still * set. */ - s3c_hsotg_handle_rx(hsotg); + dwc2_hsotg_handle_rx(hsotg); } if (gintsts & GINTSTS_ERLYSUSP) { dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n"); - writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS); } /* @@ -2568,17 +2585,51 @@ irq_retry: if (gintsts & GINTSTS_GOUTNAKEFF) { dev_info(hsotg->dev, "GOUTNakEff triggered\n"); - writel(DCTL_CGOUTNAK, hsotg->regs + DCTL); + dwc2_writel(DCTL_CGOUTNAK, hsotg->regs + DCTL); - s3c_hsotg_dump(hsotg); + dwc2_hsotg_dump(hsotg); } if (gintsts & GINTSTS_GINNAKEFF) { dev_info(hsotg->dev, "GINNakEff triggered\n"); - writel(DCTL_CGNPINNAK, hsotg->regs + DCTL); + dwc2_writel(DCTL_CGNPINNAK, hsotg->regs + DCTL); + + dwc2_hsotg_dump(hsotg); + } + + if (gintsts & GINTSTS_INCOMPL_SOIN) { + u32 idx, epctl_reg; + struct dwc2_hsotg_ep *hs_ep; + + dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOIN\n", __func__); + for (idx = 1; idx < hsotg->num_of_eps; idx++) { + hs_ep = hsotg->eps_in[idx]; + + if (!hs_ep->isochronous || hs_ep->has_correct_parity) + continue; + + epctl_reg = DIEPCTL(idx); + dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg); + } + dwc2_writel(GINTSTS_INCOMPL_SOIN, hsotg->regs + GINTSTS); + } + + if (gintsts & GINTSTS_INCOMPL_SOOUT) { + u32 idx, epctl_reg; + struct dwc2_hsotg_ep *hs_ep; - s3c_hsotg_dump(hsotg); + dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOOUT\n", __func__); + for (idx = 1; idx < hsotg->num_of_eps; idx++) { + hs_ep = hsotg->eps_out[idx]; + + if (!hs_ep->isochronous || hs_ep->has_correct_parity) + continue; + + epctl_reg = DOEPCTL(idx); + dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg); + } + dwc2_writel(GINTSTS_INCOMPL_SOOUT, hsotg->regs + GINTSTS); } /* @@ -2595,16 +2646,16 @@ irq_retry: } /** - * s3c_hsotg_ep_enable - enable the given endpoint + * dwc2_hsotg_ep_enable - enable the given endpoint * @ep: The USB endpint to configure * @desc: The USB endpoint descriptor to configure with. * * This is called from the USB gadget code's usb_ep_enable(). */ -static int s3c_hsotg_ep_enable(struct usb_ep *ep, +static int dwc2_hsotg_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; unsigned long flags; unsigned int index = hs_ep->index; @@ -2631,10 +2682,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, mps = usb_endpoint_maxp(desc); - /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ + /* note, we handle this here instead of dwc2_hsotg_set_ep_maxpacket */ epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); - epctrl = readl(hsotg->regs + epctrl_reg); + epctrl = dwc2_readl(hsotg->regs + epctrl_reg); dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", __func__, epctrl, epctrl_reg); @@ -2660,13 +2711,14 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, epctrl |= DXEPCTL_SNAK; /* update the endpoint state */ - s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in); + dwc2_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in); /* default, set to non-periodic */ hs_ep->isochronous = 0; hs_ep->periodic = 0; hs_ep->halted = 0; hs_ep->interval = desc->bInterval; + hs_ep->has_correct_parity = 0; if (hs_ep->interval > 1 && hs_ep->mc > 1) dev_err(hsotg->dev, "MC > 1 when interval is not 1\n"); @@ -2718,7 +2770,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, for (i = 1; i < hsotg->num_of_eps; ++i) { if (hsotg->fifo_map & (1<regs + DPTXFSIZN(i)); + val = dwc2_readl(hsotg->regs + DPTXFSIZN(i)); val = (val >> FIFOSIZE_DEPTH_SHIFT)*4; if (val < size) continue; @@ -2747,12 +2799,12 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n", __func__, epctrl); - writel(epctrl, hsotg->regs + epctrl_reg); + dwc2_writel(epctrl, hsotg->regs + epctrl_reg); dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x\n", - __func__, readl(hsotg->regs + epctrl_reg)); + __func__, dwc2_readl(hsotg->regs + epctrl_reg)); /* enable the endpoint interrupt */ - s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); + dwc2_hsotg_ctrl_epint(hsotg, index, dir_in, 1); error: spin_unlock_irqrestore(&hsotg->lock, flags); @@ -2760,12 +2812,12 @@ error: } /** - * s3c_hsotg_ep_disable - disable given endpoint + * dwc2_hsotg_ep_disable - disable given endpoint * @ep: The endpoint to disable. */ -static int s3c_hsotg_ep_disable(struct usb_ep *ep) +static int dwc2_hsotg_ep_disable(struct usb_ep *ep) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; int dir_in = hs_ep->dir_in; int index = hs_ep->index; @@ -2788,16 +2840,16 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) hs_ep->fifo_index = 0; hs_ep->fifo_size = 0; - ctrl = readl(hsotg->regs + epctrl_reg); + ctrl = dwc2_readl(hsotg->regs + epctrl_reg); ctrl &= ~DXEPCTL_EPENA; ctrl &= ~DXEPCTL_USBACTEP; ctrl |= DXEPCTL_SNAK; dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); - writel(ctrl, hsotg->regs + epctrl_reg); + dwc2_writel(ctrl, hsotg->regs + epctrl_reg); /* disable endpoint interrupts */ - s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); + dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN); @@ -2811,9 +2863,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) * @ep: The endpoint to check. * @test: The request to test if it is on the endpoint. */ -static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) +static bool on_list(struct dwc2_hsotg_ep *ep, struct dwc2_hsotg_req *test) { - struct s3c_hsotg_req *req, *treq; + struct dwc2_hsotg_req *req, *treq; list_for_each_entry_safe(req, treq, &ep->queue, queue) { if (req == test) @@ -2823,15 +2875,88 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) return false; } +static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg, + u32 bit, u32 timeout) +{ + u32 i; + + for (i = 0; i < timeout; i++) { + if (dwc2_readl(hs_otg->regs + reg) & bit) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep) +{ + u32 epctrl_reg; + u32 epint_reg; + + epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) : + DOEPCTL(hs_ep->index); + epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) : + DOEPINT(hs_ep->index); + + dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__, + hs_ep->name); + if (hs_ep->dir_in) { + __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK); + /* Wait for Nak effect */ + if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, + DXEPINT_INEPNAKEFF, 100)) + dev_warn(hsotg->dev, + "%s: timeout DIEPINT.NAKEFF\n", __func__); + } else { + /* Clear any pending nak effect interrupt */ + dwc2_writel(GINTSTS_GINNAKEFF, hsotg->regs + GINTSTS); + + __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK); + + /* Wait for global nak to take effect */ + if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS, + GINTSTS_GINNAKEFF, 100)) + dev_warn(hsotg->dev, + "%s: timeout GINTSTS.GINNAKEFF\n", __func__); + } + + /* Disable ep */ + __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK); + + /* Wait for ep to be disabled */ + if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100)) + dev_warn(hsotg->dev, + "%s: timeout DOEPCTL.EPDisable\n", __func__); + + if (hs_ep->dir_in) { + if (hsotg->dedicated_fifos) { + dwc2_writel(GRSTCTL_TXFNUM(hs_ep->fifo_index) | + GRSTCTL_TXFFLSH, hsotg->regs + GRSTCTL); + /* Wait for fifo flush */ + if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, + GRSTCTL_TXFFLSH, 100)) + dev_warn(hsotg->dev, + "%s: timeout flushing fifos\n", + __func__); + } + /* TODO: Flush shared tx fifo */ + } else { + /* Remove global NAKs */ + __bic32(hsotg->regs + DCTL, DCTL_SGNPINNAK); + } +} + /** - * s3c_hsotg_ep_dequeue - dequeue given endpoint + * dwc2_hsotg_ep_dequeue - dequeue given endpoint * @ep: The endpoint to dequeue. * @req: The request to be removed from a queue. */ -static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) +static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) { - struct s3c_hsotg_req *hs_req = our_req(req); - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_req *hs_req = our_req(req); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; unsigned long flags; @@ -2844,20 +2969,24 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) return -EINVAL; } - s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); + /* Dequeue already started request */ + if (req == &hs_ep->req->req) + dwc2_hsotg_ep_stop_xfr(hs, hs_ep); + + dwc2_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); spin_unlock_irqrestore(&hs->lock, flags); return 0; } /** - * s3c_hsotg_ep_sethalt - set halt on a given endpoint + * dwc2_hsotg_ep_sethalt - set halt on a given endpoint * @ep: The endpoint to set halt. * @value: Set or unset the halt. */ -static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) +static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; int index = hs_ep->index; u32 epreg; @@ -2868,7 +2997,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) if (index == 0) { if (value) - s3c_hsotg_stall_ep0(hs); + dwc2_hsotg_stall_ep0(hs); else dev_warn(hs->dev, "%s: can't clear halt on ep0\n", __func__); @@ -2877,7 +3006,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) if (hs_ep->dir_in) { epreg = DIEPCTL(index); - epctl = readl(hs->regs + epreg); + epctl = dwc2_readl(hs->regs + epreg); if (value) { epctl |= DXEPCTL_STALL | DXEPCTL_SNAK; @@ -2890,11 +3019,11 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) xfertype == DXEPCTL_EPTYPE_INTERRUPT) epctl |= DXEPCTL_SETD0PID; } - writel(epctl, hs->regs + epreg); + dwc2_writel(epctl, hs->regs + epreg); } else { epreg = DOEPCTL(index); - epctl = readl(hs->regs + epreg); + epctl = dwc2_readl(hs->regs + epreg); if (value) epctl |= DXEPCTL_STALL; @@ -2905,7 +3034,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) xfertype == DXEPCTL_EPTYPE_INTERRUPT) epctl |= DXEPCTL_SETD0PID; } - writel(epctl, hs->regs + epreg); + dwc2_writel(epctl, hs->regs + epreg); } hs_ep->halted = value; @@ -2914,97 +3043,53 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) } /** - * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held + * dwc2_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held * @ep: The endpoint to set halt. * @value: Set or unset the halt. */ -static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) +static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) { - struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; unsigned long flags = 0; int ret = 0; spin_lock_irqsave(&hs->lock, flags); - ret = s3c_hsotg_ep_sethalt(ep, value); + ret = dwc2_hsotg_ep_sethalt(ep, value); spin_unlock_irqrestore(&hs->lock, flags); return ret; } -static struct usb_ep_ops s3c_hsotg_ep_ops = { - .enable = s3c_hsotg_ep_enable, - .disable = s3c_hsotg_ep_disable, - .alloc_request = s3c_hsotg_ep_alloc_request, - .free_request = s3c_hsotg_ep_free_request, - .queue = s3c_hsotg_ep_queue_lock, - .dequeue = s3c_hsotg_ep_dequeue, - .set_halt = s3c_hsotg_ep_sethalt_lock, +static struct usb_ep_ops dwc2_hsotg_ep_ops = { + .enable = dwc2_hsotg_ep_enable, + .disable = dwc2_hsotg_ep_disable, + .alloc_request = dwc2_hsotg_ep_alloc_request, + .free_request = dwc2_hsotg_ep_free_request, + .queue = dwc2_hsotg_ep_queue_lock, + .dequeue = dwc2_hsotg_ep_dequeue, + .set_halt = dwc2_hsotg_ep_sethalt_lock, /* note, don't believe we have any call for the fifo routines */ }; /** - * s3c_hsotg_phy_enable - enable platform phy dev - * @hsotg: The driver state - * - * A wrapper for platform code responsible for controlling - * low-level USB code - */ -static void s3c_hsotg_phy_enable(struct dwc2_hsotg *hsotg) -{ - struct platform_device *pdev = to_platform_device(hsotg->dev); - - dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev); - - if (hsotg->uphy) - usb_phy_init(hsotg->uphy); - else if (hsotg->plat && hsotg->plat->phy_init) - hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); - else { - phy_init(hsotg->phy); - phy_power_on(hsotg->phy); - } -} - -/** - * s3c_hsotg_phy_disable - disable platform phy dev - * @hsotg: The driver state - * - * A wrapper for platform code responsible for controlling - * low-level USB code - */ -static void s3c_hsotg_phy_disable(struct dwc2_hsotg *hsotg) -{ - struct platform_device *pdev = to_platform_device(hsotg->dev); - - if (hsotg->uphy) - usb_phy_shutdown(hsotg->uphy); - else if (hsotg->plat && hsotg->plat->phy_exit) - hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); - else { - phy_power_off(hsotg->phy); - phy_exit(hsotg->phy); - } -} - -/** - * s3c_hsotg_init - initalize the usb core + * dwc2_hsotg_init - initalize the usb core * @hsotg: The driver state */ -static void s3c_hsotg_init(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg) { u32 trdtim; /* unmask subset of endpoint interrupts */ - writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK | - DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK, - hsotg->regs + DIEPMSK); + dwc2_writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK | + DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK, + hsotg->regs + DIEPMSK); - writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK | - DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK, - hsotg->regs + DOEPMSK); + dwc2_writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK | + DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK, + hsotg->regs + DOEPMSK); - writel(0, hsotg->regs + DAINTMSK); + dwc2_writel(0, hsotg->regs + DAINTMSK); /* Be in disconnected state until gadget is registered */ __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON); @@ -3012,14 +3097,14 @@ static void s3c_hsotg_init(struct dwc2_hsotg *hsotg) /* setup fifos */ dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(hsotg->regs + GRXFSIZ), - readl(hsotg->regs + GNPTXFSIZ)); + dwc2_readl(hsotg->regs + GRXFSIZ), + dwc2_readl(hsotg->regs + GNPTXFSIZ)); - s3c_hsotg_init_fifo(hsotg); + dwc2_hsotg_init_fifo(hsotg); /* set the PLL on, remove the HNP/SRP and set the PHY */ trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5; - writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) | + dwc2_writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) | (trdtim << GUSBCFG_USBTRDTIM_SHIFT), hsotg->regs + GUSBCFG); @@ -3028,14 +3113,14 @@ static void s3c_hsotg_init(struct dwc2_hsotg *hsotg) } /** - * s3c_hsotg_udc_start - prepare the udc for work + * dwc2_hsotg_udc_start - prepare the udc for work * @gadget: The usb gadget state * @driver: The usb gadget driver * * Perform initialization to prepare udc device and driver * to work. */ -static int s3c_hsotg_udc_start(struct usb_gadget *gadget, +static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); @@ -3060,7 +3145,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, return -EINVAL; } - mutex_lock(&hsotg->init_mutex); WARN_ON(hsotg->driver); driver->driver.bus = NULL; @@ -3068,45 +3152,38 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, hsotg->gadget.dev.of_node = hsotg->dev->of_node; hsotg->gadget.speed = USB_SPEED_UNKNOWN; - clk_enable(hsotg->clk); - - ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - if (ret) { - dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret); - goto err; + if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) { + ret = dwc2_lowlevel_hw_enable(hsotg); + if (ret) + goto err; } - s3c_hsotg_phy_enable(hsotg); if (!IS_ERR_OR_NULL(hsotg->uphy)) otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget); spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_init(hsotg); - s3c_hsotg_core_init_disconnected(hsotg, false); + dwc2_hsotg_init(hsotg); + dwc2_hsotg_core_init_disconnected(hsotg, false); hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); - mutex_unlock(&hsotg->init_mutex); - return 0; err: - mutex_unlock(&hsotg->init_mutex); hsotg->driver = NULL; return ret; } /** - * s3c_hsotg_udc_stop - stop the udc + * dwc2_hsotg_udc_stop - stop the udc * @gadget: The usb gadget state * @driver: The usb gadget driver * * Stop udc hw block and stay tunned for future transmissions */ -static int s3c_hsotg_udc_stop(struct usb_gadget *gadget) +static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); unsigned long flags = 0; @@ -3115,14 +3192,12 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget) if (!hsotg) return -ENODEV; - mutex_lock(&hsotg->init_mutex); - /* all endpoints should be shutdown */ for (ep = 1; ep < hsotg->num_of_eps; ep++) { if (hsotg->eps_in[ep]) - s3c_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); + dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); if (hsotg->eps_out[ep]) - s3c_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); + dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); } spin_lock_irqsave(&hsotg->lock, flags); @@ -3135,64 +3210,63 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget) if (!IS_ERR_OR_NULL(hsotg->uphy)) otg_set_peripheral(hsotg->uphy->otg, NULL); - s3c_hsotg_phy_disable(hsotg); - regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - - clk_disable(hsotg->clk); - - mutex_unlock(&hsotg->init_mutex); + if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) + dwc2_lowlevel_hw_disable(hsotg); return 0; } /** - * s3c_hsotg_gadget_getframe - read the frame number + * dwc2_hsotg_gadget_getframe - read the frame number * @gadget: The usb gadget state * * Read the {micro} frame number */ -static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) +static int dwc2_hsotg_gadget_getframe(struct usb_gadget *gadget) { - return s3c_hsotg_read_frameno(to_hsotg(gadget)); + return dwc2_hsotg_read_frameno(to_hsotg(gadget)); } /** - * s3c_hsotg_pullup - connect/disconnect the USB PHY + * dwc2_hsotg_pullup - connect/disconnect the USB PHY * @gadget: The usb gadget state * @is_on: Current state of the USB PHY * * Connect/Disconnect the USB PHY pullup */ -static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on) +static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); unsigned long flags = 0; - dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on); + dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on, + hsotg->op_state); + + /* Don't modify pullup state while in host mode */ + if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) { + hsotg->enabled = is_on; + return 0; + } - mutex_lock(&hsotg->init_mutex); spin_lock_irqsave(&hsotg->lock, flags); if (is_on) { - clk_enable(hsotg->clk); hsotg->enabled = 1; - s3c_hsotg_core_init_disconnected(hsotg, false); - s3c_hsotg_core_connect(hsotg); + dwc2_hsotg_core_init_disconnected(hsotg, false); + dwc2_hsotg_core_connect(hsotg); } else { - s3c_hsotg_core_disconnect(hsotg); - s3c_hsotg_disconnect(hsotg); + dwc2_hsotg_core_disconnect(hsotg); + dwc2_hsotg_disconnect(hsotg); hsotg->enabled = 0; - clk_disable(hsotg->clk); } hsotg->gadget.speed = USB_SPEED_UNKNOWN; spin_unlock_irqrestore(&hsotg->lock, flags); - mutex_unlock(&hsotg->init_mutex); return 0; } -static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) +static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); unsigned long flags; @@ -3200,23 +3274,22 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active); spin_lock_irqsave(&hsotg->lock, flags); + /* + * If controller is hibernated, it must exit from hibernation + * before being initialized / de-initialized + */ + if (hsotg->lx_state == DWC2_L2) + dwc2_exit_hibernation(hsotg, false); + if (is_active) { - /* - * If controller is hibernated, it must exit from hibernation - * before being initialized - */ - if (hsotg->lx_state == DWC2_L2) { - dwc2_exit_hibernation(hsotg, false); - hsotg->lx_state = DWC2_L0; - } - /* Kill any ep0 requests as controller will be reinitialized */ - kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); - s3c_hsotg_core_init_disconnected(hsotg, false); + hsotg->op_state = OTG_STATE_B_PERIPHERAL; + + dwc2_hsotg_core_init_disconnected(hsotg, false); if (hsotg->enabled) - s3c_hsotg_core_connect(hsotg); + dwc2_hsotg_core_connect(hsotg); } else { - s3c_hsotg_core_disconnect(hsotg); - s3c_hsotg_disconnect(hsotg); + dwc2_hsotg_core_disconnect(hsotg); + dwc2_hsotg_disconnect(hsotg); } spin_unlock_irqrestore(&hsotg->lock, flags); @@ -3224,13 +3297,13 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) } /** - * s3c_hsotg_vbus_draw - report bMaxPower field + * dwc2_hsotg_vbus_draw - report bMaxPower field * @gadget: The usb gadget state * @mA: Amount of current * * Report how much power the device may consume to the phy. */ -static int s3c_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA) +static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); @@ -3239,17 +3312,17 @@ static int s3c_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA) return usb_phy_set_power(hsotg->uphy, mA); } -static const struct usb_gadget_ops s3c_hsotg_gadget_ops = { - .get_frame = s3c_hsotg_gadget_getframe, - .udc_start = s3c_hsotg_udc_start, - .udc_stop = s3c_hsotg_udc_stop, - .pullup = s3c_hsotg_pullup, - .vbus_session = s3c_hsotg_vbus_session, - .vbus_draw = s3c_hsotg_vbus_draw, +static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = { + .get_frame = dwc2_hsotg_gadget_getframe, + .udc_start = dwc2_hsotg_udc_start, + .udc_stop = dwc2_hsotg_udc_stop, + .pullup = dwc2_hsotg_pullup, + .vbus_session = dwc2_hsotg_vbus_session, + .vbus_draw = dwc2_hsotg_vbus_draw, }; /** - * s3c_hsotg_initep - initialise a single endpoint + * dwc2_hsotg_initep - initialise a single endpoint * @hsotg: The device state. * @hs_ep: The endpoint to be initialised. * @epnum: The endpoint number @@ -3258,8 +3331,8 @@ static const struct usb_gadget_ops s3c_hsotg_gadget_ops = { * creation) to give to the gadget driver. Setup the endpoint name, any * direction information and other state that may be required. */ -static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, +static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, int epnum, bool dir_in) { @@ -3287,7 +3360,7 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg, hs_ep->parent = hsotg; hs_ep->ep.name = hs_ep->name; usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT); - hs_ep->ep.ops = &s3c_hsotg_ep_ops; + hs_ep->ep.ops = &dwc2_hsotg_ep_ops; if (epnum == 0) { hs_ep->ep.caps.type_control = true; @@ -3310,19 +3383,19 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg, if (using_dma(hsotg)) { u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15); if (dir_in) - writel(next, hsotg->regs + DIEPCTL(epnum)); + dwc2_writel(next, hsotg->regs + DIEPCTL(epnum)); else - writel(next, hsotg->regs + DOEPCTL(epnum)); + dwc2_writel(next, hsotg->regs + DOEPCTL(epnum)); } } /** - * s3c_hsotg_hw_cfg - read HW configuration registers + * dwc2_hsotg_hw_cfg - read HW configuration registers * @param: The device state * * Read the USB core HW configuration registers */ -static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) +static int dwc2_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) { u32 cfg; u32 ep_type; @@ -3330,41 +3403,41 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) /* check hardware configuration */ - cfg = readl(hsotg->regs + GHWCFG2); + cfg = dwc2_readl(hsotg->regs + GHWCFG2); hsotg->num_of_eps = (cfg >> GHWCFG2_NUM_DEV_EP_SHIFT) & 0xF; /* Add ep0 */ hsotg->num_of_eps++; - hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct s3c_hsotg_ep), + hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct dwc2_hsotg_ep), GFP_KERNEL); if (!hsotg->eps_in[0]) return -ENOMEM; - /* Same s3c_hsotg_ep is used in both directions for ep0 */ + /* Same dwc2_hsotg_ep is used in both directions for ep0 */ hsotg->eps_out[0] = hsotg->eps_in[0]; - cfg = readl(hsotg->regs + GHWCFG1); + cfg = dwc2_readl(hsotg->regs + GHWCFG1); for (i = 1, cfg >>= 2; i < hsotg->num_of_eps; i++, cfg >>= 2) { ep_type = cfg & 3; /* Direction in or both */ if (!(ep_type & 2)) { hsotg->eps_in[i] = devm_kzalloc(hsotg->dev, - sizeof(struct s3c_hsotg_ep), GFP_KERNEL); + sizeof(struct dwc2_hsotg_ep), GFP_KERNEL); if (!hsotg->eps_in[i]) return -ENOMEM; } /* Direction out or both */ if (!(ep_type & 1)) { hsotg->eps_out[i] = devm_kzalloc(hsotg->dev, - sizeof(struct s3c_hsotg_ep), GFP_KERNEL); + sizeof(struct dwc2_hsotg_ep), GFP_KERNEL); if (!hsotg->eps_out[i]) return -ENOMEM; } } - cfg = readl(hsotg->regs + GHWCFG3); + cfg = dwc2_readl(hsotg->regs + GHWCFG3); hsotg->fifo_mem = (cfg >> GHWCFG3_DFIFO_DEPTH_SHIFT); - cfg = readl(hsotg->regs + GHWCFG4); + cfg = dwc2_readl(hsotg->regs + GHWCFG4); hsotg->dedicated_fifos = (cfg >> GHWCFG4_DED_FIFO_SHIFT) & 1; dev_info(hsotg->dev, "EPs: %d, %s fifos, %d entries in SPRAM\n", @@ -3375,10 +3448,10 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) } /** - * s3c_hsotg_dump - dump state of the udc + * dwc2_hsotg_dump - dump state of the udc * @param: The device state */ -static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg) { #ifdef DEBUG struct device *dev = hsotg->dev; @@ -3387,19 +3460,19 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg) int idx; dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n", - readl(regs + DCFG), readl(regs + DCTL), - readl(regs + DIEPMSK)); + dwc2_readl(regs + DCFG), dwc2_readl(regs + DCTL), + dwc2_readl(regs + DIEPMSK)); dev_info(dev, "GAHBCFG=0x%08x, GHWCFG1=0x%08x\n", - readl(regs + GAHBCFG), readl(regs + GHWCFG1)); + dwc2_readl(regs + GAHBCFG), dwc2_readl(regs + GHWCFG1)); dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ)); + dwc2_readl(regs + GRXFSIZ), dwc2_readl(regs + GNPTXFSIZ)); /* show periodic fifo settings */ for (idx = 1; idx < hsotg->num_of_eps; idx++) { - val = readl(regs + DPTXFSIZN(idx)); + val = dwc2_readl(regs + DPTXFSIZN(idx)); dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx, val >> FIFOSIZE_DEPTH_SHIFT, val & FIFOSIZE_STARTADDR_MASK); @@ -3408,26 +3481,26 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg) for (idx = 0; idx < hsotg->num_of_eps; idx++) { dev_info(dev, "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx, - readl(regs + DIEPCTL(idx)), - readl(regs + DIEPTSIZ(idx)), - readl(regs + DIEPDMA(idx))); + dwc2_readl(regs + DIEPCTL(idx)), + dwc2_readl(regs + DIEPTSIZ(idx)), + dwc2_readl(regs + DIEPDMA(idx))); - val = readl(regs + DOEPCTL(idx)); + val = dwc2_readl(regs + DOEPCTL(idx)); dev_info(dev, "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", - idx, readl(regs + DOEPCTL(idx)), - readl(regs + DOEPTSIZ(idx)), - readl(regs + DOEPDMA(idx))); + idx, dwc2_readl(regs + DOEPCTL(idx)), + dwc2_readl(regs + DOEPTSIZ(idx)), + dwc2_readl(regs + DOEPDMA(idx))); } dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", - readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE)); + dwc2_readl(regs + DVBUSDIS), dwc2_readl(regs + DVBUSPULSE)); #endif } #ifdef CONFIG_OF -static void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) +static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg) { struct device_node *np = hsotg->dev->of_node; u32 len = 0; @@ -3468,7 +3541,7 @@ rx_fifo: &hsotg->g_np_g_tx_fifo_sz); } #else -static inline void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { } +static inline void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg) { } #endif /** @@ -3479,23 +3552,17 @@ static inline void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { } int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) { struct device *dev = hsotg->dev; - struct s3c_hsotg_plat *plat = dev->platform_data; int epnum; int ret; int i; u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE; - /* Set default UTMI width */ - hsotg->phyif = GUSBCFG_PHYIF16; - - s3c_hsotg_of_probe(hsotg); - /* Initialize to legacy fifo configuration values */ hsotg->g_rx_fifo_sz = 2048; hsotg->g_np_g_tx_fifo_sz = 1024; memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo)); /* Device tree specific probe */ - s3c_hsotg_of_probe(hsotg); + dwc2_hsotg_of_probe(hsotg); /* Dump fifo information */ dev_dbg(dev, "NonPeriodic TXFIFO size: %d\n", hsotg->g_np_g_tx_fifo_sz); @@ -3503,70 +3570,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) for (i = 0; i < MAX_EPS_CHANNELS; i++) dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i, hsotg->g_tx_fifo_sz[i]); - /* - * If platform probe couldn't find a generic PHY or an old style - * USB PHY, fall back to pdata - */ - if (IS_ERR_OR_NULL(hsotg->phy) && IS_ERR_OR_NULL(hsotg->uphy)) { - plat = dev_get_platdata(dev); - if (!plat) { - dev_err(dev, - "no platform data or transceiver defined\n"); - return -EPROBE_DEFER; - } - hsotg->plat = plat; - } else if (hsotg->phy) { - /* - * If using the generic PHY framework, check if the PHY bus - * width is 8-bit and set the phyif appropriately. - */ - if (phy_get_bus_width(hsotg->phy) == 8) - hsotg->phyif = GUSBCFG_PHYIF8; - } - - hsotg->clk = devm_clk_get(dev, "otg"); - if (IS_ERR(hsotg->clk)) { - hsotg->clk = NULL; - dev_dbg(dev, "cannot get otg clock\n"); - } hsotg->gadget.max_speed = USB_SPEED_HIGH; - hsotg->gadget.ops = &s3c_hsotg_gadget_ops; + hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); if (hsotg->dr_mode == USB_DR_MODE_OTG) hsotg->gadget.is_otg = 1; - - /* reset the system */ - - ret = clk_prepare_enable(hsotg->clk); - if (ret) { - dev_err(dev, "failed to enable otg clk\n"); - goto err_clk; - } - - - /* regulators */ - - for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) - hsotg->supplies[i].supply = s3c_hsotg_supply_names[i]; - - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - if (ret) { - dev_err(dev, "failed to request supplies: %d\n", ret); - goto err_clk; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - - if (ret) { - dev_err(dev, "failed to enable supplies: %d\n", ret); - goto err_clk; - } - - /* usb phy enable */ - s3c_hsotg_phy_enable(hsotg); + else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) + hsotg->op_state = OTG_STATE_B_PERIPHERAL; /* * Force Device mode before initialization. @@ -3581,14 +3592,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) */ msleep(25); - s3c_hsotg_corereset(hsotg); - ret = s3c_hsotg_hw_cfg(hsotg); + dwc2_hsotg_corereset(hsotg); + ret = dwc2_hsotg_hw_cfg(hsotg); if (ret) { dev_err(hsotg->dev, "Hardware configuration failed: %d\n", ret); - goto err_clk; + return ret; } - s3c_hsotg_init(hsotg); + dwc2_hsotg_init(hsotg); /* Switch back to default configuration */ __bic32(hsotg->regs + GUSBCFG, GUSBCFG_FORCEDEVMODE); @@ -3597,35 +3608,28 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) DWC2_CTRL_BUFF_SIZE, GFP_KERNEL); if (!hsotg->ctrl_buff) { dev_err(dev, "failed to allocate ctrl request buff\n"); - ret = -ENOMEM; - goto err_supplies; + return -ENOMEM; } hsotg->ep0_buff = devm_kzalloc(hsotg->dev, DWC2_CTRL_BUFF_SIZE, GFP_KERNEL); if (!hsotg->ep0_buff) { dev_err(dev, "failed to allocate ctrl reply buff\n"); - ret = -ENOMEM; - goto err_supplies; + return -ENOMEM; } - ret = devm_request_irq(hsotg->dev, irq, s3c_hsotg_irq, IRQF_SHARED, + ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED, dev_name(hsotg->dev), hsotg); if (ret < 0) { - s3c_hsotg_phy_disable(hsotg); - clk_disable_unprepare(hsotg->clk); - regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); dev_err(dev, "cannot claim IRQ for gadget\n"); - goto err_supplies; + return ret; } /* hsotg->num_of_eps holds number of EPs other than ep0 */ if (hsotg->num_of_eps == 0) { dev_err(dev, "wrong number of EPs (zero)\n"); - ret = -EINVAL; - goto err_supplies; + return -EINVAL; } /* setup endpoint information */ @@ -3635,71 +3639,49 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) /* allocate EP0 request */ - hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps_out[0]->ep, + hsotg->ctrl_req = dwc2_hsotg_ep_alloc_request(&hsotg->eps_out[0]->ep, GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); - ret = -ENOMEM; - goto err_supplies; + return -ENOMEM; } /* initialise the endpoints now the core has been initialised */ for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) { if (hsotg->eps_in[epnum]) - s3c_hsotg_initep(hsotg, hsotg->eps_in[epnum], + dwc2_hsotg_initep(hsotg, hsotg->eps_in[epnum], epnum, 1); if (hsotg->eps_out[epnum]) - s3c_hsotg_initep(hsotg, hsotg->eps_out[epnum], + dwc2_hsotg_initep(hsotg, hsotg->eps_out[epnum], epnum, 0); } - /* disable power and clock */ - s3c_hsotg_phy_disable(hsotg); - - ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - if (ret) { - dev_err(dev, "failed to disable supplies: %d\n", ret); - goto err_supplies; - } - ret = usb_add_gadget_udc(dev, &hsotg->gadget); if (ret) - goto err_supplies; + return ret; - s3c_hsotg_dump(hsotg); + dwc2_hsotg_dump(hsotg); return 0; - -err_supplies: - s3c_hsotg_phy_disable(hsotg); -err_clk: - clk_disable_unprepare(hsotg->clk); - - return ret; } /** - * s3c_hsotg_remove - remove function for hsotg driver + * dwc2_hsotg_remove - remove function for hsotg driver * @pdev: The platform information for the driver */ -int s3c_hsotg_remove(struct dwc2_hsotg *hsotg) +int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg) { usb_del_gadget_udc(&hsotg->gadget); - clk_disable_unprepare(hsotg->clk); return 0; } -int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg) +int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) { unsigned long flags; - int ret = 0; if (hsotg->lx_state != DWC2_L0) - return ret; - - mutex_lock(&hsotg->init_mutex); + return 0; if (hsotg->driver) { int ep; @@ -3709,57 +3691,39 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg) spin_lock_irqsave(&hsotg->lock, flags); if (hsotg->enabled) - s3c_hsotg_core_disconnect(hsotg); - s3c_hsotg_disconnect(hsotg); + dwc2_hsotg_core_disconnect(hsotg); + dwc2_hsotg_disconnect(hsotg); hsotg->gadget.speed = USB_SPEED_UNKNOWN; spin_unlock_irqrestore(&hsotg->lock, flags); - s3c_hsotg_phy_disable(hsotg); - for (ep = 0; ep < hsotg->num_of_eps; ep++) { if (hsotg->eps_in[ep]) - s3c_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); + dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); if (hsotg->eps_out[ep]) - s3c_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); + dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); } - - ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - clk_disable(hsotg->clk); } - mutex_unlock(&hsotg->init_mutex); - - return ret; + return 0; } -int s3c_hsotg_resume(struct dwc2_hsotg *hsotg) +int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg) { unsigned long flags; - int ret = 0; if (hsotg->lx_state == DWC2_L2) - return ret; - - mutex_lock(&hsotg->init_mutex); + return 0; if (hsotg->driver) { dev_info(hsotg->dev, "resuming usb gadget %s\n", hsotg->driver->driver.name); - clk_enable(hsotg->clk); - ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - - s3c_hsotg_phy_enable(hsotg); - spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_core_init_disconnected(hsotg, false); + dwc2_hsotg_core_init_disconnected(hsotg, false); if (hsotg->enabled) - s3c_hsotg_core_connect(hsotg); + dwc2_hsotg_core_connect(hsotg); spin_unlock_irqrestore(&hsotg->lock, flags); } - mutex_unlock(&hsotg->init_mutex); - return ret; + return 0; } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index f845c41fe..571c21727 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -80,10 +80,10 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg, if (chan == NULL) return; - hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num)); - hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num)); - hctsiz = readl(hsotg->regs + HCTSIZ(chan->hc_num)); - hc_dma = readl(hsotg->regs + HCDMA(chan->hc_num)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); + hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chan->hc_num)); + hc_dma = dwc2_readl(hsotg->regs + HCDMA(chan->hc_num)); dev_dbg(hsotg->dev, " Assigned to channel %p:\n", chan); dev_dbg(hsotg->dev, " hcchar 0x%08x, hcsplt 0x%08x\n", @@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) { list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { - dwc2_host_complete(hsotg, qtd, -ETIMEDOUT); + dwc2_host_complete(hsotg, qtd, -ECONNRESET); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); } } @@ -207,7 +207,7 @@ void dwc2_hcd_start(struct dwc2_hsotg *hsotg) */ hprt0 = dwc2_read_hprt0(hsotg); hprt0 |= HPRT0_RST; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); } queue_delayed_work(hsotg->wq_otg, &hsotg->start_work, @@ -228,11 +228,11 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) channel = hsotg->hc_ptr_array[i]; if (!list_empty(&channel->hc_list_entry)) continue; - hcchar = readl(hsotg->regs + HCCHAR(i)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); if (hcchar & HCCHAR_CHENA) { hcchar &= ~(HCCHAR_CHENA | HCCHAR_EPDIR); hcchar |= HCCHAR_CHDIS; - writel(hcchar, hsotg->regs + HCCHAR(i)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); } } } @@ -241,11 +241,11 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) channel = hsotg->hc_ptr_array[i]; if (!list_empty(&channel->hc_list_entry)) continue; - hcchar = readl(hsotg->regs + HCCHAR(i)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); if (hcchar & HCCHAR_CHENA) { /* Halt the channel */ hcchar |= HCCHAR_CHDIS; - writel(hcchar, hsotg->regs + HCCHAR(i)); + dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); } dwc2_hc_cleanup(hsotg, channel); @@ -287,11 +287,11 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) * interrupt mask and status bits and disabling subsequent host * channel interrupts. */ - intr = readl(hsotg->regs + GINTMSK); + intr = dwc2_readl(hsotg->regs + GINTMSK); intr &= ~(GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT); - writel(intr, hsotg->regs + GINTMSK); + dwc2_writel(intr, hsotg->regs + GINTMSK); intr = GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT; - writel(intr, hsotg->regs + GINTSTS); + dwc2_writel(intr, hsotg->regs + GINTSTS); /* * Turn off the vbus power only if the core has transitioned to device @@ -301,7 +301,7 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) if (dwc2_is_device_mode(hsotg)) { if (hsotg->op_state != OTG_STATE_A_SUSPEND) { dev_dbg(hsotg->dev, "Disconnect: PortPower off\n"); - writel(0, hsotg->regs + HPRT0); + dwc2_writel(0, hsotg->regs + HPRT0); } dwc2_disable_host_interrupts(hsotg); @@ -324,12 +324,13 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) */ static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg) { - if (hsotg->lx_state == DWC2_L2) { + if (hsotg->bus_suspended) { hsotg->flags.b.port_suspend_change = 1; usb_hcd_resume_root_hub(hsotg->priv); - } else { - hsotg->flags.b.port_l1_change = 1; } + + if (hsotg->lx_state == DWC2_L1) + hsotg->flags.b.port_l1_change = 1; } /** @@ -354,7 +355,7 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg) /* Turn off the vbus power */ dev_dbg(hsotg->dev, "PortPower off\n"); - writel(0, hsotg->regs + HPRT0); + dwc2_writel(0, hsotg->regs + HPRT0); } /* Caller must hold driver lock */ @@ -378,7 +379,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, if ((dev_speed == USB_SPEED_LOW) && (hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) && (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI)) { - u32 hprt0 = readl(hsotg->regs + HPRT0); + u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0); u32 prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (prtspd == HPRT0_SPD_FULL_SPEED) @@ -397,7 +398,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, return retval; } - intr_mask = readl(hsotg->regs + GINTMSK); + intr_mask = dwc2_readl(hsotg->regs + GINTMSK); if (!(intr_mask & GINTSTS_SOF)) { enum dwc2_transaction_type tr_type; @@ -1070,7 +1071,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) if (dbg_perio()) dev_vdbg(hsotg->dev, "Queue periodic transactions\n"); - tx_status = readl(hsotg->regs + HPTXSTS); + tx_status = dwc2_readl(hsotg->regs + HPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> @@ -1085,7 +1086,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) qh_ptr = hsotg->periodic_sched_assigned.next; while (qh_ptr != &hsotg->periodic_sched_assigned) { - tx_status = readl(hsotg->regs + HPTXSTS); + tx_status = dwc2_readl(hsotg->regs + HPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; if (qspcavail == 0) { @@ -1145,7 +1146,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) } if (hsotg->core_params->dma_enable <= 0) { - tx_status = readl(hsotg->regs + HPTXSTS); + tx_status = dwc2_readl(hsotg->regs + HPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> @@ -1168,9 +1169,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) * level to ensure that new requests are loaded as * soon as possible.) */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk |= GINTSTS_PTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } else { /* * Disable the Tx FIFO empty interrupt since there are @@ -1179,9 +1180,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) * handlers to queue more transactions as transfer * states change. */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk &= ~GINTSTS_PTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } } } @@ -1210,7 +1211,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "Queue non-periodic transactions\n"); - tx_status = readl(hsotg->regs + GNPTXSTS); + tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> @@ -1233,7 +1234,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) * available in the request queue or the Tx FIFO */ do { - tx_status = readl(hsotg->regs + GNPTXSTS); + tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; if (hsotg->core_params->dma_enable <= 0 && qspcavail == 0) { @@ -1270,7 +1271,7 @@ next: } while (hsotg->non_periodic_qh_ptr != orig_qh_ptr); if (hsotg->core_params->dma_enable <= 0) { - tx_status = readl(hsotg->regs + GNPTXSTS); + tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> @@ -1290,9 +1291,9 @@ next: * level to ensure that new requests are loaded as * soon as possible.) */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk |= GINTSTS_NPTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } else { /* * Disable the Tx FIFO empty interrupt since there are @@ -1301,9 +1302,9 @@ next: * handlers to queue more transactions as transfer * states change. */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk &= ~GINTSTS_NPTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } } } @@ -1341,10 +1342,10 @@ void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, * Ensure NP Tx FIFO empty interrupt is disabled when * there are no non-periodic transfers to process */ - u32 gintmsk = readl(hsotg->regs + GINTMSK); + u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk &= ~GINTSTS_NPTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } } } @@ -1355,10 +1356,11 @@ static void dwc2_conn_id_status_change(struct work_struct *work) wf_otg); u32 count = 0; u32 gotgctl; + unsigned long flags; dev_dbg(hsotg->dev, "%s()\n", __func__); - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl); dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n", !!(gotgctl & GOTGCTL_CONID_B)); @@ -1382,8 +1384,10 @@ static void dwc2_conn_id_status_change(struct work_struct *work) hsotg->op_state = OTG_STATE_B_PERIPHERAL; dwc2_core_init(hsotg, false, -1); dwc2_enable_global_interrupts(hsotg); - s3c_hsotg_core_init_disconnected(hsotg, false); - s3c_hsotg_core_connect(hsotg); + spin_lock_irqsave(&hsotg->lock, flags); + dwc2_hsotg_core_init_disconnected(hsotg, false); + spin_unlock_irqrestore(&hsotg->lock, flags); + dwc2_hsotg_core_connect(hsotg); } else { /* A-Device connector (Host Mode) */ dev_dbg(hsotg->dev, "connId A\n"); @@ -1421,11 +1425,12 @@ static void dwc2_wakeup_detected(unsigned long data) hprt0 = dwc2_read_hprt0(hsotg); dev_dbg(hsotg->dev, "Resume: HPRT0=%0x\n", hprt0); hprt0 &= ~HPRT0_RES; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n", - readl(hsotg->regs + HPRT0)); + dwc2_readl(hsotg->regs + HPRT0)); dwc2_hcd_rem_wakeup(hsotg); + hsotg->bus_suspended = 0; /* Change to L0 state */ hsotg->lx_state = DWC2_L0; @@ -1451,30 +1456,35 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) spin_lock_irqsave(&hsotg->lock, flags); if (windex == hsotg->otg_port && dwc2_host_is_b_hnp_enabled(hsotg)) { - gotgctl = readl(hsotg->regs + GOTGCTL); + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); gotgctl |= GOTGCTL_HSTSETHNPEN; - writel(gotgctl, hsotg->regs + GOTGCTL); + dwc2_writel(gotgctl, hsotg->regs + GOTGCTL); hsotg->op_state = OTG_STATE_A_SUSPEND; } hprt0 = dwc2_read_hprt0(hsotg); hprt0 |= HPRT0_SUSP; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); - /* Update lx_state */ - hsotg->lx_state = DWC2_L2; + hsotg->bus_suspended = 1; - /* Suspend the Phy Clock */ - pcgctl = readl(hsotg->regs + PCGCTL); - pcgctl |= PCGCTL_STOPPCLK; - writel(pcgctl, hsotg->regs + PCGCTL); - udelay(10); + /* + * If hibernation is supported, Phy clock will be suspended + * after registers are backuped. + */ + if (!hsotg->core_params->hibernation) { + /* Suspend the Phy Clock */ + pcgctl = dwc2_readl(hsotg->regs + PCGCTL); + pcgctl |= PCGCTL_STOPPCLK; + dwc2_writel(pcgctl, hsotg->regs + PCGCTL); + udelay(10); + } /* For HNP the bus must be suspended for at least 200ms */ if (dwc2_host_is_b_hnp_enabled(hsotg)) { - pcgctl = readl(hsotg->regs + PCGCTL); + pcgctl = dwc2_readl(hsotg->regs + PCGCTL); pcgctl &= ~PCGCTL_STOPPCLK; - writel(pcgctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgctl, hsotg->regs + PCGCTL); spin_unlock_irqrestore(&hsotg->lock, flags); @@ -1484,6 +1494,44 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) } } +/* Must NOT be called with interrupt disabled or spinlock held */ +static void dwc2_port_resume(struct dwc2_hsotg *hsotg) +{ + unsigned long flags; + u32 hprt0; + u32 pcgctl; + + spin_lock_irqsave(&hsotg->lock, flags); + + /* + * If hibernation is supported, Phy clock is already resumed + * after registers restore. + */ + if (!hsotg->core_params->hibernation) { + pcgctl = dwc2_readl(hsotg->regs + PCGCTL); + pcgctl &= ~PCGCTL_STOPPCLK; + dwc2_writel(pcgctl, hsotg->regs + PCGCTL); + spin_unlock_irqrestore(&hsotg->lock, flags); + usleep_range(20000, 40000); + spin_lock_irqsave(&hsotg->lock, flags); + } + + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_RES; + hprt0 &= ~HPRT0_SUSP; + dwc2_writel(hprt0, hsotg->regs + HPRT0); + spin_unlock_irqrestore(&hsotg->lock, flags); + + msleep(USB_RESUME_TIMEOUT); + + spin_lock_irqsave(&hsotg->lock, flags); + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 &= ~(HPRT0_RES | HPRT0_SUSP); + dwc2_writel(hprt0, hsotg->regs + HPRT0); + hsotg->bus_suspended = 0; + spin_unlock_irqrestore(&hsotg->lock, flags); +} + /* Handles hub class-specific requests */ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, u16 wvalue, u16 windex, char *buf, u16 wlength) @@ -1523,23 +1571,15 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); hprt0 = dwc2_read_hprt0(hsotg); hprt0 |= HPRT0_ENA; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); break; case USB_PORT_FEAT_SUSPEND: dev_dbg(hsotg->dev, "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); - writel(0, hsotg->regs + PCGCTL); - usleep_range(20000, 40000); - hprt0 = dwc2_read_hprt0(hsotg); - hprt0 |= HPRT0_RES; - writel(hprt0, hsotg->regs + HPRT0); - hprt0 &= ~HPRT0_SUSP; - msleep(USB_RESUME_TIMEOUT); - - hprt0 &= ~HPRT0_RES; - writel(hprt0, hsotg->regs + HPRT0); + if (hsotg->bus_suspended) + dwc2_port_resume(hsotg); break; case USB_PORT_FEAT_POWER: @@ -1547,7 +1587,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, "ClearPortFeature USB_PORT_FEAT_POWER\n"); hprt0 = dwc2_read_hprt0(hsotg); hprt0 &= ~HPRT0_PWR; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); break; case USB_PORT_FEAT_INDICATOR: @@ -1668,7 +1708,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, break; } - hprt0 = readl(hsotg->regs + HPRT0); + hprt0 = dwc2_readl(hsotg->regs + HPRT0); dev_vdbg(hsotg->dev, " HPRT0: 0x%08x\n", hprt0); if (hprt0 & HPRT0_CONNSTS) @@ -1733,18 +1773,18 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, "SetPortFeature - USB_PORT_FEAT_POWER\n"); hprt0 = dwc2_read_hprt0(hsotg); hprt0 |= HPRT0_PWR; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); break; case USB_PORT_FEAT_RESET: hprt0 = dwc2_read_hprt0(hsotg); dev_dbg(hsotg->dev, "SetPortFeature - USB_PORT_FEAT_RESET\n"); - pcgctl = readl(hsotg->regs + PCGCTL); + pcgctl = dwc2_readl(hsotg->regs + PCGCTL); pcgctl &= ~(PCGCTL_ENBL_SLEEP_GATING | PCGCTL_STOPPCLK); - writel(pcgctl, hsotg->regs + PCGCTL); + dwc2_writel(pcgctl, hsotg->regs + PCGCTL); /* ??? Original driver does this */ - writel(0, hsotg->regs + PCGCTL); + dwc2_writel(0, hsotg->regs + PCGCTL); hprt0 = dwc2_read_hprt0(hsotg); /* Clear suspend bit if resetting from suspend state */ @@ -1759,13 +1799,13 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, hprt0 |= HPRT0_PWR | HPRT0_RST; dev_dbg(hsotg->dev, "In host mode, hprt0=%08x\n", hprt0); - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); } /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ usleep_range(50000, 70000); hprt0 &= ~HPRT0_RST; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); hsotg->lx_state = DWC2_L0; /* Now back to On state */ break; @@ -1781,7 +1821,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, "SetPortFeature - USB_PORT_FEAT_TEST\n"); hprt0 &= ~HPRT0_TSTCTL_MASK; hprt0 |= (windex >> 8) << HPRT0_TSTCTL_SHIFT; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); break; default: @@ -1838,7 +1878,7 @@ static int dwc2_hcd_is_status_changed(struct dwc2_hsotg *hsotg, int port) int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg) { - u32 hfnum = readl(hsotg->regs + HFNUM); + u32 hfnum = dwc2_readl(hsotg->regs + HFNUM); #ifdef DWC2_DEBUG_SOF dev_vdbg(hsotg->dev, "DWC OTG HCD GET FRAME NUMBER %d\n", @@ -1941,11 +1981,11 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg) if (chan->xfer_started) { u32 hfnum, hcchar, hctsiz, hcint, hcintmsk; - hfnum = readl(hsotg->regs + HFNUM); - hcchar = readl(hsotg->regs + HCCHAR(i)); - hctsiz = readl(hsotg->regs + HCTSIZ(i)); - hcint = readl(hsotg->regs + HCINT(i)); - hcintmsk = readl(hsotg->regs + HCINTMSK(i)); + hfnum = dwc2_readl(hsotg->regs + HFNUM); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(i)); + hcint = dwc2_readl(hsotg->regs + HCINT(i)); + hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(i)); dev_dbg(hsotg->dev, " hfnum: 0x%08x\n", hfnum); dev_dbg(hsotg->dev, " hcchar: 0x%08x\n", hcchar); dev_dbg(hsotg->dev, " hctsiz: 0x%08x\n", hctsiz); @@ -1993,12 +2033,12 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, " periodic_channels: %d\n", hsotg->periodic_channels); dev_dbg(hsotg->dev, " periodic_usecs: %d\n", hsotg->periodic_usecs); - np_tx_status = readl(hsotg->regs + GNPTXSTS); + np_tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); dev_dbg(hsotg->dev, " NP Tx Req Queue Space Avail: %d\n", (np_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT); dev_dbg(hsotg->dev, " NP Tx FIFO Space Avail: %d\n", (np_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT); - p_tx_status = readl(hsotg->regs + HPTXSTS); + p_tx_status = dwc2_readl(hsotg->regs + HPTXSTS); dev_dbg(hsotg->dev, " P Tx Req Queue Space Avail: %d\n", (p_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT); dev_dbg(hsotg->dev, " P Tx FIFO Space Avail: %d\n", @@ -2194,11 +2234,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, usb_pipein(urb->pipe) ? "IN" : "OUT", status, urb->actual_length); - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) { - for (i = 0; i < urb->number_of_packets; i++) - dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n", - i, urb->iso_frame_desc[i].status); - } if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); @@ -2211,6 +2246,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, } } + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) { + for (i = 0; i < urb->number_of_packets; i++) + dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n", + i, urb->iso_frame_desc[i].status); + } + urb->status = status; if (!status) { if ((urb->transfer_flags & URB_SHORT_NOT_OK) && @@ -2262,7 +2303,7 @@ static void dwc2_hcd_reset_func(struct work_struct *work) dev_dbg(hsotg->dev, "USB RESET function called\n"); hprt0 = dwc2_read_hprt0(hsotg); hprt0 &= ~HPRT0_RST; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_writel(hprt0, hsotg->regs + HPRT0); hsotg->flags.b.port_reset_change = 1; } @@ -2286,8 +2327,9 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); spin_lock_irqsave(&hsotg->lock, flags); - + hsotg->lx_state = DWC2_L0; hcd->state = HC_STATE_RUNNING; + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); if (dwc2_is_device_mode(hsotg)) { spin_unlock_irqrestore(&hsotg->lock, flags); @@ -2316,8 +2358,19 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); unsigned long flags; + /* Turn off all host-specific interrupts */ + dwc2_disable_host_interrupts(hsotg); + + /* Wait for interrupt processing to finish */ + synchronize_irq(hcd->irq); + spin_lock_irqsave(&hsotg->lock, flags); + /* Ensure hcd is disconnected */ + dwc2_hcd_disconnect(hsotg); dwc2_hcd_stop(hsotg); + hsotg->lx_state = DWC2_L3; + hcd->state = HC_STATE_HALT; + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irqrestore(&hsotg->lock, flags); usleep_range(1000, 3000); @@ -2326,17 +2379,125 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) static int _dwc2_hcd_suspend(struct usb_hcd *hcd) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + unsigned long flags; + int ret = 0; + u32 hprt0; + + spin_lock_irqsave(&hsotg->lock, flags); + + if (hsotg->lx_state != DWC2_L0) + goto unlock; + + if (!HCD_HW_ACCESSIBLE(hcd)) + goto unlock; + + if (!hsotg->core_params->hibernation) + goto skip_power_saving; + + /* + * Drive USB suspend and disable port Power + * if usb bus is not suspended. + */ + if (!hsotg->bus_suspended) { + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_SUSP; + hprt0 &= ~HPRT0_PWR; + dwc2_writel(hprt0, hsotg->regs + HPRT0); + } + /* Enter hibernation */ + ret = dwc2_enter_hibernation(hsotg); + if (ret) { + if (ret != -ENOTSUPP) + dev_err(hsotg->dev, + "enter hibernation failed\n"); + goto skip_power_saving; + } + + /* Ask phy to be suspended */ + if (!IS_ERR_OR_NULL(hsotg->uphy)) { + spin_unlock_irqrestore(&hsotg->lock, flags); + usb_phy_set_suspend(hsotg->uphy, true); + spin_lock_irqsave(&hsotg->lock, flags); + } + + /* After entering hibernation, hardware is no more accessible */ + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + +skip_power_saving: hsotg->lx_state = DWC2_L2; - return 0; +unlock: + spin_unlock_irqrestore(&hsotg->lock, flags); + + return ret; } static int _dwc2_hcd_resume(struct usb_hcd *hcd) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&hsotg->lock, flags); + + if (hsotg->lx_state != DWC2_L2) + goto unlock; + + if (!hsotg->core_params->hibernation) { + hsotg->lx_state = DWC2_L0; + goto unlock; + } + + /* + * Set HW accessible bit before powering on the controller + * since an interrupt may rise. + */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* + * Enable power if not already done. + * This must not be spinlocked since duration + * of this call is unknown. + */ + if (!IS_ERR_OR_NULL(hsotg->uphy)) { + spin_unlock_irqrestore(&hsotg->lock, flags); + usb_phy_set_suspend(hsotg->uphy, false); + spin_lock_irqsave(&hsotg->lock, flags); + } + + /* Exit hibernation */ + ret = dwc2_exit_hibernation(hsotg, true); + if (ret && (ret != -ENOTSUPP)) + dev_err(hsotg->dev, "exit hibernation failed\n"); hsotg->lx_state = DWC2_L0; - return 0; + + spin_unlock_irqrestore(&hsotg->lock, flags); + + if (hsotg->bus_suspended) { + spin_lock_irqsave(&hsotg->lock, flags); + hsotg->flags.b.port_suspend_change = 1; + spin_unlock_irqrestore(&hsotg->lock, flags); + dwc2_port_resume(hsotg); + } else { + /* Wait for controller to correctly update D+/D- level */ + usleep_range(3000, 5000); + + /* + * Clear Port Enable and Port Status changes. + * Enable Port Power. + */ + dwc2_writel(HPRT0_PWR | HPRT0_CONNDET | + HPRT0_ENACHG, hsotg->regs + HPRT0); + /* Wait for controller to detect Port Connect */ + usleep_range(5000, 7000); + } + + return ret; +unlock: + spin_unlock_irqrestore(&hsotg->lock, flags); + + return ret; } /* Returns the current frame number */ @@ -2790,17 +2951,17 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) hsotg->status_buf = NULL; } - ahbcfg = readl(hsotg->regs + GAHBCFG); + ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); /* Disable all interrupts */ ahbcfg &= ~GAHBCFG_GLBL_INTR_EN; - writel(ahbcfg, hsotg->regs + GAHBCFG); - writel(0, hsotg->regs + GINTMSK); + dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); + dwc2_writel(0, hsotg->regs + GINTMSK); if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) { - dctl = readl(hsotg->regs + DCTL); + dctl = dwc2_readl(hsotg->regs + DCTL); dctl |= DCTL_SFTDISCON; - writel(dctl, hsotg->regs + DCTL); + dwc2_writel(dctl, hsotg->regs + DCTL); } if (hsotg->wq_otg) { @@ -2841,7 +3002,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) retval = -ENOMEM; - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index fc1054965..f105bada2 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -371,10 +371,10 @@ static inline struct usb_hcd *dwc2_hsotg_to_hcd(struct dwc2_hsotg *hsotg) */ static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr) { - u32 mask = readl(hsotg->regs + HCINTMSK(chnum)); + u32 mask = dwc2_readl(hsotg->regs + HCINTMSK(chnum)); mask &= ~intr; - writel(mask, hsotg->regs + HCINTMSK(chnum)); + dwc2_writel(mask, hsotg->regs + HCINTMSK(chnum)); } /* @@ -382,11 +382,11 @@ static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr) */ static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg) { - return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0; + return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0; } static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) { - return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0; + return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0; } /* @@ -395,7 +395,7 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) */ static inline u32 dwc2_read_hprt0(struct dwc2_hsotg *hsotg) { - u32 hprt0 = readl(hsotg->regs + HPRT0); + u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0); hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG); return hprt0; @@ -580,7 +580,8 @@ static inline u16 dwc2_micro_frame_num(u16 frame) */ static inline u32 dwc2_read_core_intr(struct dwc2_hsotg *hsotg) { - return readl(hsotg->regs + GINTSTS) & readl(hsotg->regs + GINTMSK); + return dwc2_readl(hsotg->regs + GINTSTS) & + dwc2_readl(hsotg->regs + GINTMSK); } static inline u32 dwc2_hcd_urb_get_status(struct dwc2_hcd_urb *dwc2_urb) @@ -732,7 +733,7 @@ do { \ qtd_list_entry); \ if (usb_pipeint(_qtd_->urb->pipe) && \ (_qh_)->start_split_frame != 0 && !_qtd_->complete_split) { \ - _hfnum_.d32 = readl((_hcd_)->regs + HFNUM); \ + _hfnum_.d32 = dwc2_readl((_hcd_)->regs + HFNUM); \ switch (_hfnum_.b.frnum & 0x7) { \ case 7: \ (_hcd_)->hfnum_7_samples_##_letter_++; \ diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 3376177e4..78993aba9 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -169,19 +169,19 @@ static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en) spin_lock_irqsave(&hsotg->lock, flags); - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); if (hcfg & HCFG_PERSCHEDENA) { /* already enabled */ spin_unlock_irqrestore(&hsotg->lock, flags); return; } - writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR); + dwc2_writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR); hcfg &= ~HCFG_FRLISTEN_MASK; hcfg |= fr_list_en | HCFG_PERSCHEDENA; dev_vdbg(hsotg->dev, "Enabling Periodic schedule\n"); - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); spin_unlock_irqrestore(&hsotg->lock, flags); } @@ -193,7 +193,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg) spin_lock_irqsave(&hsotg->lock, flags); - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); if (!(hcfg & HCFG_PERSCHEDENA)) { /* already disabled */ spin_unlock_irqrestore(&hsotg->lock, flags); @@ -202,7 +202,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg) hcfg &= ~HCFG_PERSCHEDENA; dev_vdbg(hsotg->dev, "Disabling Periodic schedule\n"); - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); spin_unlock_irqrestore(&hsotg->lock, flags); } diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 4cc95df42..bda0b21b8 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -148,7 +148,7 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg) dwc2_hcd_queue_transactions(hsotg, tr_type); /* Clear interrupt */ - writel(GINTSTS_SOF, hsotg->regs + GINTSTS); + dwc2_writel(GINTSTS_SOF, hsotg->regs + GINTSTS); } /* @@ -164,7 +164,7 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) if (dbg_perio()) dev_vdbg(hsotg->dev, "--RxFIFO Level Interrupt--\n"); - grxsts = readl(hsotg->regs + GRXSTSP); + grxsts = dwc2_readl(hsotg->regs + GRXSTSP); chnum = (grxsts & GRXSTS_HCHNUM_MASK) >> GRXSTS_HCHNUM_SHIFT; chan = hsotg->hc_ptr_array[chnum]; if (!chan) { @@ -247,11 +247,11 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, dev_vdbg(hsotg->dev, "%s(%p)\n", __func__, hsotg); /* Every time when port enables calculate HFIR.FrInterval */ - hfir = readl(hsotg->regs + HFIR); + hfir = dwc2_readl(hsotg->regs + HFIR); hfir &= ~HFIR_FRINT_MASK; hfir |= dwc2_calc_frame_interval(hsotg) << HFIR_FRINT_SHIFT & HFIR_FRINT_MASK; - writel(hfir, hsotg->regs + HFIR); + dwc2_writel(hfir, hsotg->regs + HFIR); /* Check if we need to adjust the PHY clock speed for low power */ if (!params->host_support_fs_ls_low_power) { @@ -260,7 +260,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, return; } - usbcfg = readl(hsotg->regs + GUSBCFG); + usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (prtspd == HPRT0_SPD_LOW_SPEED || prtspd == HPRT0_SPD_FULL_SPEED) { @@ -268,11 +268,11 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL)) { /* Set PHY low power clock select for FS/LS devices */ usbcfg |= GUSBCFG_PHY_LP_CLK_SEL; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); do_reset = 1; } - hcfg = readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg->regs + HCFG); fslspclksel = (hcfg & HCFG_FSLSPCLKSEL_MASK) >> HCFG_FSLSPCLKSEL_SHIFT; @@ -286,7 +286,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, fslspclksel = HCFG_FSLSPCLKSEL_6_MHZ; hcfg &= ~HCFG_FSLSPCLKSEL_MASK; hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT; - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); do_reset = 1; } } else { @@ -297,7 +297,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, fslspclksel = HCFG_FSLSPCLKSEL_48_MHZ; hcfg &= ~HCFG_FSLSPCLKSEL_MASK; hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT; - writel(hcfg, hsotg->regs + HCFG); + dwc2_writel(hcfg, hsotg->regs + HCFG); do_reset = 1; } } @@ -305,7 +305,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, /* Not low power */ if (usbcfg & GUSBCFG_PHY_LP_CLK_SEL) { usbcfg &= ~GUSBCFG_PHY_LP_CLK_SEL; - writel(usbcfg, hsotg->regs + GUSBCFG); + dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); do_reset = 1; } } @@ -332,7 +332,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "--Port Interrupt--\n"); - hprt0 = readl(hsotg->regs + HPRT0); + hprt0 = dwc2_readl(hsotg->regs + HPRT0); hprt0_modify = hprt0; /* @@ -388,7 +388,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) } /* Clear Port Interrupts */ - writel(hprt0_modify, hsotg->regs + HPRT0); + dwc2_writel(hprt0_modify, hsotg->regs + HPRT0); } /* @@ -408,7 +408,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, { u32 hctsiz, count, length; - hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); if (halt_status == DWC2_HC_XFER_COMPLETE) { if (chan->ep_is_in) { @@ -491,7 +491,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, urb->status = 0; } - hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n", __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum); dev_vdbg(hsotg->dev, " chan->xfer_len %d\n", chan->xfer_len); @@ -514,7 +514,7 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { - u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); + u32 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT; if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) { @@ -771,9 +771,9 @@ cleanup: } } - haintmsk = readl(hsotg->regs + HAINTMSK); + haintmsk = dwc2_readl(hsotg->regs + HAINTMSK); haintmsk &= ~(1 << chan->hc_num); - writel(haintmsk, hsotg->regs + HAINTMSK); + dwc2_writel(haintmsk, hsotg->regs + HAINTMSK); /* Try to queue more transfers now that there's a free channel */ tr_type = dwc2_hcd_select_transactions(hsotg); @@ -820,9 +820,9 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg, * is enabled so that the non-periodic schedule will * be processed */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk |= GINTSTS_NPTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } else { dev_vdbg(hsotg->dev, "isoc/intr\n"); /* @@ -839,9 +839,9 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg, * enabled so that the periodic schedule will be * processed */ - gintmsk = readl(hsotg->regs + GINTMSK); + gintmsk = dwc2_readl(hsotg->regs + GINTMSK); gintmsk |= GINTSTS_PTXFEMP; - writel(gintmsk, hsotg->regs + GINTMSK); + dwc2_writel(gintmsk, hsotg->regs + GINTMSK); } } } @@ -906,7 +906,7 @@ static void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { - u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); + u32 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); qtd->error_count = 0; @@ -1184,7 +1184,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, urb->actual_length += xfer_length; - hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n", __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum); dev_vdbg(hsotg->dev, " chan->start_pkt_count %d\n", @@ -1505,10 +1505,10 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, dwc2_hc_handle_tt_clear(hsotg, chan, qtd); - hcchar = readl(hsotg->regs + HCCHAR(chnum)); - hcsplt = readl(hsotg->regs + HCSPLT(chnum)); - hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); - hc_dma = readl(hsotg->regs + HCDMA(chnum)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum)); + hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chnum)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); + hc_dma = dwc2_readl(hsotg->regs + HCDMA(chnum)); dev_err(hsotg->dev, "AHB ERROR, Channel %d\n", chnum); dev_err(hsotg->dev, " hcchar 0x%08x, hcsplt 0x%08x\n", hcchar, hcsplt); @@ -1721,10 +1721,10 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg, * This code is here only as a check. This condition should * never happen. Ignore the halt if it does occur. */ - hcchar = readl(hsotg->regs + HCCHAR(chnum)); - hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); - hcintmsk = readl(hsotg->regs + HCINTMSK(chnum)); - hcsplt = readl(hsotg->regs + HCSPLT(chnum)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum)); + hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); + hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum)); + hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chnum)); dev_dbg(hsotg->dev, "%s: chan->halt_status DWC2_HC_XFER_NO_HALT_STATUS,\n", __func__); @@ -1748,7 +1748,7 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg, * when the halt interrupt occurs. Halt the channel again if it does * occur. */ - hcchar = readl(hsotg->regs + HCCHAR(chnum)); + hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum)); if (hcchar & HCCHAR_CHDIS) { dev_warn(hsotg->dev, "%s: hcchar.chdis set unexpectedly, hcchar 0x%08x, trying to halt again\n", @@ -1808,7 +1808,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, return; } - hcintmsk = readl(hsotg->regs + HCINTMSK(chnum)); + hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum)); if (chan->hcint & HCINTMSK_XFERCOMPL) { /* @@ -1903,7 +1903,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, dev_err(hsotg->dev, "hcint 0x%08x, intsts 0x%08x\n", chan->hcint, - readl(hsotg->regs + GINTSTS)); + dwc2_readl(hsotg->regs + GINTSTS)); goto error; } } @@ -1949,6 +1949,24 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg, } } +/* + * Check if the given qtd is still the top of the list (and thus valid). + * + * If dwc2_hcd_qtd_unlink_and_free() has been called since we grabbed + * the qtd from the top of the list, this will return false (otherwise true). + */ +static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh) +{ + struct dwc2_qtd *cur_head; + + if (qh == NULL) + return false; + + cur_head = list_first_entry(&qh->qtd_list, struct dwc2_qtd, + qtd_list_entry); + return (cur_head == qtd); +} + /* Handles interrupt for a specific Host Channel */ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) { @@ -1958,11 +1976,11 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) chan = hsotg->hc_ptr_array[chnum]; - hcint = readl(hsotg->regs + HCINT(chnum)); - hcintmsk = readl(hsotg->regs + HCINTMSK(chnum)); + hcint = dwc2_readl(hsotg->regs + HCINT(chnum)); + hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum)); if (!chan) { dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n"); - writel(hcint, hsotg->regs + HCINT(chnum)); + dwc2_writel(hcint, hsotg->regs + HCINT(chnum)); return; } @@ -1974,7 +1992,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) hcint, hcintmsk, hcint & hcintmsk); } - writel(hcint, hsotg->regs + HCINT(chnum)); + dwc2_writel(hcint, hsotg->regs + HCINT(chnum)); chan->hcint = hcint; hcint &= hcintmsk; @@ -2031,27 +2049,59 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) */ hcint &= ~HCINTMSK_NYET; } - if (hcint & HCINTMSK_CHHLTD) + + if (hcint & HCINTMSK_CHHLTD) { dwc2_hc_chhltd_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_AHBERR) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_AHBERR) { dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_STALL) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_STALL) { dwc2_hc_stall_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_NAK) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_NAK) { dwc2_hc_nak_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_ACK) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_ACK) { dwc2_hc_ack_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_NYET) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_NYET) { dwc2_hc_nyet_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_XACTERR) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_XACTERR) { dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_BBLERR) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_BBLERR) { dwc2_hc_babble_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_FRMOVRUN) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_FRMOVRUN) { dwc2_hc_frmovrun_intr(hsotg, chan, chnum, qtd); - if (hcint & HCINTMSK_DATATGLERR) + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } + if (hcint & HCINTMSK_DATATGLERR) { dwc2_hc_datatglerr_intr(hsotg, chan, chnum, qtd); + if (!dwc2_check_qtd_still_ok(qtd, chan->qh)) + goto exit; + } +exit: chan->hcint = 0; } @@ -2066,7 +2116,7 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg) u32 haint; int i; - haint = readl(hsotg->regs + HAINT); + haint = dwc2_readl(hsotg->regs + HAINT); if (dbg_perio()) { dev_vdbg(hsotg->dev, "%s()\n", __func__); @@ -2134,8 +2184,8 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg) "DWC OTG HCD Finished Servicing Interrupts\n"); dev_vdbg(hsotg->dev, "DWC OTG HCD gintsts=0x%08x gintmsk=0x%08x\n", - readl(hsotg->regs + GINTSTS), - readl(hsotg->regs + GINTMSK)); + dwc2_readl(hsotg->regs + GINTSTS), + dwc2_readl(hsotg->regs + GINTMSK)); } } diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 3ad63d392..7d8d06cfe 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -106,6 +106,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, USB_SPEED_HIGH : dev_speed, qh->ep_is_in, qh->ep_type == USB_ENDPOINT_XFER_ISOC, bytecount)); + + /* Ensure frame_number corresponds to the reality */ + hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); /* Start in a slightly future (micro)frame */ qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number, SCHEDULE_SLOP); @@ -115,7 +118,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, if (qh->ep_type == USB_ENDPOINT_XFER_INT) qh->interval = 8; #endif - hprt = readl(hsotg->regs + HPRT0); + hprt = dwc2_readl(hsotg->regs + HPRT0); prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (prtspd == HPRT0_SPD_HIGH_SPEED && (dev_speed == USB_SPEED_LOW || @@ -583,6 +586,14 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) /* QH already in a schedule */ return 0; + if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) && + !hsotg->frame_number) { + dev_dbg(hsotg->dev, + "reset frame number counter\n"); + qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number, + SCHEDULE_SLOP); + } + /* Add the new QH to the appropriate schedule */ if (dwc2_qh_is_non_per(qh)) { /* Always start in inactive schedule */ @@ -595,9 +606,9 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) if (status) return status; if (!hsotg->periodic_qh_count) { - intr_mask = readl(hsotg->regs + GINTMSK); + intr_mask = dwc2_readl(hsotg->regs + GINTMSK); intr_mask |= GINTSTS_SOF; - writel(intr_mask, hsotg->regs + GINTMSK); + dwc2_writel(intr_mask, hsotg->regs + GINTMSK); } hsotg->periodic_qh_count++; @@ -632,9 +643,9 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) dwc2_deschedule_periodic(hsotg, qh); hsotg->periodic_qh_count--; if (!hsotg->periodic_qh_count) { - intr_mask = readl(hsotg->regs + GINTMSK); + intr_mask = dwc2_readl(hsotg->regs + GINTMSK); intr_mask &= ~GINTSTS_SOF; - writel(intr_mask, hsotg->regs + GINTMSK); + dwc2_writel(intr_mask, hsotg->regs + GINTMSK); } } diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index d0a5ed8fa..553f24606 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h @@ -142,6 +142,7 @@ #define GINTSTS_RESETDET (1 << 23) #define GINTSTS_FET_SUSP (1 << 22) #define GINTSTS_INCOMPL_IP (1 << 21) +#define GINTSTS_INCOMPL_SOOUT (1 << 21) #define GINTSTS_INCOMPL_SOIN (1 << 20) #define GINTSTS_OEPINT (1 << 19) #define GINTSTS_IEPINT (1 << 18) diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 909353041..39c1cbf0e 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -37,11 +37,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include @@ -105,12 +108,177 @@ static const struct dwc2_core_params params_rk3066 = { .host_ls_low_power_phy_clk = -1, .ts_dline = -1, .reload_ctl = -1, - .ahbcfg = 0x7, /* INCR16 */ + .ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT, .uframe_sched = -1, .external_id_pin_ctl = -1, .hibernation = -1, }; +static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) +{ + struct platform_device *pdev = to_platform_device(hsotg->dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) + return ret; + + if (hsotg->clk) { + ret = clk_prepare_enable(hsotg->clk); + if (ret) + return ret; + } + + if (hsotg->uphy) + ret = usb_phy_init(hsotg->uphy); + else if (hsotg->plat && hsotg->plat->phy_init) + ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); + else { + ret = phy_power_on(hsotg->phy); + if (ret == 0) + ret = phy_init(hsotg->phy); + } + + return ret; +} + +/** + * dwc2_lowlevel_hw_enable - enable platform lowlevel hw resources + * @hsotg: The driver state + * + * A wrapper for platform code responsible for controlling + * low-level USB platform resources (phy, clock, regulators) + */ +int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) +{ + int ret = __dwc2_lowlevel_hw_enable(hsotg); + + if (ret == 0) + hsotg->ll_hw_enabled = true; + return ret; +} + +static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) +{ + struct platform_device *pdev = to_platform_device(hsotg->dev); + int ret = 0; + + if (hsotg->uphy) + usb_phy_shutdown(hsotg->uphy); + else if (hsotg->plat && hsotg->plat->phy_exit) + ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); + else { + ret = phy_exit(hsotg->phy); + if (ret == 0) + ret = phy_power_off(hsotg->phy); + } + if (ret) + return ret; + + if (hsotg->clk) + clk_disable_unprepare(hsotg->clk); + + ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + + return ret; +} + +/** + * dwc2_lowlevel_hw_disable - disable platform lowlevel hw resources + * @hsotg: The driver state + * + * A wrapper for platform code responsible for controlling + * low-level USB platform resources (phy, clock, regulators) + */ +int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) +{ + int ret = __dwc2_lowlevel_hw_disable(hsotg); + + if (ret == 0) + hsotg->ll_hw_enabled = false; + return ret; +} + +static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) +{ + int i, ret; + + /* Set default UTMI width */ + hsotg->phyif = GUSBCFG_PHYIF16; + + /* + * Attempt to find a generic PHY, then look for an old style + * USB PHY and then fall back to pdata + */ + hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy"); + if (IS_ERR(hsotg->phy)) { + ret = PTR_ERR(hsotg->phy); + switch (ret) { + case -ENODEV: + case -ENOSYS: + hsotg->phy = NULL; + break; + case -EPROBE_DEFER: + return ret; + default: + dev_err(hsotg->dev, "error getting phy %d\n", ret); + return ret; + } + } + + if (!hsotg->phy) { + hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2); + if (IS_ERR(hsotg->uphy)) { + ret = PTR_ERR(hsotg->uphy); + switch (ret) { + case -ENODEV: + case -ENXIO: + hsotg->uphy = NULL; + break; + case -EPROBE_DEFER: + return ret; + default: + dev_err(hsotg->dev, "error getting usb phy %d\n", + ret); + return ret; + } + } + } + + hsotg->plat = dev_get_platdata(hsotg->dev); + + if (hsotg->phy) { + /* + * If using the generic PHY framework, check if the PHY bus + * width is 8-bit and set the phyif appropriately. + */ + if (phy_get_bus_width(hsotg->phy) == 8) + hsotg->phyif = GUSBCFG_PHYIF8; + } + + /* Clock */ + hsotg->clk = devm_clk_get(hsotg->dev, "otg"); + if (IS_ERR(hsotg->clk)) { + hsotg->clk = NULL; + dev_dbg(hsotg->dev, "cannot get otg clock\n"); + } + + /* Regulators */ + for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) + hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i]; + + ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) { + dev_err(hsotg->dev, "failed to request supplies: %d\n", ret); + return ret; + } + return 0; +} + /** * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the * DWC_otg driver @@ -130,7 +298,10 @@ static int dwc2_driver_remove(struct platform_device *dev) if (hsotg->hcd_enabled) dwc2_hcd_remove(hsotg); if (hsotg->gadget_enabled) - s3c_hsotg_remove(hsotg); + dwc2_hsotg_remove(hsotg); + + if (hsotg->ll_hw_enabled) + dwc2_lowlevel_hw_disable(hsotg); return 0; } @@ -163,8 +334,6 @@ static int dwc2_driver_probe(struct platform_device *dev) struct dwc2_core_params defparams; struct dwc2_hsotg *hsotg; struct resource *res; - struct phy *phy; - struct usb_phy *uphy; int retval; int irq; @@ -198,20 +367,6 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) return retval; - irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "missing IRQ resource\n"); - return irq; - } - - dev_dbg(hsotg->dev, "registering common handler for irq%d\n", - irq); - retval = devm_request_irq(hsotg->dev, irq, - dwc2_handle_common_intr, IRQF_SHARED, - dev_name(hsotg->dev), hsotg); - if (retval) - return retval; - res = platform_get_resource(dev, IORESOURCE_MEM, 0); hsotg->regs = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(hsotg->regs)) @@ -220,34 +375,25 @@ static int dwc2_driver_probe(struct platform_device *dev) dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); - hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node); - - /* - * Attempt to find a generic PHY, then look for an old style - * USB PHY - */ - phy = devm_phy_get(&dev->dev, "usb2-phy"); - if (IS_ERR(phy)) { - hsotg->phy = NULL; - uphy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR(uphy)) - hsotg->uphy = NULL; - else - hsotg->uphy = uphy; - } else { - hsotg->phy = phy; - phy_power_on(hsotg->phy); - phy_init(hsotg->phy); + hsotg->dr_mode = usb_get_dr_mode(&dev->dev); + if (IS_ENABLED(CONFIG_USB_DWC2_HOST) && + hsotg->dr_mode != USB_DR_MODE_HOST) { + hsotg->dr_mode = USB_DR_MODE_HOST; + dev_warn(hsotg->dev, + "Configuration mismatch. Forcing host mode\n"); + } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) && + hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { + hsotg->dr_mode = USB_DR_MODE_PERIPHERAL; + dev_warn(hsotg->dev, + "Configuration mismatch. Forcing peripheral mode\n"); } - spin_lock_init(&hsotg->lock); - mutex_init(&hsotg->init_mutex); - - /* Detect config values from hardware */ - retval = dwc2_get_hwparams(hsotg); + retval = dwc2_lowlevel_hw_init(hsotg); if (retval) return retval; + spin_lock_init(&hsotg->lock); + hsotg->core_params = devm_kzalloc(&dev->dev, sizeof(*hsotg->core_params), GFP_KERNEL); if (!hsotg->core_params) @@ -255,13 +401,36 @@ static int dwc2_driver_probe(struct platform_device *dev) dwc2_set_all_params(hsotg->core_params, -1); + irq = platform_get_irq(dev, 0); + if (irq < 0) { + dev_err(&dev->dev, "missing IRQ resource\n"); + return irq; + } + + dev_dbg(hsotg->dev, "registering common handler for irq%d\n", + irq); + retval = devm_request_irq(hsotg->dev, irq, + dwc2_handle_common_intr, IRQF_SHARED, + dev_name(hsotg->dev), hsotg); + if (retval) + return retval; + + retval = dwc2_lowlevel_hw_enable(hsotg); + if (retval) + return retval; + + /* Detect config values from hardware */ + retval = dwc2_get_hwparams(hsotg); + if (retval) + goto error; + /* Validate parameter values */ dwc2_set_parameters(hsotg, params); if (hsotg->dr_mode != USB_DR_MODE_HOST) { retval = dwc2_gadget_init(hsotg, irq); if (retval) - return retval; + goto error; hsotg->gadget_enabled = 1; } @@ -269,8 +438,8 @@ static int dwc2_driver_probe(struct platform_device *dev) retval = dwc2_hcd_init(hsotg, irq); if (retval) { if (hsotg->gadget_enabled) - s3c_hsotg_remove(hsotg); - return retval; + dwc2_hsotg_remove(hsotg); + goto error; } hsotg->hcd_enabled = 1; } @@ -279,6 +448,14 @@ static int dwc2_driver_probe(struct platform_device *dev) dwc2_debugfs_init(hsotg); + /* Gadget code manages lowlevel hw on its own */ + if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) + dwc2_lowlevel_hw_disable(hsotg); + + return 0; + +error: + dwc2_lowlevel_hw_disable(hsotg); return retval; } @@ -287,15 +464,12 @@ static int __maybe_unused dwc2_suspend(struct device *dev) struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); int ret = 0; - if (dwc2_is_device_mode(dwc2)) { - ret = s3c_hsotg_suspend(dwc2); - } else { - if (dwc2->lx_state == DWC2_L0) - return 0; - phy_exit(dwc2->phy); - phy_power_off(dwc2->phy); + if (dwc2_is_device_mode(dwc2)) + dwc2_hsotg_suspend(dwc2); + + if (dwc2->ll_hw_enabled) + ret = __dwc2_lowlevel_hw_disable(dwc2); - } return ret; } @@ -304,13 +478,15 @@ static int __maybe_unused dwc2_resume(struct device *dev) struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); int ret = 0; - if (dwc2_is_device_mode(dwc2)) { - ret = s3c_hsotg_resume(dwc2); - } else { - phy_power_on(dwc2->phy); - phy_init(dwc2->phy); - + if (dwc2->ll_hw_enabled) { + ret = __dwc2_lowlevel_hw_enable(dwc2); + if (ret) + return ret; } + + if (dwc2_is_device_mode(dwc2)) + ret = dwc2_hsotg_resume(dwc2); + return ret; } -- cgit v1.2.3-54-g00ecf