Commit db4a9320 authored by B, Ravi's avatar B, Ravi Committed by Felipe Balbi

usb: musb: am335x: add support for dual instance

AM335x and TI81xx platform has dual musb controller so updating the
musb_dspc.c to support the same.

Changes:
        - Moved otg_workaround timer to glue structure
        - Moved static local variable last_timer to glue structure
        - PHY on/off related cleanups
Signed-off-by: default avatarRavi Babu <ravibabu@ti.com>
Signed-off-by: default avatarAjay Kumar Gupta <ajay.gupta@ti.com>
Signed-off-by: default avatarSanthapuri, Damodar <damodar.santhapuri@ti.com>
[afzal@ti.com: remove control module related modifications]
Signed-off-by: default avatarAfzal Mohammed <afzal@ti.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 8d2421e6
...@@ -105,6 +105,8 @@ struct dsps_musb_wrapper { ...@@ -105,6 +105,8 @@ struct dsps_musb_wrapper {
/* miscellaneous stuff */ /* miscellaneous stuff */
u32 musb_core_offset; u32 musb_core_offset;
u8 poll_seconds; u8 poll_seconds;
/* number of musb instances */
u8 instances;
}; };
/** /**
...@@ -112,9 +114,10 @@ struct dsps_musb_wrapper { ...@@ -112,9 +114,10 @@ struct dsps_musb_wrapper {
*/ */
struct dsps_glue { struct dsps_glue {
struct device *dev; struct device *dev;
struct platform_device *musb; /* child musb pdev */ struct platform_device *musb[2]; /* child musb pdev */
const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
struct timer_list timer; /* otg_workaround timer */ struct timer_list timer[2]; /* otg_workaround timer */
unsigned long last_timer[2]; /* last timer data for each instance */
}; };
/** /**
...@@ -164,8 +167,8 @@ static void otg_timer(unsigned long _musb) ...@@ -164,8 +167,8 @@ static void otg_timer(unsigned long _musb)
struct musb *musb = (void *)_musb; struct musb *musb = (void *)_musb;
void __iomem *mregs = musb->mregs; void __iomem *mregs = musb->mregs;
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev->parent); struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = platform_get_drvdata(pdev); struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
u8 devctl; u8 devctl;
unsigned long flags; unsigned long flags;
...@@ -201,7 +204,7 @@ static void otg_timer(unsigned long _musb) ...@@ -201,7 +204,7 @@ static void otg_timer(unsigned long _musb)
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
devctl = dsps_readb(mregs, MUSB_DEVCTL); devctl = dsps_readb(mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&glue->timer, mod_timer(&glue->timer[pdev->id],
jiffies + wrp->poll_seconds * HZ); jiffies + wrp->poll_seconds * HZ);
else else
musb->xceiv->state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
...@@ -215,9 +218,8 @@ static void otg_timer(unsigned long _musb) ...@@ -215,9 +218,8 @@ static void otg_timer(unsigned long _musb)
static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
{ {
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev->parent); struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = platform_get_drvdata(pdev); struct dsps_glue *glue = dev_get_drvdata(dev->parent);
static unsigned long last_timer;
if (timeout == 0) if (timeout == 0)
timeout = jiffies + msecs_to_jiffies(3); timeout = jiffies + msecs_to_jiffies(3);
...@@ -227,22 +229,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) ...@@ -227,22 +229,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n", dev_dbg(musb->controller, "%s active, deleting timer\n",
otg_state_string(musb->xceiv->state)); otg_state_string(musb->xceiv->state));
del_timer(&glue->timer); del_timer(&glue->timer[pdev->id]);
last_timer = jiffies; glue->last_timer[pdev->id] = jiffies;
return; return;
} }
if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) { if (time_after(glue->last_timer[pdev->id], timeout) &&
timer_pending(&glue->timer[pdev->id])) {
dev_dbg(musb->controller, dev_dbg(musb->controller,
"Longer idle timer already pending, ignoring...\n"); "Longer idle timer already pending, ignoring...\n");
return; return;
} }
last_timer = timeout; glue->last_timer[pdev->id] = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
otg_state_string(musb->xceiv->state), otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies)); jiffies_to_msecs(timeout - jiffies));
mod_timer(&glue->timer, timeout); mod_timer(&glue->timer[pdev->id], timeout);
} }
static irqreturn_t dsps_interrupt(int irq, void *hci) static irqreturn_t dsps_interrupt(int irq, void *hci)
...@@ -250,8 +253,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) ...@@ -250,8 +253,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
struct musb *musb = hci; struct musb *musb = hci;
void __iomem *reg_base = musb->ctrl_base; void __iomem *reg_base = musb->ctrl_base;
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev->parent); struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = platform_get_drvdata(pdev); struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
unsigned long flags; unsigned long flags;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
...@@ -310,7 +313,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) ...@@ -310,7 +313,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
*/ */
musb->int_usb &= ~MUSB_INTR_VBUSERROR; musb->int_usb &= ~MUSB_INTR_VBUSERROR;
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&glue->timer, mod_timer(&glue->timer[pdev->id],
jiffies + wrp->poll_seconds * HZ); jiffies + wrp->poll_seconds * HZ);
WARNING("VBUS error workaround (delay coming)\n"); WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) { } else if (drvvbus) {
...@@ -318,7 +321,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) ...@@ -318,7 +321,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
musb->xceiv->otg->default_a = 1; musb->xceiv->otg->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
del_timer(&glue->timer); del_timer(&glue->timer[pdev->id]);
} else { } else {
musb->is_active = 0; musb->is_active = 0;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
...@@ -345,7 +348,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) ...@@ -345,7 +348,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
/* Poll for ID change */ /* Poll for ID change */
if (musb->xceiv->state == OTG_STATE_B_IDLE) if (musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); mod_timer(&glue->timer[pdev->id],
jiffies + wrp->poll_seconds * HZ);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -356,8 +360,8 @@ static int dsps_musb_init(struct musb *musb) ...@@ -356,8 +360,8 @@ static int dsps_musb_init(struct musb *musb)
{ {
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data; struct musb_hdrc_platform_data *plat = dev->platform_data;
struct platform_device *pdev = to_platform_device(dev->parent); struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = platform_get_drvdata(pdev); struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
struct omap_musb_board_data *data = plat->board_data; struct omap_musb_board_data *data = plat->board_data;
void __iomem *reg_base = musb->ctrl_base; void __iomem *reg_base = musb->ctrl_base;
...@@ -380,7 +384,7 @@ static int dsps_musb_init(struct musb *musb) ...@@ -380,7 +384,7 @@ static int dsps_musb_init(struct musb *musb)
goto err0; goto err0;
} }
setup_timer(&glue->timer, otg_timer, (unsigned long) musb); setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);
/* Reset the musb */ /* Reset the musb */
dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
...@@ -411,10 +415,10 @@ static int dsps_musb_exit(struct musb *musb) ...@@ -411,10 +415,10 @@ static int dsps_musb_exit(struct musb *musb)
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data; struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data; struct omap_musb_board_data *data = plat->board_data;
struct platform_device *pdev = to_platform_device(dev->parent); struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = platform_get_drvdata(pdev); struct dsps_glue *glue = dev_get_drvdata(dev->parent);
del_timer_sync(&glue->timer); del_timer_sync(&glue->timer[pdev->id]);
/* Shutdown the on-chip PHY and its PLL. */ /* Shutdown the on-chip PHY and its PLL. */
if (data->set_phy_power) if (data->set_phy_power)
...@@ -493,7 +497,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) ...@@ -493,7 +497,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
musb->dev.dma_mask = &musb_dmamask; musb->dev.dma_mask = &musb_dmamask;
musb->dev.coherent_dma_mask = musb_dmamask; musb->dev.coherent_dma_mask = musb_dmamask;
glue->musb = musb; glue->musb[id] = musb;
pdata->platform_ops = &dsps_ops; pdata->platform_ops = &dsps_ops;
...@@ -525,11 +529,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) ...@@ -525,11 +529,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
return ret; return ret;
} }
static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue) static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id)
{ {
musb_put_id(glue->dev, glue->musb->id); musb_put_id(glue->dev, glue->musb[id]->id);
platform_device_del(glue->musb); platform_device_del(glue->musb[id]);
platform_device_put(glue->musb); platform_device_put(glue->musb[id]);
} }
static int __devinit dsps_probe(struct platform_device *pdev) static int __devinit dsps_probe(struct platform_device *pdev)
...@@ -539,7 +543,7 @@ static int __devinit dsps_probe(struct platform_device *pdev) ...@@ -539,7 +543,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)
(struct dsps_musb_wrapper *)id->driver_data; (struct dsps_musb_wrapper *)id->driver_data;
struct dsps_glue *glue; struct dsps_glue *glue;
struct resource *iomem; struct resource *iomem;
int ret; int ret, i;
/* allocate glue */ /* allocate glue */
glue = kzalloc(sizeof(*glue), GFP_KERNEL); glue = kzalloc(sizeof(*glue), GFP_KERNEL);
...@@ -580,7 +584,16 @@ static int __devinit dsps_probe(struct platform_device *pdev) ...@@ -580,7 +584,16 @@ static int __devinit dsps_probe(struct platform_device *pdev)
ret = pm_runtime_get_sync(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); dev_err(&pdev->dev, "pm_runtime_get_sync FAILED");
goto err3; /* create the child platform device for all instances of musb */
for (i = 0; i < wrp->instances ; i++) {
ret = dsps_create_musb_pdev(glue, i);
if (ret != 0) {
dev_err(&pdev->dev, "failed to create child pdev\n");
/* release resources of previously created instances */
for (i--; i >= 0 ; i--)
dsps_delete_musb_pdev(glue, i);
goto err3;
}
} }
return 0; return 0;
...@@ -597,9 +610,12 @@ static int __devinit dsps_probe(struct platform_device *pdev) ...@@ -597,9 +610,12 @@ static int __devinit dsps_probe(struct platform_device *pdev)
static int __devexit dsps_remove(struct platform_device *pdev) static int __devexit dsps_remove(struct platform_device *pdev)
{ {
struct dsps_glue *glue = platform_get_drvdata(pdev); struct dsps_glue *glue = platform_get_drvdata(pdev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
int i;
/* delete the child platform device */ /* delete the child platform device */
dsps_delete_musb_pdev(glue); for (i = 0; i < wrp->instances ; i++)
dsps_delete_musb_pdev(glue, i);
/* disable usbss clocks */ /* disable usbss clocks */
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
...@@ -665,6 +681,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { ...@@ -665,6 +681,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
.rxep_bitmap = (0xfffe << 16), .rxep_bitmap = (0xfffe << 16),
.musb_core_offset = 0x400, .musb_core_offset = 0x400,
.poll_seconds = 2, .poll_seconds = 2,
.instances = 2,
}; };
static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
......
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