Commit 943c1397 authored by Felipe Balbi's avatar Felipe Balbi

usb: musb: dsps: implement ->set_mode()

this will let us support broken designs such
as AM335x EVM SK where ID pin isn't routed
anywhere on a host port.

With this we can toggle internal IDDIG signal
and make sure MUSB goes into host mode as
necessary.
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 989c78dd
...@@ -106,6 +106,7 @@ struct dsps_musb_wrapper { ...@@ -106,6 +106,7 @@ struct dsps_musb_wrapper {
/* bit positions for mode */ /* bit positions for mode */
unsigned iddig:5; unsigned iddig:5;
unsigned iddig_mux:5;
/* miscellaneous stuff */ /* miscellaneous stuff */
u8 poll_seconds; u8 poll_seconds;
}; };
...@@ -406,6 +407,54 @@ static int dsps_musb_exit(struct musb *musb) ...@@ -406,6 +407,54 @@ static int dsps_musb_exit(struct musb *musb)
return 0; return 0;
} }
static int dsps_musb_set_mode(struct musb *musb, u8 mode)
{
struct device *dev = musb->controller;
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp;
void __iomem *ctrl_base = musb->ctrl_base;
void __iomem *base = musb->mregs;
u32 reg;
reg = dsps_readl(base, wrp->mode);
switch (mode) {
case MUSB_HOST:
reg &= ~(1 << wrp->iddig);
/*
* if we're setting mode to host-only or device-only, we're
* going to ignore whatever the PHY sends us and just force
* ID pin status by SW
*/
reg |= (1 << wrp->iddig_mux);
dsps_writel(base, wrp->mode, reg);
dsps_writel(ctrl_base, wrp->phy_utmi, 0x02);
break;
case MUSB_PERIPHERAL:
reg |= (1 << wrp->iddig);
/*
* if we're setting mode to host-only or device-only, we're
* going to ignore whatever the PHY sends us and just force
* ID pin status by SW
*/
reg |= (1 << wrp->iddig_mux);
dsps_writel(base, wrp->mode, reg);
break;
case MUSB_OTG:
dsps_writel(base, wrp->phy_utmi, 0x02);
break;
default:
dev_err(glue->dev, "unsupported mode %d\n", mode);
return -EINVAL;
}
return 0;
}
static struct musb_platform_ops dsps_ops = { static struct musb_platform_ops dsps_ops = {
.init = dsps_musb_init, .init = dsps_musb_init,
.exit = dsps_musb_exit, .exit = dsps_musb_exit,
...@@ -414,6 +463,7 @@ static struct musb_platform_ops dsps_ops = { ...@@ -414,6 +463,7 @@ static struct musb_platform_ops dsps_ops = {
.disable = dsps_musb_disable, .disable = dsps_musb_disable,
.try_idle = dsps_musb_try_idle, .try_idle = dsps_musb_try_idle,
.set_mode = dsps_musb_set_mode,
}; };
static u64 musb_dmamask = DMA_BIT_MASK(32); static u64 musb_dmamask = DMA_BIT_MASK(32);
...@@ -608,6 +658,7 @@ static const struct dsps_musb_wrapper am33xx_driver_data = { ...@@ -608,6 +658,7 @@ static const struct dsps_musb_wrapper am33xx_driver_data = {
.reset = 0, .reset = 0,
.otg_disable = 21, .otg_disable = 21,
.iddig = 8, .iddig = 8,
.iddig_mux = 7,
.usb_shift = 0, .usb_shift = 0,
.usb_mask = 0x1ff, .usb_mask = 0x1ff,
.usb_bitmap = (0x1ff << 0), .usb_bitmap = (0x1ff << 0),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment