From 6f7af48341abf4d4c3953cfaa157eff3157501e8 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 11 Jun 2007 00:39:09 -0700 Subject: [PATCH] musb_hdrc: Workaround for tusb spontaneous wake-up issue At least tusb3.0 has a problem of waking up to spontaneously from idle when WBUS wake-up events are enabled (Issue #2). This patch disables power detection in PHY for the duration of idle. Signed-off-by: Tony Lindgren --- drivers/usb/musb/tusb6010.c | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 23bff72bfc0..21defbb7499 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -60,6 +60,53 @@ static int __init tusb_print_revision(struct musb *musb) return TUSB_REV_MAJOR(musb_readl(base, TUSB_INT_CTRL_REV)); } +#define WBUS_QUIRK_MASK (TUSB_PHY_OTG_CTRL_TESTM2 | TUSB_PHY_OTG_CTRL_TESTM1 \ + | TUSB_PHY_OTG_CTRL_TESTM0) + +/* + * Workaround for spontaneous WBUS wake-up issue #2 for tusb3.0. + * Disables power detection in PHY for the duration of idle. + */ +static void tusb_wbus_quirk(struct musb *musb, int enabled) +{ + void __iomem *base = musb->ctrl_base; + static u32 phy_otg_ena = 0, phy_otg_ctrl = 0; + u32 int_src, tmp; + + if (enabled) { + phy_otg_ena = musb_readl(base, TUSB_PHY_OTG_CTRL_ENABLE); + phy_otg_ctrl = musb_readl(base, TUSB_PHY_OTG_CTRL); + tmp = TUSB_PHY_OTG_CTRL_WRPROTECT + | phy_otg_ena | WBUS_QUIRK_MASK; + musb_writel(base, TUSB_PHY_OTG_CTRL_ENABLE, tmp); + tmp = phy_otg_ctrl & ~WBUS_QUIRK_MASK; + tmp |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_TESTM2; + musb_writel(base, TUSB_PHY_OTG_CTRL, tmp); + DBG(2, "Enabled tusb wbus quirk ena %08x ctrl %08x\n", + musb_readl(base, TUSB_PHY_OTG_CTRL_ENABLE), + musb_readl(base, TUSB_PHY_OTG_CTRL)); + } else if (musb_readl(base, TUSB_PHY_OTG_CTRL_ENABLE) + & TUSB_PHY_OTG_CTRL_TESTM2) { + tmp = TUSB_PHY_OTG_CTRL_WRPROTECT + | phy_otg_ena | WBUS_QUIRK_MASK; + musb_writel(base, TUSB_PHY_OTG_CTRL_ENABLE, tmp); + tmp = TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ctrl; + musb_writel(base, TUSB_PHY_OTG_CTRL, tmp); + tmp = TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ena; + musb_writel(base, TUSB_PHY_OTG_CTRL_ENABLE, tmp); + DBG(2, "Disabled tusb wbus quirk ena %08x ctrl %08x\n", + musb_readl(base, TUSB_PHY_OTG_CTRL_ENABLE), + musb_readl(base, TUSB_PHY_OTG_CTRL)); + phy_otg_ena = 0; + phy_otg_ctrl = 0; + } + + int_src = musb_readl(base, TUSB_INT_SRC); + if (int_src & TUSB_INT_SRC_ID_STATUS_CHNG) + musb_writel(base, TUSB_INT_SRC_CLEAR, + TUSB_INT_SRC_ID_STATUS_CHNG); +} + /* * TUSB 6010 may use a parallel bus that doesn't support byte ops; * so both loading and unloading FIFOs need explicit byte counts. @@ -287,6 +334,10 @@ static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) void __iomem *base = musb->ctrl_base; u32 reg; + if ((wakeup_enables & TUSB_PRCM_WBUS) + && (tusb_get_revision(musb) == TUSB_REV_30)) + tusb_wbus_quirk(musb, 1); + tusb_set_clock_source(musb, 0); wakeup_enables |= TUSB_PRCM_WNORCS; @@ -685,6 +736,9 @@ static irqreturn_t tusb_interrupt(int irq, void *__hci) u32 reg; u32 i; + if (tusb_get_revision(musb) == TUSB_REV_30) + tusb_wbus_quirk(musb, 0); + /* there are issues re-locking the PLL on wakeup ... */ /* work around issue 8 */ -- 2.41.1