diff options
Diffstat (limited to 'drivers/usb/musb/davinci.c')
| -rw-r--r-- | drivers/usb/musb/davinci.c | 171 |
1 files changed, 82 insertions, 89 deletions
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 7c569f51212..de8492b06e4 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -24,16 +24,18 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> -#include <linux/init.h> #include <linux/list.h> #include <linux/delay.h> #include <linux/clk.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/usb/usb_phy_generic.h> #include <mach/cputype.h> +#include <mach/hardware.h> #include <asm/mach-types.h> @@ -113,8 +115,7 @@ static void davinci_musb_enable(struct musb *musb) dma_off = 0; /* 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); } @@ -213,7 +214,7 @@ static void otg_timer(unsigned long _musb) */ devctl = musb_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->state) { @@ -232,10 +233,8 @@ static void otg_timer(unsigned long _musb) MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); break; 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 * the DEVCTL.SESSION flag). * @@ -265,6 +264,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) unsigned long flags; irqreturn_t retval = IRQ_NONE; struct musb *musb = __hci; + struct usb_otg *otg = musb->xceiv->otg; void __iomem *tibase = musb->ctrl_base; struct cppi *cppi; u32 tmp; @@ -312,8 +312,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) u8 devctl = musb_readb(mregs, MUSB_DEVCTL); int err = musb->int_usb & MUSB_INTR_VBUSERROR; - err = is_host_enabled(musb) - && (musb->int_usb & MUSB_INTR_VBUSERROR); + err = musb->int_usb & MUSB_INTR_VBUSERROR; if (err) { /* The Mentor core doesn't debounce VBUS as needed * to cope with device connect current spikes. This @@ -329,16 +328,16 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { + } else if (drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } @@ -349,7 +348,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) davinci_musb_source_power(musb, drvvbus, 0); dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), err ? " ERROR" : "", devctl); retval = IRQ_HANDLED; @@ -362,8 +361,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) musb_writel(tibase, DAVINCI_USB_EOI_REG, 0); /* 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); spin_unlock_irqrestore(&musb->lock, flags); @@ -381,11 +379,13 @@ static int davinci_musb_init(struct musb *musb) { void __iomem *tibase = musb->ctrl_base; u32 revision; + int ret = -ENODEV; - usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); - if (!musb->xceiv) - return -ENODEV; + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(musb->xceiv)) { + ret = -EPROBE_DEFER; + goto unregister; + } musb->mregs += DAVINCI_BASE_OFFSET; @@ -394,8 +394,7 @@ static int davinci_musb_init(struct musb *musb) if (revision == 0) 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); @@ -416,12 +415,7 @@ static int davinci_musb_init(struct musb *musb) if (cpu_is_davinci_dm355()) { u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); - if (is_host_enabled(musb)) { - deepsleep &= ~DRVVBUS_OVERRIDE; - } else { - deepsleep &= ~DRVVBUS_FORCE; - deepsleep |= DRVVBUS_OVERRIDE; - } + deepsleep &= ~DRVVBUS_FORCE; __raw_writel(deepsleep, DM355_DEEPSLEEP); } @@ -442,15 +436,15 @@ static int davinci_musb_init(struct musb *musb) return 0; fail: - otg_put_transceiver(musb->xceiv); - usb_nop_xceiv_unregister(); - return -ENODEV; + usb_put_phy(musb->xceiv); +unregister: + usb_phy_generic_unregister(); + return ret; } 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 */ if (cpu_is_davinci_dm355()) { @@ -464,7 +458,7 @@ static int davinci_musb_exit(struct musb *musb) davinci_musb_source_power(musb, 0 /*off*/, 1); /* delay, to avoid problems with module reload */ - if (is_host_enabled(musb) && musb->xceiv->default_a) { + if (musb->xceiv->otg->default_a) { int maxdelay = 30; u8 devctl, warn = 0; @@ -491,8 +485,7 @@ static int davinci_musb_exit(struct musb *musb) phy_off(); - otg_put_transceiver(musb->xceiv); - usb_nop_xceiv_unregister(); + usb_put_phy(musb->xceiv); return 0; } @@ -509,13 +502,19 @@ static const struct musb_platform_ops davinci_ops = { .set_vbus = davinci_musb_set_vbus, }; -static u64 davinci_dmamask = DMA_BIT_MASK(32); +static const struct platform_device_info davinci_dev_info = { + .name = "musb-hdrc", + .id = PLATFORM_DEVID_AUTO, + .dma_mask = DMA_BIT_MASK(32), +}; -static int __init davinci_probe(struct platform_device *pdev) +static int davinci_probe(struct platform_device *pdev) { - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct resource musb_resources[3]; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct davinci_glue *glue; + struct platform_device_info pinfo; struct clk *clk; int ret = -ENOMEM; @@ -526,80 +525,84 @@ static int __init davinci_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); - if (!musb) { - dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; - } - clk = clk_get(&pdev->dev, "usb"); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(clk); - goto err2; + goto err3; } ret = clk_enable(clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); - goto err3; + goto err4; } - musb->dev.parent = &pdev->dev; - musb->dev.dma_mask = &davinci_dmamask; - musb->dev.coherent_dma_mask = davinci_dmamask; - glue->dev = &pdev->dev; - glue->musb = musb; glue->clk = clk; pdata->platform_ops = &davinci_ops; + usb_phy_generic_register(); platform_set_drvdata(pdev, glue); - ret = platform_device_add_resources(musb, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); - goto err4; - } + memset(musb_resources, 0x00, sizeof(*musb_resources) * + ARRAY_SIZE(musb_resources)); - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err4; - } + musb_resources[0].name = pdev->resource[0].name; + musb_resources[0].start = pdev->resource[0].start; + musb_resources[0].end = pdev->resource[0].end; + musb_resources[0].flags = pdev->resource[0].flags; - ret = platform_device_add(musb); - if (ret) { - dev_err(&pdev->dev, "failed to register musb device\n"); - goto err4; + musb_resources[1].name = pdev->resource[1].name; + musb_resources[1].start = pdev->resource[1].start; + musb_resources[1].end = pdev->resource[1].end; + musb_resources[1].flags = pdev->resource[1].flags; + + /* + * For DM6467 3 resources are passed. A placeholder for the 3rd + * resource is always there, so it's safe to always copy it... + */ + musb_resources[2].name = pdev->resource[2].name; + musb_resources[2].start = pdev->resource[2].start; + musb_resources[2].end = pdev->resource[2].end; + musb_resources[2].flags = pdev->resource[2].flags; + + pinfo = davinci_dev_info; + pinfo.parent = &pdev->dev; + pinfo.res = musb_resources; + pinfo.num_res = ARRAY_SIZE(musb_resources); + pinfo.data = pdata; + pinfo.size_data = sizeof(*pdata); + + glue->musb = musb = platform_device_register_full(&pinfo); + if (IS_ERR(musb)) { + ret = PTR_ERR(musb); + dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); + goto err5; } return 0; -err4: +err5: clk_disable(clk); -err3: +err4: clk_put(clk); -err2: - platform_device_put(musb); - -err1: +err3: kfree(glue); err0: return ret; } -static int __exit davinci_remove(struct platform_device *pdev) +static int davinci_remove(struct platform_device *pdev) { struct davinci_glue *glue = platform_get_drvdata(pdev); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); + usb_phy_generic_unregister(); clk_disable(glue->clk); clk_put(glue->clk); kfree(glue); @@ -608,7 +611,8 @@ static int __exit davinci_remove(struct platform_device *pdev) } static struct platform_driver davinci_driver = { - .remove = __exit_p(davinci_remove), + .probe = davinci_probe, + .remove = davinci_remove, .driver = { .name = "musb-davinci", }, @@ -617,15 +621,4 @@ static struct platform_driver davinci_driver = { MODULE_DESCRIPTION("DaVinci MUSB Glue Layer"); MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); MODULE_LICENSE("GPL v2"); - -static int __init davinci_init(void) -{ - return platform_driver_probe(&davinci_driver, davinci_probe); -} -subsys_initcall(davinci_init); - -static void __exit davinci_exit(void) -{ - platform_driver_unregister(&davinci_driver); -} -module_exit(davinci_exit); +module_platform_driver(davinci_driver); |
