diff options
Diffstat (limited to 'drivers/usb/host/ehci-omap.c')
| -rw-r--r-- | drivers/usb/host/ehci-omap.c | 114 |
1 files changed, 59 insertions, 55 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index c30435499a02..ec21f4a4a056 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
| @@ -115,9 +115,8 @@ static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) | |||
| 115 | clk_disable(usbhost_p2_fck); | 115 | clk_disable(usbhost_p2_fck); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) | 118 | static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) |
| 119 | { | 119 | { |
| 120 | struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); | ||
| 121 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | 120 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); |
| 122 | unsigned reg = 0; | 121 | unsigned reg = 0; |
| 123 | 122 | ||
| @@ -139,12 +138,63 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) | |||
| 139 | cpu_relax(); | 138 | cpu_relax(); |
| 140 | 139 | ||
| 141 | if (time_after(jiffies, timeout)) { | 140 | if (time_after(jiffies, timeout)) { |
| 142 | dev_dbg(&pdev->dev, "phy reset operation timed out\n"); | 141 | dev_dbg(hcd->self.controller, |
| 142 | "phy reset operation timed out\n"); | ||
| 143 | break; | 143 | break; |
| 144 | } | 144 | } |
| 145 | } | 145 | } |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static int omap_ehci_init(struct usb_hcd *hcd) | ||
| 149 | { | ||
| 150 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 151 | int rc; | ||
| 152 | struct ehci_hcd_omap_platform_data *pdata; | ||
| 153 | |||
| 154 | pdata = hcd->self.controller->platform_data; | ||
| 155 | if (pdata->phy_reset) { | ||
| 156 | if (gpio_is_valid(pdata->reset_gpio_port[0])) | ||
| 157 | gpio_request_one(pdata->reset_gpio_port[0], | ||
| 158 | GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); | ||
| 159 | |||
| 160 | if (gpio_is_valid(pdata->reset_gpio_port[1])) | ||
| 161 | gpio_request_one(pdata->reset_gpio_port[1], | ||
| 162 | GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); | ||
| 163 | |||
| 164 | /* Hold the PHY in RESET for enough time till DIR is high */ | ||
| 165 | udelay(10); | ||
| 166 | } | ||
| 167 | |||
| 168 | /* Soft reset the PHY using PHY reset command over ULPI */ | ||
| 169 | if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) | ||
| 170 | omap_ehci_soft_phy_reset(hcd, 0); | ||
| 171 | if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) | ||
| 172 | omap_ehci_soft_phy_reset(hcd, 1); | ||
| 173 | |||
| 174 | /* we know this is the memory we want, no need to ioremap again */ | ||
| 175 | ehci->caps = hcd->regs; | ||
| 176 | |||
| 177 | rc = ehci_setup(hcd); | ||
| 178 | |||
| 179 | if (pdata->phy_reset) { | ||
| 180 | /* Hold the PHY in RESET for enough time till | ||
| 181 | * PHY is settled and ready | ||
| 182 | */ | ||
| 183 | udelay(10); | ||
| 184 | |||
| 185 | if (gpio_is_valid(pdata->reset_gpio_port[0])) | ||
| 186 | gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); | ||
| 187 | |||
| 188 | if (gpio_is_valid(pdata->reset_gpio_port[1])) | ||
| 189 | gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); | ||
| 190 | } | ||
| 191 | |||
| 192 | /* root ports should always stay powered */ | ||
| 193 | ehci_port_power(ehci, 1); | ||
| 194 | |||
| 195 | return rc; | ||
| 196 | } | ||
| 197 | |||
| 148 | static int omap_ehci_hub_control( | 198 | static int omap_ehci_hub_control( |
| 149 | struct usb_hcd *hcd, | 199 | struct usb_hcd *hcd, |
| 150 | u16 typeReq, | 200 | u16 typeReq, |
| @@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
| 219 | struct resource *res; | 269 | struct resource *res; |
| 220 | struct usb_hcd *hcd; | 270 | struct usb_hcd *hcd; |
| 221 | void __iomem *regs; | 271 | void __iomem *regs; |
| 222 | struct ehci_hcd *omap_ehci; | ||
| 223 | int ret = -ENODEV; | 272 | int ret = -ENODEV; |
| 224 | int irq; | 273 | int irq; |
| 225 | int i; | 274 | int i; |
| @@ -281,18 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
| 281 | } | 330 | } |
| 282 | } | 331 | } |
| 283 | 332 | ||
| 284 | /* Hold PHYs in reset while initializing EHCI controller */ | ||
| 285 | if (pdata->phy_reset) { | ||
| 286 | if (gpio_is_valid(pdata->reset_gpio_port[0])) | ||
| 287 | gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); | ||
| 288 | |||
| 289 | if (gpio_is_valid(pdata->reset_gpio_port[1])) | ||
| 290 | gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); | ||
| 291 | |||
| 292 | /* Hold the PHY in RESET for enough time till DIR is high */ | ||
| 293 | udelay(10); | ||
| 294 | } | ||
| 295 | |||
| 296 | pm_runtime_enable(dev); | 333 | pm_runtime_enable(dev); |
| 297 | pm_runtime_get_sync(dev); | 334 | pm_runtime_get_sync(dev); |
| 298 | 335 | ||
| @@ -308,49 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
| 308 | ehci_write(regs, EHCI_INSNREG04, | 345 | ehci_write(regs, EHCI_INSNREG04, |
| 309 | EHCI_INSNREG04_DISABLE_UNSUSPEND); | 346 | EHCI_INSNREG04_DISABLE_UNSUSPEND); |
| 310 | 347 | ||
| 311 | /* Soft reset the PHY using PHY reset command over ULPI */ | ||
| 312 | if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) | ||
| 313 | omap_ehci_soft_phy_reset(pdev, 0); | ||
| 314 | if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) | ||
| 315 | omap_ehci_soft_phy_reset(pdev, 1); | ||
| 316 | |||
| 317 | omap_ehci = hcd_to_ehci(hcd); | ||
| 318 | omap_ehci->sbrn = 0x20; | ||
| 319 | |||
| 320 | /* we know this is the memory we want, no need to ioremap again */ | ||
| 321 | omap_ehci->caps = hcd->regs; | ||
| 322 | omap_ehci->regs = hcd->regs | ||
| 323 | + HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase)); | ||
| 324 | |||
| 325 | dbg_hcs_params(omap_ehci, "reset"); | ||
| 326 | dbg_hcc_params(omap_ehci, "reset"); | ||
| 327 | |||
| 328 | /* cache this readonly data; minimize chip reads */ | ||
| 329 | omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); | ||
| 330 | |||
| 331 | ehci_reset(omap_ehci); | ||
| 332 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | 348 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 333 | if (ret) { | 349 | if (ret) { |
| 334 | dev_err(dev, "failed to add hcd with err %d\n", ret); | 350 | dev_err(dev, "failed to add hcd with err %d\n", ret); |
| 335 | goto err_add_hcd; | 351 | goto err_pm_runtime; |
| 336 | } | 352 | } |
| 337 | 353 | ||
| 338 | if (pdata->phy_reset) { | ||
| 339 | /* Hold the PHY in RESET for enough time till | ||
| 340 | * PHY is settled and ready | ||
| 341 | */ | ||
| 342 | udelay(10); | ||
| 343 | |||
| 344 | if (gpio_is_valid(pdata->reset_gpio_port[0])) | ||
| 345 | gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); | ||
| 346 | |||
| 347 | if (gpio_is_valid(pdata->reset_gpio_port[1])) | ||
| 348 | gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); | ||
| 349 | } | ||
| 350 | |||
| 351 | /* root ports should always stay powered */ | ||
| 352 | ehci_port_power(omap_ehci, 1); | ||
| 353 | |||
| 354 | /* get clocks */ | 354 | /* get clocks */ |
| 355 | utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); | 355 | utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); |
| 356 | if (IS_ERR(utmi_p1_fck)) { | 356 | if (IS_ERR(utmi_p1_fck)) { |
| @@ -422,8 +422,12 @@ err_utmi_p1_fck: | |||
| 422 | clk_put(utmi_p1_fck); | 422 | clk_put(utmi_p1_fck); |
| 423 | 423 | ||
| 424 | err_add_hcd: | 424 | err_add_hcd: |
| 425 | usb_remove_hcd(hcd); | ||
| 426 | |||
| 427 | err_pm_runtime: | ||
| 425 | disable_put_regulator(pdata); | 428 | disable_put_regulator(pdata); |
| 426 | pm_runtime_put_sync(dev); | 429 | pm_runtime_put_sync(dev); |
| 430 | usb_put_hcd(hcd); | ||
| 427 | 431 | ||
| 428 | err_io: | 432 | err_io: |
| 429 | iounmap(regs); | 433 | iounmap(regs); |
| @@ -506,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = { | |||
| 506 | /* | 510 | /* |
| 507 | * basic lifecycle operations | 511 | * basic lifecycle operations |
| 508 | */ | 512 | */ |
| 509 | .reset = ehci_init, | 513 | .reset = omap_ehci_init, |
| 510 | .start = ehci_run, | 514 | .start = ehci_run, |
| 511 | .stop = ehci_stop, | 515 | .stop = ehci_stop, |
| 512 | .shutdown = ehci_shutdown, | 516 | .shutdown = ehci_shutdown, |
