aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/phy/phy-msm-usb.c140
-rw-r--r--include/linux/usb/msm_hsusb_hw.h5
2 files changed, 93 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");
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index e6d703567155..575c74397e52 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -42,9 +42,14 @@
42#define ULPI_DATA(n) ((n) & 255) 42#define ULPI_DATA(n) ((n) & 255)
43#define ULPI_DATA_READ(n) (((n) >> 8) & 255) 43#define ULPI_DATA_READ(n) (((n) >> 8) & 255)
44 44
45/* synopsys 28nm phy registers */
46#define ULPI_PWR_CLK_MNG_REG 0x88
47#define OTG_COMP_DISABLE BIT(0)
48
45#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */ 49#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
46#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */ 50#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
47#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */ 51#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
52#define PHY_POR_ASSERT (1 << 0) /* USB2 28nm PHY POR ASSERT */
48 53
49/* OTG definitions */ 54/* OTG definitions */
50#define OTGSC_INTSTS_MASK (0x7f << 16) 55#define OTGSC_INTSTS_MASK (0x7f << 16)