diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 10:05:06 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 10:05:06 -0800 |
commit | 36facadd9ea98f8415d0dbb63e0763b7ee9d3911 (patch) | |
tree | 99dea00b332ed852f2b0a4923b581dd723f03634 /drivers/usb/musb/da8xx.c | |
parent | 2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff) | |
parent | 0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff) |
Merge branch 'usb-next' into musb-merge
* usb-next: (132 commits)
USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path
USB: uas: Ensure we only bind to a UAS interface
USB: uas: Rename sense pipe and sense urb to status pipe and status urb
USB: uas: Use kzalloc instead of kmalloc
USB: uas: Fix up the Sense IU
usb: musb: core: kill unneeded #include's
DA8xx: assign name to MUSB IRQ resource
usb: gadget: g_ncm added
usb: gadget: f_ncm.c added
usb: gadget: u_ether: prepare for NCM
usb: pch_udc: Fix setup transfers with data out
usb: pch_udc: Fix compile error, warnings and checkpatch warnings
usb: add ab8500 usb transceiver driver
USB: gadget: Implement runtime PM for MSM bus glue driver
USB: gadget: Implement runtime PM for ci13xxx gadget
USB: gadget: Add USB controller driver for MSM SoC
USB: gadget: Introduce ci13xxx_udc_driver struct
USB: gadget: Initialize ci13xxx gadget device's coherent DMA mask
USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc
USB: gadget: Separate out PCI bus code from ci13xxx_udc
...
Diffstat (limited to 'drivers/usb/musb/da8xx.c')
-rw-r--r-- | drivers/usb/musb/da8xx.c | 170 |
1 files changed, 153 insertions, 17 deletions
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 84427bebbf62..69a0da3c8f09 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -29,6 +29,8 @@ #include <linux/init.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> #include <mach/da8xx.h> #include <mach/usb.h> @@ -78,6 +80,12 @@ #define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) +struct da8xx_glue { + struct device *dev; + struct platform_device *musb; + struct clk *clk; +}; + /* * REVISIT (PM): we should be able to keep the PHY in low power mode most * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 @@ -131,9 +139,9 @@ static inline void phy_off(void) */ /** - * musb_platform_enable - enable interrupts + * da8xx_musb_enable - enable interrupts */ -void musb_platform_enable(struct musb *musb) +static void da8xx_musb_enable(struct musb *musb) { void __iomem *reg_base = musb->ctrl_base; u32 mask; @@ -151,9 +159,9 @@ void musb_platform_enable(struct musb *musb) } /** - * musb_platform_disable - disable HDRC and flush interrupts + * da8xx_musb_disable - disable HDRC and flush interrupts */ -void musb_platform_disable(struct musb *musb) +static void da8xx_musb_disable(struct musb *musb) { void __iomem *reg_base = musb->ctrl_base; @@ -170,7 +178,7 @@ void musb_platform_disable(struct musb *musb) #define portstate(stmt) #endif -static void da8xx_set_vbus(struct musb *musb, int is_on) +static void da8xx_musb_set_vbus(struct musb *musb, int is_on) { WARN_ON(is_on && is_peripheral_active(musb)); } @@ -252,7 +260,7 @@ static void otg_timer(unsigned long _musb) spin_unlock_irqrestore(&musb->lock, flags); } -void musb_platform_try_idle(struct musb *musb, unsigned long timeout) +static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) { static unsigned long last_timer; @@ -282,7 +290,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) mod_timer(&otg_workaround, timeout); } -static irqreturn_t da8xx_interrupt(int irq, void *hci) +static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) { struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; @@ -380,7 +388,7 @@ static irqreturn_t da8xx_interrupt(int irq, void *hci) return ret; } -int musb_platform_set_mode(struct musb *musb, u8 musb_mode) +static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode) { u32 cfgchip2 = __raw_readl(CFGCHIP2); @@ -409,15 +417,13 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) return 0; } -int __init musb_platform_init(struct musb *musb, void *board_data) +static int da8xx_musb_init(struct musb *musb) { void __iomem *reg_base = musb->ctrl_base; u32 rev; musb->mregs += DA8XX_MENTOR_CORE_OFFSET; - clk_enable(musb->clock); - /* Returns zero if e.g. not clocked */ rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); if (!rev) @@ -431,8 +437,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data) if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); - musb->board_set_vbus = da8xx_set_vbus; - /* Reset the controller */ musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); @@ -446,14 +450,13 @@ int __init musb_platform_init(struct musb *musb, void *board_data) rev, __raw_readl(CFGCHIP2), musb_readb(reg_base, DA8XX_USB_CTRL_REG)); - musb->isr = da8xx_interrupt; + musb->isr = da8xx_musb_interrupt; return 0; fail: - clk_disable(musb->clock); return -ENODEV; } -int musb_platform_exit(struct musb *musb) +static int da8xx_musb_exit(struct musb *musb) { if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); @@ -463,7 +466,140 @@ int musb_platform_exit(struct musb *musb) otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); - clk_disable(musb->clock); + return 0; +} + +static const struct musb_platform_ops da8xx_ops = { + .init = da8xx_musb_init, + .exit = da8xx_musb_exit, + + .enable = da8xx_musb_enable, + .disable = da8xx_musb_disable, + + .set_mode = da8xx_musb_set_mode, + .try_idle = da8xx_musb_try_idle, + + .set_vbus = da8xx_musb_set_vbus, +}; + +static u64 da8xx_dmamask = DMA_BIT_MASK(32); + +static int __init da8xx_probe(struct platform_device *pdev) +{ + struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct platform_device *musb; + struct da8xx_glue *glue; + + struct clk *clk; + + int ret = -ENOMEM; + + glue = kzalloc(sizeof(*glue), GFP_KERNEL); + if (!glue) { + dev_err(&pdev->dev, "failed to allocate glue context\n"); + 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, "usb20"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); + ret = PTR_ERR(clk); + goto err2; + } + + ret = clk_enable(clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable clock\n"); + goto err3; + } + + musb->dev.parent = &pdev->dev; + musb->dev.dma_mask = &da8xx_dmamask; + musb->dev.coherent_dma_mask = da8xx_dmamask; + + glue->dev = &pdev->dev; + glue->musb = musb; + glue->clk = clk; + + pdata->platform_ops = &da8xx_ops; + + 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; + } + + ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); + if (ret) { + dev_err(&pdev->dev, "failed to add platform_data\n"); + goto err4; + } + + ret = platform_device_add(musb); + if (ret) { + dev_err(&pdev->dev, "failed to register musb device\n"); + goto err4; + } + + return 0; + +err4: + clk_disable(clk); + +err3: + clk_put(clk); + +err2: + platform_device_put(musb); + +err1: + kfree(glue); + +err0: + return ret; +} + +static int __exit da8xx_remove(struct platform_device *pdev) +{ + struct da8xx_glue *glue = platform_get_drvdata(pdev); + + platform_device_del(glue->musb); + platform_device_put(glue->musb); + clk_disable(glue->clk); + clk_put(glue->clk); + kfree(glue); return 0; } + +static struct platform_driver da8xx_driver = { + .remove = __exit_p(da8xx_remove), + .driver = { + .name = "musb-da8xx", + }, +}; + +MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer"); +MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>"); +MODULE_LICENSE("GPL v2"); + +static int __init da8xx_init(void) +{ + return platform_driver_probe(&da8xx_driver, da8xx_probe); +} +subsys_initcall(da8xx_init); + +static void __exit da8xx_exit(void) +{ + platform_driver_unregister(&da8xx_driver); +} +module_exit(da8xx_exit); |