> From: Jon Hunter <jon-hunter@xxxxxx> > > Depending on the OMAP3 boot mode the MUSB peripheral may or may not be > accessible when the kernel starts. > > The OMAP3 can boot from several devices including USB. The sequence of the > devices the OMAP will attempt to boot from is configured via the sys_boot > pins on the device. If USB is one of the devices the OMAP boot ROM attempts > to boot from on power-on, then the interface clock to the MUSB peripheral will > be enabled by the boot ROM and the MUSB peripheral will be accessible when the > kernel boots. However, if USB is not one of the devices OMAP will attempt to > boot from then the interface clock is not enabled and the MUSB peripheral will > not be accessible on start-up. > > If the MUSB peripheral is not accessible when the kernel boots, then the > kernel will crash when attempting to access the OTG_SYSCONFIG in the function > musb_platform_init(). The actual cause of the crash is the write to the > OTG_SYSCONFIG register in the function usb_musb_pm_init() to reset the MUSB > peripheral which occurs prior to calling musb_platform_init(). The function > usb_musb_pm_init() does not check to see if the interface clock for the MUSB > peripheral is enabled before writing to MUSB register. This write access does > not generate a data-abort at this point, but because this write does not > complete all future accesses to the MUSB controller will generate data-aborts > regardless of whether the interface clock has been enabled at a later stage. > The only way I have found to recover from this is resetting the device. > My understanding is that the interconnect works in this way to prevent a bad > access locking up the system. > > This patch crudely ensures the interface clock for the MUSB in the function > usb_musb_pm_init() is enabled. This patch also ensures that the interface > clock is disabled after the reset is complete. My reasoning for always > disabling the clock rather than maintaing its state is: > > 1). If the MUSB peripheral is not being used then the interface clock should > be disabled. > 2). The musb_set_clock() function uses a static variable called "clk_on" to > determine if the MUSB interface clock is on or off. On boot-up clk_on will be > 0 and so this function assumes that the clock is off by default which may not > be the case in the current code. > > I have also added a while-loop to wait for the reset of the MUSB module to > complete before this function exits and the interface clock it disabled. > > Signed-off-by: Jon Hunter <jon-hunter@xxxxxx> For what it's worth, Tested-by: Anand Gadiyar <gadiyar@xxxxxx> on a 3430SDP. > --- > arch/arm/mach-omap2/usb-musb.c | 30 ++++++++++++++++++++++++++++-- > 1 files changed, 28 insertions(+), 2 deletions(-) > > diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c > index 3efa19c..7cfe9bb 100644 > --- a/arch/arm/mach-omap2/usb-musb.c > +++ b/arch/arm/mach-omap2/usb-musb.c > @@ -32,25 +32,51 @@ > #include <mach/irqs.h> > #include <mach/mux.h> > #include <mach/usb.h> > +#include "cm.h" > > #define OTG_SYSCONFIG 0x404 > #define OTG_SYSC_SOFTRESET BIT(1) > +#define OTG_SYSSTATUS 0x408 > +#define OTG_SYSS_RESETDONE BIT(0) > > static void __init usb_musb_pm_init(void) > { > - void __iomem *otg_base; > + void __iomem *cm_base, *otg_base; > + unsigned int cm_iclken_core; > > if (!cpu_is_omap34xx()) > return; > > + cm_base = ioremap(OMAP3430_CM_BASE, SZ_4K); > + if (WARN_ON(!cm_base)) > + return; > + > otg_base = ioremap(OMAP34XX_HSUSB_OTG_BASE, SZ_4K); > - if (WARN_ON(!otg_base)) > + if (WARN_ON(!otg_base)) { > + iounmap(cm_base); > return; > + } > + > + /* Ensure the inferface clock for MUSB is enabled */ > + cm_iclken_core = __raw_readl(OMAP34XX_CM_REGADDR(CORE_MOD, > + CM_ICLKEN1)); > + __raw_writel((cm_iclken_core | > + (1 << OMAP3430_EN_HSOTGUSB_SHIFT)), > + OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)); > > /* Reset OTG controller. After reset, it will be in > * force-idle, force-standby mode. */ > __raw_writel(OTG_SYSC_SOFTRESET, otg_base + OTG_SYSCONFIG); > > + while (!(OTG_SYSS_RESETDONE & __raw_readl(otg_base + OTG_SYSSTATUS))) > + cpu_relax(); > + > + /* Ensure the interface clock for MUSB is disabled */ > + __raw_writel((cm_iclken_core & > + ~(1 << OMAP3430_EN_HSOTGUSB_SHIFT)), > + OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)); > + > + iounmap(cm_base); > iounmap(otg_base); > } > > -- > 1.6.0.4 > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html