Skip to content

Commit

Permalink
usb: musb: Return error value from musb_mailbox
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tony Lindgren authored and Greg Kroah-Hartman committed Jun 1, 2016
1 parent a118df0 commit 12b7db2
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 16 deletions.
14 changes: 10 additions & 4 deletions drivers/phy/phy-twl4030-usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,8 @@ static int twl4030_phy_power_on(struct phy *phy)
twl4030_usb_set_mode(twl, twl->usb_mode);
if (twl->usb_mode == T2_USB_MODE_ULPI)
twl4030_i2c_access(twl, 0);
schedule_delayed_work(&twl->id_workaround_work, 0);
twl->linkstat = MUSB_UNKNOWN;
schedule_delayed_work(&twl->id_workaround_work, HZ);

return 0;
}
Expand Down Expand Up @@ -537,6 +538,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
struct twl4030_usb *twl = _twl;
enum musb_vbus_id_status status;
bool status_changed = false;
int err;

status = twl4030_usb_linkstat(twl);

Expand Down Expand Up @@ -567,7 +569,9 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
pm_runtime_mark_last_busy(twl->dev);
pm_runtime_put_autosuspend(twl->dev);
}
musb_mailbox(status);
err = musb_mailbox(status);
if (err)
twl->linkstat = MUSB_UNKNOWN;
}

/* don't schedule during sleep - irq works right then */
Expand Down Expand Up @@ -595,7 +599,8 @@ static int twl4030_phy_init(struct phy *phy)
struct twl4030_usb *twl = phy_get_drvdata(phy);

pm_runtime_get_sync(twl->dev);
schedule_delayed_work(&twl->id_workaround_work, 0);
twl->linkstat = MUSB_UNKNOWN;
schedule_delayed_work(&twl->id_workaround_work, HZ);
pm_runtime_mark_last_busy(twl->dev);
pm_runtime_put_autosuspend(twl->dev);

Expand Down Expand Up @@ -763,7 +768,8 @@ static int twl4030_usb_remove(struct platform_device *pdev)
if (cable_present(twl->linkstat))
pm_runtime_put_noidle(twl->dev);
pm_runtime_mark_last_busy(twl->dev);
pm_runtime_put_sync_suspend(twl->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(twl->dev);
pm_runtime_disable(twl->dev);

/* autogate 60MHz ULPI clock,
Expand Down
7 changes: 4 additions & 3 deletions drivers/usb/musb/musb_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,7 +1679,7 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);
#define use_dma 0
#endif

static void (*musb_phy_callback)(enum musb_vbus_id_status status);
static int (*musb_phy_callback)(enum musb_vbus_id_status status);

/*
* musb_mailbox - optional phy notifier function
Expand All @@ -1688,11 +1688,12 @@ static void (*musb_phy_callback)(enum musb_vbus_id_status status);
* Optionally gets called from the USB PHY. Note that the USB PHY must be
* disabled at the point the phy_callback is registered or unregistered.
*/
void musb_mailbox(enum musb_vbus_id_status status)
int musb_mailbox(enum musb_vbus_id_status status)
{
if (musb_phy_callback)
musb_phy_callback(status);
return musb_phy_callback(status);

return -ENODEV;
};
EXPORT_SYMBOL_GPL(musb_mailbox);

Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/musb/musb_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ struct musb_platform_ops {
dma_addr_t *dma_addr, u32 *len);
void (*pre_root_reset_end)(struct musb *musb);
void (*post_root_reset_end)(struct musb *musb);
void (*phy_callback)(enum musb_vbus_id_status status);
int (*phy_callback)(enum musb_vbus_id_status status);
};

/*
Expand Down
8 changes: 5 additions & 3 deletions drivers/usb/musb/omap2430.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,22 +180,24 @@ static void omap2430_set_power(struct musb *musb, bool enabled, bool cable)
}
}

static void omap2430_musb_mailbox(enum musb_vbus_id_status status)
static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
{
struct omap2430_glue *glue = _glue;

if (!glue) {
pr_err("%s: musb core is not yet initialized\n", __func__);
return;
return -EPROBE_DEFER;
}
glue->status = status;

if (!glue_to_musb(glue)) {
pr_err("%s: musb core is not yet ready\n", __func__);
return;
return -EPROBE_DEFER;
}

schedule_work(&glue->omap_musb_mailbox_work);

return 0;
}

static void omap_musb_set_mailbox(struct omap2430_glue *glue)
Expand Down
12 changes: 9 additions & 3 deletions drivers/usb/phy/phy-twl6030-usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,16 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
twl->asleep = 1;
status = MUSB_VBUS_VALID;
twl->linkstat = status;
musb_mailbox(status);
ret = musb_mailbox(status);
if (ret)
twl->linkstat = MUSB_UNKNOWN;
} else {
if (twl->linkstat != MUSB_UNKNOWN) {
status = MUSB_VBUS_OFF;
twl->linkstat = status;
musb_mailbox(status);
ret = musb_mailbox(status);
if (ret)
twl->linkstat = MUSB_UNKNOWN;
if (twl->asleep) {
regulator_disable(twl->usb3v3);
twl->asleep = 0;
Expand Down Expand Up @@ -264,7 +268,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
status = MUSB_ID_GROUND;
twl->linkstat = status;
musb_mailbox(status);
ret = musb_mailbox(status);
if (ret)
twl->linkstat = MUSB_UNKNOWN;
} else {
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
Expand Down
5 changes: 3 additions & 2 deletions include/linux/usb/musb.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ enum musb_vbus_id_status {
};

#if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
void musb_mailbox(enum musb_vbus_id_status status);
int musb_mailbox(enum musb_vbus_id_status status);
#else
static inline void musb_mailbox(enum musb_vbus_id_status status)
static inline int musb_mailbox(enum musb_vbus_id_status status)
{
return 0;
}
#endif

Expand Down

0 comments on commit 12b7db2

Please sign in to comment.