From 1966b8657d058ecb95031809b607bf3fd1e01c10 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 3 Aug 2016 14:16:15 +0300 Subject: usb: dwc3: make sure UX_EXIT_PX is cleared This bit is only supposed to be used with known buggy PHYs, however some platforms might erroneously set it. In order to avoid it, let's make sure this bit is always cleared. If some PHY needs this, we will need to add a quirk flag. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 6 ++++++ drivers/usb/dwc3/core.h | 1 + 2 files changed, 7 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 369bab16a824..8173d0634d68 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -431,6 +431,12 @@ static int dwc3_phy_setup(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); + /* + * Make sure UX_EXIT_PX is cleared as that causes issues with some + * PHYs. Also, this bit is not supposed to be used in normal operation. + */ + reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; + /* * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY * to '0' during coreConsultant configuration. So default value diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2b9e4ca3c932..fd640f11c0fe 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -232,6 +232,7 @@ #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) #define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 << 29) #define DWC3_GUSB3PIPECTL_DISRXDETINP3 (1 << 28) +#define DWC3_GUSB3PIPECTL_UX_EXIT_PX (1 << 27) #define DWC3_GUSB3PIPECTL_REQP1P2P3 (1 << 24) #define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19) #define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7) -- cgit v1.2.3 From 05428ba983e64d9744c9bf32e6ac197918a0a50c Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Wed, 1 Mar 2017 08:44:06 +0800 Subject: usb: dwc3: remove dwc3_log_msg trace class dwc3_log_msg trace class isn't used any more. Suggest to remove it. Signed-off-by: Lu Baolu Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/trace.h | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 2b124f94d858..69671e4589b9 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -27,31 +27,6 @@ #include "core.h" #include "debug.h" -DECLARE_EVENT_CLASS(dwc3_log_msg, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf), - TP_STRUCT__entry(__dynamic_array(char, msg, DWC3_MSG_MAX)), - TP_fast_assign( - vsnprintf(__get_str(msg), DWC3_MSG_MAX, vaf->fmt, *vaf->va); - ), - TP_printk("%s", __get_str(msg)) -); - -DEFINE_EVENT(dwc3_log_msg, dwc3_gadget, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - -DEFINE_EVENT(dwc3_log_msg, dwc3_core, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - -DEFINE_EVENT(dwc3_log_msg, dwc3_ep0, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - DECLARE_EVENT_CLASS(dwc3_log_io, TP_PROTO(void *base, u32 offset, u32 value), TP_ARGS(base, offset, value), -- cgit v1.2.3 From 8261bd4e91e26d12c1ade9f94dae51629157c18b Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 6 Apr 2017 13:14:28 +0300 Subject: usb: dwc3: make macros safe to expression arguments We must make sure that our macros are safe against expressions passed as arguments. We have seen one problem where GTXFIFOSIZ(n) was failing when passed the expression (epnum >> 1) as argument. The problem was caused by operator precedence between >> and *. To make sure macros are safe, we just wrap argument with () when using it. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index fd640f11c0fe..2fa768637f49 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -116,20 +116,20 @@ #define DWC3_VER_NUMBER 0xc1a0 #define DWC3_VER_TYPE 0xc1a4 -#define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) -#define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04)) +#define DWC3_GUSB2PHYCFG(n) (0xc200 + ((n) * 0x04)) +#define DWC3_GUSB2I2CCTL(n) (0xc240 + ((n) * 0x04)) -#define DWC3_GUSB2PHYACC(n) (0xc280 + (n * 0x04)) +#define DWC3_GUSB2PHYACC(n) (0xc280 + ((n) * 0x04)) -#define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04)) +#define DWC3_GUSB3PIPECTL(n) (0xc2c0 + ((n) * 0x04)) -#define DWC3_GTXFIFOSIZ(n) (0xc300 + (n * 0x04)) -#define DWC3_GRXFIFOSIZ(n) (0xc380 + (n * 0x04)) +#define DWC3_GTXFIFOSIZ(n) (0xc300 + ((n) * 0x04)) +#define DWC3_GRXFIFOSIZ(n) (0xc380 + ((n) * 0x04)) -#define DWC3_GEVNTADRLO(n) (0xc400 + (n * 0x10)) -#define DWC3_GEVNTADRHI(n) (0xc404 + (n * 0x10)) -#define DWC3_GEVNTSIZ(n) (0xc408 + (n * 0x10)) -#define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) +#define DWC3_GEVNTADRLO(n) (0xc400 + ((n) * 0x10)) +#define DWC3_GEVNTADRHI(n) (0xc404 + ((n) * 0x10)) +#define DWC3_GEVNTSIZ(n) (0xc408 + ((n) * 0x10)) +#define DWC3_GEVNTCOUNT(n) (0xc40c + ((n) * 0x10)) #define DWC3_GHWPARAMS8 0xc600 #define DWC3_GFLADJ 0xc630 @@ -143,13 +143,13 @@ #define DWC3_DGCMD 0xc714 #define DWC3_DALEPENA 0xc720 -#define DWC3_DEP_BASE(n) (0xc800 + (n * 0x10)) +#define DWC3_DEP_BASE(n) (0xc800 + ((n) * 0x10)) #define DWC3_DEPCMDPAR2 0x00 #define DWC3_DEPCMDPAR1 0x04 #define DWC3_DEPCMDPAR0 0x08 #define DWC3_DEPCMD 0x0c -#define DWC3_DEV_IMOD(n) (0xca00 + (n * 0x4)) +#define DWC3_DEV_IMOD(n) (0xca00 + ((n) * 0x4)) /* OTG Registers */ #define DWC3_OCFG 0xcc00 @@ -459,7 +459,7 @@ #define DWC3_DEPCMD_CMD(x) ((x) & 0xf) /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ -#define DWC3_DALEPENA_EP(n) (1 << n) +#define DWC3_DALEPENA_EP(n) (1 << (n)) #define DWC3_DEPCMD_TYPE_CONTROL 0 #define DWC3_DEPCMD_TYPE_ISOC 1 -- cgit v1.2.3 From 47d3946ea220f2db43b3abc46c9e64287d625ac3 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 31 Jan 2017 20:58:10 +0000 Subject: usb: dwc3: refactor gadget endpoint count calculation - DWC_USB3_NUM indicates the number of Device mode single directional endpoints, including OUT and IN endpoint 0. - DWC_USB3_NUM_IN_EPS indicates the maximum number of Device mode IN endpoints active at any time, including control endpoint 0. It's possible to configure RTL such that DWC_USB3_NUM_EPS is equal to DWC_USB3_NUM_IN_EPS. dwc3-core calculates the number of OUT endpoints as DWC_USB3_NUM minus DWC_USB3_NUM_IN_EPS. If RTL has been configured with DWC_USB3_NUM_IN_EPS equal to DWC_USB3_NUM then dwc3-core will calculate the number of OUT endpoints as zero. For example a from dwc3_core_num_eps() shows: [ 1.565000] /usb0@f01d0000: found 8 IN and 0 OUT endpoints This patch refactors the endpoint calculation down to one variable dwc->num_eps taking care to maintain the current mapping of endpoints for fixed FPGA configurations as described in Table 4-7 of version 2.60a of the DWC USB3 databook. The endpoint mapping will then be EP-OUT, EP-IN etc, up to DWC_USB3_NUM. If DWC_USB3_NUM is odd then OUT will take the extra endpoint. Suggested-by: Felipe Balbi Signed-off-by: Bryan O'Donoghue Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 3 +-- drivers/usb/dwc3/core.h | 6 ++---- drivers/usb/dwc3/debugfs.c | 15 ++------------- drivers/usb/dwc3/gadget.c | 33 +++++++++------------------------ 4 files changed, 14 insertions(+), 43 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 8173d0634d68..56f136784cd3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -397,8 +397,7 @@ static void dwc3_core_num_eps(struct dwc3 *dwc) { struct dwc3_hwparams *parms = &dwc->hwparams; - dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); - dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; + dwc->num_eps = DWC3_NUM_EPS(parms); } static void dwc3_cache_hwparams(struct dwc3 *dwc) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2fa768637f49..92045efefaab 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -800,8 +800,7 @@ struct dwc3_scratchpad_array { * @u2pel: parameter from Set SEL request. * @u1sel: parameter from Set SEL request. * @u1pel: parameter from Set SEL request. - * @num_out_eps: number of out endpoints - * @num_in_eps: number of in endpoints + * @num_eps: number of endpoints * @ep0_next_event: hold the next expected event * @ep0state: state of endpoint zero * @link_state: link state @@ -961,8 +960,7 @@ struct dwc3 { u8 speed; - u8 num_out_eps; - u8 num_in_eps; + u8 num_eps; struct dwc3_hwparams hwparams; struct dentry *root; diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 31926dda43c9..7df45415ad70 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -822,19 +822,8 @@ static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc, { int i; - for (i = 0; i < dwc->num_in_eps; i++) { - u8 epnum = (i << 1) | 1; - struct dwc3_ep *dep = dwc->eps[epnum]; - - if (!dep) - continue; - - dwc3_debugfs_create_endpoint_dir(dep, parent); - } - - for (i = 0; i < dwc->num_out_eps; i++) { - u8 epnum = (i << 1); - struct dwc3_ep *dep = dwc->eps[epnum]; + for (i = 0; i < dwc->num_eps; i++) { + struct dwc3_ep *dep = dwc->eps[i]; if (!dep) continue; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 79e7a3480d51..fe4e0ac00f06 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2006,14 +2006,13 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { /* -------------------------------------------------------------------------- */ -static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, - u8 num, u32 direction) +static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, u8 num) { struct dwc3_ep *dep; - u8 i; + u8 epnum; - for (i = 0; i < num; i++) { - u8 epnum = (i << 1) | (direction ? 1 : 0); + for (epnum = 0; epnum < num; epnum++) { + bool direction = epnum & 1; dep = kzalloc(sizeof(*dep), GFP_KERNEL); if (!dep) @@ -2021,12 +2020,12 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, dep->dwc = dwc; dep->number = epnum; - dep->direction = !!direction; + dep->direction = direction; dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); dwc->eps[epnum] = dep; snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, - (epnum & 1) ? "in" : "out"); + direction ? "in" : "out"); dep->endpoint.name = dep->name; @@ -2053,7 +2052,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, /* MDWIDTH is represented in bits, we need it in bytes */ mdwidth /= 8; - size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(i)); + size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(epnum >> 1)); size = DWC3_GTXFIFOSIZ_TXFDEF(size); /* FIFO Depth is in MDWDITH bytes. Multiply */ @@ -2103,7 +2102,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, dep->endpoint.caps.type_int = true; } - dep->endpoint.caps.dir_in = !!direction; + dep->endpoint.caps.dir_in = direction; dep->endpoint.caps.dir_out = !direction; INIT_LIST_HEAD(&dep->pending_list); @@ -2115,23 +2114,9 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) { - int ret; - INIT_LIST_HEAD(&dwc->gadget.ep_list); - ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0); - if (ret < 0) { - dev_err(dwc->dev, "failed to initialize OUT endpoints\n"); - return ret; - } - - ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1); - if (ret < 0) { - dev_err(dwc->dev, "failed to initialize IN endpoints\n"); - return ret; - } - - return 0; + return dwc3_gadget_init_hw_endpoints(dwc, dwc->num_eps); } static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) -- cgit v1.2.3 From f3bcfc7e68f0f13903465dae8196dade17ebb364 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 31 Jan 2017 20:58:11 +0000 Subject: usb: dwc3: remove dwc3_gadget_init_hw_endpoints A previous patch in the series reduces the number of callsites of dwc3_gadget_init_hw_endpoints from two to one. This patch removes the redundant step of wrappering one function in the other, which can be done by adding a parameter to dwc3_gadget_init_endpoints and moving the linked-list initialization of dwc->gadet.ep_list. Signed-off-by: Bryan O'Donoghue Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fe4e0ac00f06..1a90877f8b96 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2006,11 +2006,13 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { /* -------------------------------------------------------------------------- */ -static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, u8 num) +static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num) { struct dwc3_ep *dep; u8 epnum; + INIT_LIST_HEAD(&dwc->gadget.ep_list); + for (epnum = 0; epnum < num; epnum++) { bool direction = epnum & 1; @@ -2112,13 +2114,6 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, u8 num) return 0; } -static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) -{ - INIT_LIST_HEAD(&dwc->gadget.ep_list); - - return dwc3_gadget_init_hw_endpoints(dwc, dwc->num_eps); -} - static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) { struct dwc3_ep *dep; @@ -3226,7 +3221,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) * sure we're starting from a well known location. */ - ret = dwc3_gadget_init_endpoints(dwc); + ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); if (ret) goto err6; -- cgit v1.2.3 From 3a932b0f50f4c0782a27a257b7557f8b928299b2 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 30 Jan 2017 12:25:04 -0700 Subject: usb: dwc3: exynos: change goto labels to meaningful names Change goto labels to meaningful names from a series of errNs. Signed-off-by: Shuah Khan Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 1515d45ebcec..98f74ff66120 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -147,53 +147,53 @@ static int dwc3_exynos_probe(struct platform_device *pdev) exynos->vdd33 = devm_regulator_get(dev, "vdd33"); if (IS_ERR(exynos->vdd33)) { ret = PTR_ERR(exynos->vdd33); - goto err2; + goto vdd33_err; } ret = regulator_enable(exynos->vdd33); if (ret) { dev_err(dev, "Failed to enable VDD33 supply\n"); - goto err2; + goto vdd33_err; } exynos->vdd10 = devm_regulator_get(dev, "vdd10"); if (IS_ERR(exynos->vdd10)) { ret = PTR_ERR(exynos->vdd10); - goto err3; + goto vdd10_err; } ret = regulator_enable(exynos->vdd10); if (ret) { dev_err(dev, "Failed to enable VDD10 supply\n"); - goto err3; + goto vdd10_err; } ret = dwc3_exynos_register_phys(exynos); if (ret) { dev_err(dev, "couldn't register PHYs\n"); - goto err4; + goto phys_err; } if (node) { ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to add dwc3 core\n"); - goto err5; + goto populate_err; } } else { dev_err(dev, "no device node, failed to add dwc3 core\n"); ret = -ENODEV; - goto err5; + goto populate_err; } return 0; -err5: +populate_err: platform_device_unregister(exynos->usb2_phy); platform_device_unregister(exynos->usb3_phy); -err4: +phys_err: regulator_disable(exynos->vdd10); -err3: +vdd10_err: regulator_disable(exynos->vdd33); -err2: +vdd33_err: clk_disable_unprepare(exynos->axius_clk); axius_clk_err: clk_disable_unprepare(exynos->susp_clk); -- cgit v1.2.3 From af771d731b8e31e6c5aced2b1b066edd16106a6f Mon Sep 17 00:00:00 2001 From: John Youn Date: Thu, 26 Jan 2017 11:58:40 -0800 Subject: usb: dwc3: gadget: Fix starting microframe for ISOC The gadget wants to set the starting microframe for the first ISOC TRB to 4 microframes in the future, but it does so by multiplying the dep->interval. This only works if dep->interval = 1. For other intervals it will put it 4 *intervals* in the future which may be way too much. Fix so that it always adds just one interval or at least 4 microframes. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1a90877f8b96..640e4aa5482d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1184,8 +1184,11 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, return; } - /* 4 micro frames in the future */ - uf = cur_uf + dep->interval * 4; + /* + * Schedule the first trb for one interval in the future or at + * least 4 microframes. + */ + uf = cur_uf + max_t(u32, 4, dep->interval); __dwc3_gadget_kick_transfer(dep, uf); } -- cgit v1.2.3 From aad7c25964955ccf097712d596ef00a3e187341e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 22 Mar 2017 13:03:13 +0200 Subject: usb: dwc3: trace: change format for string to cmd trace a %x is much easier for a human to parse when reading tracepoint output. Let's change it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 69671e4589b9..fd5fc91fa9a0 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -173,7 +173,7 @@ DECLARE_EVENT_CLASS(dwc3_log_generic_cmd, __entry->param = param; __entry->status = status; ), - TP_printk("cmd '%s' [%d] param %08x --> status: %s", + TP_printk("cmd '%s' [%x] param %08x --> status: %s", dwc3_gadget_generic_cmd_string(__entry->cmd), __entry->cmd, __entry->param, dwc3_gadget_generic_cmd_status_string(__entry->status) -- cgit v1.2.3 From ff3f0789b3dc37869b8c45e023f01f9dca0cdd8f Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 30 Mar 2017 09:46:40 +0300 Subject: usb: dwc3: use BIT() macro where possible To avoid checkpatch warnings with new patches let's start using the BIT() macro wherever possible. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 195 ++++++++++++++++++++++--------------------- drivers/usb/dwc3/dwc3-omap.c | 48 +++++------ drivers/usb/dwc3/gadget.h | 20 ++--- 3 files changed, 132 insertions(+), 131 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 92045efefaab..2ad8ce2a02e8 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ #define DWC3_DEVICE_EVENT_OVERFLOW 11 #define DWC3_GEVNTCOUNT_MASK 0xfffc -#define DWC3_GEVNTCOUNT_EHB (1 << 31) +#define DWC3_GEVNTCOUNT_EHB BIT(31) #define DWC3_GSNPSID_MASK 0xffff0000 #define DWC3_GSNPSREV_MASK 0xffff @@ -176,11 +177,11 @@ /* Global RX Threshold Configuration Register */ #define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) #define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24) -#define DWC3_GRXTHRCFG_PKTCNTSEL (1 << 29) +#define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29) /* Global Configuration Register */ #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) -#define DWC3_GCTL_U2RSTECN (1 << 16) +#define DWC3_GCTL_U2RSTECN BIT(16) #define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6) #define DWC3_GCTL_CLK_BUS (0) #define DWC3_GCTL_CLK_PIPE (1) @@ -193,24 +194,24 @@ #define DWC3_GCTL_PRTCAP_DEVICE 2 #define DWC3_GCTL_PRTCAP_OTG 3 -#define DWC3_GCTL_CORESOFTRESET (1 << 11) -#define DWC3_GCTL_SOFITPSYNC (1 << 10) +#define DWC3_GCTL_CORESOFTRESET BIT(11) +#define DWC3_GCTL_SOFITPSYNC BIT(10) #define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) #define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) -#define DWC3_GCTL_DISSCRAMBLE (1 << 3) -#define DWC3_GCTL_U2EXIT_LFPS (1 << 2) -#define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) -#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) +#define DWC3_GCTL_DISSCRAMBLE BIT(3) +#define DWC3_GCTL_U2EXIT_LFPS BIT(2) +#define DWC3_GCTL_GBLHIBERNATIONEN BIT(1) +#define DWC3_GCTL_DSBLCLKGTNG BIT(0) /* Global User Control 1 Register */ -#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW (1 << 24) +#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) /* Global USB2 PHY Configuration Register */ -#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) -#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30) -#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) -#define DWC3_GUSB2PHYCFG_ULPI_UTMI (1 << 4) -#define DWC3_GUSB2PHYCFG_ENBLSLPM (1 << 8) +#define DWC3_GUSB2PHYCFG_PHYSOFTRST BIT(31) +#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS BIT(30) +#define DWC3_GUSB2PHYCFG_SUSPHY BIT(6) +#define DWC3_GUSB2PHYCFG_ULPI_UTMI BIT(4) +#define DWC3_GUSB2PHYCFG_ENBLSLPM BIT(8) #define DWC3_GUSB2PHYCFG_PHYIF(n) (n << 3) #define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) #define DWC3_GUSB2PHYCFG_USBTRDTIM(n) (n << 10) @@ -221,26 +222,26 @@ #define UTMI_PHYIF_8_BIT 0 /* Global USB2 PHY Vendor Control Register */ -#define DWC3_GUSB2PHYACC_NEWREGREQ (1 << 25) -#define DWC3_GUSB2PHYACC_BUSY (1 << 23) -#define DWC3_GUSB2PHYACC_WRITE (1 << 22) +#define DWC3_GUSB2PHYACC_NEWREGREQ BIT(25) +#define DWC3_GUSB2PHYACC_BUSY BIT(23) +#define DWC3_GUSB2PHYACC_WRITE BIT(22) #define DWC3_GUSB2PHYACC_ADDR(n) (n << 16) #define DWC3_GUSB2PHYACC_EXTEND_ADDR(n) (n << 8) #define DWC3_GUSB2PHYACC_DATA(n) (n & 0xff) /* Global USB3 PIPE Control Register */ -#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) -#define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 << 29) -#define DWC3_GUSB3PIPECTL_DISRXDETINP3 (1 << 28) -#define DWC3_GUSB3PIPECTL_UX_EXIT_PX (1 << 27) -#define DWC3_GUSB3PIPECTL_REQP1P2P3 (1 << 24) +#define DWC3_GUSB3PIPECTL_PHYSOFTRST BIT(31) +#define DWC3_GUSB3PIPECTL_U2SSINP3OK BIT(29) +#define DWC3_GUSB3PIPECTL_DISRXDETINP3 BIT(28) +#define DWC3_GUSB3PIPECTL_UX_EXIT_PX BIT(27) +#define DWC3_GUSB3PIPECTL_REQP1P2P3 BIT(24) #define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19) #define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7) #define DWC3_GUSB3PIPECTL_DEP1P2P3_EN DWC3_GUSB3PIPECTL_DEP1P2P3(1) -#define DWC3_GUSB3PIPECTL_DEPOCHANGE (1 << 18) -#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) -#define DWC3_GUSB3PIPECTL_LFPSFILT (1 << 9) -#define DWC3_GUSB3PIPECTL_RX_DETOPOLL (1 << 8) +#define DWC3_GUSB3PIPECTL_DEPOCHANGE BIT(18) +#define DWC3_GUSB3PIPECTL_SUSPHY BIT(17) +#define DWC3_GUSB3PIPECTL_LFPSFILT BIT(9) +#define DWC3_GUSB3PIPECTL_RX_DETOPOLL BIT(8) #define DWC3_GUSB3PIPECTL_TX_DEEPH_MASK DWC3_GUSB3PIPECTL_TX_DEEPH(3) #define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1) @@ -249,7 +250,7 @@ #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) /* Global Event Size Registers */ -#define DWC3_GEVNTSIZ_INTMASK (1 << 31) +#define DWC3_GEVNTSIZ_INTMASK BIT(31) #define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff) /* Global HWPARAMS0 Register */ @@ -290,18 +291,18 @@ #define DWC3_MAX_HIBER_SCRATCHBUFS 15 /* Global HWPARAMS6 Register */ -#define DWC3_GHWPARAMS6_EN_FPGA (1 << 7) +#define DWC3_GHWPARAMS6_EN_FPGA BIT(7) /* Global HWPARAMS7 Register */ #define DWC3_GHWPARAMS7_RAM1_DEPTH(n) ((n) & 0xffff) #define DWC3_GHWPARAMS7_RAM2_DEPTH(n) (((n) >> 16) & 0xffff) /* Global Frame Length Adjustment Register */ -#define DWC3_GFLADJ_30MHZ_SDBND_SEL (1 << 7) +#define DWC3_GFLADJ_30MHZ_SDBND_SEL BIT(7) #define DWC3_GFLADJ_30MHZ_MASK 0x3f /* Global User Control Register 2 */ -#define DWC3_GUCTL2_RST_ACTBITLATER (1 << 14) +#define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) /* Device Configuration Register */ #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) @@ -311,23 +312,23 @@ #define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ #define DWC3_DCFG_SUPERSPEED (4 << 0) #define DWC3_DCFG_HIGHSPEED (0 << 0) -#define DWC3_DCFG_FULLSPEED (1 << 0) +#define DWC3_DCFG_FULLSPEED BIT(0) #define DWC3_DCFG_LOWSPEED (2 << 0) #define DWC3_DCFG_NUMP_SHIFT 17 #define DWC3_DCFG_NUMP(n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f) #define DWC3_DCFG_NUMP_MASK (0x1f << DWC3_DCFG_NUMP_SHIFT) -#define DWC3_DCFG_LPM_CAP (1 << 22) +#define DWC3_DCFG_LPM_CAP BIT(22) /* Device Control Register */ -#define DWC3_DCTL_RUN_STOP (1 << 31) -#define DWC3_DCTL_CSFTRST (1 << 30) -#define DWC3_DCTL_LSFTRST (1 << 29) +#define DWC3_DCTL_RUN_STOP BIT(31) +#define DWC3_DCTL_CSFTRST BIT(30) +#define DWC3_DCTL_LSFTRST BIT(29) #define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) #define DWC3_DCTL_HIRD_THRES(n) ((n) << 24) -#define DWC3_DCTL_APPL1RES (1 << 23) +#define DWC3_DCTL_APPL1RES BIT(23) /* These apply for core versions 1.87a and earlier */ #define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) @@ -342,15 +343,15 @@ #define DWC3_DCTL_LPM_ERRATA_MASK DWC3_DCTL_LPM_ERRATA(0xf) #define DWC3_DCTL_LPM_ERRATA(n) ((n) << 20) -#define DWC3_DCTL_KEEP_CONNECT (1 << 19) -#define DWC3_DCTL_L1_HIBER_EN (1 << 18) -#define DWC3_DCTL_CRS (1 << 17) -#define DWC3_DCTL_CSS (1 << 16) +#define DWC3_DCTL_KEEP_CONNECT BIT(19) +#define DWC3_DCTL_L1_HIBER_EN BIT(18) +#define DWC3_DCTL_CRS BIT(17) +#define DWC3_DCTL_CSS BIT(16) -#define DWC3_DCTL_INITU2ENA (1 << 12) -#define DWC3_DCTL_ACCEPTU2ENA (1 << 11) -#define DWC3_DCTL_INITU1ENA (1 << 10) -#define DWC3_DCTL_ACCEPTU1ENA (1 << 9) +#define DWC3_DCTL_INITU2ENA BIT(12) +#define DWC3_DCTL_ACCEPTU2ENA BIT(11) +#define DWC3_DCTL_INITU1ENA BIT(10) +#define DWC3_DCTL_ACCEPTU1ENA BIT(9) #define DWC3_DCTL_TSTCTRL_MASK (0xf << 1) #define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5) @@ -365,36 +366,36 @@ #define DWC3_DCTL_ULSTCHNG_LOOPBACK (DWC3_DCTL_ULSTCHNGREQ(11)) /* Device Event Enable Register */ -#define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN (1 << 12) -#define DWC3_DEVTEN_EVNTOVERFLOWEN (1 << 11) -#define DWC3_DEVTEN_CMDCMPLTEN (1 << 10) -#define DWC3_DEVTEN_ERRTICERREN (1 << 9) -#define DWC3_DEVTEN_SOFEN (1 << 7) -#define DWC3_DEVTEN_EOPFEN (1 << 6) -#define DWC3_DEVTEN_HIBERNATIONREQEVTEN (1 << 5) -#define DWC3_DEVTEN_WKUPEVTEN (1 << 4) -#define DWC3_DEVTEN_ULSTCNGEN (1 << 3) -#define DWC3_DEVTEN_CONNECTDONEEN (1 << 2) -#define DWC3_DEVTEN_USBRSTEN (1 << 1) -#define DWC3_DEVTEN_DISCONNEVTEN (1 << 0) +#define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN BIT(12) +#define DWC3_DEVTEN_EVNTOVERFLOWEN BIT(11) +#define DWC3_DEVTEN_CMDCMPLTEN BIT(10) +#define DWC3_DEVTEN_ERRTICERREN BIT(9) +#define DWC3_DEVTEN_SOFEN BIT(7) +#define DWC3_DEVTEN_EOPFEN BIT(6) +#define DWC3_DEVTEN_HIBERNATIONREQEVTEN BIT(5) +#define DWC3_DEVTEN_WKUPEVTEN BIT(4) +#define DWC3_DEVTEN_ULSTCNGEN BIT(3) +#define DWC3_DEVTEN_CONNECTDONEEN BIT(2) +#define DWC3_DEVTEN_USBRSTEN BIT(1) +#define DWC3_DEVTEN_DISCONNEVTEN BIT(0) /* Device Status Register */ -#define DWC3_DSTS_DCNRD (1 << 29) +#define DWC3_DSTS_DCNRD BIT(29) /* This applies for core versions 1.87a and earlier */ -#define DWC3_DSTS_PWRUPREQ (1 << 24) +#define DWC3_DSTS_PWRUPREQ BIT(24) /* These apply for core versions 1.94a and later */ -#define DWC3_DSTS_RSS (1 << 25) -#define DWC3_DSTS_SSS (1 << 24) +#define DWC3_DSTS_RSS BIT(25) +#define DWC3_DSTS_SSS BIT(24) -#define DWC3_DSTS_COREIDLE (1 << 23) -#define DWC3_DSTS_DEVCTRLHLT (1 << 22) +#define DWC3_DSTS_COREIDLE BIT(23) +#define DWC3_DSTS_DEVCTRLHLT BIT(22) #define DWC3_DSTS_USBLNKST_MASK (0x0f << 18) #define DWC3_DSTS_USBLNKST(n) (((n) & DWC3_DSTS_USBLNKST_MASK) >> 18) -#define DWC3_DSTS_RXFIFOEMPTY (1 << 17) +#define DWC3_DSTS_RXFIFOEMPTY BIT(17) #define DWC3_DSTS_SOFFN_MASK (0x3fff << 3) #define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) @@ -404,7 +405,7 @@ #define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ #define DWC3_DSTS_SUPERSPEED (4 << 0) #define DWC3_DSTS_HIGHSPEED (0 << 0) -#define DWC3_DSTS_FULLSPEED (1 << 0) +#define DWC3_DSTS_FULLSPEED BIT(0) #define DWC3_DSTS_LOWSPEED (2 << 0) /* Device Generic Command Register */ @@ -422,26 +423,26 @@ #define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10 #define DWC3_DGCMD_STATUS(n) (((n) >> 12) & 0x0F) -#define DWC3_DGCMD_CMDACT (1 << 10) -#define DWC3_DGCMD_CMDIOC (1 << 8) +#define DWC3_DGCMD_CMDACT BIT(10) +#define DWC3_DGCMD_CMDIOC BIT(8) /* Device Generic Command Parameter Register */ -#define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT (1 << 0) +#define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT BIT(0) #define DWC3_DGCMDPAR_FIFO_NUM(n) ((n) << 0) #define DWC3_DGCMDPAR_RX_FIFO (0 << 5) -#define DWC3_DGCMDPAR_TX_FIFO (1 << 5) +#define DWC3_DGCMDPAR_TX_FIFO BIT(5) #define DWC3_DGCMDPAR_LOOPBACK_DIS (0 << 0) -#define DWC3_DGCMDPAR_LOOPBACK_ENA (1 << 0) +#define DWC3_DGCMDPAR_LOOPBACK_ENA BIT(0) /* Device Endpoint Command Register */ #define DWC3_DEPCMD_PARAM_SHIFT 16 #define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT) #define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) #define DWC3_DEPCMD_STATUS(x) (((x) >> 12) & 0x0F) -#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11) -#define DWC3_DEPCMD_CLEARPENDIN (1 << 11) -#define DWC3_DEPCMD_CMDACT (1 << 10) -#define DWC3_DEPCMD_CMDIOC (1 << 8) +#define DWC3_DEPCMD_HIPRI_FORCERM BIT(11) +#define DWC3_DEPCMD_CLEARPENDIN BIT(11) +#define DWC3_DEPCMD_CMDACT BIT(10) +#define DWC3_DEPCMD_CMDIOC BIT(8) #define DWC3_DEPCMD_DEPSTARTCFG (0x09 << 0) #define DWC3_DEPCMD_ENDTRANSFER (0x08 << 0) @@ -459,7 +460,7 @@ #define DWC3_DEPCMD_CMD(x) ((x) & 0xf) /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ -#define DWC3_DALEPENA_EP(n) (1 << (n)) +#define DWC3_DALEPENA_EP(n) BIT(n) #define DWC3_DEPCMD_TYPE_CONTROL 0 #define DWC3_DEPCMD_TYPE_ISOC 1 @@ -501,8 +502,8 @@ struct dwc3_event_buffer { struct dwc3 *dwc; }; -#define DWC3_EP_FLAG_STALLED (1 << 0) -#define DWC3_EP_FLAG_WEDGED (1 << 1) +#define DWC3_EP_FLAG_STALLED BIT(0) +#define DWC3_EP_FLAG_WEDGED BIT(1) #define DWC3_EP_DIRECTION_TX true #define DWC3_EP_DIRECTION_RX false @@ -551,17 +552,17 @@ struct dwc3_ep { u32 saved_state; unsigned flags; -#define DWC3_EP_ENABLED (1 << 0) -#define DWC3_EP_STALL (1 << 1) -#define DWC3_EP_WEDGE (1 << 2) -#define DWC3_EP_BUSY (1 << 4) -#define DWC3_EP_PENDING_REQUEST (1 << 5) -#define DWC3_EP_MISSED_ISOC (1 << 6) -#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) -#define DWC3_EP_TRANSFER_STARTED (1 << 8) +#define DWC3_EP_ENABLED BIT(0) +#define DWC3_EP_STALL BIT(1) +#define DWC3_EP_WEDGE BIT(2) +#define DWC3_EP_BUSY BIT(4) +#define DWC3_EP_PENDING_REQUEST BIT(5) +#define DWC3_EP_MISSED_ISOC BIT(6) +#define DWC3_EP_END_TRANSFER_PENDING BIT(7) +#define DWC3_EP_TRANSFER_STARTED BIT(8) /* This last one is specific to EP0 */ -#define DWC3_EP0_DIR_IN (1 << 31) +#define DWC3_EP0_DIR_IN BIT(31) /* * IMPORTANT: we *know* we have 256 TRBs in our @trb_pool, so we will @@ -639,13 +640,13 @@ enum dwc3_link_state { #define DWC3_TRB_STS_XFER_IN_PROG 4 /* TRB Control */ -#define DWC3_TRB_CTRL_HWO (1 << 0) -#define DWC3_TRB_CTRL_LST (1 << 1) -#define DWC3_TRB_CTRL_CHN (1 << 2) -#define DWC3_TRB_CTRL_CSP (1 << 3) +#define DWC3_TRB_CTRL_HWO BIT(0) +#define DWC3_TRB_CTRL_LST BIT(1) +#define DWC3_TRB_CTRL_CHN BIT(2) +#define DWC3_TRB_CTRL_CSP BIT(3) #define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4) -#define DWC3_TRB_CTRL_ISP_IMI (1 << 10) -#define DWC3_TRB_CTRL_IOC (1 << 11) +#define DWC3_TRB_CTRL_ISP_IMI BIT(10) +#define DWC3_TRB_CTRL_IOC BIT(11) #define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) #define DWC3_TRBCTL_TYPE(n) ((n) & (0x3f << 4)) @@ -1053,13 +1054,13 @@ struct dwc3_event_depevt { u32 status:4; /* Within XferNotReady */ -#define DEPEVT_STATUS_TRANSFER_ACTIVE (1 << 3) +#define DEPEVT_STATUS_TRANSFER_ACTIVE BIT(3) /* Within XferComplete */ -#define DEPEVT_STATUS_BUSERR (1 << 0) -#define DEPEVT_STATUS_SHORT (1 << 1) -#define DEPEVT_STATUS_IOC (1 << 2) -#define DEPEVT_STATUS_LST (1 << 3) +#define DEPEVT_STATUS_BUSERR BIT(0) +#define DEPEVT_STATUS_SHORT BIT(1) +#define DEPEVT_STATUS_IOC BIT(2) +#define DEPEVT_STATUS_LST BIT(3) /* Stream event only */ #define DEPEVT_STREAMEVT_FOUND 1 diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index f8d0747810e7..98926504b55b 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -79,40 +79,40 @@ #define USBOTGSS_DEBUG_OFFSET 0x0600 /* SYSCONFIG REGISTER */ -#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) +#define USBOTGSS_SYSCONFIG_DMADISABLE BIT(16) /* IRQ_EOI REGISTER */ -#define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0) +#define USBOTGSS_IRQ_EOI_LINE_NUMBER BIT(0) /* IRQS0 BITS */ -#define USBOTGSS_IRQO_COREIRQ_ST (1 << 0) +#define USBOTGSS_IRQO_COREIRQ_ST BIT(0) /* IRQMISC BITS */ -#define USBOTGSS_IRQMISC_DMADISABLECLR (1 << 17) -#define USBOTGSS_IRQMISC_OEVT (1 << 16) -#define USBOTGSS_IRQMISC_DRVVBUS_RISE (1 << 13) -#define USBOTGSS_IRQMISC_CHRGVBUS_RISE (1 << 12) -#define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE (1 << 11) -#define USBOTGSS_IRQMISC_IDPULLUP_RISE (1 << 8) -#define USBOTGSS_IRQMISC_DRVVBUS_FALL (1 << 5) -#define USBOTGSS_IRQMISC_CHRGVBUS_FALL (1 << 4) -#define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL (1 << 3) -#define USBOTGSS_IRQMISC_IDPULLUP_FALL (1 << 0) +#define USBOTGSS_IRQMISC_DMADISABLECLR BIT(17) +#define USBOTGSS_IRQMISC_OEVT BIT(16) +#define USBOTGSS_IRQMISC_DRVVBUS_RISE BIT(13) +#define USBOTGSS_IRQMISC_CHRGVBUS_RISE BIT(12) +#define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE BIT(11) +#define USBOTGSS_IRQMISC_IDPULLUP_RISE BIT(8) +#define USBOTGSS_IRQMISC_DRVVBUS_FALL BIT(5) +#define USBOTGSS_IRQMISC_CHRGVBUS_FALL BIT(4) +#define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL BIT(3) +#define USBOTGSS_IRQMISC_IDPULLUP_FALL BIT(0) /* UTMI_OTG_STATUS REGISTER */ -#define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS (1 << 5) -#define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS (1 << 4) -#define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS (1 << 3) -#define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP (1 << 0) +#define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS BIT(5) +#define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS BIT(4) +#define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS BIT(3) +#define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP BIT(0) /* UTMI_OTG_CTRL REGISTER */ -#define USBOTGSS_UTMI_OTG_CTRL_SW_MODE (1 << 31) -#define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT (1 << 9) -#define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE (1 << 8) -#define USBOTGSS_UTMI_OTG_CTRL_IDDIG (1 << 4) -#define USBOTGSS_UTMI_OTG_CTRL_SESSEND (1 << 3) -#define USBOTGSS_UTMI_OTG_CTRL_SESSVALID (1 << 2) -#define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID (1 << 1) +#define USBOTGSS_UTMI_OTG_CTRL_SW_MODE BIT(31) +#define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT BIT(9) +#define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE BIT(8) +#define USBOTGSS_UTMI_OTG_CTRL_IDDIG BIT(4) +#define USBOTGSS_UTMI_OTG_CTRL_SESSEND BIT(3) +#define USBOTGSS_UTMI_OTG_CTRL_SESSVALID BIT(2) +#define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID BIT(1) struct dwc3_omap { struct device *dev; diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 265e223ab645..e4602d0e515b 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -29,16 +29,16 @@ struct dwc3; /* DEPCFG parameter 1 */ #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) -#define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8) -#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) -#define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10) -#define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11) -#define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13) +#define DWC3_DEPCFG_XFER_COMPLETE_EN BIT(8) +#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN BIT(9) +#define DWC3_DEPCFG_XFER_NOT_READY_EN BIT(10) +#define DWC3_DEPCFG_FIFO_ERROR_EN BIT(11) +#define DWC3_DEPCFG_STREAM_EVENT_EN BIT(12) #define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16) -#define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24) +#define DWC3_DEPCFG_STREAM_CAPABLE BIT(24) #define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) -#define DWC3_DEPCFG_BULK_BASED (1 << 30) -#define DWC3_DEPCFG_FIFO_BASED (1 << 31) +#define DWC3_DEPCFG_BULK_BASED BIT(30) +#define DWC3_DEPCFG_FIFO_BASED BIT(31) /* DEPCFG parameter 0 */ #define DWC3_DEPCFG_EP_TYPE(n) (((n) & 0x3) << 1) @@ -47,10 +47,10 @@ struct dwc3; #define DWC3_DEPCFG_BURST_SIZE(n) (((n) & 0xf) << 22) #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) /* This applies for core versions earlier than 1.94a */ -#define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) +#define DWC3_DEPCFG_IGN_SEQ_NUM BIT(31) /* These apply for core versions 1.94a and later */ #define DWC3_DEPCFG_ACTION_INIT (0 << 30) -#define DWC3_DEPCFG_ACTION_RESTORE (1 << 30) +#define DWC3_DEPCFG_ACTION_RESTORE BIT(30) #define DWC3_DEPCFG_ACTION_MODIFY (2 << 30) /* DEPXFERCFG parameter 0 */ -- cgit v1.2.3 From 2df301cd3d717af48692542fa634727a213c7732 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 31 Mar 2017 14:10:40 +0300 Subject: usb: dwc3: debugfs: downcase OTG on 'mode' file When writing, we expect the "otg" string. When showing, we return "OTG". Let's downcase that word to avoid confusion. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 7df45415ad70..2cda6e0dd7fa 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -300,7 +300,7 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) seq_printf(s, "device\n"); break; case DWC3_GCTL_PRTCAP_OTG: - seq_printf(s, "OTG\n"); + seq_printf(s, "otg\n"); break; default: seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); -- cgit v1.2.3 From 26c9f3e391d1aa304d89dd0a9ec98a753353e194 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 31 Mar 2017 14:28:33 +0300 Subject: usb: dwc3: debugfs: make use of dwc3_gadget_link_string() Instead of redecoding link state into a string, use our helper. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 47 +--------------------------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 2cda6e0dd7fa..d77eac7b239d 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -446,52 +446,7 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) state = DWC3_DSTS_USBLNKST(reg); spin_unlock_irqrestore(&dwc->lock, flags); - switch (state) { - case DWC3_LINK_STATE_U0: - seq_printf(s, "U0\n"); - break; - case DWC3_LINK_STATE_U1: - seq_printf(s, "U1\n"); - break; - case DWC3_LINK_STATE_U2: - seq_printf(s, "U2\n"); - break; - case DWC3_LINK_STATE_U3: - seq_printf(s, "U3\n"); - break; - case DWC3_LINK_STATE_SS_DIS: - seq_printf(s, "SS.Disabled\n"); - break; - case DWC3_LINK_STATE_RX_DET: - seq_printf(s, "Rx.Detect\n"); - break; - case DWC3_LINK_STATE_SS_INACT: - seq_printf(s, "SS.Inactive\n"); - break; - case DWC3_LINK_STATE_POLL: - seq_printf(s, "Poll\n"); - break; - case DWC3_LINK_STATE_RECOV: - seq_printf(s, "Recovery\n"); - break; - case DWC3_LINK_STATE_HRESET: - seq_printf(s, "HRESET\n"); - break; - case DWC3_LINK_STATE_CMPLY: - seq_printf(s, "Compliance\n"); - break; - case DWC3_LINK_STATE_LPBK: - seq_printf(s, "Loopback\n"); - break; - case DWC3_LINK_STATE_RESET: - seq_printf(s, "Reset\n"); - break; - case DWC3_LINK_STATE_RESUME: - seq_printf(s, "Resume\n"); - break; - default: - seq_printf(s, "UNKNOWN %d\n", state); - } + seq_printf(s, "%s\n", dwc3_gadget_link_string(state)); return 0; } -- cgit v1.2.3 From 90abb425d9493d00a49b65114dcb0f7266ba64da Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 31 Mar 2017 14:37:21 +0300 Subject: usb: dwc3: debugfs: return strings that match tracepoints In order to improve usability a tiny bit, we will return strings that match what our tracepoints return. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index d77eac7b239d..3606c28be580 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -650,13 +650,13 @@ static inline const char *dwc3_trb_type_string(struct dwc3_trb *trb) case DWC3_TRBCTL_NORMAL: return "normal"; case DWC3_TRBCTL_CONTROL_SETUP: - return "control-setup"; + return "setup"; case DWC3_TRBCTL_CONTROL_STATUS2: - return "control-status2"; + return "status2"; case DWC3_TRBCTL_CONTROL_STATUS3: - return "control-status3"; + return "status3"; case DWC3_TRBCTL_CONTROL_DATA: - return "control-data"; + return "data"; case DWC3_TRBCTL_ISOCHRONOUS_FIRST: return "isoc-first"; case DWC3_TRBCTL_ISOCHRONOUS: -- cgit v1.2.3 From b5c7ed5cca82991335ae3a66428a791acc8aa7e9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 31 Mar 2017 14:44:09 +0300 Subject: usb: dwc3: expose dwc3_trb_type_string() That helper can be used from our tracepoint interface with very minor edits. Let's do so. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 28 ++++++++++++++++++++++++++++ drivers/usb/dwc3/debugfs.c | 27 ++------------------------- drivers/usb/dwc3/trace.h | 31 +------------------------------ 3 files changed, 31 insertions(+), 55 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index eeed4ffd8131..cb2d8d3f7f3d 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -124,6 +124,34 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state) } } +/** + * dwc3_trb_type_string - returns TRB type as a string + * @type: the type of the TRB + */ +static inline const char *dwc3_trb_type_string(unsigned int type) +{ + switch (type) { + case DWC3_TRBCTL_NORMAL: + return "normal"; + case DWC3_TRBCTL_CONTROL_SETUP: + return "setup"; + case DWC3_TRBCTL_CONTROL_STATUS2: + return "status2"; + case DWC3_TRBCTL_CONTROL_STATUS3: + return "status3"; + case DWC3_TRBCTL_CONTROL_DATA: + return "data"; + case DWC3_TRBCTL_ISOCHRONOUS_FIRST: + return "isoc-first"; + case DWC3_TRBCTL_ISOCHRONOUS: + return "isoc"; + case DWC3_TRBCTL_LINK_TRB: + return "link"; + default: + return "UNKNOWN"; + } +} + static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) { switch (state) { diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 3606c28be580..b53ca3b0171a 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -644,30 +644,6 @@ out: return 0; } -static inline const char *dwc3_trb_type_string(struct dwc3_trb *trb) -{ - switch (DWC3_TRBCTL_TYPE(trb->ctrl)) { - case DWC3_TRBCTL_NORMAL: - return "normal"; - case DWC3_TRBCTL_CONTROL_SETUP: - return "setup"; - case DWC3_TRBCTL_CONTROL_STATUS2: - return "status2"; - case DWC3_TRBCTL_CONTROL_STATUS3: - return "status3"; - case DWC3_TRBCTL_CONTROL_DATA: - return "data"; - case DWC3_TRBCTL_ISOCHRONOUS_FIRST: - return "isoc-first"; - case DWC3_TRBCTL_ISOCHRONOUS: - return "isoc"; - case DWC3_TRBCTL_LINK_TRB: - return "link"; - default: - return "UNKNOWN"; - } -} - static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) { struct dwc3_ep *dep = s->private; @@ -688,10 +664,11 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) for (i = 0; i < DWC3_TRB_NUM; i++) { struct dwc3_trb *trb = &dep->trb_pool[i]; + unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl); seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n", trb->bph, trb->bpl, trb->size, - dwc3_trb_type_string(trb), + dwc3_trb_type_string(type), !!(trb->ctrl & DWC3_TRB_CTRL_IOC), !!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI), !!(trb->ctrl & DWC3_TRB_CTRL_CSP), diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index fd5fc91fa9a0..f1bd444d22a3 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -273,36 +273,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, __entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's', __entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's', __entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c', - ({char *s; - switch (__entry->ctrl & 0x3f0) { - case DWC3_TRBCTL_NORMAL: - s = "normal"; - break; - case DWC3_TRBCTL_CONTROL_SETUP: - s = "setup"; - break; - case DWC3_TRBCTL_CONTROL_STATUS2: - s = "status2"; - break; - case DWC3_TRBCTL_CONTROL_STATUS3: - s = "status3"; - break; - case DWC3_TRBCTL_CONTROL_DATA: - s = "data"; - break; - case DWC3_TRBCTL_ISOCHRONOUS_FIRST: - s = "isoc-first"; - break; - case DWC3_TRBCTL_ISOCHRONOUS: - s = "isoc"; - break; - case DWC3_TRBCTL_LINK_TRB: - s = "link"; - break; - default: - s = "UNKNOWN"; - break; - } s; }) + dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl)) ) ); -- cgit v1.2.3 From 7d5e650a5fdb82ec1994497de174650767862a49 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Apr 2017 13:34:21 +0300 Subject: usb: dwc3: ep0: use immediate SETUP on TRB If we pass TRB's own address on bpl/bph fields, we can get our SETUP packet as immediate data on the TRB itself, without having to allocate extra memory for it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 4 ---- drivers/usb/dwc3/ep0.c | 11 ++++++----- drivers/usb/dwc3/gadget.c | 39 ++++++++++++--------------------------- 3 files changed, 18 insertions(+), 36 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2ad8ce2a02e8..bbb7c3f6749e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -760,12 +760,10 @@ struct dwc3_scratchpad_array { /** * struct dwc3 - representation of our controller - * @ctrl_req: usb control request which is used for ep0 * @ep0_trb: trb which is used for the ctrl_req * @ep0_bounce: bounce buffer for ep0 * @zlp_buf: used when request->zero is set * @setup_buf: used while precessing STD USB requests - * @ctrl_req_addr: dma address of ctrl_req * @ep0_trb: dma address of ep0_trb * @ep0_usb_req: dummy req used while handling STD USB requests * @ep0_bounce_addr: dma address of ep0_bounce @@ -859,14 +857,12 @@ struct dwc3_scratchpad_array { * increments or 0 to disable. */ struct dwc3 { - struct usb_ctrlrequest *ctrl_req; struct dwc3_trb *ep0_trb; void *bounce; void *ep0_bounce; void *zlp_buf; void *scratchbuf; u8 *setup_buf; - dma_addr_t ctrl_req_addr; dma_addr_t ep0_trb_addr; dma_addr_t bounce_addr; dma_addr_t ep0_bounce_addr; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e689cede9b0e..da5e085e7889 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -283,7 +283,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) complete(&dwc->ep0_in_setup); - dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8, + dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ep0_trb_addr, 8, DWC3_TRBCTL_CONTROL_SETUP, false); ret = dwc3_ep0_start_trans(dwc, 0); WARN_ON(ret < 0); @@ -794,7 +794,7 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { - struct usb_ctrlrequest *ctrl = dwc->ctrl_req; + struct usb_ctrlrequest *ctrl = (void *) dwc->ep0_trb; int ret = -EINVAL; u32 len; @@ -916,7 +916,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, dwc->ep0_next_event = DWC3_EP0_COMPLETE; - dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr, + dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ep0_trb_addr, 0, DWC3_TRBCTL_CONTROL_DATA, false); ret = dwc3_ep0_start_trans(dwc, epnum); WARN_ON(ret < 0); @@ -997,8 +997,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, req->direction = !!dep->number; if (req->request.length == 0) { + dwc3_ep0_prepare_one_trb(dwc, dep->number, - dwc->ctrl_req_addr, 0, + dwc->ep0_trb_addr, 0, DWC3_TRBCTL_CONTROL_DATA, false); ret = dwc3_ep0_start_trans(dwc, dep->number); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) @@ -1056,7 +1057,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) : DWC3_TRBCTL_CONTROL_STATUS2; dwc3_ep0_prepare_one_trb(dwc, dep->number, - dwc->ctrl_req_addr, 0, type, false); + dwc->ep0_trb_addr, 0, type, false); return dwc3_ep0_start_trans(dwc, dep->number); } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 640e4aa5482d..4787d6f449fa 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3144,27 +3144,19 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->irq_gadget = irq; - dwc->ctrl_req = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req), - &dwc->ctrl_req_addr, GFP_KERNEL); - if (!dwc->ctrl_req) { - dev_err(dwc->dev, "failed to allocate ctrl request\n"); - ret = -ENOMEM; - goto err0; - } - dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, &dwc->ep0_trb_addr, GFP_KERNEL); if (!dwc->ep0_trb) { dev_err(dwc->dev, "failed to allocate ep0 trb\n"); ret = -ENOMEM; - goto err1; + goto err0; } dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL); if (!dwc->setup_buf) { ret = -ENOMEM; - goto err2; + goto err1; } dwc->ep0_bounce = dma_alloc_coherent(dwc->sysdev, @@ -3173,20 +3165,20 @@ int dwc3_gadget_init(struct dwc3 *dwc) if (!dwc->ep0_bounce) { dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n"); ret = -ENOMEM; - goto err3; + goto err2; } dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL); if (!dwc->zlp_buf) { ret = -ENOMEM; - goto err4; + goto err3; } dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, &dwc->bounce_addr, GFP_KERNEL); if (!dwc->bounce) { ret = -ENOMEM; - goto err5; + goto err4; } init_completion(&dwc->ep0_in_setup); @@ -3226,38 +3218,34 @@ int dwc3_gadget_init(struct dwc3 *dwc) ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); if (ret) - goto err6; + goto err5; ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); - goto err6; + goto err5; } return 0; -err6: +err5: dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, dwc->bounce_addr); -err5: +err4: kfree(dwc->zlp_buf); -err4: +err3: dwc3_gadget_free_endpoints(dwc); dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE, dwc->ep0_bounce, dwc->ep0_bounce_addr); -err3: +err2: kfree(dwc->setup_buf); -err2: +err1: dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, dwc->ep0_trb, dwc->ep0_trb_addr); -err1: - dma_free_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req), - dwc->ctrl_req, dwc->ctrl_req_addr); - err0: return ret; } @@ -3280,9 +3268,6 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, dwc->ep0_trb, dwc->ep0_trb_addr); - - dma_free_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req), - dwc->ctrl_req, dwc->ctrl_req_addr); } int dwc3_gadget_suspend(struct dwc3 *dwc) -- cgit v1.2.3 From d686a5ff6a2dd94cbe66b8cc71912c9324894c24 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Apr 2017 13:47:49 +0300 Subject: usb: dwc3: ep0: pass dep as argument to internal functions Instead of constantly recomputing how dwc and epnum relate to dep, just pass dep as argument. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 52 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index da5e085e7889..3ba2309c837f 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -39,14 +39,13 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req); -static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum, +static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep, dma_addr_t buf_dma, u32 len, u32 type, bool chain) { struct dwc3_trb *trb; - struct dwc3_ep *dep; - - dep = dwc->eps[epnum]; + struct dwc3 *dwc; + dwc = dep->dwc; trb = &dwc->ep0_trb[dep->trb_enqueue]; if (chain) @@ -69,16 +68,17 @@ static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum, trace_dwc3_prepare_trb(dep, trb); } -static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum) +static int dwc3_ep0_start_trans(struct dwc3_ep *dep) { struct dwc3_gadget_ep_cmd_params params; - struct dwc3_ep *dep; + struct dwc3 *dwc; int ret; - dep = dwc->eps[epnum]; if (dep->flags & DWC3_EP_BUSY) return 0; + dwc = dep->dwc; + memset(¶ms, 0, sizeof(params)); params.param0 = upper_32_bits(dwc->ep0_trb_addr); params.param1 = lower_32_bits(dwc->ep0_trb_addr); @@ -279,13 +279,15 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) void dwc3_ep0_out_start(struct dwc3 *dwc) { + struct dwc3_ep *dep; int ret; complete(&dwc->ep0_in_setup); - dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ep0_trb_addr, 8, + dep = dwc->eps[0]; + dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8, DWC3_TRBCTL_CONTROL_SETUP, false); - ret = dwc3_ep0_start_trans(dwc, 0); + ret = dwc3_ep0_start_trans(dep); WARN_ON(ret < 0); } @@ -912,13 +914,15 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && ur->length && ur->zero) { + struct dwc3_ep *dep; int ret; dwc->ep0_next_event = DWC3_EP0_COMPLETE; - dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ep0_trb_addr, + dep = dwc->eps[epnum]; + dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, DWC3_TRBCTL_CONTROL_DATA, false); - ret = dwc3_ep0_start_trans(dwc, epnum); + ret = dwc3_ep0_start_trans(dep); WARN_ON(ret < 0); } } @@ -997,11 +1001,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, req->direction = !!dep->number; if (req->request.length == 0) { - - dwc3_ep0_prepare_one_trb(dwc, dep->number, - dwc->ep0_trb_addr, 0, + dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, DWC3_TRBCTL_CONTROL_DATA, false); - ret = dwc3_ep0_start_trans(dwc, dep->number); + ret = dwc3_ep0_start_trans(dep); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && (dep->number == 0)) { u32 transfer_size = 0; @@ -1017,8 +1019,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { transfer_size = ALIGN(req->request.length - maxpacket, maxpacket); - dwc3_ep0_prepare_one_trb(dwc, dep->number, - req->request.dma, + dwc3_ep0_prepare_one_trb(dep, req->request.dma, transfer_size, DWC3_TRBCTL_CONTROL_DATA, true); @@ -1029,20 +1030,20 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, dwc->ep0_bounced = true; - dwc3_ep0_prepare_one_trb(dwc, dep->number, - dwc->ep0_bounce_addr, transfer_size, - DWC3_TRBCTL_CONTROL_DATA, false); - ret = dwc3_ep0_start_trans(dwc, dep->number); + dwc3_ep0_prepare_one_trb(dep, dwc->ep0_bounce_addr, + transfer_size, DWC3_TRBCTL_CONTROL_DATA, + false); + ret = dwc3_ep0_start_trans(dep); } else { ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, dep->number); if (ret) return; - dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma, + dwc3_ep0_prepare_one_trb(dep, req->request.dma, req->request.length, DWC3_TRBCTL_CONTROL_DATA, false); - ret = dwc3_ep0_start_trans(dwc, dep->number); + ret = dwc3_ep0_start_trans(dep); } WARN_ON(ret < 0); @@ -1056,9 +1057,8 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 : DWC3_TRBCTL_CONTROL_STATUS2; - dwc3_ep0_prepare_one_trb(dwc, dep->number, - dwc->ep0_trb_addr, 0, type, false); - return dwc3_ep0_start_trans(dwc, dep->number); + dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, type, false); + return dwc3_ep0_start_trans(dep); } static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) -- cgit v1.2.3 From 4199c5f8bccd7ff6923c32af0f8ef0224eeaa651 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Apr 2017 14:09:13 +0300 Subject: usb: dwc3: ep0: improve handling of unaligned OUT requests Just like we did for all other endpoint types, let's rely on a chained TRB pointing to ep0_bounce_addr in order to align transfer size. This will make the code simpler. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 6 +---- drivers/usb/dwc3/ep0.c | 65 +++++++++++++---------------------------------- drivers/usb/dwc3/gadget.c | 50 ++++++++---------------------------- 3 files changed, 29 insertions(+), 92 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index bbb7c3f6749e..8dc416daa85c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -42,7 +42,7 @@ #define DWC3_PULL_UP_TIMEOUT 500 /* ms */ #define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */ #define DWC3_BOUNCE_SIZE 1024 /* size of a superspeed bulk */ -#define DWC3_EP0_BOUNCE_SIZE 512 +#define DWC3_EP0_SETUP_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 #define DWC3_XHCI_RESOURCES_NUM 2 @@ -761,12 +761,10 @@ struct dwc3_scratchpad_array { /** * struct dwc3 - representation of our controller * @ep0_trb: trb which is used for the ctrl_req - * @ep0_bounce: bounce buffer for ep0 * @zlp_buf: used when request->zero is set * @setup_buf: used while precessing STD USB requests * @ep0_trb: dma address of ep0_trb * @ep0_usb_req: dummy req used while handling STD USB requests - * @ep0_bounce_addr: dma address of ep0_bounce * @scratch_addr: dma address of scratchbuf * @ep0_in_setup: one control transfer is completed and enter setup phase * @lock: for synchronizing @@ -859,13 +857,11 @@ struct dwc3_scratchpad_array { struct dwc3 { struct dwc3_trb *ep0_trb; void *bounce; - void *ep0_bounce; void *zlp_buf; void *scratchbuf; u8 *setup_buf; dma_addr_t ep0_trb_addr; dma_addr_t bounce_addr; - dma_addr_t ep0_bounce_addr; dma_addr_t scratch_addr; struct dwc3_request ep0_usb_req; struct completion ep0_in_setup; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3ba2309c837f..04249243e4d3 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -836,7 +836,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; - unsigned transfer_size = 0; unsigned maxp; unsigned remaining_ur_length; void *buf; @@ -849,9 +848,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ep0 = dwc->eps[0]; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; - trb = dwc->ep0_trb; - trace_dwc3_complete_trb(ep0, trb); r = next_request(&ep0->pending_list); @@ -872,39 +869,17 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, remaining_ur_length = ur->length; length = trb->size & DWC3_TRB_SIZE_MASK; - maxp = ep0->endpoint.maxpacket; + transferred = ur->length - length; + ur->actual += transferred; if (dwc->ep0_bounced) { - /* - * Handle the first TRB before handling the bounce buffer if - * the request length is greater than the bounce buffer size - */ - if (ur->length > DWC3_EP0_BOUNCE_SIZE) { - transfer_size = ALIGN(ur->length - maxp, maxp); - transferred = transfer_size - length; - buf = (u8 *)buf + transferred; - ur->actual += transferred; - remaining_ur_length -= transferred; - - trb++; - length = trb->size & DWC3_TRB_SIZE_MASK; - - ep0->trb_enqueue = 0; - } - - transfer_size = roundup((ur->length - transfer_size), - maxp); - - transferred = min_t(u32, remaining_ur_length, - transfer_size - length); - memcpy(buf, dwc->ep0_bounce, transferred); - } else { - transferred = ur->length - length; + trb++; + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + ep0->trb_enqueue = 0; + dwc->ep0_bounced = false; } - ur->actual += transferred; - if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ @@ -1006,8 +981,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, ret = dwc3_ep0_start_trans(dep); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && (dep->number == 0)) { - u32 transfer_size = 0; u32 maxpacket; + u32 rem; ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, dep->number); @@ -1015,23 +990,19 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, return; maxpacket = dep->endpoint.maxpacket; - - if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { - transfer_size = ALIGN(req->request.length - maxpacket, - maxpacket); - dwc3_ep0_prepare_one_trb(dep, req->request.dma, - transfer_size, - DWC3_TRBCTL_CONTROL_DATA, - true); - } - - transfer_size = roundup((req->request.length - transfer_size), - maxpacket); - + rem = req->request.length % maxpacket; dwc->ep0_bounced = true; - dwc3_ep0_prepare_one_trb(dep, dwc->ep0_bounce_addr, - transfer_size, DWC3_TRBCTL_CONTROL_DATA, + /* prepare normal TRB */ + dwc3_ep0_prepare_one_trb(dep, req->request.dma, + req->request.length, + DWC3_TRBCTL_CONTROL_DATA, + true); + + /* Now prepare one extra TRB to align transfer size */ + dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, + maxpacket - rem, + DWC3_TRBCTL_CONTROL_DATA, false); ret = dwc3_ep0_start_trans(dep); } else { diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4787d6f449fa..4dc80729ae11 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -171,7 +171,6 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status) { struct dwc3 *dwc = dep->dwc; - unsigned int unmap_after_complete = false; req->started = false; list_del(&req->list); @@ -181,19 +180,8 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - /* - * NOTICE we don't want to unmap before calling ->complete() if we're - * dealing with a bounced ep0 request. If we unmap it here, we would end - * up overwritting the contents of req->buf and this could confuse the - * gadget driver. - */ - if (dwc->ep0_bounced && dep->number <= 1) { - dwc->ep0_bounced = false; - unmap_after_complete = true; - } else { - usb_gadget_unmap_request_by_dev(dwc->sysdev, - &req->request, req->direction); - } + usb_gadget_unmap_request_by_dev(dwc->sysdev, + &req->request, req->direction); trace_dwc3_gadget_giveback(req); @@ -201,10 +189,6 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, usb_gadget_giveback_request(&dep->endpoint, &req->request); spin_lock(&dwc->lock); - if (unmap_after_complete) - usb_gadget_unmap_request_by_dev(dwc->sysdev, - &req->request, req->direction); - if (dep->number > 1) pm_runtime_put(dwc->dev); } @@ -3153,32 +3137,23 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err0; } - dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL); + dwc->setup_buf = kzalloc(DWC3_EP0_SETUP_SIZE, GFP_KERNEL); if (!dwc->setup_buf) { ret = -ENOMEM; goto err1; } - dwc->ep0_bounce = dma_alloc_coherent(dwc->sysdev, - DWC3_EP0_BOUNCE_SIZE, &dwc->ep0_bounce_addr, - GFP_KERNEL); - if (!dwc->ep0_bounce) { - dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n"); - ret = -ENOMEM; - goto err2; - } - dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL); if (!dwc->zlp_buf) { ret = -ENOMEM; - goto err3; + goto err2; } dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, &dwc->bounce_addr, GFP_KERNEL); if (!dwc->bounce) { ret = -ENOMEM; - goto err4; + goto err3; } init_completion(&dwc->ep0_in_setup); @@ -3218,7 +3193,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); if (ret) - goto err5; + goto err4; ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { @@ -3228,16 +3203,14 @@ int dwc3_gadget_init(struct dwc3 *dwc) return 0; err5: - dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, - dwc->bounce_addr); + dwc3_gadget_free_endpoints(dwc); err4: - kfree(dwc->zlp_buf); + dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, + dwc->bounce_addr); err3: - dwc3_gadget_free_endpoints(dwc); - dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE, - dwc->ep0_bounce, dwc->ep0_bounce_addr); + kfree(dwc->zlp_buf); err2: kfree(dwc->setup_buf); @@ -3260,9 +3233,6 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, dwc->bounce_addr); - dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE, - dwc->ep0_bounce, dwc->ep0_bounce_addr); - kfree(dwc->setup_buf); kfree(dwc->zlp_buf); -- cgit v1.2.3 From d6e5a549cc4dba504a62855d9613836f76950790 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Apr 2017 16:34:38 +0300 Subject: usb: dwc3: simplify ZLP handling It's much simpler to just add one extra TRB chained to previous TRB to handle ZLP. This helps us reduce pointless allocations and simplifies the code a little bit. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 4 +-- drivers/usb/dwc3/ep0.c | 49 +++++++++++++++----------- drivers/usb/dwc3/gadget.c | 89 +++++++++++++++-------------------------------- 3 files changed, 59 insertions(+), 83 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 8dc416daa85c..d3b824912120 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -40,7 +40,6 @@ /* Global constants */ #define DWC3_PULL_UP_TIMEOUT 500 /* ms */ -#define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */ #define DWC3_BOUNCE_SIZE 1024 /* size of a superspeed bulk */ #define DWC3_EP0_SETUP_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 @@ -748,6 +747,7 @@ struct dwc3_request { unsigned direction:1; unsigned mapped:1; unsigned started:1; + unsigned zero:1; }; /* @@ -761,7 +761,6 @@ struct dwc3_scratchpad_array { /** * struct dwc3 - representation of our controller * @ep0_trb: trb which is used for the ctrl_req - * @zlp_buf: used when request->zero is set * @setup_buf: used while precessing STD USB requests * @ep0_trb: dma address of ep0_trb * @ep0_usb_req: dummy req used while handling STD USB requests @@ -857,7 +856,6 @@ struct dwc3_scratchpad_array { struct dwc3 { struct dwc3_trb *ep0_trb; void *bounce; - void *zlp_buf; void *scratchbuf; u8 *setup_buf; dma_addr_t ep0_trb_addr; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 04249243e4d3..a78c78e7a8c3 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -873,34 +873,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, transferred = ur->length - length; ur->actual += transferred; - if (dwc->ep0_bounced) { + if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && + ur->length && ur->zero) || dwc->ep0_bounced) { trb++; trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + trace_dwc3_complete_trb(ep0, trb); ep0->trb_enqueue = 0; dwc->ep0_bounced = false; } - if ((epnum & 1) && ur->actual < ur->length) { - /* for some reason we did not get everything out */ - + if ((epnum & 1) && ur->actual < ur->length) dwc3_ep0_stall_and_restart(dwc); - } else { + else dwc3_gadget_giveback(ep0, r, 0); - - if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && - ur->length && ur->zero) { - struct dwc3_ep *dep; - int ret; - - dwc->ep0_next_event = DWC3_EP0_COMPLETE; - - dep = dwc->eps[epnum]; - dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, - 0, DWC3_TRBCTL_CONTROL_DATA, false); - ret = dwc3_ep0_start_trans(dep); - WARN_ON(ret < 0); - } - } } static void dwc3_ep0_complete_status(struct dwc3 *dwc, @@ -1005,6 +990,30 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, DWC3_TRBCTL_CONTROL_DATA, false); ret = dwc3_ep0_start_trans(dep); + } else if (IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && + req->request.length && req->request.zero) { + u32 maxpacket; + u32 rem; + + ret = usb_gadget_map_request_by_dev(dwc->sysdev, + &req->request, dep->number); + if (ret) + return; + + maxpacket = dep->endpoint.maxpacket; + rem = req->request.length % maxpacket; + + /* prepare normal TRB */ + dwc3_ep0_prepare_one_trb(dep, req->request.dma, + req->request.length, + DWC3_TRBCTL_CONTROL_DATA, + true); + + /* Now prepare one extra TRB to align transfer size */ + dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, + 0, DWC3_TRBCTL_CONTROL_DATA, + false); + ret = dwc3_ep0_start_trans(dep); } else { ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, dep->number); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4dc80729ae11..6f6f0b3be3ad 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1044,6 +1044,22 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, false, 0, req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt); + } else if (req->request.zero && req->request.length && + (IS_ALIGNED(req->request.length,dep->endpoint.maxpacket))) { + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + + req->zero = true; + + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, true, 0); + + /* Now prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, + false, 0, req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt); } else { dwc3_prepare_one_trb(dep, req, false, 0); } @@ -1259,31 +1275,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) return ret; } -static void __dwc3_gadget_ep_zlp_complete(struct usb_ep *ep, - struct usb_request *request) -{ - dwc3_gadget_ep_free_request(ep, request); -} - -static int __dwc3_gadget_ep_queue_zlp(struct dwc3 *dwc, struct dwc3_ep *dep) -{ - struct dwc3_request *req; - struct usb_request *request; - struct usb_ep *ep = &dep->endpoint; - - request = dwc3_gadget_ep_alloc_request(ep, GFP_ATOMIC); - if (!request) - return -ENOMEM; - - request->length = 0; - request->buf = dwc->zlp_buf; - request->complete = __dwc3_gadget_ep_zlp_complete; - - req = to_dwc3_request(request); - - return __dwc3_gadget_ep_queue(dep, req); -} - static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags) { @@ -1297,17 +1288,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, spin_lock_irqsave(&dwc->lock, flags); ret = __dwc3_gadget_ep_queue(dep, req); - - /* - * Okay, here's the thing, if gadget driver has requested for a ZLP by - * setting request->zero, instead of doing magic, we will just queue an - * extra usb_request ourselves so that it gets handled the same way as - * any other request. - */ - if (ret == 0 && request->zero && request->length && - (request->length % ep->maxpacket == 0)) - ret = __dwc3_gadget_ep_queue_zlp(dwc, dep); - spin_unlock_irqrestore(&dwc->lock, flags); return ret; @@ -1387,7 +1367,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, dwc3_ep_inc_deq(dep); } - if (r->unaligned) { + if (r->unaligned || r->zero) { trb = r->trb + r->num_pending_sgs + 1; trb->ctrl &= ~DWC3_TRB_CTRL_HWO; dwc3_ep_inc_deq(dep); @@ -1398,7 +1378,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, trb->ctrl &= ~DWC3_TRB_CTRL_HWO; dwc3_ep_inc_deq(dep); - if (r->unaligned) { + if (r->unaligned || r->zero) { trb = r->trb + 1; trb->ctrl &= ~DWC3_TRB_CTRL_HWO; dwc3_ep_inc_deq(dep); @@ -2164,7 +2144,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, * with one TRB pending in the ring. We need to manually clear HWO bit * from that TRB. */ - if (req->unaligned && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { + if ((req->zero || req->unaligned) && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { trb->ctrl &= ~DWC3_TRB_CTRL_HWO; return 1; } @@ -2258,11 +2238,12 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, event, status, chain); } - if (req->unaligned) { + if (req->unaligned || req->zero) { trb = &dep->trb_pool[dep->trb_dequeue]; ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status, false); req->unaligned = false; + req->zero = false; } req->request.actual = length - req->remaining; @@ -3143,17 +3124,11 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err1; } - dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL); - if (!dwc->zlp_buf) { - ret = -ENOMEM; - goto err2; - } - dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, &dwc->bounce_addr, GFP_KERNEL); if (!dwc->bounce) { ret = -ENOMEM; - goto err3; + goto err2; } init_completion(&dwc->ep0_in_setup); @@ -3193,24 +3168,22 @@ int dwc3_gadget_init(struct dwc3 *dwc) ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); if (ret) - goto err4; + goto err3; ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); - goto err5; + goto err4; } return 0; -err5: - dwc3_gadget_free_endpoints(dwc); err4: - dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, - dwc->bounce_addr); + dwc3_gadget_free_endpoints(dwc); err3: - kfree(dwc->zlp_buf); + dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, + dwc->bounce_addr); err2: kfree(dwc->setup_buf); @@ -3228,16 +3201,12 @@ err0: void dwc3_gadget_exit(struct dwc3 *dwc) { usb_del_gadget_udc(&dwc->gadget); - dwc3_gadget_free_endpoints(dwc); - dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, - dwc->bounce_addr); + dwc->bounce_addr); kfree(dwc->setup_buf); - kfree(dwc->zlp_buf); - dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, - dwc->ep0_trb, dwc->ep0_trb_addr); + dwc->ep0_trb, dwc->ep0_trb_addr); } int dwc3_gadget_suspend(struct dwc3 *dwc) -- cgit v1.2.3 From 6b3261a274285916720e91bfbfdb3505555daa76 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 4 Apr 2017 11:25:27 +0300 Subject: usb: dwc3: core: add current_dr_role member We're going to use this member to track which role we're currently playing, that way we can more easily implement dual-role swap in upcoming patches. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 ++ drivers/usb/dwc3/core.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 56f136784cd3..68e6a7b6fd81 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -108,6 +108,8 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); dwc3_writel(dwc->regs, DWC3_GCTL, reg); + + dwc->current_dr_role = mode; } u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index d3b824912120..3464dbfe153b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -781,6 +781,7 @@ struct dwc3_scratchpad_array { * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents * @dr_mode: requested mode of operation + * @current_dr_role: current role of operation when in dual-role mode * @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW @@ -891,6 +892,7 @@ struct dwc3 { size_t regs_size; enum usb_dr_mode dr_mode; + u32 current_dr_role; enum usb_phy_interface hsphy_mode; u32 fladj; -- cgit v1.2.3 From b202c42cbf812070ae1d47209d12512226d1d8a5 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 4 Apr 2017 11:27:57 +0300 Subject: usb: dwc3: debugfs: remove unnecessary | operator Each role is mutually exclusive, the | operator is unnecessary. Remove it. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index b53ca3b0171a..e72f2634e493 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -327,13 +327,13 @@ static ssize_t dwc3_mode_write(struct file *file, return -EFAULT; if (!strncmp(buf, "host", 4)) - mode |= DWC3_GCTL_PRTCAP_HOST; + mode = DWC3_GCTL_PRTCAP_HOST; if (!strncmp(buf, "device", 6)) - mode |= DWC3_GCTL_PRTCAP_DEVICE; + mode = DWC3_GCTL_PRTCAP_DEVICE; if (!strncmp(buf, "otg", 3)) - mode |= DWC3_GCTL_PRTCAP_OTG; + mode = DWC3_GCTL_PRTCAP_OTG; if (mode) { spin_lock_irqsave(&dwc->lock, flags); -- cgit v1.2.3 From 41ce1456e1dbbc7355d0fcc10cf7c337c13def24 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 4 Apr 2017 12:49:18 +0300 Subject: usb: dwc3: core: make dwc3_set_mode() work properly We can't have both Host and Peripheral roles active at the same time because of one detail on DWC3: it shares the same memory area for both Host and Peripheral registers. When swapping roles we must reinitialize the new role every time. Let's make sure this works for our debugfs interface. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 103 +++++++++++++++++++++++++++++++-------------- drivers/usb/dwc3/core.h | 7 ++- drivers/usb/dwc3/debugfs.c | 8 +--- 3 files changed, 80 insertions(+), 38 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 68e6a7b6fd81..458e7c6cc002 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -100,7 +100,10 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) return 0; } -void dwc3_set_mode(struct dwc3 *dwc, u32 mode) +static void dwc3_event_buffers_cleanup(struct dwc3 *dwc); +static int dwc3_event_buffers_setup(struct dwc3 *dwc); + +static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) { u32 reg; @@ -108,8 +111,69 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); dwc3_writel(dwc->regs, DWC3_GCTL, reg); +} + +static void __dwc3_set_mode(struct work_struct *work) +{ + struct dwc3 *dwc = work_to_dwc(work); + unsigned long flags; + int ret; + + if (!dwc->desired_dr_role) + return; + + if (dwc->desired_dr_role == dwc->current_dr_role) + return; + + if (dwc->dr_mode != USB_DR_MODE_OTG) + return; + + switch (dwc->current_dr_role) { + case DWC3_GCTL_PRTCAP_HOST: + dwc3_host_exit(dwc); + break; + case DWC3_GCTL_PRTCAP_DEVICE: + dwc3_gadget_exit(dwc); + dwc3_event_buffers_cleanup(dwc); + break; + default: + break; + } + + spin_lock_irqsave(&dwc->lock, flags); + + dwc3_set_prtcap(dwc, dwc->desired_dr_role); - dwc->current_dr_role = mode; + dwc->current_dr_role = dwc->desired_dr_role; + + spin_unlock_irqrestore(&dwc->lock, flags); + + switch (dwc->desired_dr_role) { + case DWC3_GCTL_PRTCAP_HOST: + ret = dwc3_host_init(dwc); + if (ret) + dev_err(dwc->dev, "failed to initialize host\n"); + break; + case DWC3_GCTL_PRTCAP_DEVICE: + dwc3_event_buffers_setup(dwc); + ret = dwc3_gadget_init(dwc); + if (ret) + dev_err(dwc->dev, "failed to initialize peripheral\n"); + break; + default: + break; + } +} + +void dwc3_set_mode(struct dwc3 *dwc, u32 mode) +{ + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + dwc->desired_dr_role = mode; + spin_unlock_irqrestore(&dwc->lock, flags); + + queue_work(system_power_efficient_wq, &dwc->drd_work); } u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) @@ -721,21 +785,6 @@ static int dwc3_core_init(struct dwc3 *dwc) goto err4; } - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); - break; - case USB_DR_MODE_HOST: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); - break; - case USB_DR_MODE_OTG: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); - break; - default: - dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode); - break; - } - /* * ENDXFER polling is available on version 3.10a and later of * the DWC_usb3 controller. It is NOT available in the @@ -853,6 +902,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) @@ -861,6 +911,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; case USB_DR_MODE_HOST: + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) @@ -869,19 +920,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; case USB_DR_MODE_OTG: - ret = dwc3_host_init(dwc); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to initialize host\n"); - return ret; - } - - ret = dwc3_gadget_init(dwc); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to initialize gadget\n"); - return ret; - } + INIT_WORK(&dwc->drd_work, __dwc3_set_mode); + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); break; default: dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); @@ -901,8 +941,9 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) dwc3_host_exit(dwc); break; case USB_DR_MODE_OTG: - dwc3_host_exit(dwc); + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); dwc3_gadget_exit(dwc); + flush_work(&dwc->drd_work); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 3464dbfe153b..1fe23e36485f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -760,6 +761,7 @@ struct dwc3_scratchpad_array { /** * struct dwc3 - representation of our controller + * @drd_work - workqueue used for role swapping * @ep0_trb: trb which is used for the ctrl_req * @setup_buf: used while precessing STD USB requests * @ep0_trb: dma address of ep0_trb @@ -782,6 +784,7 @@ struct dwc3_scratchpad_array { * @revision: revision register contents * @dr_mode: requested mode of operation * @current_dr_role: current role of operation when in dual-role mode + * @desired_dr_role: desired role of operation when in dual-role mode * @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW @@ -855,6 +858,7 @@ struct dwc3_scratchpad_array { * increments or 0 to disable. */ struct dwc3 { + struct work_struct drd_work; struct dwc3_trb *ep0_trb; void *bounce; void *scratchbuf; @@ -893,6 +897,7 @@ struct dwc3 { enum usb_dr_mode dr_mode; u32 current_dr_role; + u32 desired_dr_role; enum usb_phy_interface hsphy_mode; u32 fladj; @@ -1002,7 +1007,7 @@ struct dwc3 { u16 imod_interval; }; -/* -------------------------------------------------------------------------- */ +#define work_to_dwc(w) (container_of((w), struct dwc3, drd_work)) /* -------------------------------------------------------------------------- */ diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index e72f2634e493..7be963dd8e3b 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -319,7 +319,6 @@ static ssize_t dwc3_mode_write(struct file *file, { struct seq_file *s = file->private_data; struct dwc3 *dwc = s->private; - unsigned long flags; u32 mode = 0; char buf[32]; @@ -335,11 +334,8 @@ static ssize_t dwc3_mode_write(struct file *file, if (!strncmp(buf, "otg", 3)) mode = DWC3_GCTL_PRTCAP_OTG; - if (mode) { - spin_lock_irqsave(&dwc->lock, flags); - dwc3_set_mode(dwc, mode); - spin_unlock_irqrestore(&dwc->lock, flags); - } + dwc3_set_mode(dwc, mode); + return count; } -- cgit v1.2.3 From 9840354ff429d4a392a96dff5ab6b5df609b8dc1 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 5 Apr 2017 13:39:31 +0300 Subject: usb: dwc3: Add dual-role support If dr_mode is "otg" then support dual role mode of operation. Currently this mode is only supported when an extcon handle is present in the dwc3 device tree node. This is needed to get the ID status events of the port. We're using a workqueue to manage the dual-role state transitions as the extcon notifier (dwc3_drd_notifier) is called in an atomic context by extcon_sync() and this doesn't go well with usb_del_gadget_udc() causing a lockdep and softirq warning. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 1 + drivers/usb/dwc3/Makefile | 4 +++ drivers/usb/dwc3/core.c | 11 +++--- drivers/usb/dwc3/core.h | 14 ++++++++ drivers/usb/dwc3/drd.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 drivers/usb/dwc3/drd.c (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index c5aa235863e8..aee55114d269 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -41,6 +41,7 @@ config USB_DWC3_GADGET config USB_DWC3_DUAL_ROLE bool "Dual Role mode" depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3)) + depends on (EXTCON=y || EXTCON=USB_DWC3) help This is the default mode of working of DWC3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index ffca34029b21..f15fabbd1e59 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -17,6 +17,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += gadget.o ep0.o endif +ifneq ($(CONFIG_USB_DWC3_DUAL_ROLE),) + dwc3-y += drd.o +endif + ifneq ($(CONFIG_USB_DWC3_ULPI),) dwc3-y += ulpi.o endif diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 458e7c6cc002..455d89a1cd6d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -921,7 +921,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) break; case USB_DR_MODE_OTG: INIT_WORK(&dwc->drd_work, __dwc3_set_mode); - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); + ret = dwc3_drd_init(dwc); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to initialize dual-role\n"); + return ret; + } break; default: dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); @@ -941,9 +946,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) dwc3_host_exit(dwc); break; case USB_DR_MODE_OTG: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); - dwc3_gadget_exit(dwc); - flush_work(&dwc->drd_work); + dwc3_drd_exit(dwc); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 1fe23e36485f..981c77f5628e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -785,6 +785,8 @@ struct dwc3_scratchpad_array { * @dr_mode: requested mode of operation * @current_dr_role: current role of operation when in dual-role mode * @desired_dr_role: desired role of operation when in dual-role mode + * @edev: extcon handle + * @edev_nb: extcon notifier * @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW @@ -898,6 +900,8 @@ struct dwc3 { enum usb_dr_mode dr_mode; u32 current_dr_role; u32 desired_dr_role; + struct extcon_dev *edev; + struct notifier_block edev_nb; enum usb_phy_interface hsphy_mode; u32 fladj; @@ -1218,6 +1222,16 @@ static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc, { return 0; } #endif +#if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) +int dwc3_drd_init(struct dwc3 *dwc); +void dwc3_drd_exit(struct dwc3 *dwc); +#else +static inline int dwc3_drd_init(struct dwc3 *dwc) +{ return 0; } +static inline void dwc3_drd_exit(struct dwc3 *dwc) +{ } +#endif + /* power management interface */ #if !IS_ENABLED(CONFIG_USB_DWC3_HOST) int dwc3_gadget_suspend(struct dwc3 *dwc); diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c new file mode 100644 index 000000000000..2765c51c7ef5 --- /dev/null +++ b/drivers/usb/dwc3/drd.c @@ -0,0 +1,85 @@ +/** + * drd.c - DesignWare USB3 DRD Controller Dual-role support + * + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com + * + * Authors: Roger Quadros + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "debug.h" +#include "core.h" +#include "gadget.h" + +static void dwc3_drd_update(struct dwc3 *dwc) +{ + int id; + + id = extcon_get_state(dwc->edev, EXTCON_USB_HOST); + if (id < 0) + id = 0; + + dwc3_set_mode(dwc, id ? + DWC3_GCTL_PRTCAP_HOST : + DWC3_GCTL_PRTCAP_DEVICE); +} + +static int dwc3_drd_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct dwc3 *dwc = container_of(nb, struct dwc3, edev_nb); + + dwc3_set_mode(dwc, event ? + DWC3_GCTL_PRTCAP_HOST : + DWC3_GCTL_PRTCAP_DEVICE); + + return NOTIFY_DONE; +} + +int dwc3_drd_init(struct dwc3 *dwc) +{ + int ret; + + if (dwc->dev->of_node) { + if (of_property_read_bool(dwc->dev->of_node, "extcon")) + dwc->edev = extcon_get_edev_by_phandle(dwc->dev, 0); + + if (IS_ERR(dwc->edev)) + return PTR_ERR(dwc->edev); + + dwc->edev_nb.notifier_call = dwc3_drd_notifier; + ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, + &dwc->edev_nb); + if (ret < 0) { + dev_err(dwc->dev, "couldn't register cable notifier\n"); + return ret; + } + } + + dwc3_drd_update(dwc); + + return 0; +} + +void dwc3_drd_exit(struct dwc3 *dwc) +{ + extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST, + &dwc->edev_nb); + + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); + flush_work(&dwc->drd_work); + dwc3_gadget_exit(dwc); +} -- cgit v1.2.3