aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2016-05-31 11:05:19 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-06-01 17:58:59 -0400
commit12b7db2bf8b88938798c60416172b53225207b1f (patch)
tree43e7c3b09fec20d63799e5a2740e0e1b26c25f46 /drivers
parenta118df07f5b19e4879fd67e98a69f4644136877f (diff)
usb: musb: Return error value from musb_mailbox
At least on n900 we have phy-twl4030-usb only generating cable interrupts, and then have a separate USB PHY. In order for musb to know the real cable status, we need to clear any cached state until musb is ready. Otherwise the cable status interrupts will get just ignored if the status does not change from the initial state. To do this, let's add a return value to musb_mailbox(), and reset cached linkstat to MUSB_UNKNOWN on error. Sorry to cause a bit of churn here, I should have added that already last time patching musb_mailbox(). Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/phy/phy-twl4030-usb.c14
-rw-r--r--drivers/usb/musb/musb_core.c7
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/omap2430.c8
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c12
5 files changed, 29 insertions, 14 deletions
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index 6b6af6cba454..d9b10a39a2cf 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -463,7 +463,8 @@ static int twl4030_phy_power_on(struct phy *phy)
463 twl4030_usb_set_mode(twl, twl->usb_mode); 463 twl4030_usb_set_mode(twl, twl->usb_mode);
464 if (twl->usb_mode == T2_USB_MODE_ULPI) 464 if (twl->usb_mode == T2_USB_MODE_ULPI)
465 twl4030_i2c_access(twl, 0); 465 twl4030_i2c_access(twl, 0);
466 schedule_delayed_work(&twl->id_workaround_work, 0); 466 twl->linkstat = MUSB_UNKNOWN;
467 schedule_delayed_work(&twl->id_workaround_work, HZ);
467 468
468 return 0; 469 return 0;
469} 470}
@@ -537,6 +538,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
537 struct twl4030_usb *twl = _twl; 538 struct twl4030_usb *twl = _twl;
538 enum musb_vbus_id_status status; 539 enum musb_vbus_id_status status;
539 bool status_changed = false; 540 bool status_changed = false;
541 int err;
540 542
541 status = twl4030_usb_linkstat(twl); 543 status = twl4030_usb_linkstat(twl);
542 544
@@ -567,7 +569,9 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
567 pm_runtime_mark_last_busy(twl->dev); 569 pm_runtime_mark_last_busy(twl->dev);
568 pm_runtime_put_autosuspend(twl->dev); 570 pm_runtime_put_autosuspend(twl->dev);
569 } 571 }
570 musb_mailbox(status); 572 err = musb_mailbox(status);
573 if (err)
574 twl->linkstat = MUSB_UNKNOWN;
571 } 575 }
572 576
573 /* don't schedule during sleep - irq works right then */ 577 /* don't schedule during sleep - irq works right then */
@@ -595,7 +599,8 @@ static int twl4030_phy_init(struct phy *phy)
595 struct twl4030_usb *twl = phy_get_drvdata(phy); 599 struct twl4030_usb *twl = phy_get_drvdata(phy);
596 600
597 pm_runtime_get_sync(twl->dev); 601 pm_runtime_get_sync(twl->dev);
598 schedule_delayed_work(&twl->id_workaround_work, 0); 602 twl->linkstat = MUSB_UNKNOWN;
603 schedule_delayed_work(&twl->id_workaround_work, HZ);
599 pm_runtime_mark_last_busy(twl->dev); 604 pm_runtime_mark_last_busy(twl->dev);
600 pm_runtime_put_autosuspend(twl->dev); 605 pm_runtime_put_autosuspend(twl->dev);
601 606
@@ -763,7 +768,8 @@ static int twl4030_usb_remove(struct platform_device *pdev)
763 if (cable_present(twl->linkstat)) 768 if (cable_present(twl->linkstat))
764 pm_runtime_put_noidle(twl->dev); 769 pm_runtime_put_noidle(twl->dev);
765 pm_runtime_mark_last_busy(twl->dev); 770 pm_runtime_mark_last_busy(twl->dev);
766 pm_runtime_put_sync_suspend(twl->dev); 771 pm_runtime_dont_use_autosuspend(&pdev->dev);
772 pm_runtime_put_sync(twl->dev);
767 pm_runtime_disable(twl->dev); 773 pm_runtime_disable(twl->dev);
768 774
769 /* autogate 60MHz ULPI clock, 775 /* autogate 60MHz ULPI clock,
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 23888d579e8b..6469eff4fc30 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1679,7 +1679,7 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);
1679#define use_dma 0 1679#define use_dma 0
1680#endif 1680#endif
1681 1681
1682static void (*musb_phy_callback)(enum musb_vbus_id_status status); 1682static int (*musb_phy_callback)(enum musb_vbus_id_status status);
1683 1683
1684/* 1684/*
1685 * musb_mailbox - optional phy notifier function 1685 * musb_mailbox - optional phy notifier function
@@ -1688,11 +1688,12 @@ static void (*musb_phy_callback)(enum musb_vbus_id_status status);
1688 * Optionally gets called from the USB PHY. Note that the USB PHY must be 1688 * Optionally gets called from the USB PHY. Note that the USB PHY must be
1689 * disabled at the point the phy_callback is registered or unregistered. 1689 * disabled at the point the phy_callback is registered or unregistered.
1690 */ 1690 */
1691void musb_mailbox(enum musb_vbus_id_status status) 1691int musb_mailbox(enum musb_vbus_id_status status)
1692{ 1692{
1693 if (musb_phy_callback) 1693 if (musb_phy_callback)
1694 musb_phy_callback(status); 1694 return musb_phy_callback(status);
1695 1695
1696 return -ENODEV;
1696}; 1697};
1697EXPORT_SYMBOL_GPL(musb_mailbox); 1698EXPORT_SYMBOL_GPL(musb_mailbox);
1698 1699
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 29473846b098..b55a776b03eb 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -215,7 +215,7 @@ struct musb_platform_ops {
215 dma_addr_t *dma_addr, u32 *len); 215 dma_addr_t *dma_addr, u32 *len);
216 void (*pre_root_reset_end)(struct musb *musb); 216 void (*pre_root_reset_end)(struct musb *musb);
217 void (*post_root_reset_end)(struct musb *musb); 217 void (*post_root_reset_end)(struct musb *musb);
218 void (*phy_callback)(enum musb_vbus_id_status status); 218 int (*phy_callback)(enum musb_vbus_id_status status);
219}; 219};
220 220
221/* 221/*
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index d312d42592d6..2c54f52ae386 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -180,22 +180,24 @@ static void omap2430_set_power(struct musb *musb, bool enabled, bool cable)
180 } 180 }
181} 181}
182 182
183static void omap2430_musb_mailbox(enum musb_vbus_id_status status) 183static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
184{ 184{
185 struct omap2430_glue *glue = _glue; 185 struct omap2430_glue *glue = _glue;
186 186
187 if (!glue) { 187 if (!glue) {
188 pr_err("%s: musb core is not yet initialized\n", __func__); 188 pr_err("%s: musb core is not yet initialized\n", __func__);
189 return; 189 return -EPROBE_DEFER;
190 } 190 }
191 glue->status = status; 191 glue->status = status;
192 192
193 if (!glue_to_musb(glue)) { 193 if (!glue_to_musb(glue)) {
194 pr_err("%s: musb core is not yet ready\n", __func__); 194 pr_err("%s: musb core is not yet ready\n", __func__);
195 return; 195 return -EPROBE_DEFER;
196 } 196 }
197 197
198 schedule_work(&glue->omap_musb_mailbox_work); 198 schedule_work(&glue->omap_musb_mailbox_work);
199
200 return 0;
199} 201}
200 202
201static void omap_musb_set_mailbox(struct omap2430_glue *glue) 203static void omap_musb_set_mailbox(struct omap2430_glue *glue)
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 24e2b3cf1867..c66a447c3dfe 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -227,12 +227,16 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
227 twl->asleep = 1; 227 twl->asleep = 1;
228 status = MUSB_VBUS_VALID; 228 status = MUSB_VBUS_VALID;
229 twl->linkstat = status; 229 twl->linkstat = status;
230 musb_mailbox(status); 230 ret = musb_mailbox(status);
231 if (ret)
232 twl->linkstat = MUSB_UNKNOWN;
231 } else { 233 } else {
232 if (twl->linkstat != MUSB_UNKNOWN) { 234 if (twl->linkstat != MUSB_UNKNOWN) {
233 status = MUSB_VBUS_OFF; 235 status = MUSB_VBUS_OFF;
234 twl->linkstat = status; 236 twl->linkstat = status;
235 musb_mailbox(status); 237 ret = musb_mailbox(status);
238 if (ret)
239 twl->linkstat = MUSB_UNKNOWN;
236 if (twl->asleep) { 240 if (twl->asleep) {
237 regulator_disable(twl->usb3v3); 241 regulator_disable(twl->usb3v3);
238 twl->asleep = 0; 242 twl->asleep = 0;
@@ -264,7 +268,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
264 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); 268 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
265 status = MUSB_ID_GROUND; 269 status = MUSB_ID_GROUND;
266 twl->linkstat = status; 270 twl->linkstat = status;
267 musb_mailbox(status); 271 ret = musb_mailbox(status);
272 if (ret)
273 twl->linkstat = MUSB_UNKNOWN;
268 } else { 274 } else {
269 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); 275 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
270 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 276 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);