diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/am35x.c | 130 |
1 files changed, 45 insertions, 85 deletions
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 62e65f0a7284..d5a3da37c90c 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
34 | 34 | ||
35 | #include <plat/control.h> | ||
36 | #include <plat/usb.h> | 35 | #include <plat/usb.h> |
37 | 36 | ||
38 | #include "musb_core.h" | 37 | #include "musb_core.h" |
@@ -90,47 +89,6 @@ struct am35x_glue { | |||
90 | }; | 89 | }; |
91 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | 90 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
92 | 91 | ||
93 | static inline void phy_on(void) | ||
94 | { | ||
95 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | ||
96 | u32 devconf2; | ||
97 | |||
98 | /* | ||
99 | * Start the on-chip PHY and its PLL. | ||
100 | */ | ||
101 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
102 | |||
103 | devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); | ||
104 | devconf2 |= CONF2_PHY_PLLON; | ||
105 | |||
106 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
107 | |||
108 | DBG(1, "Waiting for PHY clock good...\n"); | ||
109 | while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) | ||
110 | & CONF2_PHYCLKGD)) { | ||
111 | cpu_relax(); | ||
112 | |||
113 | if (time_after(jiffies, timeout)) { | ||
114 | DBG(1, "musb PHY clock good timed out\n"); | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static inline void phy_off(void) | ||
121 | { | ||
122 | u32 devconf2; | ||
123 | |||
124 | /* | ||
125 | * Power down the on-chip PHY. | ||
126 | */ | ||
127 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
128 | |||
129 | devconf2 &= ~CONF2_PHY_PLLON; | ||
130 | devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; | ||
131 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
132 | } | ||
133 | |||
134 | /* | 92 | /* |
135 | * am35x_musb_enable - enable interrupts | 93 | * am35x_musb_enable - enable interrupts |
136 | */ | 94 | */ |
@@ -265,9 +223,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) | |||
265 | { | 223 | { |
266 | struct musb *musb = hci; | 224 | struct musb *musb = hci; |
267 | void __iomem *reg_base = musb->ctrl_base; | 225 | void __iomem *reg_base = musb->ctrl_base; |
226 | struct device *dev = musb->controller; | ||
227 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
228 | struct omap_musb_board_data *data = plat->board_data; | ||
268 | unsigned long flags; | 229 | unsigned long flags; |
269 | irqreturn_t ret = IRQ_NONE; | 230 | irqreturn_t ret = IRQ_NONE; |
270 | u32 epintr, usbintr, lvl_intr; | 231 | u32 epintr, usbintr; |
271 | 232 | ||
272 | spin_lock_irqsave(&musb->lock, flags); | 233 | spin_lock_irqsave(&musb->lock, flags); |
273 | 234 | ||
@@ -356,9 +317,8 @@ eoi: | |||
356 | /* EOI needs to be written for the IRQ to be re-asserted. */ | 317 | /* EOI needs to be written for the IRQ to be re-asserted. */ |
357 | if (ret == IRQ_HANDLED || epintr || usbintr) { | 318 | if (ret == IRQ_HANDLED || epintr || usbintr) { |
358 | /* clear level interrupt */ | 319 | /* clear level interrupt */ |
359 | lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 320 | if (data->clear_irq) |
360 | lvl_intr |= AM35XX_USBOTGSS_INT_CLR; | 321 | data->clear_irq(); |
361 | omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
362 | /* write EOI */ | 322 | /* write EOI */ |
363 | musb_writel(reg_base, USB_END_OF_INTR_REG, 0); | 323 | musb_writel(reg_base, USB_END_OF_INTR_REG, 0); |
364 | } | 324 | } |
@@ -374,37 +334,26 @@ eoi: | |||
374 | 334 | ||
375 | static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) | 335 | static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) |
376 | { | 336 | { |
377 | u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | 337 | struct device *dev = musb->controller; |
338 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
339 | struct omap_musb_board_data *data = plat->board_data; | ||
340 | int retval = 0; | ||
378 | 341 | ||
379 | devconf2 &= ~CONF2_OTGMODE; | 342 | if (data->set_mode) |
380 | switch (musb_mode) { | 343 | data->set_mode(musb_mode); |
381 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 344 | else |
382 | case MUSB_HOST: /* Force VBUS valid, ID = 0 */ | 345 | retval = -EIO; |
383 | devconf2 |= CONF2_FORCE_HOST; | ||
384 | break; | ||
385 | #endif | ||
386 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
387 | case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ | ||
388 | devconf2 |= CONF2_FORCE_DEVICE; | ||
389 | break; | ||
390 | #endif | ||
391 | #ifdef CONFIG_USB_MUSB_OTG | ||
392 | case MUSB_OTG: /* Don't override the VBUS/ID comparators */ | ||
393 | devconf2 |= CONF2_NO_OVERRIDE; | ||
394 | break; | ||
395 | #endif | ||
396 | default: | ||
397 | DBG(2, "Trying to set unsupported mode %u\n", musb_mode); | ||
398 | } | ||
399 | 346 | ||
400 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | 347 | return retval; |
401 | return 0; | ||
402 | } | 348 | } |
403 | 349 | ||
404 | static int am35x_musb_init(struct musb *musb) | 350 | static int am35x_musb_init(struct musb *musb) |
405 | { | 351 | { |
352 | struct device *dev = musb->controller; | ||
353 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
354 | struct omap_musb_board_data *data = plat->board_data; | ||
406 | void __iomem *reg_base = musb->ctrl_base; | 355 | void __iomem *reg_base = musb->ctrl_base; |
407 | u32 rev, lvl_intr, sw_reset; | 356 | u32 rev; |
408 | 357 | ||
409 | musb->mregs += USB_MENTOR_CORE_OFFSET; | 358 | musb->mregs += USB_MENTOR_CORE_OFFSET; |
410 | 359 | ||
@@ -421,39 +370,40 @@ static int am35x_musb_init(struct musb *musb) | |||
421 | if (is_host_enabled(musb)) | 370 | if (is_host_enabled(musb)) |
422 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | 371 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); |
423 | 372 | ||
424 | /* Global reset */ | 373 | /* Reset the musb */ |
425 | sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | 374 | if (data->reset) |
426 | 375 | data->reset(); | |
427 | sw_reset |= AM35XX_USBOTGSS_SW_RST; | ||
428 | omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); | ||
429 | |||
430 | sw_reset &= ~AM35XX_USBOTGSS_SW_RST; | ||
431 | omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); | ||
432 | 376 | ||
433 | /* Reset the controller */ | 377 | /* Reset the controller */ |
434 | musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); | 378 | musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); |
435 | 379 | ||
436 | /* Start the on-chip PHY and its PLL. */ | 380 | /* Start the on-chip PHY and its PLL. */ |
437 | phy_on(); | 381 | if (data->set_phy_power) |
382 | data->set_phy_power(1); | ||
438 | 383 | ||
439 | msleep(5); | 384 | msleep(5); |
440 | 385 | ||
441 | musb->isr = am35x_musb_interrupt; | 386 | musb->isr = am35x_musb_interrupt; |
442 | 387 | ||
443 | /* clear level interrupt */ | 388 | /* clear level interrupt */ |
444 | lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 389 | if (data->clear_irq) |
445 | lvl_intr |= AM35XX_USBOTGSS_INT_CLR; | 390 | data->clear_irq(); |
446 | omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
447 | 391 | ||
448 | return 0; | 392 | return 0; |
449 | } | 393 | } |
450 | 394 | ||
451 | static int am35x_musb_exit(struct musb *musb) | 395 | static int am35x_musb_exit(struct musb *musb) |
452 | { | 396 | { |
397 | struct device *dev = musb->controller; | ||
398 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
399 | struct omap_musb_board_data *data = plat->board_data; | ||
400 | |||
453 | if (is_host_enabled(musb)) | 401 | if (is_host_enabled(musb)) |
454 | del_timer_sync(&otg_workaround); | 402 | del_timer_sync(&otg_workaround); |
455 | 403 | ||
456 | phy_off(); | 404 | /* Shutdown the on-chip PHY and its PLL. */ |
405 | if (data->set_phy_power) | ||
406 | data->set_phy_power(0); | ||
457 | 407 | ||
458 | otg_put_transceiver(musb->xceiv); | 408 | otg_put_transceiver(musb->xceiv); |
459 | usb_nop_xceiv_unregister(); | 409 | usb_nop_xceiv_unregister(); |
@@ -630,8 +580,13 @@ static int __exit am35x_remove(struct platform_device *pdev) | |||
630 | static int am35x_suspend(struct device *dev) | 580 | static int am35x_suspend(struct device *dev) |
631 | { | 581 | { |
632 | struct am35x_glue *glue = dev_get_drvdata(dev); | 582 | struct am35x_glue *glue = dev_get_drvdata(dev); |
583 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
584 | struct omap_musb_board_data *data = plat->board_data; | ||
585 | |||
586 | /* Shutdown the on-chip PHY and its PLL. */ | ||
587 | if (data->set_phy_power) | ||
588 | data->set_phy_power(0); | ||
633 | 589 | ||
634 | phy_off(); | ||
635 | clk_disable(glue->phy_clk); | 590 | clk_disable(glue->phy_clk); |
636 | clk_disable(glue->clk); | 591 | clk_disable(glue->clk); |
637 | 592 | ||
@@ -641,9 +596,14 @@ static int am35x_suspend(struct device *dev) | |||
641 | static int am35x_resume(struct device *dev) | 596 | static int am35x_resume(struct device *dev) |
642 | { | 597 | { |
643 | struct am35x_glue *glue = dev_get_drvdata(dev); | 598 | struct am35x_glue *glue = dev_get_drvdata(dev); |
599 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
600 | struct omap_musb_board_data *data = plat->board_data; | ||
644 | int ret; | 601 | int ret; |
645 | 602 | ||
646 | phy_on(); | 603 | /* Start the on-chip PHY and its PLL. */ |
604 | if (data->set_phy_power) | ||
605 | data->set_phy_power(1); | ||
606 | |||
647 | ret = clk_enable(glue->phy_clk); | 607 | ret = clk_enable(glue->phy_clk); |
648 | if (ret) { | 608 | if (ret) { |
649 | dev_err(dev, "failed to enable PHY clock\n"); | 609 | dev_err(dev, "failed to enable PHY clock\n"); |