Merge tag 'usb-for-v3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes: usb: patches for v3.17 merge window Surprisingly enough, while a big set of patches, the majority is composed of cleanups (using devm_*, fixing sparse errors, moving code around, adding const, etc). The highlights are addition of new support for PLX USB338x devices, and support for USB 2.0-only configurations of the DWC3 IP core. Signed-of-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
@@ -56,16 +56,24 @@ static const struct of_device_id musb_dsps_of_match[];
|
||||
* dependent on musb core layer symbols.
|
||||
*/
|
||||
static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
|
||||
{ return __raw_readb(addr + offset); }
|
||||
{
|
||||
return __raw_readb(addr + offset);
|
||||
}
|
||||
|
||||
static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
|
||||
{ return __raw_readl(addr + offset); }
|
||||
{
|
||||
return __raw_readl(addr + offset);
|
||||
}
|
||||
|
||||
static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
|
||||
{ __raw_writeb(data, addr + offset); }
|
||||
{
|
||||
__raw_writeb(data, addr + offset);
|
||||
}
|
||||
|
||||
static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
|
||||
{ __raw_writel(data, addr + offset); }
|
||||
{
|
||||
__raw_writel(data, addr + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* DSPS musb wrapper register offset.
|
||||
@@ -136,6 +144,7 @@ struct dsps_glue {
|
||||
const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
|
||||
struct timer_list timer; /* otg_workaround timer */
|
||||
unsigned long last_timer; /* last timer data for each instance */
|
||||
bool sw_babble_enabled;
|
||||
|
||||
struct dsps_context context;
|
||||
struct debugfs_regset32 regset;
|
||||
@@ -469,6 +478,19 @@ static int dsps_musb_init(struct musb *musb)
|
||||
val &= ~(1 << wrp->otg_disable);
|
||||
dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
|
||||
|
||||
/*
|
||||
* Check whether the dsps version has babble control enabled.
|
||||
* In latest silicon revision the babble control logic is enabled.
|
||||
* If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
|
||||
* logic enabled.
|
||||
*/
|
||||
val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
|
||||
if (val == MUSB_BABBLE_RCV_DISABLE) {
|
||||
glue->sw_babble_enabled = true;
|
||||
val |= MUSB_BABBLE_SW_SESSION_CTRL;
|
||||
dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
|
||||
}
|
||||
|
||||
ret = dsps_musb_dbg_init(musb, glue);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -535,14 +557,82 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsps_musb_reset(struct musb *musb)
|
||||
static bool sw_babble_control(struct musb *musb)
|
||||
{
|
||||
u8 babble_ctl;
|
||||
bool session_restart = false;
|
||||
|
||||
babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
|
||||
dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
|
||||
babble_ctl);
|
||||
/*
|
||||
* check line monitor flag to check whether babble is
|
||||
* due to noise
|
||||
*/
|
||||
dev_dbg(musb->controller, "STUCK_J is %s\n",
|
||||
babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
|
||||
|
||||
if (babble_ctl & MUSB_BABBLE_STUCK_J) {
|
||||
int timeout = 10;
|
||||
|
||||
/*
|
||||
* babble is due to noise, then set transmit idle (d7 bit)
|
||||
* to resume normal operation
|
||||
*/
|
||||
babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
|
||||
babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
|
||||
dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
|
||||
|
||||
/* wait till line monitor flag cleared */
|
||||
dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
|
||||
do {
|
||||
babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
|
||||
udelay(1);
|
||||
} while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
|
||||
|
||||
/* check whether stuck_at_j bit cleared */
|
||||
if (babble_ctl & MUSB_BABBLE_STUCK_J) {
|
||||
/*
|
||||
* real babble condition has occurred
|
||||
* restart the controller to start the
|
||||
* session again
|
||||
*/
|
||||
dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
|
||||
babble_ctl);
|
||||
session_restart = true;
|
||||
}
|
||||
} else {
|
||||
session_restart = true;
|
||||
}
|
||||
|
||||
return session_restart;
|
||||
}
|
||||
|
||||
static int dsps_musb_reset(struct musb *musb)
|
||||
{
|
||||
struct device *dev = musb->controller;
|
||||
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
|
||||
const struct dsps_musb_wrapper *wrp = glue->wrp;
|
||||
int session_restart = 0;
|
||||
|
||||
dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
|
||||
udelay(100);
|
||||
if (glue->sw_babble_enabled)
|
||||
session_restart = sw_babble_control(musb);
|
||||
/*
|
||||
* In case of new silicon version babble condition can be recovered
|
||||
* without resetting the MUSB. But for older silicon versions, MUSB
|
||||
* reset is needed
|
||||
*/
|
||||
if (session_restart || !glue->sw_babble_enabled) {
|
||||
dev_info(musb->controller, "Restarting MUSB to recover from Babble\n");
|
||||
dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
|
||||
usleep_range(100, 200);
|
||||
usb_phy_shutdown(musb->xceiv);
|
||||
usleep_range(100, 200);
|
||||
usb_phy_init(musb->xceiv);
|
||||
session_restart = 1;
|
||||
}
|
||||
|
||||
return !session_restart;
|
||||
}
|
||||
|
||||
static struct musb_platform_ops dsps_ops = {
|
||||
|
Viittaa uudesa ongelmassa
Block a user