Commit 1cd572fc authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'musb-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

usb: musb: patches for v3.7 merge window

Here we have a bunch of miscellaneous cleanups and fixes
to the musb driver. It fixes a bunch of mistakes errors
which nobody has triggered before, so I'm not Ccing stable
tree.

We are finally improving OMAP's VBUS/ID Mailbox usage so
that we can introduce our PHY drivers properly. Also, we're
adding support for multiple instances of the MUSB IP in
the same SoC, as seen on some platforms from TI which
have 2 MUSB instances.

Other than that, we have some small fixes like not kicking
DMA for a zero byte transfer, or properly handling NAK timeout
on MUSB's host side, and the enabling of DMA Mode1 for any
transfers which are aligned to wMaxPacketSize.

All patches have been pending on mailing list for a long time
and I don't expect any big surprises with this pull request.
parents e6d49d09 d8c3ef25
AM33XX MUSB GLUE
- compatible : Should be "ti,musb-am33xx"
- ti,hwmods : must be "usb_otg_hs"
- multipoint : Should be "1" indicating the musb controller supports
multipoint. This is a MUSB configuration-specific setting.
- num_eps : Specifies the number of endpoints. This is also a
MUSB configuration-specific setting. Should be set to "16"
- ram_bits : Specifies the ram address size. Should be set to "12"
- port0_mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
represents PERIPHERAL.
- port1_mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
represents PERIPHERAL.
- power : Should be "250". This signifies the controller can supply upto
500mA when operating in host mode.
OMAP GLUE
OMAP MUSB GLUE
- compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
- ti,hwmods : must be "usb_otg_hs"
- multipoint : Should be "1" indicating the musb controller supports
multipoint. This is a MUSB configuration-specific setting.
- num_eps : Specifies the number of endpoints. This is also a
MUSB configuration-specific setting. Should be set to "16"
- ram_bits : Specifies the ram address size. Should be set to "12"
- interface_type : This is a board specific setting to describe the type of
interface between the controller and the phy. It should be "0" or "1"
specifying ULPI and UTMI respectively.
- mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
represents PERIPHERAL.
- power : Should be "50". This signifies the controller can supply upto
100mA when operating in host mode.
SOC specific device node entry
usb_otg_hs: usb_otg_hs@4a0ab000 {
compatible = "ti,omap4-musb";
ti,hwmods = "usb_otg_hs";
multipoint = <1>;
num_eps = <16>;
ram_bits = <12>;
};
Board specific device node entry
&usb_otg_hs {
interface_type = <1>;
mode = <3>;
power = <50>;
};
...@@ -5890,6 +5890,12 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = { ...@@ -5890,6 +5890,12 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
.pa_end = 0x4a0ab003, .pa_end = 0x4a0ab003,
.flags = ADDR_TYPE_RT .flags = ADDR_TYPE_RT
}, },
{
/* XXX: Remove this once control module driver is in place */
.pa_start = 0x4a00233c,
.pa_end = 0x4a00233f,
.flags = ADDR_TYPE_RT
},
{ } { }
}; };
......
...@@ -19,7 +19,7 @@ config USB_MUSB_HDRC ...@@ -19,7 +19,7 @@ config USB_MUSB_HDRC
it's being used with, including the USB peripheral role, it's being used with, including the USB peripheral role,
or the USB host role, or both. or the USB host role, or both.
Texas Instruments familiies using this IP include DaVinci Texas Instruments families using this IP include DaVinci
(35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010.
Analog Devices parts using this IP include Blackfin BF54x, Analog Devices parts using this IP include Blackfin BF54x,
......
...@@ -108,9 +108,8 @@ static void am35x_musb_enable(struct musb *musb) ...@@ -108,9 +108,8 @@ static void am35x_musb_enable(struct musb *musb)
musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK); musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK);
/* Force the DRVVBUS IRQ so we can start polling for ID change. */ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
if (is_otg_enabled(musb)) musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
musb_writel(reg_base, CORE_INTR_SRC_SET_REG, AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
} }
/* /*
...@@ -174,9 +173,6 @@ static void otg_timer(unsigned long _musb) ...@@ -174,9 +173,6 @@ static void otg_timer(unsigned long _musb)
MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT); MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
break; break;
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
if (!is_peripheral_enabled(musb))
break;
devctl = musb_readb(mregs, MUSB_DEVCTL); devctl = musb_readb(mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
...@@ -193,9 +189,6 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) ...@@ -193,9 +189,6 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
{ {
static unsigned long last_timer; static unsigned long last_timer;
if (!is_otg_enabled(musb))
return;
if (timeout == 0) if (timeout == 0)
timeout = jiffies + msecs_to_jiffies(3); timeout = jiffies + msecs_to_jiffies(3);
...@@ -272,8 +265,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ...@@ -272,8 +265,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
u8 devctl = musb_readb(mregs, MUSB_DEVCTL); u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
int err; int err;
err = is_host_enabled(musb) && (musb->int_usb & err = musb->int_usb & MUSB_INTR_VBUSERROR;
MUSB_INTR_VBUSERROR);
if (err) { if (err) {
/* /*
* The Mentor core doesn't debounce VBUS as needed * The Mentor core doesn't debounce VBUS as needed
...@@ -290,7 +282,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ...@@ -290,7 +282,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n"); WARNING("VBUS error workaround (delay coming)\n");
} else if (is_host_enabled(musb) && drvvbus) { } else if (drvvbus) {
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
otg->default_a = 1; otg->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
...@@ -327,7 +319,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ...@@ -327,7 +319,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
} }
/* Poll for ID change */ /* Poll for ID change */
if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) if (musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -370,8 +362,7 @@ static int am35x_musb_init(struct musb *musb) ...@@ -370,8 +362,7 @@ static int am35x_musb_init(struct musb *musb)
if (IS_ERR_OR_NULL(musb->xceiv)) if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV; return -ENODEV;
if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
/* Reset the musb */ /* Reset the musb */
if (data->reset) if (data->reset)
...@@ -401,8 +392,7 @@ static int am35x_musb_exit(struct musb *musb) ...@@ -401,8 +392,7 @@ static int am35x_musb_exit(struct musb *musb)
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;
if (is_host_enabled(musb)) del_timer_sync(&otg_workaround);
del_timer_sync(&otg_workaround);
/* 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)
...@@ -469,6 +459,7 @@ static int __devinit am35x_probe(struct platform_device *pdev) ...@@ -469,6 +459,7 @@ static int __devinit am35x_probe(struct platform_device *pdev)
struct clk *clk; struct clk *clk;
int ret = -ENOMEM; int ret = -ENOMEM;
int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL); glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) { if (!glue) {
...@@ -476,38 +467,47 @@ static int __devinit am35x_probe(struct platform_device *pdev) ...@@ -476,38 +467,47 @@ static int __devinit am35x_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err1;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1; goto err2;
} }
phy_clk = clk_get(&pdev->dev, "fck"); phy_clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(phy_clk)) { if (IS_ERR(phy_clk)) {
dev_err(&pdev->dev, "failed to get PHY clock\n"); dev_err(&pdev->dev, "failed to get PHY clock\n");
ret = PTR_ERR(phy_clk); ret = PTR_ERR(phy_clk);
goto err2; goto err3;
} }
clk = clk_get(&pdev->dev, "ick"); clk = clk_get(&pdev->dev, "ick");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n"); dev_err(&pdev->dev, "failed to get clock\n");
ret = PTR_ERR(clk); ret = PTR_ERR(clk);
goto err3; goto err4;
} }
ret = clk_enable(phy_clk); ret = clk_enable(phy_clk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to enable PHY clock\n"); dev_err(&pdev->dev, "failed to enable PHY clock\n");
goto err4; goto err5;
} }
ret = clk_enable(clk); ret = clk_enable(clk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n"); dev_err(&pdev->dev, "failed to enable clock\n");
goto err5; goto err6;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &am35x_dmamask; musb->dev.dma_mask = &am35x_dmamask;
musb->dev.coherent_dma_mask = am35x_dmamask; musb->dev.coherent_dma_mask = am35x_dmamask;
...@@ -525,38 +525,41 @@ static int __devinit am35x_probe(struct platform_device *pdev) ...@@ -525,38 +525,41 @@ static int __devinit am35x_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err6; goto err7;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err6; goto err7;
} }
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err6; goto err7;
} }
return 0; return 0;
err6: err7:
clk_disable(clk); clk_disable(clk);
err5: err6:
clk_disable(phy_clk); clk_disable(phy_clk);
err4: err5:
clk_put(clk); clk_put(clk);
err3: err4:
clk_put(phy_clk); clk_put(phy_clk);
err2: err3:
platform_device_put(musb); platform_device_put(musb);
err2:
musb_put_id(&pdev->dev, musbid);
err1: err1:
kfree(glue); kfree(glue);
...@@ -568,6 +571,7 @@ static int __devexit am35x_remove(struct platform_device *pdev) ...@@ -568,6 +571,7 @@ static int __devexit am35x_remove(struct platform_device *pdev)
{ {
struct am35x_glue *glue = platform_get_drvdata(pdev); struct am35x_glue *glue = platform_get_drvdata(pdev);
musb_put_id(&pdev->dev, glue->musb->id);
platform_device_del(glue->musb); platform_device_del(glue->musb);
platform_device_put(glue->musb); platform_device_put(glue->musb);
clk_disable(glue->clk); clk_disable(glue->clk);
......
...@@ -185,8 +185,8 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci) ...@@ -185,8 +185,8 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci)
} }
/* Start sampling ID pin, when plug is removed from MUSB */ /* Start sampling ID pin, when plug is removed from MUSB */
if ((is_otg_enabled(musb) && (musb->xceiv->state == OTG_STATE_B_IDLE if ((musb->xceiv->state == OTG_STATE_B_IDLE
|| musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) || || musb->xceiv->state == OTG_STATE_A_WAIT_BCON) ||
(musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) { (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) {
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
musb->a_wait_bcon = TIMER_DELAY; musb->a_wait_bcon = TIMER_DELAY;
...@@ -229,18 +229,13 @@ static void musb_conn_timer_handler(unsigned long _musb) ...@@ -229,18 +229,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR;
musb_writeb(musb->mregs, MUSB_INTRUSB, val); musb_writeb(musb->mregs, MUSB_INTRUSB, val);
if (is_otg_enabled(musb)) musb->xceiv->state = OTG_STATE_B_IDLE;
musb->xceiv->state = OTG_STATE_B_IDLE;
else
musb_writeb(musb->mregs, MUSB_POWER, MUSB_POWER_HSENAB);
} }
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
break; break;
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
/*
if (!is_peripheral_enabled(musb)) * Start a new session. It seems that MUSB needs taking
break;
/* Start a new session. It seems that MUSB needs taking
* some time to recognize the type of the plug inserted? * some time to recognize the type of the plug inserted?
*/ */
val = musb_readw(musb->mregs, MUSB_DEVCTL); val = musb_readw(musb->mregs, MUSB_DEVCTL);
...@@ -296,10 +291,7 @@ static void musb_conn_timer_handler(unsigned long _musb) ...@@ -296,10 +291,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
static void bfin_musb_enable(struct musb *musb) static void bfin_musb_enable(struct musb *musb)
{ {
if (!is_otg_enabled(musb) && is_host_enabled(musb)) { /* REVISIT is this really correct ? */
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
musb->a_wait_bcon = TIMER_DELAY;
}
} }
static void bfin_musb_disable(struct musb *musb) static void bfin_musb_disable(struct musb *musb)
...@@ -324,12 +316,6 @@ static int bfin_musb_set_power(struct usb_phy *x, unsigned mA) ...@@ -324,12 +316,6 @@ static int bfin_musb_set_power(struct usb_phy *x, unsigned mA)
return 0; return 0;
} }
static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout)
{
if (!is_otg_enabled(musb) && is_host_enabled(musb))
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
}
static int bfin_musb_vbus_status(struct musb *musb) static int bfin_musb_vbus_status(struct musb *musb)
{ {
return 0; return 0;
...@@ -425,12 +411,10 @@ static int bfin_musb_init(struct musb *musb) ...@@ -425,12 +411,10 @@ static int bfin_musb_init(struct musb *musb)
bfin_musb_reg_init(musb); bfin_musb_reg_init(musb);
if (is_host_enabled(musb)) { setup_timer(&musb_conn_timer, musb_conn_timer_handler,
setup_timer(&musb_conn_timer, (unsigned long) musb);
musb_conn_timer_handler, (unsigned long) musb);
} musb->xceiv->set_power = bfin_musb_set_power;
if (is_peripheral_enabled(musb))
musb->xceiv->set_power = bfin_musb_set_power;
musb->isr = blackfin_interrupt; musb->isr = blackfin_interrupt;
musb->double_buffer_not_ok = true; musb->double_buffer_not_ok = true;
...@@ -455,7 +439,6 @@ static const struct musb_platform_ops bfin_ops = { ...@@ -455,7 +439,6 @@ static const struct musb_platform_ops bfin_ops = {
.disable = bfin_musb_disable, .disable = bfin_musb_disable,
.set_mode = bfin_musb_set_mode, .set_mode = bfin_musb_set_mode,
.try_idle = bfin_musb_try_idle,
.vbus_status = bfin_musb_vbus_status, .vbus_status = bfin_musb_vbus_status,
.set_vbus = bfin_musb_set_vbus, .set_vbus = bfin_musb_set_vbus,
...@@ -472,6 +455,7 @@ static int __devinit bfin_probe(struct platform_device *pdev) ...@@ -472,6 +455,7 @@ static int __devinit bfin_probe(struct platform_device *pdev)
struct bfin_glue *glue; struct bfin_glue *glue;
int ret = -ENOMEM; int ret = -ENOMEM;
int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL); glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) { if (!glue) {
...@@ -479,12 +463,21 @@ static int __devinit bfin_probe(struct platform_device *pdev) ...@@ -479,12 +463,21 @@ static int __devinit bfin_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err1;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1; goto err2;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &bfin_dmamask; musb->dev.dma_mask = &bfin_dmamask;
musb->dev.coherent_dma_mask = bfin_dmamask; musb->dev.coherent_dma_mask = bfin_dmamask;
...@@ -500,26 +493,29 @@ static int __devinit bfin_probe(struct platform_device *pdev) ...@@ -500,26 +493,29 @@ static int __devinit bfin_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err2; goto err3;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err2; goto err3;
} }
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err2; goto err3;
} }
return 0; return 0;
err2: err3:
platform_device_put(musb); platform_device_put(musb);
err2:
musb_put_id(&pdev->dev, musbid);
err1: err1:
kfree(glue); kfree(glue);
...@@ -531,6 +527,7 @@ static int __devexit bfin_remove(struct platform_device *pdev) ...@@ -531,6 +527,7 @@ static int __devexit bfin_remove(struct platform_device *pdev)
{ {
struct bfin_glue *glue = platform_get_drvdata(pdev); struct bfin_glue *glue = platform_get_drvdata(pdev);
musb_put_id(&pdev->dev, glue->musb->id);
platform_device_del(glue->musb); platform_device_del(glue->musb);
platform_device_put(glue->musb); platform_device_put(glue->musb);
kfree(glue); kfree(glue);
......
...@@ -1316,7 +1316,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) ...@@ -1316,7 +1316,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
} }
/* Instantiate a software object representing a DMA controller. */ /* Instantiate a software object representing a DMA controller. */
struct dma_controller *__init struct dma_controller *__devinit
dma_controller_create(struct musb *musb, void __iomem *mregs) dma_controller_create(struct musb *musb, void __iomem *mregs)
{ {
struct cppi *controller; struct cppi *controller;
......
...@@ -156,9 +156,8 @@ static void da8xx_musb_enable(struct musb *musb) ...@@ -156,9 +156,8 @@ static void da8xx_musb_enable(struct musb *musb)
musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask); musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask);
/* Force the DRVVBUS IRQ so we can start polling for ID change. */ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
if (is_otg_enabled(musb)) musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG,
musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG, DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT);
DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT);
} }
/** /**
...@@ -232,9 +231,6 @@ static void otg_timer(unsigned long _musb) ...@@ -232,9 +231,6 @@ static void otg_timer(unsigned long _musb)
MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT); MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT);
break; break;
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
if (!is_peripheral_enabled(musb))
break;
/* /*
* There's no ID-changed IRQ, so we have no good way to tell * There's no ID-changed IRQ, so we have no good way to tell
* when to switch to the A-Default state machine (by setting * when to switch to the A-Default state machine (by setting
...@@ -264,9 +260,6 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) ...@@ -264,9 +260,6 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
{ {
static unsigned long last_timer; static unsigned long last_timer;
if (!is_otg_enabled(musb))
return;
if (timeout == 0) if (timeout == 0)
timeout = jiffies + msecs_to_jiffies(3); timeout = jiffies + msecs_to_jiffies(3);
...@@ -334,8 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) ...@@ -334,8 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
u8 devctl = musb_readb(mregs, MUSB_DEVCTL); u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
int err; int err;
err = is_host_enabled(musb) && (musb->int_usb & err = musb->int_usb & USB_INTR_VBUSERROR;
MUSB_INTR_VBUSERROR);
if (err) { if (err) {
/* /*
* The Mentor core doesn't debounce VBUS as needed * The Mentor core doesn't debounce VBUS as needed
...@@ -352,7 +344,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) ...@@ -352,7 +344,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n"); WARNING("VBUS error workaround (delay coming)\n");
} else if (is_host_enabled(musb) && drvvbus) { } else if (drvvbus) {
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
otg->default_a = 1; otg->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
...@@ -383,7 +375,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) ...@@ -383,7 +375,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
/* Poll for ID change */ /* Poll for ID change */
if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) if (musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -431,8 +423,7 @@ static int da8xx_musb_init(struct musb *musb) ...@@ -431,8 +423,7 @@ static int da8xx_musb_init(struct musb *musb)
if (IS_ERR_OR_NULL(musb->xceiv)) if (IS_ERR_OR_NULL(musb->xceiv))
goto fail; goto fail;
if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
/* Reset the controller */ /* Reset the controller */
musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
...@@ -455,8 +446,7 @@ static int da8xx_musb_init(struct musb *musb) ...@@ -455,8 +446,7 @@ static int da8xx_musb_init(struct musb *musb)
static int da8xx_musb_exit(struct musb *musb) static int da8xx_musb_exit(struct musb *musb)
{ {
if (is_host_enabled(musb)) del_timer_sync(&otg_workaround);
del_timer_sync(&otg_workaround);
phy_off(); phy_off();
...@@ -490,6 +480,7 @@ static int __devinit da8xx_probe(struct platform_device *pdev) ...@@ -490,6 +480,7 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
struct clk *clk; struct clk *clk;
int ret = -ENOMEM; int ret = -ENOMEM;
int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL); glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) { if (!glue) {
...@@ -497,25 +488,34 @@ static int __devinit da8xx_probe(struct platform_device *pdev) ...@@ -497,25 +488,34 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err1;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1; goto err2;
} }
clk = clk_get(&pdev->dev, "usb20"); clk = clk_get(&pdev->dev, "usb20");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n"); dev_err(&pdev->dev, "failed to get clock\n");
ret = PTR_ERR(clk); ret = PTR_ERR(clk);
goto err2; goto err3;
} }
ret = clk_enable(clk); ret = clk_enable(clk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n"); dev_err(&pdev->dev, "failed to enable clock\n");
goto err3; goto err4;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &da8xx_dmamask; musb->dev.dma_mask = &da8xx_dmamask;
musb->dev.coherent_dma_mask = da8xx_dmamask; musb->dev.coherent_dma_mask = da8xx_dmamask;
...@@ -532,32 +532,35 @@ static int __devinit da8xx_probe(struct platform_device *pdev) ...@@ -532,32 +532,35 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err4; goto err5;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err4; goto err5;
} }
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err4; goto err5;
} }
return 0; return 0;
err4: err5:
clk_disable(clk); clk_disable(clk);
err3: err4:
clk_put(clk); clk_put(clk);
err2: err3:
platform_device_put(musb); platform_device_put(musb);
err2:
musb_put_id(&pdev->dev, musbid);
err1: err1:
kfree(glue); kfree(glue);
...@@ -569,6 +572,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev) ...@@ -569,6 +572,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev)
{ {
struct da8xx_glue *glue = platform_get_drvdata(pdev); struct da8xx_glue *glue = platform_get_drvdata(pdev);
musb_put_id(&pdev->dev, glue->musb->id);
platform_device_del(glue->musb); platform_device_del(glue->musb);
platform_device_put(glue->musb); platform_device_put(glue->musb);
clk_disable(glue->clk); clk_disable(glue->clk);
......
...@@ -116,8 +116,7 @@ static void davinci_musb_enable(struct musb *musb) ...@@ -116,8 +116,7 @@ static void davinci_musb_enable(struct musb *musb)
dma_off = 0; dma_off = 0;
/* force a DRVVBUS irq so we can start polling for ID change */ /* force a DRVVBUS irq so we can start polling for ID change */
if (is_otg_enabled(musb)) musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT); DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT);
} }
...@@ -235,10 +234,8 @@ static void otg_timer(unsigned long _musb) ...@@ -235,10 +234,8 @@ static void otg_timer(unsigned long _musb)
MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
break; break;
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
if (!is_peripheral_enabled(musb)) /*
break; * There's no ID-changed IRQ, so we have no good way to tell
/* There's no ID-changed IRQ, so we have no good way to tell
* when to switch to the A-Default state machine (by setting * when to switch to the A-Default state machine (by setting
* the DEVCTL.SESSION flag). * the DEVCTL.SESSION flag).
* *
...@@ -316,8 +313,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) ...@@ -316,8 +313,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
u8 devctl = musb_readb(mregs, MUSB_DEVCTL); u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
int err = musb->int_usb & MUSB_INTR_VBUSERROR; int err = musb->int_usb & MUSB_INTR_VBUSERROR;
err = is_host_enabled(musb) err = musb->int_usb & MUSB_INTR_VBUSERROR;
&& (musb->int_usb & MUSB_INTR_VBUSERROR);
if (err) { if (err) {
/* The Mentor core doesn't debounce VBUS as needed /* The Mentor core doesn't debounce VBUS as needed
* to cope with device connect current spikes. This * to cope with device connect current spikes. This
...@@ -333,7 +329,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) ...@@ -333,7 +329,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n"); WARNING("VBUS error workaround (delay coming)\n");
} else if (is_host_enabled(musb) && drvvbus) { } else if (drvvbus) {
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
otg->default_a = 1; otg->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
...@@ -366,8 +362,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) ...@@ -366,8 +362,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
musb_writel(tibase, DAVINCI_USB_EOI_REG, 0); musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
/* poll for ID change */ /* poll for ID change */
if (is_otg_enabled(musb) if (musb->xceiv->state == OTG_STATE_B_IDLE)
&& musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -398,8 +393,7 @@ static int davinci_musb_init(struct musb *musb) ...@@ -398,8 +393,7 @@ static int davinci_musb_init(struct musb *musb)
if (revision == 0) if (revision == 0)
goto fail; goto fail;
if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
davinci_musb_source_power(musb, 0, 1); davinci_musb_source_power(musb, 0, 1);
...@@ -420,12 +414,7 @@ static int davinci_musb_init(struct musb *musb) ...@@ -420,12 +414,7 @@ static int davinci_musb_init(struct musb *musb)
if (cpu_is_davinci_dm355()) { if (cpu_is_davinci_dm355()) {
u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); u32 deepsleep = __raw_readl(DM355_DEEPSLEEP);
if (is_host_enabled(musb)) { deepsleep &= ~DRVVBUS_FORCE;
deepsleep &= ~DRVVBUS_OVERRIDE;
} else {
deepsleep &= ~DRVVBUS_FORCE;
deepsleep |= DRVVBUS_OVERRIDE;
}
__raw_writel(deepsleep, DM355_DEEPSLEEP); __raw_writel(deepsleep, DM355_DEEPSLEEP);
} }
...@@ -454,8 +443,7 @@ static int davinci_musb_init(struct musb *musb) ...@@ -454,8 +443,7 @@ static int davinci_musb_init(struct musb *musb)
static int davinci_musb_exit(struct musb *musb) static int davinci_musb_exit(struct musb *musb)
{ {
if (is_host_enabled(musb)) del_timer_sync(&otg_workaround);
del_timer_sync(&otg_workaround);
/* force VBUS off */ /* force VBUS off */
if (cpu_is_davinci_dm355()) { if (cpu_is_davinci_dm355()) {
...@@ -469,7 +457,7 @@ static int davinci_musb_exit(struct musb *musb) ...@@ -469,7 +457,7 @@ static int davinci_musb_exit(struct musb *musb)
davinci_musb_source_power(musb, 0 /*off*/, 1); davinci_musb_source_power(musb, 0 /*off*/, 1);
/* delay, to avoid problems with module reload */ /* delay, to avoid problems with module reload */
if (is_host_enabled(musb) && musb->xceiv->otg->default_a) { if (musb->xceiv->otg->default_a) {
int maxdelay = 30; int maxdelay = 30;
u8 devctl, warn = 0; u8 devctl, warn = 0;
...@@ -524,6 +512,7 @@ static int __devinit davinci_probe(struct platform_device *pdev) ...@@ -524,6 +512,7 @@ static int __devinit davinci_probe(struct platform_device *pdev)
struct clk *clk; struct clk *clk;
int ret = -ENOMEM; int ret = -ENOMEM;
int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL); glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) { if (!glue) {
...@@ -531,25 +520,34 @@ static int __devinit davinci_probe(struct platform_device *pdev) ...@@ -531,25 +520,34 @@ static int __devinit davinci_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err1;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1; goto err2;
} }
clk = clk_get(&pdev->dev, "usb"); clk = clk_get(&pdev->dev, "usb");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n"); dev_err(&pdev->dev, "failed to get clock\n");
ret = PTR_ERR(clk); ret = PTR_ERR(clk);
goto err2; goto err3;
} }
ret = clk_enable(clk); ret = clk_enable(clk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n"); dev_err(&pdev->dev, "failed to enable clock\n");
goto err3; goto err4;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &davinci_dmamask; musb->dev.dma_mask = &davinci_dmamask;
musb->dev.coherent_dma_mask = davinci_dmamask; musb->dev.coherent_dma_mask = davinci_dmamask;
...@@ -566,32 +564,35 @@ static int __devinit davinci_probe(struct platform_device *pdev) ...@@ -566,32 +564,35 @@ static int __devinit davinci_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err4; goto err5;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err4; goto err5;
} }
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err4; goto err5;
} }
return 0; return 0;
err4: err5:
clk_disable(clk); clk_disable(clk);
err3: err4:
clk_put(clk); clk_put(clk);
err2: err3:
platform_device_put(musb); platform_device_put(musb);
err2:
musb_put_id(&pdev->dev, musbid);
err1: err1:
kfree(glue); kfree(glue);
...@@ -603,6 +604,7 @@ static int __devexit davinci_remove(struct platform_device *pdev) ...@@ -603,6 +604,7 @@ static int __devexit davinci_remove(struct platform_device *pdev)
{ {
struct davinci_glue *glue = platform_get_drvdata(pdev); struct davinci_glue *glue = platform_get_drvdata(pdev);
musb_put_id(&pdev->dev, glue->musb->id);
platform_device_del(glue->musb); platform_device_del(glue->musb);
platform_device_put(glue->musb); platform_device_put(glue->musb);
clk_disable(glue->clk); clk_disable(glue->clk);
......
This diff is collapsed.
...@@ -71,10 +71,6 @@ struct musb_ep; ...@@ -71,10 +71,6 @@ struct musb_ep;
#include <linux/usb/hcd.h> #include <linux/usb/hcd.h>
#include "musb_host.h" #include "musb_host.h"
#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL)
#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG)
/* NOTE: otg and peripheral-only state machines start at B_IDLE. /* NOTE: otg and peripheral-only state machines start at B_IDLE.
* OTG or host-only go to A_IDLE when ID is sensed. * OTG or host-only go to A_IDLE when ID is sensed.
*/ */
...@@ -88,8 +84,6 @@ struct musb_ep; ...@@ -88,8 +84,6 @@ struct musb_ep;
/****************************** PERIPHERAL ROLE *****************************/ /****************************** PERIPHERAL ROLE *****************************/
#define is_peripheral_capable() (1)
extern irqreturn_t musb_g_ep0_irq(struct musb *); extern irqreturn_t musb_g_ep0_irq(struct musb *);
extern void musb_g_tx(struct musb *, u8); extern void musb_g_tx(struct musb *, u8);
extern void musb_g_rx(struct musb *, u8); extern void musb_g_rx(struct musb *, u8);
...@@ -101,8 +95,6 @@ extern void musb_g_disconnect(struct musb *); ...@@ -101,8 +95,6 @@ extern void musb_g_disconnect(struct musb *);
/****************************** HOST ROLE ***********************************/ /****************************** HOST ROLE ***********************************/
#define is_host_capable() (1)
extern irqreturn_t musb_h_ep0_irq(struct musb *); extern irqreturn_t musb_h_ep0_irq(struct musb *);
extern void musb_host_tx(struct musb *, u8); extern void musb_host_tx(struct musb *, u8);
extern void musb_host_rx(struct musb *, u8); extern void musb_host_rx(struct musb *, u8);
...@@ -376,7 +368,6 @@ struct musb { ...@@ -376,7 +368,6 @@ struct musb {
u16 epmask; u16 epmask;
u8 nr_endpoints; u8 nr_endpoints;
u8 board_mode; /* enum musb_mode */
int (*board_set_power)(int state); int (*board_set_power)(int state);
u8 min_power; /* vbus for periph, in mA/2 */ u8 min_power; /* vbus for periph, in mA/2 */
...@@ -445,6 +436,10 @@ struct musb { ...@@ -445,6 +436,10 @@ struct musb {
#ifdef MUSB_CONFIG_PROC_FS #ifdef MUSB_CONFIG_PROC_FS
struct proc_dir_entry *proc_entry; struct proc_dir_entry *proc_entry;
#endif
int xceiv_old_state;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
#endif #endif
}; };
...@@ -484,7 +479,7 @@ static inline void musb_configure_ep0(struct musb *musb) ...@@ -484,7 +479,7 @@ static inline void musb_configure_ep0(struct musb *musb)
static inline int musb_read_fifosize(struct musb *musb, static inline int musb_read_fifosize(struct musb *musb,
struct musb_hw_ep *hw_ep, u8 epnum) struct musb_hw_ep *hw_ep, u8 epnum)
{ {
void *mbase = musb->mregs; void __iomem *mbase = musb->mregs;
u8 reg = 0; u8 reg = 0;
/* read from core using indexed model */ /* read from core using indexed model */
...@@ -526,6 +521,8 @@ extern const char musb_driver_name[]; ...@@ -526,6 +521,8 @@ extern const char musb_driver_name[];
extern void musb_start(struct musb *musb); extern void musb_start(struct musb *musb);
extern void musb_stop(struct musb *musb); extern void musb_stop(struct musb *musb);
extern int musb_get_id(struct device *dev, gfp_t gfp_mask);
extern void musb_put_id(struct device *dev, int id);
extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
......
...@@ -103,8 +103,6 @@ static const struct musb_register_map musb_regmap[] = { ...@@ -103,8 +103,6 @@ static const struct musb_register_map musb_regmap[] = {
{ } /* Terminating Entry */ { } /* Terminating Entry */
}; };
static struct dentry *musb_debugfs_root;
static int musb_regdump_show(struct seq_file *s, void *unused) static int musb_regdump_show(struct seq_file *s, void *unused)
{ {
struct musb *musb = s->private; struct musb *musb = s->private;
...@@ -241,7 +239,7 @@ int __devinit musb_init_debugfs(struct musb *musb) ...@@ -241,7 +239,7 @@ int __devinit musb_init_debugfs(struct musb *musb)
struct dentry *file; struct dentry *file;
int ret; int ret;
root = debugfs_create_dir("musb", NULL); root = debugfs_create_dir(dev_name(musb->controller), NULL);
if (!root) { if (!root) {
ret = -ENOMEM; ret = -ENOMEM;
goto err0; goto err0;
...@@ -261,7 +259,7 @@ int __devinit musb_init_debugfs(struct musb *musb) ...@@ -261,7 +259,7 @@ int __devinit musb_init_debugfs(struct musb *musb)
goto err1; goto err1;
} }
musb_debugfs_root = root; musb->debugfs_root = root;
return 0; return 0;
...@@ -274,5 +272,5 @@ int __devinit musb_init_debugfs(struct musb *musb) ...@@ -274,5 +272,5 @@ int __devinit musb_init_debugfs(struct musb *musb)
void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb) void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb)
{ {
debugfs_remove_recursive(musb_debugfs_root); debugfs_remove_recursive(musb->debugfs_root);
} }
...@@ -178,7 +178,7 @@ struct dma_controller { ...@@ -178,7 +178,7 @@ struct dma_controller {
extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit); extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
extern struct dma_controller *__init extern struct dma_controller *__devinit
dma_controller_create(struct musb *, void __iomem *); dma_controller_create(struct musb *, void __iomem *);
extern void dma_controller_destroy(struct dma_controller *); extern void dma_controller_destroy(struct dma_controller *);
......
This diff is collapsed.
...@@ -373,7 +373,7 @@ static void txstate(struct musb *musb, struct musb_request *req) ...@@ -373,7 +373,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
request_size = min_t(size_t, request->length - request->actual, request_size = min_t(size_t, request->length - request->actual,
musb_ep->dma->max_len); musb_ep->dma->max_len);
use_dma = (request->dma != DMA_ADDR_INVALID); use_dma = (request->dma != DMA_ADDR_INVALID && request_size);
/* MUSB_TXCSR_P_ISO is still set correctly */ /* MUSB_TXCSR_P_ISO is still set correctly */
...@@ -644,8 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -644,8 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
struct usb_request *request = &req->request; struct usb_request *request = &req->request;
struct musb_ep *musb_ep; struct musb_ep *musb_ep;
void __iomem *epio = musb->endpoints[epnum].regs; void __iomem *epio = musb->endpoints[epnum].regs;
unsigned fifo_count = 0; unsigned len = 0;
u16 len; u16 fifo_count;
u16 csr = musb_readw(epio, MUSB_RXCSR); u16 csr = musb_readw(epio, MUSB_RXCSR);
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
u8 use_mode_1; u8 use_mode_1;
...@@ -655,7 +655,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -655,7 +655,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
else else
musb_ep = &hw_ep->ep_out; musb_ep = &hw_ep->ep_out;
len = musb_ep->packet_sz; fifo_count = musb_ep->packet_sz;
/* Check if EP is disabled */ /* Check if EP is disabled */
if (!musb_ep->desc) { if (!musb_ep->desc) {
...@@ -704,15 +704,14 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -704,15 +704,14 @@ static void rxstate(struct musb *musb, struct musb_request *req)
} }
if (csr & MUSB_RXCSR_RXPKTRDY) { if (csr & MUSB_RXCSR_RXPKTRDY) {
len = musb_readw(epio, MUSB_RXCOUNT); fifo_count = musb_readw(epio, MUSB_RXCOUNT);
/* /*
* Enable Mode 1 on RX transfers only when short_not_ok flag * use mode 1 only if we expect data of at least ep packet_sz
* is set. Currently short_not_ok flag is set only from * and have not yet received a short packet
* file_storage and f_mass_storage drivers
*/ */
if ((request->length - request->actual >= musb_ep->packet_sz) &&
if (request->short_not_ok && len == musb_ep->packet_sz) (fifo_count >= musb_ep->packet_sz))
use_mode_1 = 1; use_mode_1 = 1;
else else
use_mode_1 = 0; use_mode_1 = 0;
...@@ -723,31 +722,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -723,31 +722,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
struct dma_controller *c; struct dma_controller *c;
struct dma_channel *channel; struct dma_channel *channel;
int use_dma = 0; int use_dma = 0;
int transfer_size;
c = musb->dma_controller; c = musb->dma_controller;
channel = musb_ep->dma; channel = musb_ep->dma;
/* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
* mode 0 only. So we do not get endpoint interrupts due to DMA
* completion. We only get interrupts from DMA controller.
*
* We could operate in DMA mode 1 if we knew the size of the tranfer
* in advance. For mass storage class, request->length = what the host
* sends, so that'd work. But for pretty much everything else,
* request->length is routinely more than what the host sends. For
* most these gadgets, end of is signified either by a short packet,
* or filling the last byte of the buffer. (Sending extra data in
* that last pckate should trigger an overflow fault.) But in mode 1,
* we don't get DMA completion interrupt for short packets.
*
* Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
* to get endpoint interrupt on every DMA req, but that didn't seem
* to work reliably.
*
* REVISIT an updated g_file_storage can set req->short_not_ok, which
* then becomes usable as a runtime "use mode 1" hint...
*/
/* Experimental: Mode1 works with mass storage use cases */ /* Experimental: Mode1 works with mass storage use cases */
if (use_mode_1) { if (use_mode_1) {
csr |= MUSB_RXCSR_AUTOCLEAR; csr |= MUSB_RXCSR_AUTOCLEAR;
...@@ -764,35 +743,30 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -764,35 +743,30 @@ static void rxstate(struct musb *musb, struct musb_request *req)
csr | MUSB_RXCSR_DMAMODE); csr | MUSB_RXCSR_DMAMODE);
musb_writew(epio, MUSB_RXCSR, csr); musb_writew(epio, MUSB_RXCSR, csr);
transfer_size = min(request->length - request->actual,
channel->max_len);
musb_ep->dma->desired_mode = 1;
} else { } else {
if (!musb_ep->hb_mult && if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered) musb_ep->hw_ep->rx_double_buffered)
csr |= MUSB_RXCSR_AUTOCLEAR; csr |= MUSB_RXCSR_AUTOCLEAR;
csr |= MUSB_RXCSR_DMAENAB; csr |= MUSB_RXCSR_DMAENAB;
musb_writew(epio, MUSB_RXCSR, csr); musb_writew(epio, MUSB_RXCSR, csr);
}
if (request->actual < request->length) { transfer_size = min(request->length - request->actual,
int transfer_size = 0; (unsigned)fifo_count);
if (use_mode_1) { musb_ep->dma->desired_mode = 0;
transfer_size = min(request->length - request->actual,
channel->max_len);
musb_ep->dma->desired_mode = 1;
} else {
transfer_size = min(request->length - request->actual,
(unsigned)len);
musb_ep->dma->desired_mode = 0;
}
use_dma = c->channel_program(
channel,
musb_ep->packet_sz,
channel->desired_mode,
request->dma
+ request->actual,
transfer_size);
} }
use_dma = c->channel_program(
channel,
musb_ep->packet_sz,
channel->desired_mode,
request->dma
+ request->actual,
transfer_size);
if (use_dma) if (use_dma)
return; return;
} }
...@@ -808,8 +782,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -808,8 +782,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
channel = musb_ep->dma; channel = musb_ep->dma;
/* In case first packet is short */ /* In case first packet is short */
if (len < musb_ep->packet_sz) if (fifo_count < musb_ep->packet_sz)
transfer_size = len; transfer_size = fifo_count;
else if (request->short_not_ok) else if (request->short_not_ok)
transfer_size = min(request->length - transfer_size = min(request->length -
request->actual, request->actual,
...@@ -817,7 +791,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -817,7 +791,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
else else
transfer_size = min(request->length - transfer_size = min(request->length -
request->actual, request->actual,
(unsigned)len); (unsigned)fifo_count);
csr &= ~MUSB_RXCSR_DMAMODE; csr &= ~MUSB_RXCSR_DMAMODE;
csr |= (MUSB_RXCSR_DMAENAB | csr |= (MUSB_RXCSR_DMAENAB |
...@@ -845,10 +819,10 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -845,10 +819,10 @@ static void rxstate(struct musb *musb, struct musb_request *req)
} }
#endif /* Mentor's DMA */ #endif /* Mentor's DMA */
fifo_count = request->length - request->actual; len = request->length - request->actual;
dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n", dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
musb_ep->end_point.name, musb_ep->end_point.name,
len, fifo_count, fifo_count, len,
musb_ep->packet_sz); musb_ep->packet_sz);
fifo_count = min_t(unsigned, len, fifo_count); fifo_count = min_t(unsigned, len, fifo_count);
...@@ -901,7 +875,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -901,7 +875,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
} }
/* reach the end or short packet detected */ /* reach the end or short packet detected */
if (request->actual == request->length || len < musb_ep->packet_sz) if (request->actual == request->length ||
fifo_count < musb_ep->packet_sz)
musb_g_giveback(musb_ep, request, 0); musb_g_giveback(musb_ep, request, 0);
} }
...@@ -1885,8 +1860,7 @@ int __devinit musb_gadget_setup(struct musb *musb) ...@@ -1885,8 +1860,7 @@ int __devinit musb_gadget_setup(struct musb *musb)
musb->g.dev.release = musb_gadget_release; musb->g.dev.release = musb_gadget_release;
musb->g.name = musb_driver_name; musb->g.name = musb_driver_name;
if (is_otg_enabled(musb)) musb->g.is_otg = 1;
musb->g.is_otg = 1;
musb_g_init_endpoints(musb); musb_g_init_endpoints(musb);
...@@ -1932,11 +1906,14 @@ static int musb_gadget_start(struct usb_gadget *g, ...@@ -1932,11 +1906,14 @@ static int musb_gadget_start(struct usb_gadget *g,
{ {
struct musb *musb = gadget_to_musb(g); struct musb *musb = gadget_to_musb(g);
struct usb_otg *otg = musb->xceiv->otg; struct usb_otg *otg = musb->xceiv->otg;
struct usb_hcd *hcd = musb_to_hcd(musb);
unsigned long flags; unsigned long flags;
int retval = -EINVAL; int retval = 0;
if (driver->max_speed < USB_SPEED_HIGH) if (driver->max_speed < USB_SPEED_HIGH) {
goto err0; retval = -EINVAL;
goto err;
}
pm_runtime_get_sync(musb->controller); pm_runtime_get_sync(musb->controller);
...@@ -1950,49 +1927,30 @@ static int musb_gadget_start(struct usb_gadget *g, ...@@ -1950,49 +1927,30 @@ static int musb_gadget_start(struct usb_gadget *g,
otg_set_peripheral(otg, &musb->g); otg_set_peripheral(otg, &musb->g);
musb->xceiv->state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
/*
* FIXME this ignores the softconnect flag. Drivers are
* allowed hold the peripheral inactive until for example
* userspace hooks up printer hardware or DSP codecs, so
* hosts only see fully functional devices.
*/
if (!is_otg_enabled(musb))
musb_start(musb);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) { /* REVISIT: funcall to other code, which also
struct usb_hcd *hcd = musb_to_hcd(musb); * handles power budgeting ... this way also
* ensures HdrcStart is indirectly called.
dev_dbg(musb->controller, "OTG startup...\n"); */
retval = usb_add_hcd(hcd, 0, 0);
if (retval < 0) {
dev_dbg(musb->controller, "add_hcd failed, %d\n", retval);
goto err;
}
/* REVISIT: funcall to other code, which also if ((musb->xceiv->last_event == USB_EVENT_ID)
* handles power budgeting ... this way also && otg->set_vbus)
* ensures HdrcStart is indirectly called. otg_set_vbus(otg, 1);
*/
retval = usb_add_hcd(musb_to_hcd(musb), 0, 0);
if (retval < 0) {
dev_dbg(musb->controller, "add_hcd failed, %d\n", retval);
goto err2;
}
if ((musb->xceiv->last_event == USB_EVENT_ID) hcd->self.uses_pio_for_control = 1;
&& otg->set_vbus)
otg_set_vbus(otg, 1);
hcd->self.uses_pio_for_control = 1;
}
if (musb->xceiv->last_event == USB_EVENT_NONE) if (musb->xceiv->last_event == USB_EVENT_NONE)
pm_runtime_put(musb->controller); pm_runtime_put(musb->controller);
return 0; return 0;
err2: err:
if (!is_otg_enabled(musb))
musb_stop(musb);
err0:
return retval; return retval;
} }
...@@ -2070,16 +2028,12 @@ static int musb_gadget_stop(struct usb_gadget *g, ...@@ -2070,16 +2028,12 @@ static int musb_gadget_stop(struct usb_gadget *g,
musb_platform_try_idle(musb, 0); musb_platform_try_idle(musb, 0);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) { usb_remove_hcd(musb_to_hcd(musb));
usb_remove_hcd(musb_to_hcd(musb)); /*
/* FIXME we need to be able to register another * FIXME we need to be able to register another
* gadget driver here and have everything work; * gadget driver here and have everything work;
* that currently misbehaves. * that currently misbehaves.
*/ */
}
if (!is_otg_enabled(musb))
musb_stop(musb);
pm_runtime_put(musb->controller); pm_runtime_put(musb->controller);
...@@ -2241,13 +2195,11 @@ __acquires(musb->lock) ...@@ -2241,13 +2195,11 @@ __acquires(musb->lock)
if (devctl & MUSB_DEVCTL_BDEVICE) { if (devctl & MUSB_DEVCTL_BDEVICE) {
musb->xceiv->state = OTG_STATE_B_PERIPHERAL; musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb->g.is_a_peripheral = 0; musb->g.is_a_peripheral = 0;
} else if (is_otg_enabled(musb)) { } else {
musb->xceiv->state = OTG_STATE_A_PERIPHERAL; musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
musb->g.is_a_peripheral = 1; musb->g.is_a_peripheral = 1;
} else }
WARN_ON(1);
/* start with default limits on VBUS power draw */ /* start with default limits on VBUS power draw */
(void) musb_gadget_vbus_draw(&musb->g, (void) musb_gadget_vbus_draw(&musb->g, 8);
is_otg_enabled(musb) ? 8 : 100);
} }
This diff is collapsed.
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#ifndef _MUSB_HOST_H #ifndef _MUSB_HOST_H
#define _MUSB_HOST_H #define _MUSB_HOST_H
#include <linux/scatterlist.h>
static inline struct usb_hcd *musb_to_hcd(struct musb *musb) static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
{ {
return container_of((void *) musb, struct usb_hcd, hcd_priv); return container_of((void *) musb, struct usb_hcd, hcd_priv);
...@@ -71,6 +73,7 @@ struct musb_qh { ...@@ -71,6 +73,7 @@ struct musb_qh {
u16 maxpacket; u16 maxpacket;
u16 frame; /* for periodic schedule */ u16 frame; /* for periodic schedule */
unsigned iso_idx; /* in urb->iso_frame_desc[] */ unsigned iso_idx; /* in urb->iso_frame_desc[] */
struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */
}; };
/* map from control or bulk queue head to the first qh on that ring */ /* map from control or bulk queue head to the first qh on that ring */
......
...@@ -81,8 +81,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) ...@@ -81,8 +81,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
switch (musb->xceiv->state) { switch (musb->xceiv->state) {
case OTG_STATE_A_HOST: case OTG_STATE_A_HOST:
musb->xceiv->state = OTG_STATE_A_SUSPEND; musb->xceiv->state = OTG_STATE_A_SUSPEND;
musb->is_active = is_otg_enabled(musb) musb->is_active = otg->host->b_hnp_enable;
&& otg->host->b_hnp_enable;
if (musb->is_active) if (musb->is_active)
mod_timer(&musb->otg_timer, jiffies mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies( + msecs_to_jiffies(
...@@ -91,8 +90,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) ...@@ -91,8 +90,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
break; break;
case OTG_STATE_B_HOST: case OTG_STATE_B_HOST:
musb->xceiv->state = OTG_STATE_B_WAIT_ACON; musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
musb->is_active = is_otg_enabled(musb) musb->is_active = otg->host->b_hnp_enable;
&& otg->host->b_hnp_enable;
musb_platform_try_idle(musb, 0); musb_platform_try_idle(musb, 0);
break; break;
default: default:
...@@ -190,8 +188,7 @@ void musb_root_disconnect(struct musb *musb) ...@@ -190,8 +188,7 @@ void musb_root_disconnect(struct musb *musb)
switch (musb->xceiv->state) { switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND: case OTG_STATE_A_SUSPEND:
if (is_otg_enabled(musb) if (otg->host->b_hnp_enable) {
&& otg->host->b_hnp_enable) {
musb->xceiv->state = OTG_STATE_A_PERIPHERAL; musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
musb->g.is_a_peripheral = 1; musb->g.is_a_peripheral = 1;
break; break;
...@@ -273,7 +270,7 @@ int musb_hub_control( ...@@ -273,7 +270,7 @@ int musb_hub_control(
musb_port_suspend(musb, false); musb_port_suspend(musb, false);
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) if (!hcd->self.is_b_host)
musb_platform_set_vbus(musb, 0); musb_platform_set_vbus(musb, 0);
break; break;
case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_CONNECTION:
...@@ -369,7 +366,7 @@ int musb_hub_control( ...@@ -369,7 +366,7 @@ int musb_hub_control(
* initialization logic, e.g. for OTG, or change any * initialization logic, e.g. for OTG, or change any
* logic relating to VBUS power-up. * logic relating to VBUS power-up.
*/ */
if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) if (!hcd->self.is_b_host)
musb_start(musb); musb_start(musb);
break; break;
case USB_PORT_FEAT_RESET: case USB_PORT_FEAT_RESET:
......
...@@ -380,7 +380,7 @@ void dma_controller_destroy(struct dma_controller *c) ...@@ -380,7 +380,7 @@ void dma_controller_destroy(struct dma_controller *c)
kfree(controller); kfree(controller);
} }
struct dma_controller *__init struct dma_controller *__devinit
dma_controller_create(struct musb *musb, void __iomem *base) dma_controller_create(struct musb *musb, void __iomem *base)
{ {
struct musb_dma_controller *controller; struct musb_dma_controller *controller;
......
...@@ -30,10 +30,12 @@ ...@@ -30,10 +30,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/delay.h>
#include <linux/usb/musb-omap.h> #include <linux/usb/musb-omap.h>
#include "musb_core.h" #include "musb_core.h"
...@@ -44,6 +46,7 @@ struct omap2430_glue { ...@@ -44,6 +46,7 @@ struct omap2430_glue {
struct platform_device *musb; struct platform_device *musb;
enum omap_musb_vbus_id_status status; enum omap_musb_vbus_id_status status;
struct work_struct omap_musb_mailbox_work; struct work_struct omap_musb_mailbox_work;
u32 __iomem *control_otghs;
}; };
#define glue_to_musb(g) platform_get_drvdata(g->musb) #define glue_to_musb(g) platform_get_drvdata(g->musb)
...@@ -51,6 +54,26 @@ struct omap2430_glue *_glue; ...@@ -51,6 +54,26 @@ struct omap2430_glue *_glue;
static struct timer_list musb_idle_timer; static struct timer_list musb_idle_timer;
/**
* omap4_usb_phy_mailbox - write to usb otg mailbox
* @glue: struct omap2430_glue *
* @val: the value to be written to the mailbox
*
* On detection of a device (ID pin is grounded), this API should be called
* to set AVALID, VBUSVALID and ID pin is grounded.
*
* When OMAP is connected to a host (OMAP in device mode), this API
* is called to set AVALID, VBUSVALID and ID pin in high impedance.
*
* XXX: This function will be removed once we have a seperate driver for
* control module
*/
static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
{
if (glue->control_otghs)
writel(val, glue->control_otghs);
}
static void musb_do_idle(unsigned long _musb) static void musb_do_idle(unsigned long _musb)
{ {
struct musb *musb = (void *)_musb; struct musb *musb = (void *)_musb;
...@@ -140,7 +163,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) ...@@ -140,7 +163,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
struct usb_otg *otg = musb->xceiv->otg; struct usb_otg *otg = musb->xceiv->otg;
u8 devctl; u8 devctl;
unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned long timeout = jiffies + msecs_to_jiffies(1000);
int ret = 1;
/* HDRC controls CPEN, but beware current surges during device /* HDRC controls CPEN, but beware current surges during device
* connect. They can trigger transient overcurrent conditions * connect. They can trigger transient overcurrent conditions
* that must be ignored. * that must be ignored.
...@@ -150,6 +172,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) ...@@ -150,6 +172,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
if (is_on) { if (is_on) {
if (musb->xceiv->state == OTG_STATE_A_IDLE) { if (musb->xceiv->state == OTG_STATE_A_IDLE) {
int loops = 100;
/* start the session */ /* start the session */
devctl |= MUSB_DEVCTL_SESSION; devctl |= MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
...@@ -159,17 +182,18 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) ...@@ -159,17 +182,18 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
*/ */
while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
mdelay(5);
cpu_relax(); cpu_relax();
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)
|| loops-- <= 0) {
dev_err(musb->controller, dev_err(musb->controller,
"configured as A device timeout"); "configured as A device timeout");
ret = -EINVAL;
break; break;
} }
} }
if (ret && otg->set_vbus) if (otg->set_vbus)
otg_set_vbus(otg, 1); otg_set_vbus(otg, 1);
} else { } else {
musb->is_active = 1; musb->is_active = 1;
...@@ -245,6 +269,7 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox); ...@@ -245,6 +269,7 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox);
static void omap_musb_set_mailbox(struct omap2430_glue *glue) static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{ {
u32 val;
struct musb *musb = glue_to_musb(glue); struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data; struct musb_hdrc_platform_data *pdata = dev->platform_data;
...@@ -258,9 +283,10 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) ...@@ -258,9 +283,10 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
otg->default_a = true; otg->default_a = true;
musb->xceiv->state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
musb->xceiv->last_event = USB_EVENT_ID; musb->xceiv->last_event = USB_EVENT_ID;
if (!is_otg_enabled(musb) || musb->gadget_driver) { if (musb->gadget_driver) {
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv); val = AVALID | VBUSVALID;
omap4_usb_phy_mailbox(glue, val);
omap2430_musb_set_vbus(musb, 1); omap2430_musb_set_vbus(musb, 1);
} }
break; break;
...@@ -273,7 +299,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) ...@@ -273,7 +299,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
musb->xceiv->last_event = USB_EVENT_VBUS; musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver) if (musb->gadget_driver)
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv); val = IDDIG | AVALID | VBUSVALID;
omap4_usb_phy_mailbox(glue, val);
break; break;
case OMAP_MUSB_ID_FLOAT: case OMAP_MUSB_ID_FLOAT:
...@@ -281,17 +308,17 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) ...@@ -281,17 +308,17 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
dev_dbg(dev, "VBUS Disconnect\n"); dev_dbg(dev, "VBUS Disconnect\n");
musb->xceiv->last_event = USB_EVENT_NONE; musb->xceiv->last_event = USB_EVENT_NONE;
if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (musb->gadget_driver) {
if (musb->gadget_driver) { pm_runtime_mark_last_busy(dev);
pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev);
pm_runtime_put_autosuspend(dev); }
}
if (data->interface_type == MUSB_INTERFACE_UTMI) { if (data->interface_type == MUSB_INTERFACE_UTMI) {
if (musb->xceiv->otg->set_vbus) if (musb->xceiv->otg->set_vbus)
otg_set_vbus(musb->xceiv->otg, 0); otg_set_vbus(musb->xceiv->otg, 0);
} }
usb_phy_shutdown(musb->xceiv); val = SESSEND | IDDIG;
omap4_usb_phy_mailbox(glue, val);
break; break;
default: default:
dev_dbg(dev, "ID float\n"); dev_dbg(dev, "ID float\n");
...@@ -366,6 +393,7 @@ static int omap2430_musb_init(struct musb *musb) ...@@ -366,6 +393,7 @@ static int omap2430_musb_init(struct musb *musb)
static void omap2430_musb_enable(struct musb *musb) static void omap2430_musb_enable(struct musb *musb)
{ {
u8 devctl; u8 devctl;
u32 val;
unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent); struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
...@@ -375,7 +403,8 @@ static void omap2430_musb_enable(struct musb *musb) ...@@ -375,7 +403,8 @@ static void omap2430_musb_enable(struct musb *musb)
switch (glue->status) { switch (glue->status) {
case OMAP_MUSB_ID_GROUND: case OMAP_MUSB_ID_GROUND:
usb_phy_init(musb->xceiv); val = AVALID | VBUSVALID;
omap4_usb_phy_mailbox(glue, val);
if (data->interface_type != MUSB_INTERFACE_UTMI) if (data->interface_type != MUSB_INTERFACE_UTMI)
break; break;
devctl = musb_readb(musb->mregs, MUSB_DEVCTL); devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
...@@ -394,7 +423,8 @@ static void omap2430_musb_enable(struct musb *musb) ...@@ -394,7 +423,8 @@ static void omap2430_musb_enable(struct musb *musb)
break; break;
case OMAP_MUSB_VBUS_VALID: case OMAP_MUSB_VBUS_VALID:
usb_phy_init(musb->xceiv); val = IDDIG | AVALID | VBUSVALID;
omap4_usb_phy_mailbox(glue, val);
break; break;
default: default:
...@@ -404,11 +434,14 @@ static void omap2430_musb_enable(struct musb *musb) ...@@ -404,11 +434,14 @@ static void omap2430_musb_enable(struct musb *musb)
static void omap2430_musb_disable(struct musb *musb) static void omap2430_musb_disable(struct musb *musb)
{ {
u32 val;
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent); struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
if (glue->status != OMAP_MUSB_UNKNOWN) if (glue->status != OMAP_MUSB_UNKNOWN) {
usb_phy_shutdown(musb->xceiv); val = SESSEND | IDDIG;
omap4_usb_phy_mailbox(glue, val);
}
} }
static int omap2430_musb_exit(struct musb *musb) static int omap2430_musb_exit(struct musb *musb)
...@@ -438,9 +471,14 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32); ...@@ -438,9 +471,14 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32);
static int __devinit omap2430_probe(struct platform_device *pdev) static int __devinit omap2430_probe(struct platform_device *pdev)
{ {
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct omap_musb_board_data *data;
struct platform_device *musb; struct platform_device *musb;
struct omap2430_glue *glue; struct omap2430_glue *glue;
struct device_node *np = pdev->dev.of_node;
struct musb_hdrc_config *config;
struct resource *res;
int ret = -ENOMEM; int ret = -ENOMEM;
int musbid;
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue) { if (!glue) {
...@@ -448,12 +486,21 @@ static int __devinit omap2430_probe(struct platform_device *pdev) ...@@ -448,12 +486,21 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err0;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err0; goto err1;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &omap2430_dmamask; musb->dev.dma_mask = &omap2430_dmamask;
musb->dev.coherent_dma_mask = omap2430_dmamask; musb->dev.coherent_dma_mask = omap2430_dmamask;
...@@ -462,6 +509,48 @@ static int __devinit omap2430_probe(struct platform_device *pdev) ...@@ -462,6 +509,48 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
glue->musb = musb; glue->musb = musb;
glue->status = OMAP_MUSB_UNKNOWN; glue->status = OMAP_MUSB_UNKNOWN;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
if (glue->control_otghs == NULL)
dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
if (np) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev,
"failed to allocate musb platfrom data\n");
ret = -ENOMEM;
goto err1;
}
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev,
"failed to allocate musb board data\n");
ret = -ENOMEM;
goto err1;
}
config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev,
"failed to allocate musb hdrc config\n");
goto err1;
}
of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
of_property_read_u32(np, "interface_type",
(u32 *)&data->interface_type);
of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps);
of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
of_property_read_u32(np, "power", (u32 *)&pdata->power);
config->multipoint = of_property_read_bool(np, "multipoint");
pdata->board_data = data;
pdata->config = config;
}
pdata->platform_ops = &omap2430_ops; pdata->platform_ops = &omap2430_ops;
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
...@@ -478,13 +567,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev) ...@@ -478,13 +567,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err1; goto err2;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err1; goto err2;
} }
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
...@@ -492,14 +581,17 @@ static int __devinit omap2430_probe(struct platform_device *pdev) ...@@ -492,14 +581,17 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err1; goto err2;
} }
return 0; return 0;
err1: err2:
platform_device_put(musb); platform_device_put(musb);
err1:
musb_put_id(&pdev->dev, musbid);
err0: err0:
return ret; return ret;
} }
...@@ -509,8 +601,8 @@ static int __devexit omap2430_remove(struct platform_device *pdev) ...@@ -509,8 +601,8 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
struct omap2430_glue *glue = platform_get_drvdata(pdev); struct omap2430_glue *glue = platform_get_drvdata(pdev);
cancel_work_sync(&glue->omap_musb_mailbox_work); cancel_work_sync(&glue->omap_musb_mailbox_work);
platform_device_del(glue->musb); musb_put_id(&pdev->dev, glue->musb->id);
platform_device_put(glue->musb); platform_device_unregister(glue->musb);
return 0; return 0;
} }
...@@ -559,12 +651,26 @@ static struct dev_pm_ops omap2430_pm_ops = { ...@@ -559,12 +651,26 @@ static struct dev_pm_ops omap2430_pm_ops = {
#define DEV_PM_OPS NULL #define DEV_PM_OPS NULL
#endif #endif
#ifdef CONFIG_OF
static const struct of_device_id omap2430_id_table[] = {
{
.compatible = "ti,omap4-musb"
},
{
.compatible = "ti,omap3-musb"
},
{},
};
MODULE_DEVICE_TABLE(of, omap2430_id_table);
#endif
static struct platform_driver omap2430_driver = { static struct platform_driver omap2430_driver = {
.probe = omap2430_probe, .probe = omap2430_probe,
.remove = __devexit_p(omap2430_remove), .remove = __devexit_p(omap2430_remove),
.driver = { .driver = {
.name = "musb-omap2430", .name = "musb-omap2430",
.pm = DEV_PM_OPS, .pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(omap2430_id_table),
}, },
}; };
......
...@@ -49,4 +49,13 @@ ...@@ -49,4 +49,13 @@
#define OTG_FORCESTDBY 0x414 #define OTG_FORCESTDBY 0x414
# define ENABLEFORCE (1 << 0) # define ENABLEFORCE (1 << 0)
/*
* Control Module bit definitions
* XXX: Will be removed once we have a driver for control module.
*/
#define AVALID BIT(0)
#define BVALID BIT(1)
#define VBUSVALID BIT(2)
#define SESSEND BIT(3)
#define IDDIG BIT(4)
#endif /* __MUSB_OMAP243X_H__ */ #endif /* __MUSB_OMAP243X_H__ */
...@@ -154,7 +154,7 @@ tusb_fifo_write_unaligned(void __iomem *fifo, const u8 *buf, u16 len) ...@@ -154,7 +154,7 @@ tusb_fifo_write_unaligned(void __iomem *fifo, const u8 *buf, u16 len)
} }
static inline void tusb_fifo_read_unaligned(void __iomem *fifo, static inline void tusb_fifo_read_unaligned(void __iomem *fifo,
void __iomem *buf, u16 len) void *buf, u16 len)
{ {
u32 val; u32 val;
int i; int i;
...@@ -438,14 +438,13 @@ static void musb_do_idle(unsigned long _musb) ...@@ -438,14 +438,13 @@ static void musb_do_idle(unsigned long _musb)
if (is_host_active(musb) && (musb->port1_status >> 16)) if (is_host_active(musb) && (musb->port1_status >> 16))
goto done; goto done;
if (is_peripheral_enabled(musb) && !musb->gadget_driver) { if (!musb->gadget_driver) {
wakeups = 0; wakeups = 0;
} else { } else {
wakeups = TUSB_PRCM_WHOSTDISCON wakeups = TUSB_PRCM_WHOSTDISCON
| TUSB_PRCM_WBUS | TUSB_PRCM_WBUS
| TUSB_PRCM_WVBUS; | TUSB_PRCM_WVBUS;
if (is_otg_enabled(musb)) wakeups |= TUSB_PRCM_WID;
wakeups |= TUSB_PRCM_WID;
} }
tusb_allow_idle(musb, wakeups); tusb_allow_idle(musb, wakeups);
} }
...@@ -583,21 +582,12 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) ...@@ -583,21 +582,12 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on)
* *
* Note that if a mini-A cable is plugged in the ID line will stay down as * Note that if a mini-A cable is plugged in the ID line will stay down as
* the weak ID pull-up is not able to pull the ID up. * the weak ID pull-up is not able to pull the ID up.
*
* REVISIT: It would be possible to add support for changing between host
* and peripheral modes in non-OTG configurations by reconfiguring hardware
* and then setting musb->board_mode. For now, only support OTG mode.
*/ */
static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode) static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode)
{ {
void __iomem *tbase = musb->ctrl_base; void __iomem *tbase = musb->ctrl_base;
u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf;
if (musb->board_mode != MUSB_OTG) {
ERR("Changing mode currently only supported in OTG mode\n");
return -EINVAL;
}
otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL); phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL);
phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE); phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE);
...@@ -653,10 +643,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -653,10 +643,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) { if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) {
int default_a; int default_a;
if (is_otg_enabled(musb)) default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS);
default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS);
else
default_a = is_host_enabled(musb);
dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B'); dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B');
otg->default_a = default_a; otg->default_a = default_a;
tusb_musb_set_vbus(musb, default_a); tusb_musb_set_vbus(musb, default_a);
...@@ -670,8 +657,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -670,8 +657,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) {
/* B-dev state machine: no vbus ~= disconnect */ /* B-dev state machine: no vbus ~= disconnect */
if ((is_otg_enabled(musb) && !otg->default_a) if (!otg->default_a) {
|| !is_host_enabled(musb)) {
/* ? musb_root_disconnect(musb); */ /* ? musb_root_disconnect(musb); */
musb->port1_status &= musb->port1_status &=
~(USB_PORT_STAT_CONNECTION ~(USB_PORT_STAT_CONNECTION
...@@ -1120,10 +1106,8 @@ static int tusb_musb_init(struct musb *musb) ...@@ -1120,10 +1106,8 @@ static int tusb_musb_init(struct musb *musb)
} }
musb->isr = tusb_musb_interrupt; musb->isr = tusb_musb_interrupt;
if (is_peripheral_enabled(musb)) { musb->xceiv->set_power = tusb_draw_power;
musb->xceiv->set_power = tusb_draw_power; the_musb = musb;
the_musb = musb;
}
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
...@@ -1176,6 +1160,7 @@ static int __devinit tusb_probe(struct platform_device *pdev) ...@@ -1176,6 +1160,7 @@ static int __devinit tusb_probe(struct platform_device *pdev)
struct tusb6010_glue *glue; struct tusb6010_glue *glue;
int ret = -ENOMEM; int ret = -ENOMEM;
int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL); glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) { if (!glue) {
...@@ -1183,12 +1168,21 @@ static int __devinit tusb_probe(struct platform_device *pdev) ...@@ -1183,12 +1168,21 @@ static int __devinit tusb_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err1;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1; goto err2;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &tusb_dmamask; musb->dev.dma_mask = &tusb_dmamask;
musb->dev.coherent_dma_mask = tusb_dmamask; musb->dev.coherent_dma_mask = tusb_dmamask;
...@@ -1204,26 +1198,29 @@ static int __devinit tusb_probe(struct platform_device *pdev) ...@@ -1204,26 +1198,29 @@ static int __devinit tusb_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err2; goto err3;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err2; goto err3;
} }
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err1; goto err3;
} }
return 0; return 0;
err2: err3:
platform_device_put(musb); platform_device_put(musb);
err2:
musb_put_id(&pdev->dev, musbid);
err1: err1:
kfree(glue); kfree(glue);
...@@ -1235,6 +1232,7 @@ static int __devexit tusb_remove(struct platform_device *pdev) ...@@ -1235,6 +1232,7 @@ static int __devexit tusb_remove(struct platform_device *pdev)
{ {
struct tusb6010_glue *glue = platform_get_drvdata(pdev); struct tusb6010_glue *glue = platform_get_drvdata(pdev);
musb_put_id(&pdev->dev, glue->musb->id);
platform_device_del(glue->musb); platform_device_del(glue->musb);
platform_device_put(glue->musb); platform_device_put(glue->musb);
kfree(glue); kfree(glue);
......
...@@ -662,7 +662,7 @@ void dma_controller_destroy(struct dma_controller *c) ...@@ -662,7 +662,7 @@ void dma_controller_destroy(struct dma_controller *c)
kfree(tusb_dma); kfree(tusb_dma);
} }
struct dma_controller *__init struct dma_controller *__devinit
dma_controller_create(struct musb *musb, void __iomem *base) dma_controller_create(struct musb *musb, void __iomem *base)
{ {
void __iomem *tbase = musb->ctrl_base; void __iomem *tbase = musb->ctrl_base;
......
...@@ -74,25 +74,34 @@ static int __devinit ux500_probe(struct platform_device *pdev) ...@@ -74,25 +74,34 @@ static int __devinit ux500_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
musb = platform_device_alloc("musb-hdrc", -1); /* get the musb id */
musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
if (musbid < 0) {
dev_err(&pdev->dev, "failed to allocate musb id\n");
ret = -ENOMEM;
goto err1;
}
musb = platform_device_alloc("musb-hdrc", musbid);
if (!musb) { if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n"); dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1; goto err2;
} }
clk = clk_get(&pdev->dev, "usb"); clk = clk_get(&pdev->dev, "usb");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n"); dev_err(&pdev->dev, "failed to get clock\n");
ret = PTR_ERR(clk); ret = PTR_ERR(clk);
goto err2; goto err3;
} }
ret = clk_enable(clk); ret = clk_enable(clk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n"); dev_err(&pdev->dev, "failed to enable clock\n");
goto err3; goto err4;
} }
musb->id = musbid;
musb->dev.parent = &pdev->dev; musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = pdev->dev.dma_mask; musb->dev.dma_mask = pdev->dev.dma_mask;
musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask;
...@@ -109,32 +118,35 @@ static int __devinit ux500_probe(struct platform_device *pdev) ...@@ -109,32 +118,35 @@ static int __devinit ux500_probe(struct platform_device *pdev)
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add resources\n"); dev_err(&pdev->dev, "failed to add resources\n");
goto err4; goto err5;
} }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n"); dev_err(&pdev->dev, "failed to add platform_data\n");
goto err4; goto err5;
} }
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err4; goto err5;
} }
return 0; return 0;
err4: err5:
clk_disable(clk); clk_disable(clk);
err3: err4:
clk_put(clk); clk_put(clk);
err2: err3:
platform_device_put(musb); platform_device_put(musb);
err2:
musb_put_id(&pdev->dev, musbid);
err1: err1:
kfree(glue); kfree(glue);
...@@ -146,6 +158,7 @@ static int __devexit ux500_remove(struct platform_device *pdev) ...@@ -146,6 +158,7 @@ static int __devexit ux500_remove(struct platform_device *pdev)
{ {
struct ux500_glue *glue = platform_get_drvdata(pdev); struct ux500_glue *glue = platform_get_drvdata(pdev);
musb_put_id(&pdev->dev, glue->musb->id);
platform_device_del(glue->musb); platform_device_del(glue->musb);
platform_device_put(glue->musb); platform_device_put(glue->musb);
clk_disable(glue->clk); clk_disable(glue->clk);
......
...@@ -364,7 +364,7 @@ void dma_controller_destroy(struct dma_controller *c) ...@@ -364,7 +364,7 @@ void dma_controller_destroy(struct dma_controller *c)
kfree(controller); kfree(controller);
} }
struct dma_controller *__init struct dma_controller *__devinit
dma_controller_create(struct musb *musb, void __iomem *base) dma_controller_create(struct musb *musb, void __iomem *base)
{ {
struct ux500_dma_controller *controller; struct ux500_dma_controller *controller;
......
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