| .. | .. |
|---|
| 97 | 97 | dwc2_writel(hsotg, intmsk, GINTMSK); |
|---|
| 98 | 98 | } |
|---|
| 99 | 99 | |
|---|
| 100 | | -/* |
|---|
| 101 | | - * Initializes the FSLSPClkSel field of the HCFG register depending on the |
|---|
| 102 | | - * PHY type |
|---|
| 103 | | - */ |
|---|
| 104 | | -static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) |
|---|
| 105 | | -{ |
|---|
| 106 | | - u32 hcfg, val; |
|---|
| 107 | | - |
|---|
| 108 | | - if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && |
|---|
| 109 | | - hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && |
|---|
| 110 | | - hsotg->params.ulpi_fs_ls) || |
|---|
| 111 | | - hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) { |
|---|
| 112 | | - /* Full speed PHY */ |
|---|
| 113 | | - val = HCFG_FSLSPCLKSEL_48_MHZ; |
|---|
| 114 | | - } else { |
|---|
| 115 | | - /* High speed PHY running at full speed or high speed */ |
|---|
| 116 | | - val = HCFG_FSLSPCLKSEL_30_60_MHZ; |
|---|
| 117 | | - } |
|---|
| 118 | | - |
|---|
| 119 | | - dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val); |
|---|
| 120 | | - hcfg = dwc2_readl(hsotg, HCFG); |
|---|
| 121 | | - hcfg &= ~HCFG_FSLSPCLKSEL_MASK; |
|---|
| 122 | | - hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT; |
|---|
| 123 | | - dwc2_writel(hsotg, hcfg, HCFG); |
|---|
| 124 | | -} |
|---|
| 125 | | - |
|---|
| 126 | | -static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) |
|---|
| 127 | | -{ |
|---|
| 128 | | - u32 usbcfg, ggpio, i2cctl; |
|---|
| 129 | | - int retval = 0; |
|---|
| 130 | | - |
|---|
| 131 | | - /* |
|---|
| 132 | | - * core_init() is now called on every switch so only call the |
|---|
| 133 | | - * following for the first time through |
|---|
| 134 | | - */ |
|---|
| 135 | | - if (select_phy) { |
|---|
| 136 | | - dev_dbg(hsotg->dev, "FS PHY selected\n"); |
|---|
| 137 | | - |
|---|
| 138 | | - usbcfg = dwc2_readl(hsotg, GUSBCFG); |
|---|
| 139 | | - if (!(usbcfg & GUSBCFG_PHYSEL)) { |
|---|
| 140 | | - usbcfg |= GUSBCFG_PHYSEL; |
|---|
| 141 | | - dwc2_writel(hsotg, usbcfg, GUSBCFG); |
|---|
| 142 | | - |
|---|
| 143 | | - /* Reset after a PHY select */ |
|---|
| 144 | | - retval = dwc2_core_reset(hsotg, false); |
|---|
| 145 | | - |
|---|
| 146 | | - if (retval) { |
|---|
| 147 | | - dev_err(hsotg->dev, |
|---|
| 148 | | - "%s: Reset failed, aborting", __func__); |
|---|
| 149 | | - return retval; |
|---|
| 150 | | - } |
|---|
| 151 | | - } |
|---|
| 152 | | - |
|---|
| 153 | | - if (hsotg->params.activate_stm_fs_transceiver) { |
|---|
| 154 | | - ggpio = dwc2_readl(hsotg, GGPIO); |
|---|
| 155 | | - if (!(ggpio & GGPIO_STM32_OTG_GCCFG_PWRDWN)) { |
|---|
| 156 | | - dev_dbg(hsotg->dev, "Activating transceiver\n"); |
|---|
| 157 | | - /* |
|---|
| 158 | | - * STM32F4x9 uses the GGPIO register as general |
|---|
| 159 | | - * core configuration register. |
|---|
| 160 | | - */ |
|---|
| 161 | | - ggpio |= GGPIO_STM32_OTG_GCCFG_PWRDWN; |
|---|
| 162 | | - dwc2_writel(hsotg, ggpio, GGPIO); |
|---|
| 163 | | - } |
|---|
| 164 | | - } |
|---|
| 165 | | - } |
|---|
| 166 | | - |
|---|
| 167 | | - /* |
|---|
| 168 | | - * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also |
|---|
| 169 | | - * do this on HNP Dev/Host mode switches (done in dev_init and |
|---|
| 170 | | - * host_init). |
|---|
| 171 | | - */ |
|---|
| 172 | | - if (dwc2_is_host_mode(hsotg)) |
|---|
| 173 | | - dwc2_init_fs_ls_pclk_sel(hsotg); |
|---|
| 174 | | - |
|---|
| 175 | | - if (hsotg->params.i2c_enable) { |
|---|
| 176 | | - dev_dbg(hsotg->dev, "FS PHY enabling I2C\n"); |
|---|
| 177 | | - |
|---|
| 178 | | - /* Program GUSBCFG.OtgUtmiFsSel to I2C */ |
|---|
| 179 | | - usbcfg = dwc2_readl(hsotg, GUSBCFG); |
|---|
| 180 | | - usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL; |
|---|
| 181 | | - dwc2_writel(hsotg, usbcfg, GUSBCFG); |
|---|
| 182 | | - |
|---|
| 183 | | - /* Program GI2CCTL.I2CEn */ |
|---|
| 184 | | - i2cctl = dwc2_readl(hsotg, GI2CCTL); |
|---|
| 185 | | - i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK; |
|---|
| 186 | | - i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT; |
|---|
| 187 | | - i2cctl &= ~GI2CCTL_I2CEN; |
|---|
| 188 | | - dwc2_writel(hsotg, i2cctl, GI2CCTL); |
|---|
| 189 | | - i2cctl |= GI2CCTL_I2CEN; |
|---|
| 190 | | - dwc2_writel(hsotg, i2cctl, GI2CCTL); |
|---|
| 191 | | - } |
|---|
| 192 | | - |
|---|
| 193 | | - return retval; |
|---|
| 194 | | -} |
|---|
| 195 | | - |
|---|
| 196 | | -static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) |
|---|
| 197 | | -{ |
|---|
| 198 | | - u32 usbcfg, usbcfg_old; |
|---|
| 199 | | - int retval = 0; |
|---|
| 200 | | - |
|---|
| 201 | | - if (!select_phy) |
|---|
| 202 | | - return 0; |
|---|
| 203 | | - |
|---|
| 204 | | - usbcfg = dwc2_readl(hsotg, GUSBCFG); |
|---|
| 205 | | - usbcfg_old = usbcfg; |
|---|
| 206 | | - |
|---|
| 207 | | - /* |
|---|
| 208 | | - * HS PHY parameters. These parameters are preserved during soft reset |
|---|
| 209 | | - * so only program the first time. Do a soft reset immediately after |
|---|
| 210 | | - * setting phyif. |
|---|
| 211 | | - */ |
|---|
| 212 | | - switch (hsotg->params.phy_type) { |
|---|
| 213 | | - case DWC2_PHY_TYPE_PARAM_ULPI: |
|---|
| 214 | | - /* ULPI interface */ |
|---|
| 215 | | - dev_dbg(hsotg->dev, "HS ULPI PHY selected\n"); |
|---|
| 216 | | - usbcfg |= GUSBCFG_ULPI_UTMI_SEL; |
|---|
| 217 | | - usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL); |
|---|
| 218 | | - if (hsotg->params.phy_ulpi_ddr) |
|---|
| 219 | | - usbcfg |= GUSBCFG_DDRSEL; |
|---|
| 220 | | - |
|---|
| 221 | | - /* Set external VBUS indicator as needed. */ |
|---|
| 222 | | - if (hsotg->params.oc_disable) |
|---|
| 223 | | - usbcfg |= (GUSBCFG_ULPI_INT_VBUS_IND | |
|---|
| 224 | | - GUSBCFG_INDICATORPASSTHROUGH); |
|---|
| 225 | | - break; |
|---|
| 226 | | - case DWC2_PHY_TYPE_PARAM_UTMI: |
|---|
| 227 | | - /* UTMI+ interface */ |
|---|
| 228 | | - dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n"); |
|---|
| 229 | | - usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); |
|---|
| 230 | | - if (hsotg->params.phy_utmi_width == 16) |
|---|
| 231 | | - usbcfg |= GUSBCFG_PHYIF16; |
|---|
| 232 | | - break; |
|---|
| 233 | | - default: |
|---|
| 234 | | - dev_err(hsotg->dev, "FS PHY selected at HS!\n"); |
|---|
| 235 | | - break; |
|---|
| 236 | | - } |
|---|
| 237 | | - |
|---|
| 238 | | - if (usbcfg != usbcfg_old) { |
|---|
| 239 | | - dwc2_writel(hsotg, usbcfg, GUSBCFG); |
|---|
| 240 | | - |
|---|
| 241 | | - /* Reset after setting the PHY parameters */ |
|---|
| 242 | | - retval = dwc2_core_reset(hsotg, false); |
|---|
| 243 | | - if (retval) { |
|---|
| 244 | | - dev_err(hsotg->dev, |
|---|
| 245 | | - "%s: Reset failed, aborting", __func__); |
|---|
| 246 | | - return retval; |
|---|
| 247 | | - } |
|---|
| 248 | | - } |
|---|
| 249 | | - |
|---|
| 250 | | - return retval; |
|---|
| 251 | | -} |
|---|
| 252 | | - |
|---|
| 253 | | -static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) |
|---|
| 254 | | -{ |
|---|
| 255 | | - u32 usbcfg; |
|---|
| 256 | | - int retval = 0; |
|---|
| 257 | | - |
|---|
| 258 | | - if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL || |
|---|
| 259 | | - hsotg->params.speed == DWC2_SPEED_PARAM_LOW) && |
|---|
| 260 | | - hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) { |
|---|
| 261 | | - /* If FS/LS mode with FS/LS PHY */ |
|---|
| 262 | | - retval = dwc2_fs_phy_init(hsotg, select_phy); |
|---|
| 263 | | - if (retval) |
|---|
| 264 | | - return retval; |
|---|
| 265 | | - } else { |
|---|
| 266 | | - /* High speed PHY */ |
|---|
| 267 | | - retval = dwc2_hs_phy_init(hsotg, select_phy); |
|---|
| 268 | | - if (retval) |
|---|
| 269 | | - return retval; |
|---|
| 270 | | - } |
|---|
| 271 | | - |
|---|
| 272 | | - if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && |
|---|
| 273 | | - hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && |
|---|
| 274 | | - hsotg->params.ulpi_fs_ls) { |
|---|
| 275 | | - dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); |
|---|
| 276 | | - usbcfg = dwc2_readl(hsotg, GUSBCFG); |
|---|
| 277 | | - usbcfg |= GUSBCFG_ULPI_FS_LS; |
|---|
| 278 | | - usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M; |
|---|
| 279 | | - dwc2_writel(hsotg, usbcfg, GUSBCFG); |
|---|
| 280 | | - } else { |
|---|
| 281 | | - usbcfg = dwc2_readl(hsotg, GUSBCFG); |
|---|
| 282 | | - usbcfg &= ~GUSBCFG_ULPI_FS_LS; |
|---|
| 283 | | - usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M; |
|---|
| 284 | | - dwc2_writel(hsotg, usbcfg, GUSBCFG); |
|---|
| 285 | | - } |
|---|
| 286 | | - |
|---|
| 287 | | - return retval; |
|---|
| 288 | | -} |
|---|
| 289 | | - |
|---|
| 290 | 100 | static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) |
|---|
| 291 | 101 | { |
|---|
| 292 | 102 | u32 ahbcfg = dwc2_readl(hsotg, GAHBCFG); |
|---|
| .. | .. |
|---|
| 358 | 168 | |
|---|
| 359 | 169 | static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) |
|---|
| 360 | 170 | { |
|---|
| 361 | | - int ret; |
|---|
| 171 | + if (hsotg->vbus_supply) |
|---|
| 172 | + return regulator_enable(hsotg->vbus_supply); |
|---|
| 362 | 173 | |
|---|
| 363 | | - hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); |
|---|
| 364 | | - if (IS_ERR(hsotg->vbus_supply)) { |
|---|
| 365 | | - ret = PTR_ERR(hsotg->vbus_supply); |
|---|
| 366 | | - hsotg->vbus_supply = NULL; |
|---|
| 367 | | - return ret == -ENODEV ? 0 : ret; |
|---|
| 368 | | - } |
|---|
| 369 | | - |
|---|
| 370 | | - return regulator_enable(hsotg->vbus_supply); |
|---|
| 174 | + return 0; |
|---|
| 371 | 175 | } |
|---|
| 372 | 176 | |
|---|
| 373 | 177 | static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg) |
|---|
| .. | .. |
|---|
| 1330 | 1134 | u32 remaining_count; |
|---|
| 1331 | 1135 | u32 byte_count; |
|---|
| 1332 | 1136 | u32 dword_count; |
|---|
| 1333 | | - u32 __iomem *data_fifo; |
|---|
| 1334 | 1137 | u32 *data_buf = (u32 *)chan->xfer_buf; |
|---|
| 1335 | 1138 | |
|---|
| 1336 | 1139 | if (dbg_hc(chan)) |
|---|
| 1337 | 1140 | dev_vdbg(hsotg->dev, "%s()\n", __func__); |
|---|
| 1338 | | - |
|---|
| 1339 | | - data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num)); |
|---|
| 1340 | 1141 | |
|---|
| 1341 | 1142 | remaining_count = chan->xfer_len - chan->xfer_count; |
|---|
| 1342 | 1143 | if (remaining_count > chan->max_packet) |
|---|
| .. | .. |
|---|
| 2451 | 2252 | num_channels = hsotg->params.host_channels; |
|---|
| 2452 | 2253 | for (i = 0; i < num_channels; i++) { |
|---|
| 2453 | 2254 | hcchar = dwc2_readl(hsotg, HCCHAR(i)); |
|---|
| 2454 | | - hcchar &= ~HCCHAR_CHENA; |
|---|
| 2455 | | - hcchar |= HCCHAR_CHDIS; |
|---|
| 2456 | | - hcchar &= ~HCCHAR_EPDIR; |
|---|
| 2457 | | - dwc2_writel(hsotg, hcchar, HCCHAR(i)); |
|---|
| 2255 | + if (hcchar & HCCHAR_CHENA) { |
|---|
| 2256 | + hcchar &= ~HCCHAR_CHENA; |
|---|
| 2257 | + hcchar |= HCCHAR_CHDIS; |
|---|
| 2258 | + hcchar &= ~HCCHAR_EPDIR; |
|---|
| 2259 | + dwc2_writel(hsotg, hcchar, HCCHAR(i)); |
|---|
| 2260 | + } |
|---|
| 2458 | 2261 | } |
|---|
| 2459 | 2262 | |
|---|
| 2460 | 2263 | /* Halt all channels to put them into a known state */ |
|---|
| 2461 | 2264 | for (i = 0; i < num_channels; i++) { |
|---|
| 2462 | 2265 | hcchar = dwc2_readl(hsotg, HCCHAR(i)); |
|---|
| 2463 | | - hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS; |
|---|
| 2464 | | - hcchar &= ~HCCHAR_EPDIR; |
|---|
| 2465 | | - dwc2_writel(hsotg, hcchar, HCCHAR(i)); |
|---|
| 2466 | | - dev_dbg(hsotg->dev, "%s: Halt channel %d\n", |
|---|
| 2467 | | - __func__, i); |
|---|
| 2266 | + if (hcchar & HCCHAR_CHENA) { |
|---|
| 2267 | + hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS; |
|---|
| 2268 | + hcchar &= ~HCCHAR_EPDIR; |
|---|
| 2269 | + dwc2_writel(hsotg, hcchar, HCCHAR(i)); |
|---|
| 2270 | + dev_dbg(hsotg->dev, "%s: Halt channel %d\n", |
|---|
| 2271 | + __func__, i); |
|---|
| 2468 | 2272 | |
|---|
| 2469 | | - if (dwc2_hsotg_wait_bit_clear(hsotg, HCCHAR(i), |
|---|
| 2470 | | - HCCHAR_CHENA, 1000)) { |
|---|
| 2471 | | - dev_warn(hsotg->dev, "Unable to clear enable on channel %d\n", |
|---|
| 2472 | | - i); |
|---|
| 2273 | + if (dwc2_hsotg_wait_bit_clear(hsotg, HCCHAR(i), |
|---|
| 2274 | + HCCHAR_CHENA, |
|---|
| 2275 | + 1000)) { |
|---|
| 2276 | + dev_warn(hsotg->dev, |
|---|
| 2277 | + "Unable to clear enable on channel %d\n", |
|---|
| 2278 | + i); |
|---|
| 2279 | + } |
|---|
| 2473 | 2280 | } |
|---|
| 2474 | 2281 | } |
|---|
| 2475 | 2282 | } |
|---|
| .. | .. |
|---|
| 3844 | 3651 | "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); |
|---|
| 3845 | 3652 | if (windex != hsotg->otg_port) |
|---|
| 3846 | 3653 | goto error; |
|---|
| 3847 | | - if (hsotg->params.power_down == 2) |
|---|
| 3654 | + if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION) |
|---|
| 3848 | 3655 | dwc2_enter_hibernation(hsotg, 1); |
|---|
| 3849 | 3656 | else |
|---|
| 3850 | 3657 | dwc2_port_suspend(hsotg, windex); |
|---|
| .. | .. |
|---|
| 3862 | 3669 | break; |
|---|
| 3863 | 3670 | |
|---|
| 3864 | 3671 | case USB_PORT_FEAT_RESET: |
|---|
| 3865 | | - if (hsotg->params.power_down == 2 && |
|---|
| 3672 | + if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION && |
|---|
| 3866 | 3673 | hsotg->hibernated) |
|---|
| 3867 | 3674 | dwc2_exit_hibernation(hsotg, 0, 1, 1); |
|---|
| 3868 | 3675 | hprt0 = dwc2_read_hprt0(hsotg); |
|---|
| .. | .. |
|---|
| 4017 | 3824 | gfp_t mem_flags) |
|---|
| 4018 | 3825 | { |
|---|
| 4019 | 3826 | struct dwc2_hcd_urb *urb; |
|---|
| 4020 | | - u32 size = sizeof(*urb) + iso_desc_count * |
|---|
| 4021 | | - sizeof(struct dwc2_hcd_iso_packet_desc); |
|---|
| 4022 | 3827 | |
|---|
| 4023 | | - urb = kzalloc(size, mem_flags); |
|---|
| 3828 | + urb = kzalloc(struct_size(urb, iso_descs, iso_desc_count), mem_flags); |
|---|
| 4024 | 3829 | if (urb) |
|---|
| 4025 | 3830 | urb->packet_count = iso_desc_count; |
|---|
| 4026 | 3831 | return urb; |
|---|
| .. | .. |
|---|
| 4417 | 4222 | spin_unlock_irqrestore(&hsotg->lock, flags); |
|---|
| 4418 | 4223 | } |
|---|
| 4419 | 4224 | |
|---|
| 4225 | +static void dwc2_hcd_phy_reset_func(struct work_struct *work) |
|---|
| 4226 | +{ |
|---|
| 4227 | + struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, |
|---|
| 4228 | + phy_reset_work); |
|---|
| 4229 | + int ret; |
|---|
| 4230 | + |
|---|
| 4231 | + ret = phy_reset(hsotg->phy); |
|---|
| 4232 | + if (ret) |
|---|
| 4233 | + dev_warn(hsotg->dev, "PHY reset failed\n"); |
|---|
| 4234 | +} |
|---|
| 4235 | + |
|---|
| 4420 | 4236 | /* |
|---|
| 4421 | 4237 | * ========================================================================= |
|---|
| 4422 | 4238 | * Linux HC Driver Functions |
|---|
| .. | .. |
|---|
| 4528 | 4344 | if (hsotg->op_state == OTG_STATE_B_PERIPHERAL) |
|---|
| 4529 | 4345 | goto unlock; |
|---|
| 4530 | 4346 | |
|---|
| 4347 | + if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL || |
|---|
| 4348 | + hsotg->flags.b.port_connect_status == 0) |
|---|
| 4349 | + goto skip_power_saving; |
|---|
| 4350 | + |
|---|
| 4531 | 4351 | /* |
|---|
| 4532 | 4352 | * Drive USB suspend and disable port Power |
|---|
| 4533 | 4353 | * if usb bus is not suspended. |
|---|
| .. | .. |
|---|
| 4536 | 4356 | hprt0 = dwc2_read_hprt0(hsotg); |
|---|
| 4537 | 4357 | if (hprt0 & HPRT0_CONNSTS) { |
|---|
| 4538 | 4358 | hprt0 |= HPRT0_SUSP; |
|---|
| 4539 | | - if (hsotg->params.power_down == |
|---|
| 4540 | | - DWC2_POWER_DOWN_PARAM_PARTIAL) |
|---|
| 4359 | + if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) |
|---|
| 4541 | 4360 | hprt0 &= ~HPRT0_PWR; |
|---|
| 4542 | 4361 | dwc2_writel(hsotg, hprt0, HPRT0); |
|---|
| 4543 | | - hsotg->bus_suspended = true; |
|---|
| 4544 | 4362 | } |
|---|
| 4545 | 4363 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) { |
|---|
| 4546 | 4364 | spin_unlock_irqrestore(&hsotg->lock, flags); |
|---|
| 4547 | 4365 | dwc2_vbus_supply_exit(hsotg); |
|---|
| 4548 | 4366 | spin_lock_irqsave(&hsotg->lock, flags); |
|---|
| 4549 | 4367 | } else { |
|---|
| 4550 | | - pcgctl = dwc2_readl(hsotg, PCGCTL); |
|---|
| 4368 | + pcgctl = readl(hsotg->regs + PCGCTL); |
|---|
| 4551 | 4369 | pcgctl |= PCGCTL_STOPPCLK; |
|---|
| 4552 | | - dwc2_writel(hsotg, pcgctl, PCGCTL); |
|---|
| 4370 | + writel(pcgctl, hsotg->regs + PCGCTL); |
|---|
| 4553 | 4371 | } |
|---|
| 4554 | 4372 | } |
|---|
| 4555 | 4373 | |
|---|
| .. | .. |
|---|
| 4563 | 4381 | goto skip_power_saving; |
|---|
| 4564 | 4382 | } |
|---|
| 4565 | 4383 | |
|---|
| 4566 | | - /* |
|---|
| 4567 | | - * After entering partial_power_down, |
|---|
| 4568 | | - * hardware is no more accessible. |
|---|
| 4569 | | - */ |
|---|
| 4384 | + /* After entering partial_power_down, hardware is no more accessible */ |
|---|
| 4570 | 4385 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
|---|
| 4571 | 4386 | } |
|---|
| 4572 | 4387 | |
|---|
| .. | .. |
|---|
| 4589 | 4404 | { |
|---|
| 4590 | 4405 | struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); |
|---|
| 4591 | 4406 | unsigned long flags; |
|---|
| 4592 | | - int ret = 0; |
|---|
| 4593 | 4407 | u32 pcgctl; |
|---|
| 4408 | + int ret = 0; |
|---|
| 4594 | 4409 | |
|---|
| 4595 | 4410 | spin_lock_irqsave(&hsotg->lock, flags); |
|---|
| 4596 | 4411 | |
|---|
| .. | .. |
|---|
| 4599 | 4414 | |
|---|
| 4600 | 4415 | if (hsotg->lx_state != DWC2_L2) |
|---|
| 4601 | 4416 | goto unlock; |
|---|
| 4417 | + |
|---|
| 4418 | + if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) { |
|---|
| 4419 | + hsotg->lx_state = DWC2_L0; |
|---|
| 4420 | + goto unlock; |
|---|
| 4421 | + } |
|---|
| 4602 | 4422 | |
|---|
| 4603 | 4423 | /* |
|---|
| 4604 | 4424 | * Enable power if not already done. |
|---|
| .. | .. |
|---|
| 4618 | 4438 | */ |
|---|
| 4619 | 4439 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
|---|
| 4620 | 4440 | |
|---|
| 4441 | + |
|---|
| 4621 | 4442 | /* Exit partial_power_down */ |
|---|
| 4622 | 4443 | ret = dwc2_exit_partial_power_down(hsotg, true); |
|---|
| 4623 | 4444 | if (ret && (ret != -ENOTSUPP)) |
|---|
| 4624 | 4445 | dev_err(hsotg->dev, "exit partial_power_down failed\n"); |
|---|
| 4625 | 4446 | } else { |
|---|
| 4626 | | - pcgctl = dwc2_readl(hsotg, PCGCTL); |
|---|
| 4447 | + pcgctl = readl(hsotg->regs + PCGCTL); |
|---|
| 4627 | 4448 | pcgctl &= ~PCGCTL_STOPPCLK; |
|---|
| 4628 | | - dwc2_writel(hsotg, pcgctl, PCGCTL); |
|---|
| 4449 | + writel(pcgctl, hsotg->regs + PCGCTL); |
|---|
| 4629 | 4450 | } |
|---|
| 4630 | 4451 | |
|---|
| 4631 | 4452 | hsotg->lx_state = DWC2_L0; |
|---|
| .. | .. |
|---|
| 4641 | 4462 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) { |
|---|
| 4642 | 4463 | dwc2_vbus_supply_init(hsotg); |
|---|
| 4643 | 4464 | |
|---|
| 4644 | | - /* |
|---|
| 4645 | | - * Wait for controller to correctly |
|---|
| 4646 | | - * update D+/D- level. |
|---|
| 4647 | | - */ |
|---|
| 4465 | + /* Wait for controller to correctly update D+/D- level */ |
|---|
| 4648 | 4466 | usleep_range(3000, 5000); |
|---|
| 4649 | 4467 | } |
|---|
| 4650 | 4468 | |
|---|
| .. | .. |
|---|
| 4814 | 4632 | |
|---|
| 4815 | 4633 | buf = urb->transfer_buffer; |
|---|
| 4816 | 4634 | |
|---|
| 4817 | | - if (hcd->self.uses_dma) { |
|---|
| 4635 | + if (hcd_uses_dma(hcd)) { |
|---|
| 4818 | 4636 | if (!buf && (urb->transfer_dma & 3)) { |
|---|
| 4819 | 4637 | dev_err(hsotg->dev, |
|---|
| 4820 | 4638 | "%s: unaligned transfer with no transfer_buffer", |
|---|
| .. | .. |
|---|
| 4891 | 4709 | spin_unlock_irqrestore(&hsotg->lock, flags); |
|---|
| 4892 | 4710 | urb->hcpriv = NULL; |
|---|
| 4893 | 4711 | kfree(qtd); |
|---|
| 4894 | | - qtd = NULL; |
|---|
| 4895 | 4712 | fail1: |
|---|
| 4896 | 4713 | if (qh_allocated) { |
|---|
| 4897 | 4714 | struct dwc2_qtd *qtd2, *qtd2_tmp; |
|---|
| .. | .. |
|---|
| 5194 | 5011 | destroy_workqueue(hsotg->wq_otg); |
|---|
| 5195 | 5012 | } |
|---|
| 5196 | 5013 | |
|---|
| 5014 | + cancel_work_sync(&hsotg->phy_reset_work); |
|---|
| 5015 | + |
|---|
| 5197 | 5016 | del_timer(&hsotg->wkp_timer); |
|---|
| 5198 | 5017 | } |
|---|
| 5199 | 5018 | |
|---|
| .. | .. |
|---|
| 5267 | 5086 | dwc2_hc_driver.reset_device = dwc2_reset_device; |
|---|
| 5268 | 5087 | } |
|---|
| 5269 | 5088 | |
|---|
| 5089 | + if (hsotg->params.host_dma) |
|---|
| 5090 | + dwc2_hc_driver.flags |= HCD_DMA; |
|---|
| 5091 | + |
|---|
| 5270 | 5092 | hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); |
|---|
| 5271 | 5093 | if (!hcd) |
|---|
| 5272 | 5094 | goto error1; |
|---|
| 5273 | | - |
|---|
| 5274 | | - if (!hsotg->params.host_dma) |
|---|
| 5275 | | - hcd->self.uses_dma = 0; |
|---|
| 5276 | 5095 | |
|---|
| 5277 | 5096 | hcd->has_tt = 1; |
|---|
| 5278 | 5097 | |
|---|
| 5279 | 5098 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 5280 | 5099 | if (!res) { |
|---|
| 5281 | 5100 | retval = -EINVAL; |
|---|
| 5282 | | - goto error1; |
|---|
| 5101 | + goto error2; |
|---|
| 5283 | 5102 | } |
|---|
| 5284 | 5103 | hcd->rsrc_start = res->start; |
|---|
| 5285 | 5104 | hcd->rsrc_len = resource_size(res); |
|---|
| .. | .. |
|---|
| 5339 | 5158 | hsotg->hc_ptr_array[i] = channel; |
|---|
| 5340 | 5159 | } |
|---|
| 5341 | 5160 | |
|---|
| 5342 | | - /* Initialize hsotg start work */ |
|---|
| 5161 | + /* Initialize work */ |
|---|
| 5343 | 5162 | INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func); |
|---|
| 5344 | | - |
|---|
| 5345 | | - /* Initialize port reset work */ |
|---|
| 5346 | 5163 | INIT_DELAYED_WORK(&hsotg->reset_work, dwc2_hcd_reset_func); |
|---|
| 5164 | + INIT_WORK(&hsotg->phy_reset_work, dwc2_hcd_phy_reset_func); |
|---|
| 5347 | 5165 | |
|---|
| 5348 | 5166 | /* |
|---|
| 5349 | 5167 | * Allocate space for storing data on status transactions. Normally no |
|---|
| .. | .. |
|---|
| 5811 | 5629 | dev_dbg(hsotg->dev, "Host hibernation restore complete\n"); |
|---|
| 5812 | 5630 | return ret; |
|---|
| 5813 | 5631 | } |
|---|
| 5632 | + |
|---|
| 5633 | +bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2) |
|---|
| 5634 | +{ |
|---|
| 5635 | + struct usb_device *root_hub = dwc2_hsotg_to_hcd(dwc2)->self.root_hub; |
|---|
| 5636 | + |
|---|
| 5637 | + /* If the controller isn't allowed to wakeup then we can power off. */ |
|---|
| 5638 | + if (!device_may_wakeup(dwc2->dev)) |
|---|
| 5639 | + return true; |
|---|
| 5640 | + |
|---|
| 5641 | + /* |
|---|
| 5642 | + * We don't want to power off the PHY if something under the |
|---|
| 5643 | + * root hub has wakeup enabled. |
|---|
| 5644 | + */ |
|---|
| 5645 | + if (usb_wakeup_enabled_descendants(root_hub)) |
|---|
| 5646 | + return false; |
|---|
| 5647 | + |
|---|
| 5648 | + /* No reason to keep the PHY powered, so allow poweroff */ |
|---|
| 5649 | + return true; |
|---|
| 5650 | +} |
|---|