aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb
diff options
context:
space:
mode:
authorSanthapuri, Damodar <damodar.santhapuri@ti.com>2012-11-02 12:32:53 -0400
committerFelipe Balbi <balbi@ti.com>2012-11-06 08:03:02 -0500
commitc68bb4c679e68b2814bc5de812665fbd37f8a9b1 (patch)
tree4e024c8efe2affb784f0803e6d06252b2338d668 /drivers/usb/musb
parent3e594b18f1871a758812aa5e705873012cabf0e8 (diff)
usb: musb: dsps: control module handling (quirk)
am335x uses nop transceiver driver and need to enable builtin phy by writing into usb_ctrl register available in system control module register space. This is being added at musb glue driver layer until a separate system control module driver is available. Proper solution is to make use of control module driver, but it is not expected to be ready soon. Other options available are providing control module register space as memory resource via DT or using omap hwmod. DT approach has been rejected by Rob Herring, while resources are being moved from hwmod to DT. And both of the above approaches require that control module registers be configured in wrapper itself requring a quirk in driver as well as DT or hwmod. Here another option is used, providing driver with control module register physical address. Even though this a hack, there is no other option left till control module driver is ready. As of now only am335x is using dsps wrapper, and so driver is made aware of am335x control module physical address. Please note that this is a temporary arrangment till omap control module driver is available. [afzal@ti.com: limit quirk to dsps wrapper] Signed-off-by: Santhapuri, Damodar <damodar.santhapuri@ti.com> Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> Signed-off-by: Ravi Babu <ravibabu@ti.com> Signed-off-by: Afzal Mohammed <afzal@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/musb_dsps.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index b159fc92f84..6053af1f57c 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -124,8 +124,44 @@ struct dsps_glue {
124 const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ 124 const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
125 struct timer_list timer[2]; /* otg_workaround timer */ 125 struct timer_list timer[2]; /* otg_workaround timer */
126 unsigned long last_timer[2]; /* last timer data for each instance */ 126 unsigned long last_timer[2]; /* last timer data for each instance */
127 u32 __iomem *usb_ctrl[2];
127}; 128};
128 129
130#define DSPS_AM33XX_CONTROL_MODULE_PHYS_0 0x44e10620
131#define DSPS_AM33XX_CONTROL_MODULE_PHYS_1 0x44e10628
132
133static const resource_size_t dsps_control_module_phys[] = {
134 DSPS_AM33XX_CONTROL_MODULE_PHYS_0,
135 DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
136};
137
138/**
139 * musb_dsps_phy_control - phy on/off
140 * @glue: struct dsps_glue *
141 * @id: musb instance
142 * @on: flag for phy to be switched on or off
143 *
144 * This is to enable the PHY using usb_ctrl register in system control
145 * module space.
146 *
147 * XXX: This function will be removed once we have a seperate driver for
148 * control module
149 */
150static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
151{
152 u32 usbphycfg;
153
154 usbphycfg = readl(glue->usb_ctrl[id]);
155
156 if (on) {
157 usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
158 usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
159 } else {
160 usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
161 }
162
163 writel(usbphycfg, glue->usb_ctrl[id]);
164}
129/** 165/**
130 * dsps_musb_enable - enable interrupts 166 * dsps_musb_enable - enable interrupts
131 */ 167 */
@@ -392,6 +428,9 @@ static int dsps_musb_init(struct musb *musb)
392 /* Reset the musb */ 428 /* Reset the musb */
393 dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); 429 dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
394 430
431 /* Start the on-chip PHY and its PLL. */
432 musb_dsps_phy_control(glue, pdev->id, 1);
433
395 musb->isr = dsps_interrupt; 434 musb->isr = dsps_interrupt;
396 435
397 /* reset the otgdisable bit, needed for host mode to work */ 436 /* reset the otgdisable bit, needed for host mode to work */
@@ -417,6 +456,9 @@ static int dsps_musb_exit(struct musb *musb)
417 456
418 del_timer_sync(&glue->timer[pdev->id]); 457 del_timer_sync(&glue->timer[pdev->id]);
419 458
459 /* Shutdown the on-chip PHY and its PLL. */
460 musb_dsps_phy_control(glue, pdev->id, 0);
461
420 /* NOP driver needs change if supporting dual instance */ 462 /* NOP driver needs change if supporting dual instance */
421 usb_put_phy(musb->xceiv); 463 usb_put_phy(musb->xceiv);
422 usb_nop_xceiv_unregister(); 464 usb_nop_xceiv_unregister();
@@ -449,6 +491,17 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
449 char res_name[10]; 491 char res_name[10];
450 int ret; 492 int ret;
451 493
494 resources[0].start = dsps_control_module_phys[id];
495 resources[0].end = resources[0].start + SZ_4 - 1;
496 resources[0].flags = IORESOURCE_MEM;
497
498 glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources);
499 if (glue->usb_ctrl[id] == NULL) {
500 dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id);
501 ret = -ENODEV;
502 goto err0;
503 }
504
452 /* first resource is for usbss, so start index from 1 */ 505 /* first resource is for usbss, so start index from 1 */
453 res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1); 506 res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);
454 if (!res) { 507 if (!res) {
@@ -635,11 +688,27 @@ static int __devexit dsps_remove(struct platform_device *pdev)
635#ifdef CONFIG_PM_SLEEP 688#ifdef CONFIG_PM_SLEEP
636static int dsps_suspend(struct device *dev) 689static int dsps_suspend(struct device *dev)
637{ 690{
691 struct platform_device *pdev = to_platform_device(dev->parent);
692 struct dsps_glue *glue = platform_get_drvdata(pdev);
693 const struct dsps_musb_wrapper *wrp = glue->wrp;
694 int i;
695
696 for (i = 0; i < wrp->instances; i++)
697 musb_dsps_phy_control(glue, i, 0);
698
638 return 0; 699 return 0;
639} 700}
640 701
641static int dsps_resume(struct device *dev) 702static int dsps_resume(struct device *dev)
642{ 703{
704 struct platform_device *pdev = to_platform_device(dev->parent);
705 struct dsps_glue *glue = platform_get_drvdata(pdev);
706 const struct dsps_musb_wrapper *wrp = glue->wrp;
707 int i;
708
709 for (i = 0; i < wrp->instances; i++)
710 musb_dsps_phy_control(glue, i, 1);
711
643 return 0; 712 return 0;
644} 713}
645#endif 714#endif