summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc2/gadget.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2015-10-14 09:52:29 +0300
committerFelipe Balbi <balbi@ti.com>2015-10-14 16:40:15 +0300
commit09a75e8577901489f77a14a3b305a9a1f67bf25b (patch)
tree70fa7f23a08ce55aa0c1d4ebb7aaa6e1ae38fe0d /drivers/usb/dwc2/gadget.c
parent758ed196fcc4373a129fd661875af52d7e7d4e73 (diff)
downloadlinux-09a75e8577901489f77a14a3b305a9a1f67bf25b.tar.xz
usb: dwc2: refactor common low-level hw code to platform.c
DWC2 module on some platforms needs three additional hardware resources: phy controller, clock and power supply. All of them must be enabled/activated to properly initialize and operate. This was initially handled in s3c-hsotg driver, which has been converted to 'gadget' part of dwc2 driver. Unfortunately, not all of this code got moved to common platform code, what resulted in accessing DWC2 registers without enabling low-level hardware resources. This fails for example on Exynos SoCs. This patch moves all the code for managing those resources to common platform.c file and provides convenient wrappers for controlling them. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: John Youn <johnyoun@synopsys.com> Tested-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc2/gadget.c')
-rw-r--r--drivers/usb/dwc2/gadget.c186
1 files changed, 17 insertions, 169 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 79d9f3bf5cf7..0abf73c91beb 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -25,15 +25,11 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
#include <linux/of_platform.h>
-#include <linux/phy/phy.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/phy.h>
-#include <linux/platform_data/s3c-hsotg.h>
#include "core.h"
#include "hw.h"
@@ -3077,50 +3073,6 @@ static struct usb_ep_ops dwc2_hsotg_ep_ops = {
};
/**
- * dwc2_hsotg_phy_enable - enable platform phy dev
- * @hsotg: The driver state
- *
- * A wrapper for platform code responsible for controlling
- * low-level USB code
- */
-static void dwc2_hsotg_phy_enable(struct dwc2_hsotg *hsotg)
-{
- struct platform_device *pdev = to_platform_device(hsotg->dev);
-
- dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
-
- if (hsotg->uphy)
- usb_phy_init(hsotg->uphy);
- else if (hsotg->plat && hsotg->plat->phy_init)
- hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
- else {
- phy_init(hsotg->phy);
- phy_power_on(hsotg->phy);
- }
-}
-
-/**
- * dwc2_hsotg_phy_disable - disable platform phy dev
- * @hsotg: The driver state
- *
- * A wrapper for platform code responsible for controlling
- * low-level USB code
- */
-static void dwc2_hsotg_phy_disable(struct dwc2_hsotg *hsotg)
-{
- struct platform_device *pdev = to_platform_device(hsotg->dev);
-
- if (hsotg->uphy)
- usb_phy_shutdown(hsotg->uphy);
- else if (hsotg->plat && hsotg->plat->phy_exit)
- hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
- else {
- phy_power_off(hsotg->phy);
- phy_exit(hsotg->phy);
- }
-}
-
-/**
* dwc2_hsotg_init - initalize the usb core
* @hsotg: The driver state
*/
@@ -3200,14 +3152,12 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
hsotg->gadget.dev.of_node = hsotg->dev->of_node;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
- ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- if (ret) {
- dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
- goto err;
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
+ ret = dwc2_lowlevel_hw_enable(hsotg);
+ if (ret)
+ goto err;
}
- dwc2_hsotg_phy_enable(hsotg);
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
@@ -3260,9 +3210,9 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_peripheral(hsotg->uphy->otg, NULL);
- dwc2_hsotg_phy_disable(hsotg);
- regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+ dwc2_lowlevel_hw_disable(hsotg);
return 0;
}
@@ -3602,15 +3552,11 @@ static inline void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{
struct device *dev = hsotg->dev;
- struct dwc2_hsotg_plat *plat = dev->platform_data;
int epnum;
int ret;
int i;
u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
- /* Set default UTMI width */
- hsotg->phyif = GUSBCFG_PHYIF16;
-
/* Initialize to legacy fifo configuration values */
hsotg->g_rx_fifo_sz = 2048;
hsotg->g_np_g_tx_fifo_sz = 1024;
@@ -3624,32 +3570,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
for (i = 0; i < MAX_EPS_CHANNELS; i++)
dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i,
hsotg->g_tx_fifo_sz[i]);
- /*
- * If platform probe couldn't find a generic PHY or an old style
- * USB PHY, fall back to pdata
- */
- if (IS_ERR_OR_NULL(hsotg->phy) && IS_ERR_OR_NULL(hsotg->uphy)) {
- plat = dev_get_platdata(dev);
- if (!plat) {
- dev_err(dev,
- "no platform data or transceiver defined\n");
- return -EPROBE_DEFER;
- }
- hsotg->plat = plat;
- } else if (hsotg->phy) {
- /*
- * If using the generic PHY framework, check if the PHY bus
- * width is 8-bit and set the phyif appropriately.
- */
- if (phy_get_bus_width(hsotg->phy) == 8)
- hsotg->phyif = GUSBCFG_PHYIF8;
- }
-
- hsotg->clk = devm_clk_get(dev, "otg");
- if (IS_ERR(hsotg->clk)) {
- hsotg->clk = NULL;
- dev_dbg(dev, "cannot get otg clock\n");
- }
hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = &dwc2_hsotg_gadget_ops;
@@ -3659,38 +3579,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
- /* reset the system */
-
- ret = clk_prepare_enable(hsotg->clk);
- if (ret) {
- dev_err(dev, "failed to enable otg clk\n");
- goto err_clk;
- }
-
-
- /* regulators */
-
- for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
- hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
-
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- if (ret) {
- dev_err(dev, "failed to request supplies: %d\n", ret);
- goto err_clk;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
-
- if (ret) {
- dev_err(dev, "failed to enable supplies: %d\n", ret);
- goto err_clk;
- }
-
- /* usb phy enable */
- dwc2_hsotg_phy_enable(hsotg);
-
/*
* Force Device mode before initialization.
* This allows correctly configuring fifo for device mode.
@@ -3708,7 +3596,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
ret = dwc2_hsotg_hw_cfg(hsotg);
if (ret) {
dev_err(hsotg->dev, "Hardware configuration failed: %d\n", ret);
- goto err_clk;
+ return ret;
}
dwc2_hsotg_init(hsotg);
@@ -3720,35 +3608,28 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
DWC2_CTRL_BUFF_SIZE, GFP_KERNEL);
if (!hsotg->ctrl_buff) {
dev_err(dev, "failed to allocate ctrl request buff\n");
- ret = -ENOMEM;
- goto err_supplies;
+ return -ENOMEM;
}
hsotg->ep0_buff = devm_kzalloc(hsotg->dev,
DWC2_CTRL_BUFF_SIZE, GFP_KERNEL);
if (!hsotg->ep0_buff) {
dev_err(dev, "failed to allocate ctrl reply buff\n");
- ret = -ENOMEM;
- goto err_supplies;
+ return -ENOMEM;
}
ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED,
dev_name(hsotg->dev), hsotg);
if (ret < 0) {
- dwc2_hsotg_phy_disable(hsotg);
- clk_disable_unprepare(hsotg->clk);
- regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
dev_err(dev, "cannot claim IRQ for gadget\n");
- goto err_supplies;
+ return ret;
}
/* hsotg->num_of_eps holds number of EPs other than ep0 */
if (hsotg->num_of_eps == 0) {
dev_err(dev, "wrong number of EPs (zero)\n");
- ret = -EINVAL;
- goto err_supplies;
+ return -EINVAL;
}
/* setup endpoint information */
@@ -3762,8 +3643,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
GFP_KERNEL);
if (!hsotg->ctrl_req) {
dev_err(dev, "failed to allocate ctrl req\n");
- ret = -ENOMEM;
- goto err_supplies;
+ return -ENOMEM;
}
/* initialise the endpoints now the core has been initialised */
@@ -3776,30 +3656,13 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
epnum, 0);
}
- /* disable power and clock */
- dwc2_hsotg_phy_disable(hsotg);
-
- ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- if (ret) {
- dev_err(dev, "failed to disable supplies: %d\n", ret);
- goto err_supplies;
- }
-
ret = usb_add_gadget_udc(dev, &hsotg->gadget);
if (ret)
- goto err_supplies;
+ return ret;
dwc2_hsotg_dump(hsotg);
return 0;
-
-err_supplies:
- dwc2_hsotg_phy_disable(hsotg);
-err_clk:
- clk_disable_unprepare(hsotg->clk);
-
- return ret;
}
/**
@@ -3809,7 +3672,6 @@ err_clk:
int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg)
{
usb_del_gadget_udc(&hsotg->gadget);
- clk_disable_unprepare(hsotg->clk);
return 0;
}
@@ -3817,10 +3679,9 @@ int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg)
int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
{
unsigned long flags;
- int ret = 0;
if (hsotg->lx_state != DWC2_L0)
- return ret;
+ return 0;
if (hsotg->driver) {
int ep;
@@ -3835,41 +3696,28 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock_irqrestore(&hsotg->lock, flags);
- dwc2_hsotg_phy_disable(hsotg);
-
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
if (hsotg->eps_in[ep])
dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
if (hsotg->eps_out[ep])
dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
}
-
- ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- clk_disable(hsotg->clk);
}
- return ret;
+ return 0;
}
int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg)
{
unsigned long flags;
- int ret = 0;
if (hsotg->lx_state == DWC2_L2)
- return ret;
+ return 0;
if (hsotg->driver) {
dev_info(hsotg->dev, "resuming usb gadget %s\n",
hsotg->driver->driver.name);
- clk_enable(hsotg->clk);
- ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
-
- dwc2_hsotg_phy_enable(hsotg);
-
spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
@@ -3877,5 +3725,5 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg)
spin_unlock_irqrestore(&hsotg->lock, flags);
}
- return ret;
+ return 0;
}