aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/lpc32xx_udc.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 15:10:09 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 15:10:09 -0700
commit94ff447cf275170042a7a05b972b6da8b94754ca (patch)
treef3d20c78d5ec68f29874be4cdce3c5a8d1c5de53 /drivers/usb/gadget/lpc32xx_udc.c
parent979eef33267ec230b820f4f76b2103e8b567fa57 (diff)
parent65c84ea18b1b4b8c03fb67c3bea023ed1446bd2e (diff)
Merge tag 'gadget-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
usb: gadget: patches for v3.6 merge window This is quite a big pull request and contains patches all over the place. omap_udc is now a bit cleaner after removing omap2 support, fixing some checkpatch.pl warnings and errors, switching over to generic map/unmap routines and preventing a NULL pointer de-reference. s3c-hsotg has been switched over to devm_* API, got some locking fixes and improvements and it also got an implementation for the pullup() method. the mass storage gadgets changed default value of the removable parameter, dropped some unused options and made "file" and "ro" module_parameters read-only in some cases. ffs function got support for HID descriptor. Some UDCs have been converted to clk_prepare_enable() and clk_disable_unprepare(). Marvell now got support for its USB3 controller in mainline after introducing its mv_u3d_core.c driver.
Diffstat (limited to 'drivers/usb/gadget/lpc32xx_udc.c')
-rw-r--r--drivers/usb/gadget/lpc32xx_udc.c85
1 files changed, 25 insertions, 60 deletions
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index 2ab0388d93e..f1ec99e69cb 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -165,6 +165,7 @@ struct lpc32xx_udc {
int udp_irq[4];
struct clk *usb_pll_clk;
struct clk *usb_slv_clk;
+ struct clk *usb_otg_clk;
/* DMA support */
u32 *udca_v_base;
@@ -227,33 +228,15 @@ static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g)
#define UDCA_BUFF_SIZE (128)
/* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will
- * be replaced with an inremap()ed pointer, see USB_OTG_CLK_CTRL()
+ * be replaced with an inremap()ed pointer
* */
#define USB_CTRL IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64)
-#define USB_CLOCK_MASK (AHB_M_CLOCK_ON | OTG_CLOCK_ON | \
- DEV_CLOCK_ON | I2C_CLOCK_ON)
/* USB_CTRL bit defines */
#define USB_SLAVE_HCLK_EN (1 << 24)
#define USB_HOST_NEED_CLK_EN (1 << 21)
#define USB_DEV_NEED_CLK_EN (1 << 22)
-#define USB_OTG_CLK_CTRL(udc) ((udc)->udp_baseaddr + 0xFF4)
-#define USB_OTG_CLK_STAT(udc) ((udc)->udp_baseaddr + 0xFF8)
-
-/* USB_OTG_CLK_CTRL bit defines */
-#define AHB_M_CLOCK_ON (1 << 4)
-#define OTG_CLOCK_ON (1 << 3)
-#define I2C_CLOCK_ON (1 << 2)
-#define DEV_CLOCK_ON (1 << 1)
-#define HOST_CLOCK_ON (1 << 0)
-
-#define USB_OTG_STAT_CONTROL(udc) (udc->udp_baseaddr + 0x110)
-
-/* USB_OTG_STAT_CONTROL bit defines */
-#define TRANSPARENT_I2C_EN (1 << 7)
-#define HOST_EN (1 << 0)
-
/**********************************************************************
* USB device controller register offsets
**********************************************************************/
@@ -677,7 +660,7 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc)
ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
/* Enable usb_need_clk clock after transceiver is initialized */
- writel((readl(USB_CTRL) | (1 << 22)), USB_CTRL);
+ writel((readl(USB_CTRL) | USB_DEV_NEED_CLK_EN), USB_CTRL);
dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n",
i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
@@ -1010,11 +993,8 @@ static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd)
/* Enables or disables most of the USB system clocks when low power mode is
* needed. Clocks are typically started on a connection event, and disabled
* when a cable is disconnected */
-#define OTGOFF_CLK_MASK (AHB_M_CLOCK_ON | I2C_CLOCK_ON)
static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
{
- int to = 1000;
-
if (enable != 0) {
if (udc->clocked)
return;
@@ -1028,14 +1008,7 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN,
USB_CTRL);
- /* Set to enable all needed USB OTG clocks */
- writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc));
-
- while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) !=
- USB_CLOCK_MASK) && (to > 0))
- to--;
- if (!to)
- dev_dbg(udc->dev, "Cannot enable USB OTG clocking\n");
+ clk_enable(udc->usb_otg_clk);
} else {
if (!udc->clocked)
return;
@@ -1047,19 +1020,11 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
/* 48MHz PLL dpwn */
clk_disable(udc->usb_pll_clk);
- /* Enable the USB device clock */
+ /* Disable the USB device clock */
writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN,
USB_CTRL);
- /* Set to enable all needed USB OTG clocks */
- writel(OTGOFF_CLK_MASK, USB_OTG_CLK_CTRL(udc));
-
- while (((readl(USB_OTG_CLK_STAT(udc)) &
- OTGOFF_CLK_MASK) !=
- OTGOFF_CLK_MASK) && (to > 0))
- to--;
- if (!to)
- dev_dbg(udc->dev, "Cannot disable USB OTG clocking\n");
+ clk_disable(udc->usb_otg_clk);
}
}
@@ -3041,6 +3006,7 @@ static int lpc32xx_start(struct usb_gadget_driver *driver,
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
+ udc->gadget.dev.of_node = udc->dev->of_node;
udc->enabled = 1;
udc->selfpowered = 1;
udc->vbus = 0;
@@ -3239,6 +3205,12 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
retval = PTR_ERR(udc->usb_slv_clk);
goto usb_clk_get_fail;
}
+ udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg");
+ if (IS_ERR(udc->usb_otg_clk)) {
+ dev_err(udc->dev, "failed to acquire USB otg clock\n");
+ retval = PTR_ERR(udc->usb_slv_clk);
+ goto usb_otg_clk_get_fail;
+ }
/* Setup PLL clock to 48MHz */
retval = clk_enable(udc->usb_pll_clk);
@@ -3262,15 +3234,12 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
goto usb_clk_enable_fail;
}
- /* Set to enable all needed USB OTG clocks */
- writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc));
-
- i = 1000;
- while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) !=
- USB_CLOCK_MASK) && (i > 0))
- i--;
- if (!i)
- dev_dbg(udc->dev, "USB OTG clocks not correctly enabled\n");
+ /* Enable USB OTG clock */
+ retval = clk_enable(udc->usb_otg_clk);
+ if (retval < 0) {
+ dev_err(udc->dev, "failed to start USB otg clock\n");
+ goto usb_otg_clk_enable_fail;
+ }
/* Setup deferred workqueue data */
udc->poweron = udc->pullup = 0;
@@ -3390,12 +3359,16 @@ dma_alloc_fail:
dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
udc->udca_v_base, udc->udca_p_base);
i2c_fail:
+ clk_disable(udc->usb_otg_clk);
+usb_otg_clk_enable_fail:
clk_disable(udc->usb_slv_clk);
usb_clk_enable_fail:
pll_set_fail:
clk_disable(udc->usb_pll_clk);
pll_enable_fail:
clk_put(udc->usb_slv_clk);
+usb_otg_clk_get_fail:
+ clk_put(udc->usb_otg_clk);
usb_clk_get_fail:
clk_put(udc->usb_pll_clk);
pll_get_fail:
@@ -3433,6 +3406,8 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
device_unregister(&udc->gadget.dev);
+ clk_disable(udc->usb_otg_clk);
+ clk_put(udc->usb_otg_clk);
clk_disable(udc->usb_slv_clk);
clk_put(udc->usb_slv_clk);
clk_disable(udc->usb_pll_clk);
@@ -3446,7 +3421,6 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- int to = 1000;
struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
if (udc->clocked) {
@@ -3461,15 +3435,6 @@ static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
on resume */
udc->clocked = 1;
- /* Kill OTG and I2C clocks */
- writel(0, USB_OTG_CLK_CTRL(udc));
- while (((readl(USB_OTG_CLK_STAT(udc)) & OTGOFF_CLK_MASK) !=
- OTGOFF_CLK_MASK) && (to > 0))
- to--;
- if (!to)
- dev_dbg(udc->dev,
- "USB OTG clocks not correctly enabled\n");
-
/* Kill global USB clock */
clk_disable(udc->usb_slv_clk);
}