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/davinci.c | |
| parent | 2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff) | |
| parent | 0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff) | |
| download | olio-linux-3.10-36facadd9ea98f8415d0dbb63e0763b7ee9d3911.tar.xz olio-linux-3.10-36facadd9ea98f8415d0dbb63e0763b7ee9d3911.zip  | |
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/davinci.c')
| -rw-r--r-- | drivers/usb/musb/davinci.c | 174 | 
1 files changed, 154 insertions, 20 deletions
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 6e67629f50c..e6de097fb7e 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -30,6 +30,8 @@  #include <linux/clk.h>  #include <linux/io.h>  #include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h>  #include <mach/hardware.h>  #include <mach/memory.h> @@ -51,6 +53,12 @@  #define USB_PHY_CTRL	IO_ADDRESS(USBPHY_CTL_PADDR)  #define DM355_DEEPSLEEP	IO_ADDRESS(DM355_DEEPSLEEP_PADDR) +struct davinci_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   * and, when in host mode, autosuspending idle root ports... PHYPLLON @@ -83,7 +91,7 @@ static inline void phy_off(void)  static int dma_off = 1; -void musb_platform_enable(struct musb *musb) +static void davinci_musb_enable(struct musb *musb)  {  	u32	tmp, old, val; @@ -116,7 +124,7 @@ void musb_platform_enable(struct musb *musb)  /*   * Disable the HDRC and flush interrupts   */ -void musb_platform_disable(struct musb *musb) +static void davinci_musb_disable(struct musb *musb)  {  	/* because we don't set CTRLR.UINT, "important" to:  	 *  - not read/write INTRUSB/INTRUSBE @@ -167,7 +175,7 @@ static void evm_deferred_drvvbus(struct work_struct *ignored)  #endif	/* EVM */ -static void davinci_source_power(struct musb *musb, int is_on, int immediate) +static void davinci_musb_source_power(struct musb *musb, int is_on, int immediate)  {  #ifdef CONFIG_MACH_DAVINCI_EVM  	if (is_on) @@ -190,10 +198,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate)  #endif  } -static void davinci_set_vbus(struct musb *musb, int is_on) +static void davinci_musb_set_vbus(struct musb *musb, int is_on)  {  	WARN_ON(is_on && is_peripheral_active(musb)); -	davinci_source_power(musb, is_on, 0); +	davinci_musb_source_power(musb, is_on, 0);  } @@ -259,7 +267,7 @@ static void otg_timer(unsigned long _musb)  	spin_unlock_irqrestore(&musb->lock, flags);  } -static irqreturn_t davinci_interrupt(int irq, void *__hci) +static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)  {  	unsigned long	flags;  	irqreturn_t	retval = IRQ_NONE; @@ -345,7 +353,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)  		/* NOTE:  this must complete poweron within 100 msec  		 * (OTG_TIME_A_WAIT_VRISE) but we don't check for that.  		 */ -		davinci_source_power(musb, drvvbus, 0); +		davinci_musb_source_power(musb, drvvbus, 0);  		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",  				drvvbus ? "on" : "off",  				otg_state_string(musb), @@ -370,13 +378,13 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)  	return retval;  } -int musb_platform_set_mode(struct musb *musb, u8 mode) +static int davinci_musb_set_mode(struct musb *musb, u8 mode)  {  	/* EVM can't do this (right?) */  	return -EIO;  } -int __init musb_platform_init(struct musb *musb, void *board_data) +static int davinci_musb_init(struct musb *musb)  {  	void __iomem	*tibase = musb->ctrl_base;  	u32		revision; @@ -388,8 +396,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data)  	musb->mregs += DAVINCI_BASE_OFFSET; -	clk_enable(musb->clock); -  	/* returns zero if e.g. not clocked */  	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);  	if (revision == 0) @@ -398,8 +404,7 @@ 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 = davinci_set_vbus; -	davinci_source_power(musb, 0, 1); +	davinci_musb_source_power(musb, 0, 1);  	/* dm355 EVM swaps D+/D- for signal integrity, and  	 * is clocked from the main 24 MHz crystal. @@ -440,18 +445,16 @@ int __init musb_platform_init(struct musb *musb, void *board_data)  		revision, __raw_readl(USB_PHY_CTRL),  		musb_readb(tibase, DAVINCI_USB_CTRL_REG)); -	musb->isr = davinci_interrupt; +	musb->isr = davinci_musb_interrupt;  	return 0;  fail: -	clk_disable(musb->clock); -  	otg_put_transceiver(musb->xceiv);  	usb_nop_xceiv_unregister();  	return -ENODEV;  } -int musb_platform_exit(struct musb *musb) +static int davinci_musb_exit(struct musb *musb)  {  	if (is_host_enabled(musb))  		del_timer_sync(&otg_workaround); @@ -465,7 +468,7 @@ int musb_platform_exit(struct musb *musb)  		__raw_writel(deepsleep, DM355_DEEPSLEEP);  	} -	davinci_source_power(musb, 0 /*off*/, 1); +	davinci_musb_source_power(musb, 0 /*off*/, 1);  	/* delay, to avoid problems with module reload */  	if (is_host_enabled(musb) && musb->xceiv->default_a) { @@ -495,10 +498,141 @@ int musb_platform_exit(struct musb *musb)  	phy_off(); -	clk_disable(musb->clock); -  	otg_put_transceiver(musb->xceiv);  	usb_nop_xceiv_unregister();  	return 0;  } + +static const struct musb_platform_ops davinci_ops = { +	.init		= davinci_musb_init, +	.exit		= davinci_musb_exit, + +	.enable		= davinci_musb_enable, +	.disable	= davinci_musb_disable, + +	.set_mode	= davinci_musb_set_mode, + +	.set_vbus	= davinci_musb_set_vbus, +}; + +static u64 davinci_dmamask = DMA_BIT_MASK(32); + +static int __init davinci_probe(struct platform_device *pdev) +{ +	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data; +	struct platform_device		*musb; +	struct davinci_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, "usb"); +	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		= &davinci_dmamask; +	musb->dev.coherent_dma_mask	= davinci_dmamask; + +	glue->dev			= &pdev->dev; +	glue->musb			= musb; +	glue->clk			= clk; + +	pdata->platform_ops		= &davinci_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 davinci_remove(struct platform_device *pdev) +{ +	struct davinci_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 davinci_driver = { +	.remove		= __exit_p(davinci_remove), +	.driver		= { +		.name	= "musb-davinci", +	}, +}; + +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);  |