From 1f91b4cc03556ba0d43ac80621dac8263cda3880 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Aug 2015 18:11:54 -0500 Subject: usb: dwc2: rename all s3c_* to dwc2_* this driver has long ago became dwc2.ko with both peripheral and host roles, there's no point in keeping the old function names. Acked-by: John Youn Tested-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/platform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 90935304185a..3d1f82def2f3 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -130,7 +130,7 @@ static int dwc2_driver_remove(struct platform_device *dev) if (hsotg->hcd_enabled) dwc2_hcd_remove(hsotg); if (hsotg->gadget_enabled) - s3c_hsotg_remove(hsotg); + dwc2_hsotg_remove(hsotg); return 0; } @@ -269,7 +269,7 @@ static int dwc2_driver_probe(struct platform_device *dev) retval = dwc2_hcd_init(hsotg, irq); if (retval) { if (hsotg->gadget_enabled) - s3c_hsotg_remove(hsotg); + dwc2_hsotg_remove(hsotg); return retval; } hsotg->hcd_enabled = 1; @@ -288,7 +288,7 @@ static int __maybe_unused dwc2_suspend(struct device *dev) int ret = 0; if (dwc2_is_device_mode(dwc2)) { - ret = s3c_hsotg_suspend(dwc2); + ret = dwc2_hsotg_suspend(dwc2); } else { if (dwc2->lx_state == DWC2_L0) return 0; @@ -305,7 +305,7 @@ static int __maybe_unused dwc2_resume(struct device *dev) int ret = 0; if (dwc2_is_device_mode(dwc2)) { - ret = s3c_hsotg_resume(dwc2); + ret = dwc2_hsotg_resume(dwc2); } else { phy_power_on(dwc2->phy); phy_init(dwc2->phy); -- cgit v1.2.3 From 06e7114f0d8297278eb24f4e9bee3393a94bd8ce Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 21 Sep 2015 11:14:34 +0300 Subject: usb: common: of_usb_get_dr_mode to usb_get_dr_mode By using the unified device property interface, the function can be made available for all platforms and not just the ones using DT. Signed-off-by: Heikki Krogerus Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/core.c | 2 +- drivers/usb/common/common.c | 15 ++++----------- drivers/usb/dwc2/platform.c | 2 +- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/dwc3-st.c | 2 +- drivers/usb/musb/musb_dsps.c | 2 +- drivers/usb/musb/sunxi.c | 2 +- drivers/usb/phy/phy-msm-usb.c | 2 +- drivers/usb/phy/phy-tegra-usb.c | 2 +- include/linux/usb/of.h | 6 ------ include/linux/usb/otg.h | 9 +++++++++ 11 files changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index ce7153232425..bf2599757f55 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -611,7 +611,7 @@ static int ci_get_platdata(struct device *dev, platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); if (!platdata->dr_mode) - platdata->dr_mode = of_usb_get_dr_mode(dev->of_node); + platdata->dr_mode = usb_get_dr_mode(dev); if (platdata->dr_mode == USB_DR_MODE_UNKNOWN) platdata->dr_mode = USB_DR_MODE_OTG; diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index b25a111903ab..673d53038ed2 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -99,7 +99,6 @@ const char *usb_state_string(enum usb_device_state state) } EXPORT_SYMBOL_GPL(usb_state_string); -#ifdef CONFIG_OF static const char *const usb_dr_modes[] = { [USB_DR_MODE_UNKNOWN] = "", [USB_DR_MODE_HOST] = "host", @@ -107,19 +106,12 @@ static const char *const usb_dr_modes[] = { [USB_DR_MODE_OTG] = "otg", }; -/** - * of_usb_get_dr_mode - Get dual role mode for given device_node - * @np: Pointer to the given device_node - * - * The function gets phy interface string from property 'dr_mode', - * and returns the correspondig enum usb_dr_mode - */ -enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) +enum usb_dr_mode usb_get_dr_mode(struct device *dev) { const char *dr_mode; int err, i; - err = of_property_read_string(np, "dr_mode", &dr_mode); + err = device_property_read_string(dev, "dr_mode", &dr_mode); if (err < 0) return USB_DR_MODE_UNKNOWN; @@ -129,8 +121,9 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) return USB_DR_MODE_UNKNOWN; } -EXPORT_SYMBOL_GPL(of_usb_get_dr_mode); +EXPORT_SYMBOL_GPL(usb_get_dr_mode); +#ifdef CONFIG_OF /** * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported * for given targeted hosts (non-PC hosts) diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 3d1f82def2f3..28abd1f90900 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -220,7 +220,7 @@ static int dwc2_driver_probe(struct platform_device *dev) dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); - hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node); + hsotg->dr_mode = usb_get_dr_mode(&dev->dev); /* * Attempt to find a generic PHY, then look for an old style diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 61a56357baf0..407151465645 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -871,6 +871,7 @@ static int dwc3_probe(struct platform_device *pdev) hird_threshold = 12; dwc->maximum_speed = usb_get_maximum_speed(dev); + dwc->dr_mode = usb_get_dr_mode(dev); if (node) { dwc->has_lpm_erratum = of_property_read_bool(node, @@ -886,7 +887,6 @@ static int dwc3_probe(struct platform_device *pdev) dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); - dwc->dr_mode = of_usb_get_dr_mode(node); dwc->disable_scramble_quirk = of_property_read_bool(node, "snps,disable_scramble_quirk"); diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index 02d47d50905b..5c0adb9c6fb2 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c @@ -268,7 +268,7 @@ static int st_dwc3_probe(struct platform_device *pdev) goto undo_softreset; } - dwc3_data->dr_mode = of_usb_get_dr_mode(child_pdev->dev.of_node); + dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev); /* * Configure the USB port as device or host according to the static diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index c6a69eaf280f..eeb7d9ecf7df 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -666,7 +666,7 @@ static int get_musb_port_mode(struct device *dev) { enum usb_dr_mode mode; - mode = of_usb_get_dr_mode(dev->of_node); + mode = usb_get_dr_mode(dev); switch (mode) { case USB_DR_MODE_HOST: return MUSB_PORT_MODE_HOST; diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index f9f6304ad854..f11b8f681b30 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -617,7 +617,7 @@ static int sunxi_musb_probe(struct platform_device *pdev) return -ENOMEM; memset(&pdata, 0, sizeof(pdata)); - switch (of_usb_get_dr_mode(np)) { + switch (usb_get_dr_mode(&pdev->dev)) { #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST case USB_DR_MODE_HOST: pdata.mode = MUSB_PORT_MODE_HOST; diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index c58c3c0dbe35..80eb991c2506 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1529,7 +1529,7 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) if (IS_ERR(motg->phy_rst)) motg->phy_rst = NULL; - pdata->mode = of_usb_get_dr_mode(node); + pdata->mode = usb_get_dr_mode(&pdev->dev); if (pdata->mode == USB_DR_MODE_UNKNOWN) pdata->mode = USB_DR_MODE_OTG; diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index ab025b00964c..5fe4a5704bde 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -1029,7 +1029,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) } if (of_find_property(np, "dr_mode", NULL)) - tegra_phy->mode = of_usb_get_dr_mode(np); + tegra_phy->mode = usb_get_dr_mode(&pdev->dev); else tegra_phy->mode = USB_DR_MODE_HOST; diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index ff23fea49fca..c3fe9e48ce27 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -12,16 +12,10 @@ #include #if IS_ENABLED(CONFIG_OF) -enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np); bool of_usb_host_tpl_support(struct device_node *np); int of_usb_update_otg_caps(struct device_node *np, struct usb_otg_caps *otg_caps); #else -static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) -{ - return USB_DR_MODE_UNKNOWN; -} - static inline bool of_usb_host_tpl_support(struct device_node *np) { return false; diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index bd1dcf816100..67929df86df5 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -119,4 +119,13 @@ enum usb_dr_mode { USB_DR_MODE_OTG, }; +/** + * usb_get_dr_mode - Get dual role mode for given device + * @dev: Pointer to the given device + * + * The function gets phy interface string from property 'dr_mode', + * and returns the correspondig enum usb_dr_mode + */ +extern enum usb_dr_mode usb_get_dr_mode(struct device *dev); + #endif /* __LINUX_USB_OTG_H */ -- cgit v1.2.3 From 857512d0ebf838d8a2b600234debdbfc1e97f919 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 29 Sep 2015 12:08:18 +0200 Subject: usb: dwc2: force dr_mode in case of configuration mismatch If dual role configuration is not selected, check and force dr_mode based on the selected configuration. Signed-off-by: Mian Yousaf Kaukab Tested-by: Robert Baldyga Tested-by: Dinh Nguyen Tested-by: John Youn Acked-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/platform.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 28abd1f90900..a013ea9f2c9c 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -221,6 +221,17 @@ static int dwc2_driver_probe(struct platform_device *dev) (unsigned long)res->start, hsotg->regs); hsotg->dr_mode = usb_get_dr_mode(&dev->dev); + if (IS_ENABLED(CONFIG_USB_DWC2_HOST) && + hsotg->dr_mode != USB_DR_MODE_HOST) { + hsotg->dr_mode = USB_DR_MODE_HOST; + dev_warn(hsotg->dev, + "Configuration mismatch. Forcing host mode\n"); + } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) && + hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { + hsotg->dr_mode = USB_DR_MODE_PERIPHERAL; + dev_warn(hsotg->dev, + "Configuration mismatch. Forcing peripheral mode\n"); + } /* * Attempt to find a generic PHY, then look for an old style -- cgit v1.2.3 From 5ee2a003e8622d51e865ffa5547a5708e592a1a5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Sep 2015 12:16:11 +0200 Subject: usb: dwc2: fix unbalanced phy control Even when DWC2 is in (internal) suspended state, it should disable PHY in suspend and then enable it in resume. This patch fixes unbalanced PHY control sequence. Tested-by: John Youn Acked-by: John Youn Signed-off-by: Marek Szyprowski Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/platform.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index a013ea9f2c9c..b920e438cd49 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -301,8 +301,6 @@ static int __maybe_unused dwc2_suspend(struct device *dev) if (dwc2_is_device_mode(dwc2)) { ret = dwc2_hsotg_suspend(dwc2); } else { - if (dwc2->lx_state == DWC2_L0) - return 0; phy_exit(dwc2->phy); phy_power_off(dwc2->phy); -- cgit v1.2.3 From 758ed196fcc4373a129fd661875af52d7e7d4e73 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 14 Oct 2015 08:52:28 +0200 Subject: usb: dwc2: remove no longer needed init_mutex init_mutex is a leftover from the time, when s3c-hsotg driver did not implement proper pull up/down control and emulated it by enabling enabling/disabling usb phy. Proper pull up/down control has been added by commit 5b9451f8c4fbaf0549139755fb45ff2b57975b7f ("usb: dwc2: gadget: use soft-disconnect udc feature in pullup() method"), so init_muxtex can be removed now to avoid potential deadlocks with other locks. Signed-off-by: Marek Szyprowski Acked-by: John Youn Tested-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.h | 1 - drivers/usb/dwc2/gadget.c | 17 ----------------- drivers/usb/dwc2/platform.c | 1 - 3 files changed, 19 deletions(-) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index ebf25045b4e8..89091db8cf02 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -712,7 +712,6 @@ struct dwc2_hsotg { struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)]; spinlock_t lock; - struct mutex init_mutex; void *priv; int irq; struct clk *clk; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 7e5670c4532d..79d9f3bf5cf7 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3193,7 +3193,6 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, return -EINVAL; } - mutex_lock(&hsotg->init_mutex); WARN_ON(hsotg->driver); driver->driver.bus = NULL; @@ -3220,12 +3219,9 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); - mutex_unlock(&hsotg->init_mutex); - return 0; err: - mutex_unlock(&hsotg->init_mutex); hsotg->driver = NULL; return ret; } @@ -3246,8 +3242,6 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) if (!hsotg) return -ENODEV; - mutex_lock(&hsotg->init_mutex); - /* all endpoints should be shutdown */ for (ep = 1; ep < hsotg->num_of_eps; ep++) { if (hsotg->eps_in[ep]) @@ -3270,8 +3264,6 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - mutex_unlock(&hsotg->init_mutex); - return 0; } @@ -3307,7 +3299,6 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on) return 0; } - mutex_lock(&hsotg->init_mutex); spin_lock_irqsave(&hsotg->lock, flags); if (is_on) { hsotg->enabled = 1; @@ -3321,7 +3312,6 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on) hsotg->gadget.speed = USB_SPEED_UNKNOWN; spin_unlock_irqrestore(&hsotg->lock, flags); - mutex_unlock(&hsotg->init_mutex); return 0; } @@ -3832,8 +3822,6 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) if (hsotg->lx_state != DWC2_L0) return ret; - mutex_lock(&hsotg->init_mutex); - if (hsotg->driver) { int ep; @@ -3861,8 +3849,6 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) clk_disable(hsotg->clk); } - mutex_unlock(&hsotg->init_mutex); - return ret; } @@ -3874,8 +3860,6 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg) if (hsotg->lx_state == DWC2_L2) return ret; - mutex_lock(&hsotg->init_mutex); - if (hsotg->driver) { dev_info(hsotg->dev, "resuming usb gadget %s\n", hsotg->driver->driver.name); @@ -3892,7 +3876,6 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg) dwc2_hsotg_core_connect(hsotg); spin_unlock_irqrestore(&hsotg->lock, flags); } - mutex_unlock(&hsotg->init_mutex); return ret; } diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index b920e438cd49..581e9cad6800 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -252,7 +252,6 @@ static int dwc2_driver_probe(struct platform_device *dev) } spin_lock_init(&hsotg->lock); - mutex_init(&hsotg->init_mutex); /* Detect config values from hardware */ retval = dwc2_get_hwparams(hsotg); -- cgit v1.2.3 From 09a75e8577901489f77a14a3b305a9a1f67bf25b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 14 Oct 2015 08:52:29 +0200 Subject: 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 Acked-by: John Youn Tested-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.h | 24 +++-- drivers/usb/dwc2/gadget.c | 186 ++++---------------------------------- drivers/usb/dwc2/platform.c | 216 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 210 insertions(+), 216 deletions(-) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 89091db8cf02..a66d3cb62b65 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -579,6 +579,15 @@ struct dwc2_hregs_backup { * - USB_DR_MODE_PERIPHERAL * - USB_DR_MODE_HOST * - USB_DR_MODE_OTG + * @hcd_enabled Host mode sub-driver initialization indicator. + * @gadget_enabled Peripheral mode sub-driver initialization indicator. + * @ll_hw_enabled Status of low-level hardware resources. + * @phy: The otg phy transceiver structure for phy control. + * @uphy: The otg phy transceiver structure for old USB phy control. + * @plat: The platform specific configuration data. This can be removed once + * all SoCs support usb transceiver. + * @supplies: Definition of USB power supplies + * @phyif: PHY interface width * @lock: Spinlock that protects all the driver data structures * @priv: Stores a pointer to the struct usb_hcd * @queuing_high_bandwidth: True if multiple packets of a high-bandwidth @@ -671,12 +680,6 @@ struct dwc2_hregs_backup { * These are for peripheral mode: * * @driver: USB gadget driver - * @phy: The otg phy transceiver structure for phy control. - * @uphy: The otg phy transceiver structure for old USB phy control. - * @plat: The platform specific configuration data. This can be removed once - * all SoCs support usb transceiver. - * @supplies: Definition of USB power supplies - * @phyif: PHY interface width * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. * @num_of_eps: Number of available EPs (excluding EP0) * @debug_root: Root directrory for debugfs. @@ -706,10 +709,13 @@ struct dwc2_hsotg { enum usb_dr_mode dr_mode; unsigned int hcd_enabled:1; unsigned int gadget_enabled:1; + unsigned int ll_hw_enabled:1; struct phy *phy; struct usb_phy *uphy; + struct dwc2_hsotg_plat *plat; struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)]; + u32 phyif; spinlock_t lock; void *priv; @@ -812,9 +818,6 @@ struct dwc2_hsotg { #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) /* Gadget structures */ struct usb_gadget_driver *driver; - struct dwc2_hsotg_plat *plat; - - u32 phyif; int fifo_mem; unsigned int dedicated_fifos:1; unsigned char num_of_eps; @@ -1103,7 +1106,8 @@ extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); - +extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg); +extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg); /* * Dump core registers and SPRAM 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 #include #include -#include -#include #include -#include #include #include #include -#include #include "core.h" #include "hw.h" @@ -3076,50 +3072,6 @@ static struct usb_ep_ops dwc2_hsotg_ep_ops = { /* note, don't believe we have any call for the fifo routines */ }; -/** - * 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; } diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 581e9cad6800..5859b0fa19ee 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -37,11 +37,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include @@ -111,6 +114,145 @@ static const struct dwc2_core_params params_rk3066 = { .hibernation = -1, }; +static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) +{ + struct platform_device *pdev = to_platform_device(hsotg->dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) + return ret; + + ret = clk_prepare_enable(hsotg->clk); + if (ret) + return ret; + + if (hsotg->uphy) + ret = usb_phy_init(hsotg->uphy); + else if (hsotg->plat && hsotg->plat->phy_init) + ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); + else { + ret = phy_power_on(hsotg->phy); + if (ret == 0) + ret = phy_init(hsotg->phy); + } + + return ret; +} + +/** + * dwc2_lowlevel_hw_enable - enable platform lowlevel hw resources + * @hsotg: The driver state + * + * A wrapper for platform code responsible for controlling + * low-level USB platform resources (phy, clock, regulators) + */ +int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) +{ + int ret = __dwc2_lowlevel_hw_enable(hsotg); + + if (ret == 0) + hsotg->ll_hw_enabled = true; + return ret; +} + +static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) +{ + struct platform_device *pdev = to_platform_device(hsotg->dev); + int ret = 0; + + if (hsotg->uphy) + usb_phy_shutdown(hsotg->uphy); + else if (hsotg->plat && hsotg->plat->phy_exit) + ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); + else { + ret = phy_exit(hsotg->phy); + if (ret == 0) + ret = phy_power_off(hsotg->phy); + } + if (ret) + return ret; + + clk_disable_unprepare(hsotg->clk); + + ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + + return ret; +} + +/** + * dwc2_lowlevel_hw_disable - disable platform lowlevel hw resources + * @hsotg: The driver state + * + * A wrapper for platform code responsible for controlling + * low-level USB platform resources (phy, clock, regulators) + */ +int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) +{ + int ret = __dwc2_lowlevel_hw_disable(hsotg); + + if (ret == 0) + hsotg->ll_hw_enabled = false; + return ret; +} + +static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) +{ + int i, ret; + + /* Set default UTMI width */ + hsotg->phyif = GUSBCFG_PHYIF16; + + /* + * Attempt to find a generic PHY, then look for an old style + * USB PHY and then fall back to pdata + */ + hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy"); + if (IS_ERR(hsotg->phy)) { + hsotg->phy = NULL; + hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2); + if (IS_ERR(hsotg->uphy)) + hsotg->uphy = NULL; + else + hsotg->plat = dev_get_platdata(hsotg->dev); + } + + 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; + } + + if (!hsotg->phy && !hsotg->uphy && !hsotg->plat) { + dev_err(hsotg->dev, "no platform data or transceiver defined\n"); + return -EPROBE_DEFER; + } + + /* Clock */ + hsotg->clk = devm_clk_get(hsotg->dev, "otg"); + if (IS_ERR(hsotg->clk)) { + hsotg->clk = NULL; + dev_dbg(hsotg->dev, "cannot get otg clock\n"); + } + + /* Regulators */ + for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) + hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i]; + + ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) { + dev_err(hsotg->dev, "failed to request supplies: %d\n", ret); + return ret; + } + return 0; +} + /** * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the * DWC_otg driver @@ -132,6 +274,9 @@ static int dwc2_driver_remove(struct platform_device *dev) if (hsotg->gadget_enabled) dwc2_hsotg_remove(hsotg); + if (hsotg->ll_hw_enabled) + dwc2_lowlevel_hw_disable(hsotg); + return 0; } @@ -163,8 +308,6 @@ static int dwc2_driver_probe(struct platform_device *dev) struct dwc2_core_params defparams; struct dwc2_hsotg *hsotg; struct resource *res; - struct phy *phy; - struct usb_phy *uphy; int retval; int irq; @@ -233,31 +376,12 @@ static int dwc2_driver_probe(struct platform_device *dev) "Configuration mismatch. Forcing peripheral mode\n"); } - /* - * Attempt to find a generic PHY, then look for an old style - * USB PHY - */ - phy = devm_phy_get(&dev->dev, "usb2-phy"); - if (IS_ERR(phy)) { - hsotg->phy = NULL; - uphy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR(uphy)) - hsotg->uphy = NULL; - else - hsotg->uphy = uphy; - } else { - hsotg->phy = phy; - phy_power_on(hsotg->phy); - phy_init(hsotg->phy); - } - - spin_lock_init(&hsotg->lock); - - /* Detect config values from hardware */ - retval = dwc2_get_hwparams(hsotg); + retval = dwc2_lowlevel_hw_init(hsotg); if (retval) return retval; + spin_lock_init(&hsotg->lock); + hsotg->core_params = devm_kzalloc(&dev->dev, sizeof(*hsotg->core_params), GFP_KERNEL); if (!hsotg->core_params) @@ -265,13 +389,22 @@ static int dwc2_driver_probe(struct platform_device *dev) dwc2_set_all_params(hsotg->core_params, -1); + retval = dwc2_lowlevel_hw_enable(hsotg); + if (retval) + return retval; + + /* Detect config values from hardware */ + retval = dwc2_get_hwparams(hsotg); + if (retval) + goto error; + /* Validate parameter values */ dwc2_set_parameters(hsotg, params); if (hsotg->dr_mode != USB_DR_MODE_HOST) { retval = dwc2_gadget_init(hsotg, irq); if (retval) - return retval; + goto error; hsotg->gadget_enabled = 1; } @@ -280,7 +413,7 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) { if (hsotg->gadget_enabled) dwc2_hsotg_remove(hsotg); - return retval; + goto error; } hsotg->hcd_enabled = 1; } @@ -289,6 +422,14 @@ static int dwc2_driver_probe(struct platform_device *dev) dwc2_debugfs_init(hsotg); + /* Gadget code manages lowlevel hw on its own */ + if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) + dwc2_lowlevel_hw_disable(hsotg); + + return 0; + +error: + dwc2_lowlevel_hw_disable(hsotg); return retval; } @@ -297,13 +438,12 @@ static int __maybe_unused dwc2_suspend(struct device *dev) struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); int ret = 0; - if (dwc2_is_device_mode(dwc2)) { - ret = dwc2_hsotg_suspend(dwc2); - } else { - phy_exit(dwc2->phy); - phy_power_off(dwc2->phy); + if (dwc2_is_device_mode(dwc2)) + dwc2_hsotg_suspend(dwc2); + + if (dwc2->ll_hw_enabled) + ret = __dwc2_lowlevel_hw_disable(dwc2); - } return ret; } @@ -312,13 +452,15 @@ static int __maybe_unused dwc2_resume(struct device *dev) struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); int ret = 0; - if (dwc2_is_device_mode(dwc2)) { + if (dwc2->ll_hw_enabled) { + ret = __dwc2_lowlevel_hw_enable(dwc2); + if (ret) + return ret; + } + + if (dwc2_is_device_mode(dwc2)) ret = dwc2_hsotg_resume(dwc2); - } else { - phy_power_on(dwc2->phy); - phy_init(dwc2->phy); - } return ret; } -- cgit v1.2.3 From f16593034a30bcbef8f63c37d0f2b9e1a0902c2d Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 20 Oct 2015 16:33:53 -0700 Subject: usb: dwc2: host: Fix ahbcfg for rk3066 The comment for ahbcfg for rk3066 parameters (also used for rk3288) claimed that ahbcfg was INCR16, but it wasn't. Since the bits weren't shifted properly, the 0x7 ended up being masked and we ended up programming 0x3 for the HBstLen. Let's set it to INCR16 properly. As per Wu Liang Feng at Rockchip this may increase transmission efficiency. I did blackbox tests with writing 0s to a USB-based SD reader (forcefully capping CPU Freq to try to measure efficiency): cd /sys/devices/system/cpu/cpu0/cpufreq echo userspace > scaling_governor echo 126000 > scaling_setspeed for i in $(seq 10); do dd if=/dev/zero of=/dev/sdb bs=1M count=750 done With the above tests I found that speeds went from ~15MB/s to ~18MB/s. Note that most other tests I did (including reading from the same USB reader) didn't show any difference in performance. Tested-by: Heiko Stuebner Acked-by: John Youn Reviewed-by: Liangfeng Wu Signed-off-by: Douglas Anderson Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/dwc2/platform.c') diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 5859b0fa19ee..e61d773cf65e 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -108,7 +108,8 @@ static const struct dwc2_core_params params_rk3066 = { .host_ls_low_power_phy_clk = -1, .ts_dline = -1, .reload_ctl = -1, - .ahbcfg = 0x7, /* INCR16 */ + .ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT, .uframe_sched = -1, .external_id_pin_ctl = -1, .hibernation = -1, -- cgit v1.2.3