From db2be4e9e30c6e43e48c5749d3fc74cee0a6bbb3 Mon Sep 17 00:00:00 2001 From: Nikhil Badola Date: Fri, 4 Sep 2015 10:15:58 +0530 Subject: usb: dwc3: Add frame length adjustment quirk Add adjust_frame_length_quirk for writing to fladj register which adjusts (micro)frame length to value provided by "snps,quirk-frame-length-adjustment" property thus avoiding USB 2.0 devices to time-out over a longer run Signed-off-by: Nikhil Badola Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/usb/dwc3/core.c') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 064123e44566..6270581fc7a9 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -143,6 +143,32 @@ static int dwc3_soft_reset(struct dwc3 *dwc) return 0; } +/* + * dwc3_frame_length_adjustment - Adjusts frame length if required + * @dwc3: Pointer to our controller context structure + * @fladj: Value of GFLADJ_30MHZ to adjust frame length + */ +static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj) +{ + u32 reg; + u32 dft; + + if (dwc->revision < DWC3_REVISION_250A) + return; + + if (fladj == 0) + return; + + reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); + dft = reg & DWC3_GFLADJ_30MHZ_MASK; + if (!dev_WARN_ONCE(dwc->dev, dft == fladj, + "request value same as default, ignoring\n")) { + reg &= ~DWC3_GFLADJ_30MHZ_MASK; + reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj; + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); + } +} + /** * dwc3_free_one_event_buffer - Frees one event buffer * @dwc: Pointer to our controller context structure @@ -779,6 +805,7 @@ static int dwc3_probe(struct platform_device *pdev) u8 lpm_nyet_threshold; u8 tx_de_emphasis; u8 hird_threshold; + u32 fladj = 0; int ret; @@ -886,6 +913,9 @@ static int dwc3_probe(struct platform_device *pdev) &tx_de_emphasis); of_property_read_string(node, "snps,hsphy_interface", &dwc->hsphy_interface); + of_property_read_u32(node, + "snps,quirk-frame-length-adjustment", + &fladj); } else if (pdata) { dwc->maximum_speed = pdata->maximum_speed; dwc->has_lpm_erratum = pdata->has_lpm_erratum; @@ -915,6 +945,7 @@ static int dwc3_probe(struct platform_device *pdev) tx_de_emphasis = pdata->tx_de_emphasis; dwc->hsphy_interface = pdata->hsphy_interface; + fladj = pdata->fladj_value; } /* default to superspeed if no maximum_speed passed */ @@ -971,6 +1002,9 @@ static int dwc3_probe(struct platform_device *pdev) goto err1; } + /* Adjust Frame Length */ + dwc3_frame_length_adjustment(dwc, fladj); + usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); -- cgit v1.2.3 From 6344475f53977d329ec50f49805fd4ab83df4011 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Mon, 31 Aug 2015 21:09:08 +0530 Subject: usb: dwc3: support for pinctrl state change during system sleep Add support for USB DRVVBUS pinctrl state change during suspend/resume. This helps is conserving power during system sleep. Signed-off-by: Sekhar Nori Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb/dwc3/core.c') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 6270581fc7a9..cfbcebe2cf8f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -1125,6 +1126,8 @@ static int dwc3_suspend(struct device *dev) phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); + pinctrl_pm_select_sleep_state(dev); + return 0; } @@ -1134,6 +1137,8 @@ static int dwc3_resume(struct device *dev) unsigned long flags; int ret; + pinctrl_pm_select_default_state(dev); + usb_phy_init(dwc->usb3_phy); usb_phy_init(dwc->usb2_phy); ret = phy_init(dwc->usb2_generic_phy); -- cgit v1.2.3 From 63863b988eeca2823ce76b28b104e0b8366cafec Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 21 Sep 2015 11:14:32 +0300 Subject: usb: common: of_usb_get_maximum_speed to usb_get_maximum_speed 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 | 44 ++++++++++++++++++-------------------------- drivers/usb/dwc3/core.c | 3 ++- drivers/usb/musb/musb_dsps.c | 2 +- include/linux/usb/ch9.h | 11 ++++++++++- include/linux/usb/of.h | 6 ------ 6 files changed, 32 insertions(+), 36 deletions(-) (limited to 'drivers/usb/dwc3/core.c') diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3feebf7f31f0..ce7153232425 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -648,7 +648,7 @@ static int ci_get_platdata(struct device *dev, return ret; } - if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL) + if (usb_get_maximum_speed(dev) == USB_SPEED_FULL) platdata->flags |= CI_HDRC_FORCE_FULLSPEED; platdata->itc_setting = 1; diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index 9e39286a4e5a..b25a111903ab 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -60,6 +60,24 @@ const char *usb_speed_string(enum usb_device_speed speed) } EXPORT_SYMBOL_GPL(usb_speed_string); +enum usb_device_speed usb_get_maximum_speed(struct device *dev) +{ + const char *maximum_speed; + int err; + int i; + + err = device_property_read_string(dev, "maximum-speed", &maximum_speed); + if (err < 0) + return USB_SPEED_UNKNOWN; + + for (i = 0; i < ARRAY_SIZE(speed_names); i++) + if (strcmp(maximum_speed, speed_names[i]) == 0) + return i; + + return USB_SPEED_UNKNOWN; +} +EXPORT_SYMBOL_GPL(usb_get_maximum_speed); + const char *usb_state_string(enum usb_device_state state) { static const char *const names[] = { @@ -113,32 +131,6 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) } EXPORT_SYMBOL_GPL(of_usb_get_dr_mode); -/** - * of_usb_get_maximum_speed - Get maximum requested speed for a given USB - * controller. - * @np: Pointer to the given device_node - * - * The function gets the maximum speed string from property "maximum-speed", - * and returns the corresponding enum usb_device_speed. - */ -enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np) -{ - const char *maximum_speed; - int err; - int i; - - err = of_property_read_string(np, "maximum-speed", &maximum_speed); - if (err < 0) - return USB_SPEED_UNKNOWN; - - for (i = 0; i < ARRAY_SIZE(speed_names); i++) - if (strcmp(maximum_speed, speed_names[i]) == 0) - return i; - - return USB_SPEED_UNKNOWN; -} -EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed); - /** * 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/dwc3/core.c b/drivers/usb/dwc3/core.c index cfbcebe2cf8f..61a56357baf0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -870,8 +870,9 @@ static int dwc3_probe(struct platform_device *pdev) */ hird_threshold = 12; + dwc->maximum_speed = usb_get_maximum_speed(dev); + if (node) { - dwc->maximum_speed = of_usb_get_maximum_speed(node); dwc->has_lpm_erratum = of_property_read_bool(node, "snps,has-lpm-erratum"); of_property_read_u8(node, "snps,lpm-nyet-threshold", diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index c8b2ec9a79d6..c6a69eaf280f 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -747,7 +747,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, if (!ret && val) config->multipoint = true; - config->maximum_speed = of_usb_get_maximum_speed(dn); + config->maximum_speed = usb_get_maximum_speed(&parent->dev); switch (config->maximum_speed) { case USB_SPEED_LOW: case USB_SPEED_FULL: diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 27603bcbb9b9..6cc96bb12ddc 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -32,9 +32,9 @@ #ifndef __LINUX_USB_CH9_H #define __LINUX_USB_CH9_H +#include #include - /** * usb_speed_string() - Returns human readable-name of the speed. * @speed: The speed to return human-readable name for. If it's not @@ -43,6 +43,15 @@ */ extern const char *usb_speed_string(enum usb_device_speed speed); +/** + * usb_get_maximum_speed - Get maximum requested speed for a given USB + * controller. + * @dev: Pointer to the given USB controller device + * + * The function gets the maximum speed string from property "maximum-speed", + * and returns the corresponding enum usb_device_speed. + */ +extern enum usb_device_speed usb_get_maximum_speed(struct device *dev); /** * usb_state_string - Returns human readable name for the state. diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index 8c5a818ec244..ff23fea49fca 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -13,7 +13,6 @@ #if IS_ENABLED(CONFIG_OF) enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np); -enum usb_device_speed of_usb_get_maximum_speed(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); @@ -23,11 +22,6 @@ static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) return USB_DR_MODE_UNKNOWN; } -static inline enum usb_device_speed -of_usb_get_maximum_speed(struct device_node *np) -{ - return USB_SPEED_UNKNOWN; -} static inline bool of_usb_host_tpl_support(struct device_node *np) { return false; -- 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/dwc3/core.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 3d128919b7e514f0e489ab863c572a1e7032276a Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 21 Sep 2015 11:14:35 +0300 Subject: usb: dwc3: core: convert to unified device property interface No functional affect on existing platforms, but the driver is now ready to extract the properties also from ACPI tables as well as from DT. Signed-off-by: Heikki Krogerus Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 50 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'drivers/usb/dwc3/core.c') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 407151465645..c72c8c5c1c5a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -800,7 +800,6 @@ static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dwc3_platform_data *pdata = dev_get_platdata(dev); - struct device_node *node = dev->of_node; struct resource *res; struct dwc3 *dwc; u8 lpm_nyet_threshold; @@ -873,52 +872,51 @@ static int dwc3_probe(struct platform_device *pdev) 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, + dwc->has_lpm_erratum = device_property_read_bool(dev, "snps,has-lpm-erratum"); - of_property_read_u8(node, "snps,lpm-nyet-threshold", + device_property_read_u8(dev, "snps,lpm-nyet-threshold", &lpm_nyet_threshold); - dwc->is_utmi_l1_suspend = of_property_read_bool(node, + dwc->is_utmi_l1_suspend = device_property_read_bool(dev, "snps,is-utmi-l1-suspend"); - of_property_read_u8(node, "snps,hird-threshold", + device_property_read_u8(dev, "snps,hird-threshold", &hird_threshold); - dwc->usb3_lpm_capable = of_property_read_bool(node, + dwc->usb3_lpm_capable = device_property_read_bool(dev, "snps,usb3_lpm_capable"); - dwc->needs_fifo_resize = of_property_read_bool(node, + dwc->needs_fifo_resize = device_property_read_bool(dev, "tx-fifo-resize"); - dwc->disable_scramble_quirk = of_property_read_bool(node, + dwc->disable_scramble_quirk = device_property_read_bool(dev, "snps,disable_scramble_quirk"); - dwc->u2exit_lfps_quirk = of_property_read_bool(node, + dwc->u2exit_lfps_quirk = device_property_read_bool(dev, "snps,u2exit_lfps_quirk"); - dwc->u2ss_inp3_quirk = of_property_read_bool(node, + dwc->u2ss_inp3_quirk = device_property_read_bool(dev, "snps,u2ss_inp3_quirk"); - dwc->req_p1p2p3_quirk = of_property_read_bool(node, + dwc->req_p1p2p3_quirk = device_property_read_bool(dev, "snps,req_p1p2p3_quirk"); - dwc->del_p1p2p3_quirk = of_property_read_bool(node, + dwc->del_p1p2p3_quirk = device_property_read_bool(dev, "snps,del_p1p2p3_quirk"); - dwc->del_phy_power_chg_quirk = of_property_read_bool(node, + dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, "snps,del_phy_power_chg_quirk"); - dwc->lfps_filter_quirk = of_property_read_bool(node, + dwc->lfps_filter_quirk = device_property_read_bool(dev, "snps,lfps_filter_quirk"); - dwc->rx_detect_poll_quirk = of_property_read_bool(node, + dwc->rx_detect_poll_quirk = device_property_read_bool(dev, "snps,rx_detect_poll_quirk"); - dwc->dis_u3_susphy_quirk = of_property_read_bool(node, + dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, "snps,dis_u3_susphy_quirk"); - dwc->dis_u2_susphy_quirk = of_property_read_bool(node, + dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, "snps,dis_u2_susphy_quirk"); - dwc->tx_de_emphasis_quirk = of_property_read_bool(node, + dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, "snps,tx_de_emphasis_quirk"); - of_property_read_u8(node, "snps,tx_de_emphasis", + device_property_read_u8(dev, "snps,tx_de_emphasis", &tx_de_emphasis); - of_property_read_string(node, "snps,hsphy_interface", - &dwc->hsphy_interface); - of_property_read_u32(node, - "snps,quirk-frame-length-adjustment", - &fladj); - } else if (pdata) { + device_property_read_string(dev, "snps,hsphy_interface", + &dwc->hsphy_interface); + device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", + &fladj); + + if (pdata) { dwc->maximum_speed = pdata->maximum_speed; dwc->has_lpm_erratum = pdata->has_lpm_erratum; if (pdata->lpm_nyet_threshold) -- cgit v1.2.3 From 690fb3718a70c66004342f6f5e2e8a5f95b977db Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 4 Sep 2015 19:15:10 -0700 Subject: usb: dwc3: Support Synopsys USB 3.1 IP This patch allows the dwc3 driver to run on the new Synopsys USB 3.1 IP core, albeit in USB 3.0 mode only. The Synopsys USB 3.1 IP (DWC_usb31) retains mostly the same register interface and programming model as the existing USB 3.0 controller IP (DWC_usb3). However the GSNPSID and version numbers are different. Add checking for the new ID to pass driver probe. Also, since the DWC_usb31 version number is lower in value than the full GSNPSID of the DWC_usb3 IP, we set the high bit to identify DWC_usb31 and to ensure the values are higher. Finally, add a documentation note about the revision numbering scheme. Any future revision checks (for STARS, workarounds, and new features) should take into consideration how it applies to both the 3.1/3.0 IP. Cc: # v3.18+ Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 10 ++++++++-- drivers/usb/dwc3/core.h | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers/usb/dwc3/core.c') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c72c8c5c1c5a..1e276d5662f2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -534,12 +534,18 @@ static int dwc3_core_init(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); /* This should read as U3 followed by revision number */ - if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { + if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { + /* Detected DWC_usb3 IP */ + dwc->revision = reg; + } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { + /* Detected DWC_usb31 IP */ + dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); + dwc->revision |= DWC3_REVISION_IS_DWC31; + } else { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } - dwc->revision = reg; /* * Write Linux Version Code to our GUID register so it's easy to figure diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 91887455133a..0d65be744552 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -108,6 +108,9 @@ #define DWC3_GPRTBIMAP_FS0 0xc188 #define DWC3_GPRTBIMAP_FS1 0xc18c +#define DWC3_VER_NUMBER 0xc1a0 +#define DWC3_VER_TYPE 0xc1a4 + #define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) #define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04)) @@ -771,6 +774,14 @@ struct dwc3 { u32 num_event_buffers; u32 u1u2; u32 maximum_speed; + + /* + * All 3.1 IP version constants are greater than the 3.0 IP + * version constants. This works for most version checks in + * dwc3. However, in the future, this may not apply as + * features may be developed on newer versions of the 3.0 IP + * that are not in the 3.1 IP. + */ u32 revision; #define DWC3_REVISION_173A 0x5533173a @@ -793,6 +804,13 @@ struct dwc3 { #define DWC3_REVISION_270A 0x5533270a #define DWC3_REVISION_280A 0x5533280a +/* + * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really + * just so dwc31 revisions are always larger than dwc3. + */ +#define DWC3_REVISION_IS_DWC31 0x80000000 +#define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_USB31) + enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; enum dwc3_link_state link_state; -- cgit v1.2.3 From ec791d149bca4511e7d3a6a92bb3b030c5a443f9 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 2 Oct 2015 20:30:57 -0700 Subject: usb: dwc3: Add dis_enblslpm_quirk Add a quirk to clear the GUSB2PHYCFG.ENBLSLPM bit, which controls whether the PHY receives the suspend signal from the controller. Cc: # v3.18+ Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/dwc3.txt | 2 ++ drivers/usb/dwc3/core.c | 6 ++++++ drivers/usb/dwc3/core.h | 4 ++++ drivers/usb/dwc3/platform_data.h | 1 + 4 files changed, 13 insertions(+) (limited to 'drivers/usb/dwc3/core.c') diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 8c7d58553681..9ff48e0defb4 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -35,6 +35,8 @@ Optional properties: LTSSM during USB3 Compliance mode. - snps,dis_u3_susphy_quirk: when set core will disable USB3 suspend phy. - snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy. + - snps,dis_enblslpm_quirk: when set clears the enblslpm in GUSB2PHYCFG, + disabling the suspend signal to the PHY. - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal utmi_l1_suspend_n, false when asserts utmi_sleep_n - snps,hird-threshold: HIRD threshold diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 1e276d5662f2..22b4797383cd 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -515,6 +515,9 @@ static int dwc3_phy_setup(struct dwc3 *dwc) if (dwc->dis_u2_susphy_quirk) reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + if (dwc->dis_enblslpm_quirk) + reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); return 0; @@ -912,6 +915,8 @@ static int dwc3_probe(struct platform_device *pdev) "snps,dis_u3_susphy_quirk"); dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, "snps,dis_u2_susphy_quirk"); + dwc->dis_enblslpm_quirk = device_property_read_bool(dev, + "snps,dis_enblslpm_quirk"); dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, "snps,tx_de_emphasis_quirk"); @@ -945,6 +950,7 @@ static int dwc3_probe(struct platform_device *pdev) dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; + dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk; dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; if (pdata->tx_de_emphasis) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0d65be744552..36f1cb74588c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -179,6 +179,7 @@ #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) #define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) #define DWC3_GUSB2PHYCFG_ULPI_UTMI (1 << 4) +#define DWC3_GUSB2PHYCFG_ENBLSLPM (1 << 8) /* Global USB2 PHY Vendor Control Register */ #define DWC3_GUSB2PHYACC_NEWREGREQ (1 << 25) @@ -720,6 +721,8 @@ struct dwc3_scratchpad_array { * @rx_detect_poll_quirk: set if we enable rx_detect to polling lfps quirk * @dis_u3_susphy_quirk: set if we disable usb3 suspend phy * @dis_u2_susphy_quirk: set if we disable usb2 suspend phy + * @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG, + * disabling the suspend signal to the PHY. * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk * @tx_de_emphasis: Tx de-emphasis value * 0 - -6dB de-emphasis @@ -864,6 +867,7 @@ struct dwc3 { unsigned rx_detect_poll_quirk:1; unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; + unsigned dis_enblslpm_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index 400b197d9985..2bb4d3ad0e6b 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -42,6 +42,7 @@ struct dwc3_platform_data { unsigned rx_detect_poll_quirk:1; unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; + unsigned dis_enblslpm_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; -- cgit v1.2.3