From 8478536463f4b43357049ea5b1c7e0da0f80b8fb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 21 Nov 2019 10:21:44 +0100 Subject: usb: dwc3: remove unnecessary warning The dwc3 driver warns when the value written to DWC3_GFLADJ happens to be same as already read from the register. This always happens when the driver was previously running when started 2nd stage from another barebox. Signed-off-by: Sascha Hauer --- drivers/usb/dwc3/core.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c17327c791..ad84708da2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -348,12 +348,9 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); dft = reg & DWC3_GFLADJ_30MHZ_MASK; - if (!WARN(dft == dwc->fladj, - "request value same as default, ignoring\n")) { - reg &= ~DWC3_GFLADJ_30MHZ_MASK; - reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; - dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); - } + reg &= ~DWC3_GFLADJ_30MHZ_MASK; + reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); } static void dwc3_core_num_eps(struct dwc3 *dwc) -- cgit v1.2.3 From a2a05df5c5c45dce786b23d22700befddd0439ea Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 21 Nov 2019 11:22:20 +0100 Subject: usb: Add function to register otg dev We have two drivers in the tree which register an "otg" device to configure the host/peripheral switching. Before introducing a third driver create a common function for it. Signed-off-by: Sascha Hauer --- drivers/usb/otg/Kconfig | 4 +++ drivers/usb/otg/Makefile | 2 +- drivers/usb/otg/otgdev.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ include/usb/usb.h | 3 +++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/otg/otgdev.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 2c9fb46e4d..2c094452b6 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -6,3 +6,7 @@ config USB_ULPI config USB_TWL4030 depends on MFD_TWL4030 bool "TWL4030 Transceiver support" + +config USB_OTGDEV + bool + diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 465a7f098c..49c2491e58 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_TWL4030) += twl4030.o - +obj-$(CONFIG_USB_OTGDEV) += otgdev.o diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c new file mode 100644 index 0000000000..7017796e8c --- /dev/null +++ b/drivers/usb/otg/otgdev.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +static int (*set_mode_callback)(void *ctx, enum usb_dr_mode mode); +static unsigned int otg_mode; + +static int otg_set_mode(struct param_d *param, void *ctx) +{ + static int cur_mode = USB_DR_MODE_OTG; + int ret; + + if (otg_mode == USB_DR_MODE_UNKNOWN) + return -EINVAL; + + if (otg_mode == cur_mode) + return 0; + + if (cur_mode != USB_DR_MODE_OTG) + return -EBUSY; + + ret = set_mode_callback(ctx, otg_mode); + if (ret) + return ret; + + cur_mode = otg_mode; + + return 0; +} + +static const char *otg_mode_names[] = { + [USB_DR_MODE_UNKNOWN] = "unknown", + [USB_DR_MODE_HOST] = "host", + [USB_DR_MODE_PERIPHERAL] = "peripheral", + [USB_DR_MODE_OTG] = "otg", +}; + +static struct device_d otg_device = { + .name = "otg", + .id = DEVICE_ID_SINGLE, +}; + +int usb_register_otg_device(struct device_d *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx) +{ + int ret; + struct param_d *param_mode; + + if (otg_device.parent) + return -EBUSY; + + otg_device.parent = parent; + set_mode_callback = set_mode; + otg_mode = USB_DR_MODE_OTG; + + ret = register_device(&otg_device); + if (ret) + return ret; + + param_mode = dev_add_param_enum(&otg_device, "mode", + otg_set_mode, NULL, &otg_mode, + otg_mode_names, ARRAY_SIZE(otg_mode_names), ctx); + if (IS_ERR(param_mode)) + return PTR_ERR(param_mode); + + return 0; +} diff --git a/include/usb/usb.h b/include/usb/usb.h index 0045608d64..d39de71aff 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -444,6 +444,9 @@ enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np, enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np, const char *propname); +int usb_register_otg_device(struct device_d *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx); + extern struct list_head usb_device_list; #endif /*_USB_H_ */ -- cgit v1.2.3 From fd716ce4e8c909545eac5dd254b82a8081b02c28 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 21 Nov 2019 11:50:59 +0100 Subject: usb: dwc3: register otg device When the role in the device tree is specified as "otg" then register a otg device in barebox so that the user can configure the desired mode. Signed-off-by: Sascha Hauer --- drivers/usb/dwc3/Kconfig | 1 + drivers/usb/dwc3/core.c | 14 +++++++++++--- drivers/usb/dwc3/core.h | 1 - 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 09da121374..2eb8e9c85a 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -2,6 +2,7 @@ config USB_DWC3 tristate "DesignWare USB3 DRD Core Support" depends on USB && HAS_DMA select USB_XHCI + select USB_OTGDEV help Say Y or M here if your system has a Dual Role SuperSpeed USB controller based on the DesignWare USB3 IP Core. diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ad84708da2..04b700d12d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -936,12 +936,13 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) return 0; } -static int dwc3_core_init_mode(struct dwc3 *dwc) +static int dwc3_set_mode(void *ctx, enum usb_dr_mode mode) { + struct dwc3 *dwc = ctx; struct device_d *dev = dwc->dev; int ret; - switch (dwc->dr_mode) { + switch (mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); @@ -963,13 +964,20 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; default: - dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); return -EINVAL; } return 0; } +static int dwc3_core_init_mode(struct dwc3 *dwc) +{ + if (dwc->dr_mode == USB_DR_MODE_OTG) + return usb_register_otg_device(dwc->dev, dwc3_set_mode, dwc); + else + return dwc3_set_mode(dwc, dwc->dr_mode); +} + static void dwc3_get_properties(struct dwc3 *dwc) { struct device_d *dev = dwc->dev; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index df0a188a63..f2f7a311d1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1336,7 +1336,6 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode); -void dwc3_set_mode(struct dwc3 *dwc, u32 mode); /* check whether we are on the DWC_usb3 core */ static inline bool dwc3_is_usb3(struct dwc3 *dwc) -- cgit v1.2.3 From def39084c54a0975c745905cd4cf94d1a043bf85 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 21 Nov 2019 11:53:15 +0100 Subject: usb: i.MX: Use usb_register_otg_device() We now have usb_register_otg_device() to register an "otg" device. Use it and drop the custom code. Signed-off-by: Sascha Hauer --- arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c | 4 +- arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c | 4 +- drivers/usb/imx/Kconfig | 1 + drivers/usb/imx/chipidea-imx.c | 85 ++++------------------- include/usb/chipidea-imx.h | 8 +-- 5 files changed, 18 insertions(+), 84 deletions(-) diff --git a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c index 76d6f5ba86..77d92f0403 100644 --- a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c +++ b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c @@ -145,14 +145,14 @@ static iomux_v3_cfg_t eukrea_cpuimx25_pads[] = { #ifndef CONFIG_USB_GADGET struct imxusb_platformdata otg_pdata = { .flags = MXC_EHCI_INTERFACE_DIFF_UNI, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, .phymode = USBPHY_INTERFACE_MODE_UTMI, }; #endif struct imxusb_platformdata hs_pdata = { .flags = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, }; #endif diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c index a10763780e..220a484bde 100644 --- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c +++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c @@ -95,14 +95,14 @@ static struct imx_ipu_fb_platform_data ipu_fb_data = { #ifndef CONFIG_USB_GADGET struct imxusb_platformdata otg_pdata = { .flags = MXC_EHCI_INTERFACE_DIFF_UNI, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, .phymode = USBPHY_INTERFACE_MODE_UTMI, }; #endif struct imxusb_platformdata hs_pdata = { .flags = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, }; #endif diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig index 05f17fbd2f..34f35e0ff6 100644 --- a/drivers/usb/imx/Kconfig +++ b/drivers/usb/imx/Kconfig @@ -2,6 +2,7 @@ config USB_IMX_CHIPIDEA bool "i.MX USB support (read help)" depends on ARCH_IMX + select USB_OTGDEV help The Freescale i.MX SoCs have a variant of the chipidea ci13xxx for USB support. Traditionally in barebox this is supported through the diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 6c60c383f0..3cf5d26dcd 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -36,12 +36,11 @@ struct imx_chipidea { void __iomem *base; struct ehci_data data; unsigned long flags; - uint32_t mode; + enum usb_dr_mode mode; int portno; struct device_d *usbmisc; enum usb_phy_interface phymode; struct param_d *param_mode; - int role_registered; struct regulator *vbus; struct phy *phy; struct usb_phy *usbphy; @@ -103,7 +102,6 @@ static int imx_chipidea_port_post_init(void *drvdata) static int imx_chipidea_probe_dt(struct imx_chipidea *ci) { struct of_phandle_args out_args; - enum usb_dr_mode mode; if (of_parse_phandle_with_args(ci->dev->device_node, "fsl,usbmisc", "#index-cells", 0, &out_args)) @@ -116,29 +114,17 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci) ci->portno = out_args.args[0]; ci->flags = MXC_EHCI_MODE_UTMI_8BIT; - mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); + ci->mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); - switch (mode) { - case USB_DR_MODE_HOST: - default: - ci->mode = IMX_USB_MODE_HOST; - break; - case USB_DR_MODE_PERIPHERAL: - ci->mode = IMX_USB_MODE_DEVICE; - break; - case USB_DR_MODE_OTG: - ci->mode = IMX_USB_MODE_OTG; - break; - case USB_DR_MODE_UNKNOWN: + if (ci->mode == USB_DR_MODE_UNKNOWN) { /* * No dr_mode specified. This means it can either be OTG * for port 0 or host mode for the other host-only ports. */ if (ci->portno == 0) - ci->mode = IMX_USB_MODE_OTG; + ci->mode = USB_DR_MODE_OTG; else - ci->mode = IMX_USB_MODE_HOST; - break; + ci->mode = USB_DR_MODE_HOST; } ci->phymode = of_usb_get_phy_mode(ci->dev->device_node, NULL); @@ -184,18 +170,15 @@ static int ci_ehci_detect(struct device_d *dev) return ehci_detect(ci->ehci); } -static int ci_register_role(struct imx_chipidea *ci) +static int ci_set_mode(void *ctx, enum usb_dr_mode mode) { + struct imx_chipidea *ci = ctx; int ret; - if (ci->role_registered != IMX_USB_MODE_OTG) - return -EBUSY; - - if (ci->mode == IMX_USB_MODE_HOST) { + if (mode == USB_DR_MODE_HOST) { if (IS_ENABLED(CONFIG_USB_EHCI)) { struct ehci_host *ehci; - ci->role_registered = IMX_USB_MODE_HOST; ret = regulator_enable(ci->vbus); if (ret) return ret; @@ -215,10 +198,9 @@ static int ci_register_role(struct imx_chipidea *ci) } } - if (ci->mode == IMX_USB_MODE_DEVICE) { + if (mode == USB_DR_MODE_PERIPHERAL) { if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) { struct fsl_udc *udc; - ci->role_registered = IMX_USB_MODE_DEVICE; udc = ci_udc_register(ci->dev, ci->base); if (IS_ERR(udc)) @@ -234,48 +216,6 @@ static int ci_register_role(struct imx_chipidea *ci) return 0; } -static int ci_set_mode(struct param_d *param, void *priv) -{ - struct imx_chipidea *ci = priv; - - if (ci->role_registered != IMX_USB_MODE_OTG) { - if (ci->role_registered == ci->mode) - return 0; - else - return -EBUSY; - } - - return ci_register_role(ci); -} - -static const char *ci_mode_names[] = { - "host", "peripheral", "otg" -}; - -static struct device_d imx_otg_device = { - .name = "otg", - .id = DEVICE_ID_SINGLE, -}; - -static int ci_register_otg_device(struct imx_chipidea *ci) -{ - int ret; - - if (imx_otg_device.parent) - return -EBUSY; - - imx_otg_device.parent = ci->dev; - - ret = register_device(&imx_otg_device); - if (ret) - return ret; - - ci->param_mode = dev_add_param_enum(&imx_otg_device, "mode", - ci_set_mode, NULL, &ci->mode, - ci_mode_names, ARRAY_SIZE(ci_mode_names), ci); - return 0; -} - static int imx_chipidea_probe(struct device_d *dev) { struct resource *iores; @@ -288,7 +228,6 @@ static int imx_chipidea_probe(struct device_d *dev) ci = xzalloc(sizeof(*ci)); ci->dev = dev; dev->priv = ci; - ci->role_registered = IMX_USB_MODE_OTG; if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) { ret = imx_chipidea_probe_dt(ci); @@ -361,10 +300,10 @@ static int imx_chipidea_probe(struct device_d *dev) ci->data.hcor = base + 0x140; ci->data.flags = EHCI_HAS_TT; - if (ci->mode == IMX_USB_MODE_OTG) - ret = ci_register_otg_device(ci); + if (ci->mode == USB_DR_MODE_OTG) + ret = usb_register_otg_device(ci->dev, ci_set_mode, ci); else - ret = ci_register_role(ci); + ret = ci_set_mode(ci, ci->mode); return ret; }; diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index 973aee6a0e..5ea5fcc26d 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -37,16 +37,10 @@ #define MXC_EHCI_DISABLE_OVERCURRENT (1 << 14) -enum imx_usb_mode { - IMX_USB_MODE_HOST, - IMX_USB_MODE_DEVICE, - IMX_USB_MODE_OTG, -}; - struct imxusb_platformdata { unsigned long flags; enum usb_phy_interface phymode; - enum imx_usb_mode mode; + enum usb_dr_mode mode; }; int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags); -- cgit v1.2.3 From c56443efe14cc1991fcbf52ffba2b6e872b0cf61 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 21 Nov 2019 12:05:42 +0100 Subject: usb: musb: use usb_register_otg_device() We now have usb_register_otg_device() to register an "otg" device. Use it and drop the custom code. Signed-off-by: Sascha Hauer --- drivers/usb/musb/Kconfig | 1 + drivers/usb/musb/musb_dsps.c | 44 +++++++------------------------------------- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index b795f30275..127d6d1955 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -6,6 +6,7 @@ if USB_MUSB config USB_MUSB_DSPS tristate select OFDEVICE + select USB_OTGDEV config USB_MUSB_AM335X tristate "AM335x USB support" diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 5fe3bcb7cd..3b76b6cc61 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -303,50 +303,20 @@ static int get_musb_port_mode(struct device_d *dev) } } -static int dsps_set_mode(struct param_d *param, void *priv) +static int dsps_set_mode(void *ctx, enum usb_dr_mode mode) { - struct dsps_glue *glue = priv; + struct dsps_glue *glue = ctx; - if (glue->pdata.mode != MUSB_PORT_MODE_DUAL_ROLE) - return -EBUSY; - - switch (glue->otgmode) { - case 0: - default: - return -EINVAL; - case 1: + if (mode == USB_DR_MODE_HOST) glue->pdata.mode = MUSB_PORT_MODE_HOST; - break; - case 2: + else if (mode == USB_DR_MODE_PERIPHERAL) glue->pdata.mode = MUSB_PORT_MODE_GADGET; - break; - } + else + return -EINVAL; return musb_init_controller(&glue->musb, &glue->pdata); } -static const char *dsps_mode_names[] = { - "otg", "host", "peripheral" -}; - -static int dsps_register_otg_device(struct dsps_glue *glue) -{ - int ret; - - dev_set_name(&glue->otg_dev, "otg"); - glue->otg_dev.id = DEVICE_ID_DYNAMIC, - glue->otg_dev.parent = glue->dev; - - ret = register_device(&glue->otg_dev); - if (ret) - return ret; - - dev_add_param_enum(&glue->otg_dev, "mode", - dsps_set_mode, NULL, &glue->otgmode, - dsps_mode_names, ARRAY_SIZE(dsps_mode_names), glue); - return 0; -} - static int dsps_probe(struct device_d *dev) { struct resource *iores; @@ -405,7 +375,7 @@ static int dsps_probe(struct device_d *dev) config->multipoint = of_property_read_bool(dn, "mentor,multipoint"); if (pdata->mode == MUSB_PORT_MODE_DUAL_ROLE) { - ret = dsps_register_otg_device(glue); + ret = usb_register_otg_device(dev, dsps_set_mode, glue); if (ret) return ret; return 0; -- cgit v1.2.3