aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy
diff options
context:
space:
mode:
authorIvan T. Ivanov <iivanov@mm-sol.com>2014-04-28 09:34:18 -0400
committerFelipe Balbi <balbi@ti.com>2014-04-30 12:28:45 -0400
commitd69c6f5df376ea40df5886468b155f515fddfbb2 (patch)
treefa1cbe3473abe6991397971430dfe56e3a33bf44 /drivers/usb/phy
parentcfa3ff5dfe6a11ac8bc4a080416984ab00b0980c (diff)
usb: phy: msm: Correct USB PHY Reset sequence for newer platform
On few legacy platforms, USB PHY is having dedicated reset clk. It is used to reset USB PHY after putting USB PHY into low power mode and for calibration of USB PHY. Putting USB PHY into low power mode is causing ulpi read/write timeout as expected. USB PHY reset clk is not available on newer platform. For 28nm PHY, reset USB PHY after resetting USB LINK. Also reset USB PHY using USB_PHY_PON bit with USB_OTG_HS_PHY_CTRL register after programming USB PHY Override registers as suggested with hardware programming guidelines. Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com> Signed-off-by: Tim Bird <tim.bird@sonymobile.com> Cc: Mayank Rana <mrana@codeaurora.org> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r--drivers/usb/phy/phy-msm-usb.c140
1 files changed, 88 insertions, 52 deletions
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 8d57045ac938..bb339963f8bb 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -48,6 +48,7 @@
48#define DRIVER_NAME "msm_otg" 48#define DRIVER_NAME "msm_otg"
49 49
50#define ULPI_IO_TIMEOUT_USEC (10 * 1000) 50#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
51#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
51 52
52#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */ 53#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
53#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */ 54#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
@@ -267,77 +268,35 @@ static int msm_otg_phy_clk_reset(struct msm_otg *motg)
267 return ret; 268 return ret;
268} 269}
269 270
270static int msm_otg_phy_reset(struct msm_otg *motg) 271static int msm_link_reset(struct msm_otg *motg)
271{ 272{
272 u32 val; 273 u32 val;
273 int ret; 274 int ret;
274 int retries;
275 275
276 ret = msm_otg_link_clk_reset(motg, 1); 276 ret = msm_otg_link_clk_reset(motg, 1);
277 if (ret) 277 if (ret)
278 return ret; 278 return ret;
279 ret = msm_otg_phy_clk_reset(motg);
280 if (ret)
281 return ret;
282 ret = msm_otg_link_clk_reset(motg, 0);
283 if (ret)
284 return ret;
285 279
286 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; 280 /* wait for 1ms delay as suggested in HPG. */
287 writel(val | PORTSC_PTS_ULPI, USB_PORTSC); 281 usleep_range(1000, 1200);
288
289 for (retries = 3; retries > 0; retries--) {
290 ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM,
291 ULPI_CLR(ULPI_FUNC_CTRL));
292 if (!ret)
293 break;
294 ret = msm_otg_phy_clk_reset(motg);
295 if (ret)
296 return ret;
297 }
298 if (!retries)
299 return -ETIMEDOUT;
300 282
301 /* This reset calibrates the phy, if the above write succeeded */ 283 ret = msm_otg_link_clk_reset(motg, 0);
302 ret = msm_otg_phy_clk_reset(motg);
303 if (ret) 284 if (ret)
304 return ret; 285 return ret;
305 286
306 for (retries = 3; retries > 0; retries--) {
307 ret = ulpi_read(&motg->phy, ULPI_DEBUG);
308 if (ret != -ETIMEDOUT)
309 break;
310 ret = msm_otg_phy_clk_reset(motg);
311 if (ret)
312 return ret;
313 }
314 if (!retries)
315 return -ETIMEDOUT;
316
317 if (motg->phy_number) 287 if (motg->phy_number)
318 writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); 288 writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2);
319 289
320 dev_info(motg->phy.dev, "phy_reset: success\n"); 290 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
291 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
292
321 return 0; 293 return 0;
322} 294}
323 295
324#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
325static int msm_otg_reset(struct usb_phy *phy) 296static int msm_otg_reset(struct usb_phy *phy)
326{ 297{
327 struct msm_otg *motg = container_of(phy, struct msm_otg, phy); 298 struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
328 struct msm_otg_platform_data *pdata = motg->pdata;
329 int cnt = 0; 299 int cnt = 0;
330 int ret;
331 u32 val = 0;
332 u32 ulpi_val = 0;
333
334 ret = msm_otg_phy_reset(motg);
335 if (ret) {
336 dev_err(phy->dev, "phy_reset failed\n");
337 return ret;
338 }
339
340 ulpi_init(motg);
341 300
342 writel(USBCMD_RESET, USB_USBCMD); 301 writel(USBCMD_RESET, USB_USBCMD);
343 while (cnt < LINK_RESET_TIMEOUT_USEC) { 302 while (cnt < LINK_RESET_TIMEOUT_USEC) {
@@ -351,11 +310,86 @@ static int msm_otg_reset(struct usb_phy *phy)
351 310
352 /* select ULPI phy */ 311 /* select ULPI phy */
353 writel(0x80000000, USB_PORTSC); 312 writel(0x80000000, USB_PORTSC);
313 writel(0x0, USB_AHBBURST);
314 writel(0x08, USB_AHBMODE);
315
316 if (motg->phy_number)
317 writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2);
318 return 0;
319}
320
321static void msm_phy_reset(struct msm_otg *motg)
322{
323 void __iomem *addr;
324
325 if (motg->pdata->phy_type != SNPS_28NM_INTEGRATED_PHY) {
326 msm_otg_phy_clk_reset(motg);
327 return;
328 }
329
330 addr = USB_PHY_CTRL;
331 if (motg->phy_number)
332 addr = USB_PHY_CTRL2;
333
334 /* Assert USB PHY_POR */
335 writel(readl(addr) | PHY_POR_ASSERT, addr);
336
337 /*
338 * wait for minimum 10 microseconds as suggested in HPG.
339 * Use a slightly larger value since the exact value didn't
340 * work 100% of the time.
341 */
342 udelay(12);
343
344 /* Deassert USB PHY_POR */
345 writel(readl(addr) & ~PHY_POR_ASSERT, addr);
346}
347
348static int msm_usb_reset(struct usb_phy *phy)
349{
350 struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
351 int ret;
352
353 if (!IS_ERR(motg->core_clk))
354 clk_prepare_enable(motg->core_clk);
355
356 ret = msm_link_reset(motg);
357 if (ret) {
358 dev_err(phy->dev, "phy_reset failed\n");
359 return ret;
360 }
361
362 ret = msm_otg_reset(&motg->phy);
363 if (ret) {
364 dev_err(phy->dev, "link reset failed\n");
365 return ret;
366 }
354 367
355 msleep(100); 368 msleep(100);
356 369
357 writel(0x0, USB_AHBBURST); 370 /* Reset USB PHY after performing USB Link RESET */
358 writel(0x00, USB_AHBMODE); 371 msm_phy_reset(motg);
372
373 if (!IS_ERR(motg->core_clk))
374 clk_disable_unprepare(motg->core_clk);
375
376 return 0;
377}
378
379static int msm_phy_init(struct usb_phy *phy)
380{
381 struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
382 struct msm_otg_platform_data *pdata = motg->pdata;
383 u32 val, ulpi_val = 0;
384
385 /* Program USB PHY Override registers. */
386 ulpi_init(motg);
387
388 /*
389 * It is recommended in HPG to reset USB PHY after programming
390 * USB PHY Override registers.
391 */
392 msm_phy_reset(motg);
359 393
360 if (pdata->otg_control == OTG_PHY_CONTROL) { 394 if (pdata->otg_control == OTG_PHY_CONTROL) {
361 val = readl(USB_OTGSC); 395 val = readl(USB_OTGSC);
@@ -1574,7 +1608,7 @@ static int msm_otg_probe(struct platform_device *pdev)
1574 goto disable_ldo; 1608 goto disable_ldo;
1575 } 1609 }
1576 1610
1577 phy->init = msm_otg_reset; 1611 phy->init = msm_phy_init;
1578 phy->set_power = msm_otg_set_power; 1612 phy->set_power = msm_otg_set_power;
1579 1613
1580 phy->io_ops = &msm_otg_io_ops; 1614 phy->io_ops = &msm_otg_io_ops;
@@ -1583,6 +1617,8 @@ static int msm_otg_probe(struct platform_device *pdev)
1583 phy->otg->set_host = msm_otg_set_host; 1617 phy->otg->set_host = msm_otg_set_host;
1584 phy->otg->set_peripheral = msm_otg_set_peripheral; 1618 phy->otg->set_peripheral = msm_otg_set_peripheral;
1585 1619
1620 msm_usb_reset(phy);
1621
1586 ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2); 1622 ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
1587 if (ret) { 1623 if (ret) {
1588 dev_err(&pdev->dev, "usb_add_phy failed\n"); 1624 dev_err(&pdev->dev, "usb_add_phy failed\n");