Re: [PATCH 2/5] USB: io_ti: use serial->interface for messages in download_fw
On Tue, 2015-09-01 at 17:54 -0500, Peter E. Berger wrote: > From: "Peter E. Berger"> > Use serial->interface instead of serial->dev for messages in download_fw(). Why? The firmware is per device isn't it? So what sense is there in messaging about it at interface level? Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] Revert "usb: dwc3: gadget: drop unnecessary loop when cleaning up TRBs"
Hi, On Mon, 31 Aug 2015 11:54:13 -0500 Felipe Balbiwrote: > On Mon, Aug 31, 2015 at 07:48:28PM +0300, ville.syrj...@linux.intel.com wrote: > > From: Ville Syrj舁\xE7 > > > > This reverts commit 8f2c9544aba636134303105ecb164190a39dece4. > > > > As it breaks g_ether on my Baytrail FFRD8 device. Everything starts out > > fine, but after a bit of data has been transferred it just stops > > flowing. > > > > Note that I do get a bunch of these "NOHZ: local_softirq_pending 08" > > when booting the machine, but I'm not really sure if they're related > > to this problem. > > I have a feeling your problem is elsewhere. We *are* completing one TRB > at a time. If usb_request.no_interrupt is flagged, it seems dwc3 does not set IOC on the corresponding TRB. Does it break the assumption every TRB (without SG) will trigger one corresponding EP event? u_ether is the function module that utilizes 'no_interrupt' flag. -- Masakazu Mokuno -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 1/1] usb: misc: usbtest: add bulk queue test
The bulk queue tests are used to show 'best performance' for bulk transfer, we are often asked this question by users. It's result should be very close to IC simulation, in order to get that, the device side should also need to prepare enough queue. We have got the 'best performance' (IN: ~41MB, OUT: ~39MB) at i.mx platform (USB2, ARM Cortex A9) with below command: Host side: modprobe usbtest ./testusb -a -t 27 -g 64 -s 16384 ./testusb -a -t 28 -g 64 -s 16384 Gadget side: modprobe g_zero loopdefault=1 qlen=64 buflen=16384 Signed-off-by: Peter Chen--- I am not sure if it is good to reuse iso structure, so I take it as RFC. If reuse is accepted, I will rename the iso structures to common one. drivers/usb/misc/usbtest.c | 88 -- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index ad6dd4a..f1faeb9 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -17,6 +17,7 @@ static int override_alt = -1; module_param_named(alt, override_alt, int, 0644); MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection"); +static void iso_callback(struct urb *urb); /*-*/ @@ -239,7 +240,8 @@ static struct urb *usbtest_alloc_urb( unsigned long bytes, unsignedtransfer_flags, unsignedoffset, - u8 bInterval) + u8 bInterval, + boolqueue_callback) { struct urb *urb; @@ -250,9 +252,14 @@ static struct urb *usbtest_alloc_urb( if (bInterval) usb_fill_int_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL, bInterval); - else - usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, + else { + if (queue_callback) + usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, iso_callback, NULL); + else + usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, + NULL); + } urb->interval = (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) @@ -296,7 +303,17 @@ static struct urb *simple_alloc_urb( u8 bInterval) { return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0, - bInterval); + bInterval, false); +} + +static struct urb *test_queue_alloc_urb( + struct usb_device *udev, + int pipe, + unsigned long bytes, + u8 bInterval) +{ + return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0, + bInterval, true); } static unsigned pattern; @@ -1809,6 +1826,7 @@ struct iso_context { unsigned long errors; unsigned long packet_count; struct usbtest_dev *dev; + boolis_iso; }; static void iso_callback(struct urb *urb) @@ -1822,7 +1840,7 @@ static void iso_callback(struct urb *urb) if (urb->error_count > 0) ctx->errors += urb->error_count; else if (urb->status != 0) - ctx->errors += urb->number_of_packets; + ctx->errors += (ctx->is_iso ? urb->number_of_packets : 1); else if (urb->actual_length != urb->transfer_buffer_length) ctx->errors++; else if (check_guard_bytes(ctx->dev, urb) != 0) @@ -1930,20 +1948,20 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, memset(, 0, sizeof(context)); context.count = param->iterations * param->sglen; context.dev = dev; + context.is_iso = !!desc; init_completion(); spin_lock_init(); udev = testdev_to_usbdev(dev); - dev_info(>intf->dev, - "iso period %d %sframes, wMaxPacket %d, transactions: %d\n", - 1 << (desc->bInterval - 1), - (udev->speed == USB_SPEED_HIGH) ? "micro" : "", - usb_endpoint_maxp(desc) & 0x7ff, - 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11))); for (i = 0; i < param->sglen; i++) { - urbs[i] = iso_alloc_urb(udev, pipe, desc, + if (context.is_iso) + urbs[i] = iso_alloc_urb(udev, pipe, desc, param->length, offset); + else + urbs[i] = test_queue_alloc_urb(udev, pipe, + param->length, 0); + if (!urbs[i]) { status = -ENOMEM; goto fail; @@ -1952,11
Re: usb: musb: host: enumeration issues
Hey, On 02.09.2015 14:28, Felipe Balbi wrote: > Hi, > > On Wed, Sep 02, 2015 at 11:35:45AM +0200, Pascal Huerst wrote: >> Hey Felipe, >> >> on a custom built, am335x based board, running v4.0, I'm facing an issue >> with usb: >> >> After suspend, storage devices are not being enumerated correctly. I > > hmm, mainline kernel doesn't support suspend/resume on AM335x devices so > I'm gonna say you need to ask for support from whoever gave you this > kernel. If that's TI, then you need to either ask for help on TI's e2e > forums or talk to your FAE... Well, that would be me. It's a vanilla kernel, except for some ASoC patches and v5 of Dave's PM series, which was for v3.19-rc5, if I remember that correctly, which I rebased on v4.0.0 later. >> have seen and applied your recent patch: >> >> usb: musb: host: rely on port_mode to call musb_start() >> >> Now, the issue only happens once. So if the device resumes the first >> time, I face the same enumeration problem, but all following times, it >> seems to work properly. >> >> I figureed out, that in a working situation: >> >> void musb_start(...) >> >> -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L1027 >> >> is called before the isr: >> >> static irqreturn_t musb_stage0_irq(...) >> >> -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L539 >> >> And in a non working situation, its the other way arround. (Which should >> not happen!?) I'm not too familiar with usb. Do you have any ideas, what >> could cause that behavior? > > ... with that said, you didn't give me logs of the problem happening nor > gave me any instructions on how to reproduce. > > based on the description alone, I think making sure MUSB IRQs are masked > on suspen and unmask on resume might be enough, though you'd have to > patch that up and check. To reproduce, I just have an usb block device inserted, trigger suspend by: echo mem > /sys/power/state wake it up by GPIO on bank0 and then I get: usb 1-1: new high-speed USB device number 3 using musb-hdrc usb 1-1: new high-speed USB device number 4 using musb-hdrc usb 1-1: new high-speed USB device number 5 using musb-hdrc usb 1-1: new high-speed USB device number 6 using musb-hdrc Since I applied your patch mentioned above, this only happens once (first suspend). So I had to reboot every time, to provoke it. Without your patch applied, it happened on almost all suspend/resume cycles. If I disable the interrupt in musb_suspend() and reactivate them in musb_resume() everything seems to works fine. (At least the for ~20 times I tried to reproduce afterwards) I guess this is the case on other hw was well, such as BBB. If you think, that this is worth further investigation in order to fix it upstream, I can do some testing on BBB and provide you with more detail? Just for clarification about my changes, I applied a patch. regards pascal --- drivers/usb/musb/musb_core.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 68bf6d8..d861c21 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2421,6 +2421,9 @@ static int musb_suspend(struct device *dev) struct musb *musb = dev_to_musb(dev); unsigned long flags; + musb_platform_disable(musb); + musb_generic_disable(musb); + spin_lock_irqsave(>lock, flags); if (is_peripheral_active(musb)) { @@ -2474,6 +2477,9 @@ static int musb_resume(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); + + musb_start(musb); + return 0; } -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 9/9] usb: dwc3: core: don't break during suspend/resume while we're dual-role
Hello. On 09/02/2015 05:24 PM, Roger Quadros wrote: We can't rely just on dr_mode to decide if we're in host or gadget mode when we're configured as otg/dual-role. So while dr_mode is OTG, we find out from the otg state machine if we're in host or gadget mode and take the necessary actions during suspend/resume. Also make sure that we disable OTG irq and events during system suspend so that we don't lockup the system during system suspend/resume. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.c | 27 +-- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 654aebf..25891e3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1455,18 +1455,15 @@ static int dwc3_suspend(struct device *dev) dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL); dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT); dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); + dwc3_writel(dwc->regs, DWC3_OEVTEN, 0); + disable_irq(dwc->otg_irq); } - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + if (dwc->dr_mode == USB_DR_MODE_PERIPHERAL || + ((dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->fsm->protocol == PROTO_GADGET))) Hm, you're not very consistent about your parens. :-) [...] @@ -1506,18 +1503,12 @@ static int dwc3_resume(struct device *dev) dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl); dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt); dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); + enable_irq(dwc->otg_irq); } - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + if (dwc->dr_mode == USB_DR_MODE_PERIPHERAL || + ((dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->fsm->protocol == PROTO_GADGET))) Same here... [...] WBR, Sergei -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Doubt bulk communication
Hi, On Wed, Sep 02, 2015 at 08:12:19PM -0300, Rodolfo Labiapari Mansur wrote: > Your answering a help wanted me doubt. I am developing a driver for > communication with an FPGA. For communication I am using a UART > converter that is making the USB converter of paper for serial. And which USB-to-UART converter would that be ? Most likely we already have support for it in the kernel and if we do, it's far better that you read the source code that's in place, than try to roll your own. If you want to start learning kernel development, my suggestion would be spend time on something else, rather than trying to solve something that was already solved (in this USB-to-UART devices). > I'm doing my own driver this converter because I want to learn how to > develop drivers. > > I followed the example usb-skel.c available on the internet. In my > driver, I can recognize the converter device, get all your > information. :) > However, when we send data to the drive, the driver reports it was > sent successfully but the converter does not receive. (I also tried what do you mean it "it was sent successfully but the converted does not receive." ? Do you mean to say that a function returned zero ? Or that the device returned you an ACK package > with Arduino and RS-232, but did not succeed). :( okay, so what happened there ? Have you tried usbmon ? (see Documentation/usb/usbmon.txt from a kernel source tree for details) > So in the current situation, my driver informs that has been sent, but > the device connected to the computer receives no signal. and how do you know it "received no signal" ? Which signal are you talking about ? > My main question is: I need to 'start' communication before sending a > package? For example, you would have to tell the device will start > sending the package? Because it makes no sense I send my package, > return success and the device does not receive anything. My driver > needs to send pro device control signals warning that he wants to > start data transmission? you need to figure out the protocol which your device talks. Sometimes they just want raw data, but sometimes there's something else they need. Also, are you sending your data to the correct endpoints ? Grab some usbmon traces, then it'll be easier to figure out what's going on. -- balbi signature.asc Description: Digital signature
Re: Doubt bulk communication
Hi again, (off-list now) Quer explicar em português os problemas ? O que você está tentando fazer e o que está dando errado ? regards On Wed, Sep 02, 2015 at 06:47:21PM -0500, Felipe Balbi wrote: > Hi, > > On Wed, Sep 02, 2015 at 08:12:19PM -0300, Rodolfo Labiapari Mansur wrote: > > Your answering a help wanted me doubt. I am developing a driver for > > communication with an FPGA. For communication I am using a UART > > converter that is making the USB converter of paper for serial. And > > which USB-to-UART converter would that be ? Most likely we already have > support for it in the kernel and if we do, it's far better that you read > the source code that's in place, than try to roll your own. If you want > to start learning kernel development, my suggestion would be spend time > on something else, rather than trying to solve something that was > already solved (in this USB-to-UART devices). > > > I'm doing my own driver this converter because I want to learn how to > > develop drivers. > > > > I followed the example usb-skel.c available on the internet. In my > > driver, I can recognize the converter device, get all your > > information. :) > > However, when we send data to the drive, the driver reports it was > > sent successfully but the converter does not receive. (I also tried > > what do you mean it "it was sent successfully but the converted does not > receive." ? Do you mean to say that a function returned zero ? Or that > the device returned you an ACK package > > > with Arduino and RS-232, but did not succeed). :( > > okay, so what happened there ? Have you tried usbmon ? (see > Documentation/usb/usbmon.txt from a kernel source tree for details) > > > So in the current situation, my driver informs that has been sent, but > > the device connected to the computer receives no signal. > > and how do you know it "received no signal" ? Which signal are you > talking about ? > > > My main question is: I need to 'start' communication before sending a > > package? For example, you would have to tell the device will start > > sending the package? Because it makes no sense I send my package, > > return success and the device does not receive anything. My driver > > needs to send pro device control signals warning that he wants to > > start data transmission? > > you need to figure out the protocol which your device talks. Sometimes > they just want raw data, but sometimes there's something else they need. > > Also, are you sending your data to the correct endpoints ? Grab some > usbmon traces, then it'll be easier to figure out what's going on. > > -- > balbi -- balbi signature.asc Description: Digital signature
Re: [PATCH 7/7] usb: dwc2: refactor common low-level hw code to platform.c
On 8/21/2015 5:39 AM, Marek Szyprowski wrote: > DWC2 module on some platforms needs three additional hardware > resources: phy controller, clock and power supply. All of them must be > enabled/activated to properly initialize and operate. This was initially > handled in s3c-hsotg driver, which has been converted to 'gadget' part > of dwc2 driver. Unfortunately, not all of this code got moved to common > platform code, what resulted in accessing DWC2 registers without > enabling low-level hardware resources. This fails for example on Exynos > SoCs. This patch moves all the code for managing those resources to > common platform.c file and provides convenient wrappers for controlling > them. > > Signed-off-by: Marek Szyprowski> --- > drivers/usb/dwc2/core.h | 4 +- > drivers/usb/dwc2/gadget.c | 188 +--- > drivers/usb/dwc2/platform.c | 207 > > 3 files changed, 195 insertions(+), 204 deletions(-) > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index 0ed87620941b..ec820bdf98c0 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -690,6 +690,7 @@ struct dwc2_hsotg { > enum usb_dr_mode dr_mode; > unsigned int hcd_enabled:1; > unsigned int gadget_enabled:1; > + unsigned int ll_hw_enabled:1; It seems like this flag is used to restore the state of the lowlevel_hw on suspend/resume? I think it is clearer to put the setting/clearing of the flag inside the ll_hw_enable/disable and then check and adjust on suspend/resume. That way you don't have to manage this flag everywhere you call enable/disable(). John -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3][v3] drivers: usb: dwc3: Add frame length adjustment quirk
Add adjust_frame_length_quirk for writing to fladj register which adjusts (micro)frame length to value provided by "snps,quirk-frame-length-adjustment" property thus avoiding USB 2.0 devices to time-out over a longer run Signed-off-by: Nikhil Badola--- Changes for v3: - removed unnecessary if(fladj) condition - removed stray newline drivers/usb/dwc3/core.c | 34 ++ drivers/usb/dwc3/core.h | 5 + drivers/usb/dwc3/platform_data.h | 2 ++ 3 files changed, 41 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 064123e..75a17bf 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -143,6 +143,32 @@ static int dwc3_soft_reset(struct dwc3 *dwc) return 0; } +/* + * dwc3_frame_length_adjustment - Adjusts frame length if required + * @dwc3: Pointer to our controller context structure + * @fladj: Value of GFLADJ_30MHZ to adjust frame length + */ +static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj) +{ + if (dwc->revision < DWC3_REVISION_250A) + return; + + if (fladj == 0) + return; + + u32 reg; + u32 dft; + + reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); + dft = reg & DWC3_GFLADJ_30MHZ_MASK; + if (!dev_WARN_ONCE(dwc->dev, dft == fladj, + "request value same as default, ignoring\n")) { + reg &= ~DWC3_GFLADJ_30MHZ_MASK; + reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj; + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); + } +} + /** * dwc3_free_one_event_buffer - Frees one event buffer * @dwc: Pointer to our controller context structure @@ -779,6 +805,7 @@ static int dwc3_probe(struct platform_device *pdev) u8 lpm_nyet_threshold; u8 tx_de_emphasis; u8 hird_threshold; + u32 fladj = 0; int ret; @@ -886,6 +913,9 @@ static int dwc3_probe(struct platform_device *pdev) _de_emphasis); of_property_read_string(node, "snps,hsphy_interface", >hsphy_interface); + of_property_read_u32(node, +"snps,quirk-frame-length-adjustment", +); } else if (pdata) { dwc->maximum_speed = pdata->maximum_speed; dwc->has_lpm_erratum = pdata->has_lpm_erratum; @@ -915,6 +945,7 @@ static int dwc3_probe(struct platform_device *pdev) tx_de_emphasis = pdata->tx_de_emphasis; dwc->hsphy_interface = pdata->hsphy_interface; + fladj = pdata->fladj_value; } /* default to superspeed if no maximum_speed passed */ @@ -971,6 +1002,9 @@ static int dwc3_probe(struct platform_device *pdev) goto err1; } + /* Adjust Frame Length */ + dwc3_frame_length_adjustment(dwc, fladj); + usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0447788..9188745 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -124,6 +124,7 @@ #define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) #define DWC3_GHWPARAMS80xc600 +#define DWC3_GFLADJ0xc630 /* Device Registers */ #define DWC3_DCFG 0xc700 @@ -234,6 +235,10 @@ /* Global HWPARAMS6 Register */ #define DWC3_GHWPARAMS6_EN_FPGA(1 << 7) +/* Global Frame Length Adjustment Register */ +#define DWC3_GFLADJ_30MHZ_SDBND_SEL(1 << 7) +#define DWC3_GFLADJ_30MHZ_MASK 0x3f + /* Device Configuration Register */ #define DWC3_DCFG_DEVADDR(addr)((addr) << 3) #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index d3614ec..400b197 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -46,5 +46,7 @@ struct dwc3_platform_data { unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; + u32 fladj_value; + const char *hsphy_interface; }; -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3][v3] Documentation: dt: dwc3: Add snps,quirk-frame-length-adjustment property
Add snps,quirk-frame-length-adjustment property which provides value for post silicon frame length adjustment Signed-off-by: Nikhil Badola--- Changes for v3 : None Documentation/devicetree/bindings/usb/dwc3.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 0815eac..8c7d585 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -40,6 +40,9 @@ Optional properties: - snps,hird-threshold: HIRD threshold - snps,hsphy_interface: High-Speed PHY interface selection between "utmi" for UTMI+ and "ulpi" for ULPI when the DWC_USB3_HSPHY_INTERFACE has value 3. + - snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ + register for post-silicon frame length adjustment when the + fladj_30mhz_sdbnd signal is invalid or incorrect. This is usually a subnode to DWC3 glue to which it is connected. -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3][v3] arm: dts: ls1021a: Add quirk for Erratum A009116
Add "snps,quirk-frame-length-adjustment" property to USB3 node for erratum A009116. This property provides value of GFLADJ_30MHZ for post silicon frame length adjustment. Signed-off-by: Nikhil Badola--- Changes for v3 : None arch/arm/boot/dts/ls1021a.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index c70bb27..50ac0d4 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -404,6 +404,7 @@ reg = <0x0 0x310 0x0 0x1>; interrupts = ; dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; }; }; }; -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: usb: musb: host: enumeration issues
Hi, On Wed, Sep 02, 2015 at 06:33:11PM +0200, Pascal Huerst wrote: > Hey, > > On 02.09.2015 14:28, Felipe Balbi wrote: > > Hi, > > > > On Wed, Sep 02, 2015 at 11:35:45AM +0200, Pascal Huerst wrote: > >> Hey Felipe, > >> > >> on a custom built, am335x based board, running v4.0, I'm facing an issue > >> with usb: > >> > >> After suspend, storage devices are not being enumerated correctly. I > > > > hmm, mainline kernel doesn't support suspend/resume on AM335x devices so > > I'm gonna say you need to ask for support from whoever gave you this > > kernel. If that's TI, then you need to either ask for help on TI's e2e > > forums or talk to your FAE... > > Well, that would be me. It's a vanilla kernel, except for some ASoC > patches and v5 of Dave's PM series, which was for v3.19-rc5, if I > remember that correctly, which I rebased on v4.0.0 later. > > >> have seen and applied your recent patch: > >> > >> usb: musb: host: rely on port_mode to call musb_start() > >> > >> Now, the issue only happens once. So if the device resumes the first > >> time, I face the same enumeration problem, but all following times, it > >> seems to work properly. > >> > >> I figureed out, that in a working situation: > >> > >> void musb_start(...) > >> > >> -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L1027 > >> > >> is called before the isr: > >> > >> static irqreturn_t musb_stage0_irq(...) > >> > >> -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L539 > >> > >> And in a non working situation, its the other way arround. (Which should > >> not happen!?) I'm not too familiar with usb. Do you have any ideas, what > >> could cause that behavior? > > > > ... with that said, you didn't give me logs of the problem happening nor > > gave me any instructions on how to reproduce. > > > > based on the description alone, I think making sure MUSB IRQs are masked > > on suspen and unmask on resume might be enough, though you'd have to > > patch that up and check. > > To reproduce, I just have an usb block device inserted, trigger suspend by: > > echo mem > /sys/power/state > > wake it up by GPIO on bank0 and then I get: > > usb 1-1: new high-speed USB device number 3 using musb-hdrc > usb 1-1: new high-speed USB device number 4 using musb-hdrc > usb 1-1: new high-speed USB device number 5 using musb-hdrc > usb 1-1: new high-speed USB device number 6 using musb-hdrc > > Since I applied your patch mentioned above, this only happens once > (first suspend). So I had to reboot every time, to provoke it. Without > your patch applied, it happened on almost all suspend/resume cycles. > > If I disable the interrupt in musb_suspend() and reactivate them in > musb_resume() everything seems to works fine. (At least the for ~20 > times I tried to reproduce afterwards) > > I guess this is the case on other hw was well, such as BBB. If you > think, that this is worth further investigation in order to fix it > upstream, I can do some testing on BBB and provide you with more detail? > > Just for clarification about my changes, I applied a patch. > > regards > pascal > > > --- > drivers/usb/musb/musb_core.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c > index 68bf6d8..d861c21 100644 > --- a/drivers/usb/musb/musb_core.c > +++ b/drivers/usb/musb/musb_core.c > @@ -2421,6 +2421,9 @@ static int musb_suspend(struct device *dev) > struct musb *musb = dev_to_musb(dev); > unsigned long flags; > > + musb_platform_disable(musb); > + musb_generic_disable(musb); > + > spin_lock_irqsave(>lock, flags); > > if (is_peripheral_active(musb)) { > @@ -2474,6 +2477,9 @@ static int musb_resume(struct device *dev) > pm_runtime_disable(dev); > pm_runtime_set_active(dev); > pm_runtime_enable(dev); > + > + musb_start(musb); this looks correct to me. Can you send it as a proper patch ? -- balbi signature.asc Description: Digital signature
Doubt bulk communication
Hello everyone, Your answering a help wanted me doubt. I am developing a driver for communication with an FPGA. For communication I am using a UART converter that is making the USB converter of paper for serial. And I'm doing my own driver this converter because I want to learn how to develop drivers. I followed the example usb-skel.c available on the internet. In my driver, I can recognize the converter device, get all your information. :) However, when we send data to the drive, the driver reports it was sent successfully but the converter does not receive. (I also tried with Arduino and RS-232, but did not succeed). :( So in the current situation, my driver informs that has been sent, but the device connected to the computer receives no signal. My main question is: I need to 'start' communication before sending a package? For example, you would have to tell the device will start sending the package? Because it makes no sense I send my package, return success and the device does not receive anything. My driver needs to send pro device control signals warning that he wants to start data transmission? All the communication devices that I have used as bulk package. I hope it was clear. Sorry for the english translated automatically. Formiga / Cláudio - MG - Brasil Corpo discente do Inst. Federal de Educação, Ciência e Tecnologia Minas Gerais - IFMG Lattes http://lattes.cnpq.br/7459046239105308 Rodolfo Labiapari Mansur Guimarães-- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
usb: musb: host: enumeration issues
Hey Felipe, on a custom built, am335x based board, running v4.0, I'm facing an issue with usb: After suspend, storage devices are not being enumerated correctly. I have seen and applied your recent patch: usb: musb: host: rely on port_mode to call musb_start() Now, the issue only happens once. So if the device resumes the first time, I face the same enumeration problem, but all following times, it seems to work properly. I figureed out, that in a working situation: void musb_start(...) -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L1027 is called before the isr: static irqreturn_t musb_stage0_irq(...) -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L539 And in a non working situation, its the other way arround. (Which should not happen!?) I'm not too familiar with usb. Do you have any ideas, what could cause that behavior? regards pascal -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2 1/7] usb: misc: usbtest: allocate size of urb array according to user parameter
On Wed, 2 Sep 2015, Peter Chen wrote: > > > @@ -1911,10 +1912,7 @@ test_iso_queue(struct usbtest_dev *dev, struct > > usbtest_param *param, > > > unsignedi; > > > unsigned long packets = 0; > > > int status = 0; > > > - struct urb *urbs[10]; /* FIXME no limit */ > > > - > > > - if (param->sglen > 10) > > > - return -EDOM; > > > + struct urb *urbs[param->sglen]; > > > > > > memset(, 0, sizeof(context)); > > > context.count = param->iterations * param->sglen; @@ -2061,6 > > +2059,9 > > > @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) > > > if (param->iterations <= 0) > > > return -EINVAL; > > > > > > + if (param->sglen > MAX_SGLEN) > > > + return -EINVAL; > > > > This will not prevent problems. The stack space gets allocated as soon as > > the > > function starts, and if param->sglen is very big then the damage will > > already > > have occurred by this point. > > > > Sorry? It is the beginning of usbtest_ioctl, the test_iso_queue has still not > been called. Oh, you are right. I didn't read the patch carefully enough. Sorry. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: usb: musb: host: enumeration issues
Hi, On Wed, Sep 02, 2015 at 11:35:45AM +0200, Pascal Huerst wrote: > Hey Felipe, > > on a custom built, am335x based board, running v4.0, I'm facing an issue > with usb: > > After suspend, storage devices are not being enumerated correctly. I hmm, mainline kernel doesn't support suspend/resume on AM335x devices so I'm gonna say you need to ask for support from whoever gave you this kernel. If that's TI, then you need to either ask for help on TI's e2e forums or talk to your FAE... > have seen and applied your recent patch: > > usb: musb: host: rely on port_mode to call musb_start() > > Now, the issue only happens once. So if the device resumes the first > time, I face the same enumeration problem, but all following times, it > seems to work properly. > > I figureed out, that in a working situation: > > void musb_start(...) > > -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L1027 > > is called before the isr: > > static irqreturn_t musb_stage0_irq(...) > > -> http://lxr.free-electrons.com/source/drivers/usb/musb/musb_core.c#L539 > > And in a non working situation, its the other way arround. (Which should > not happen!?) I'm not too familiar with usb. Do you have any ideas, what > could cause that behavior? ... with that said, you didn't give me logs of the problem happening nor gave me any instructions on how to reproduce. based on the description alone, I think making sure MUSB IRQs are masked on suspen and unmask on resume might be enough, though you'd have to patch that up and check. -- balbi signature.asc Description: Digital signature
Re: [PATCH] Revert "usb: dwc3: gadget: drop unnecessary loop when cleaning up TRBs"
On Wed, Sep 02, 2015 at 05:09:39PM +0900, Masakazu Mokuno wrote: > Hi, > > On Mon, 31 Aug 2015 11:54:13 -0500 > Felipe Balbiwrote: > > > On Mon, Aug 31, 2015 at 07:48:28PM +0300, ville.syrj...@linux.intel.com > > wrote: > > > From: Ville Syrj舁・ > > > > > > This reverts commit 8f2c9544aba636134303105ecb164190a39dece4. > > > > > > As it breaks g_ether on my Baytrail FFRD8 device. Everything starts out > > > fine, but after a bit of data has been transferred it just stops > > > flowing. > > > > > > Note that I do get a bunch of these "NOHZ: local_softirq_pending 08" > > > when booting the machine, but I'm not really sure if they're related > > > to this problem. > > > > I have a feeling your problem is elsewhere. We *are* completing one TRB > > at a time. > > If usb_request.no_interrupt is flagged, it seems dwc3 does not set IOC > on the corresponding TRB. Does it break the assumption every TRB > (without SG) will trigger one corresponding EP event? > u_ether is the function module that utilizes 'no_interrupt' flag. XferInProgress should still trigger. Besides, I tested with the exact same setup (different SoC though), just look at the thread. -- balbi signature.asc Description: Digital signature
Re: [PATCH 5/5] USB: io_ti: Move request_firmware from edge_startup to download_fw
On 9/2/2015 1:54 AM, Peter E. Berger wrote: From: "Peter E. Berger"Move request_firmware from edge_startup to download_fw Signed-off-by: Peter E. Berger --- drivers/usb/serial/io_ti.c | 56 -- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a226424..9fe12cc 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c [...] @@ -1483,7 +1498,6 @@ stayinbootmode: return 0; } - static int ti_do_config(struct edgeport_port *port, int feature, int on) { int port_number = port->port->port_number; Unrelated white-space change, please don't do this. MBR, Sergei -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/5] USB: io_ti: Remove obsolete dev argument from build_i2c_fw_hdr
Hello. On 9/2/2015 1:54 AM, Peter E. Berger wrote: From: "Peter E. Berger"Remove unused "dev" argument from build_i2c_fw_hdr() and its caller. Arguments are values passed to a function, you meant a parameter. Signed-off-by: Peter E. Berger [...] MBR, Sergei -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 8/9] usb: dwc3: core: Prevent otg events from disabling themselves
On Wed, Sep 02, 2015 at 05:24:23PM +0300, Roger Quadros wrote: > There is a race happening during dwc3_drd_init() that causes > otg events to get disabled. This is what happens. > > dwc3_otg_irq() happens immediately when PRTCAP is set to OTG, > even though OEVTEN is 0. This is because BIT 31 IRQ of > OEVT can't be disabled by OEVTEN. > We configure OEVTEN in dwc3_otg_init() but dwc3_otg_irq() has > already saved OEVTEN as 0 into dwc->oevten. So finally when > dwc3_irq_thread_irq() is called we save 0 into OEVTEN > thus disabling OTG irqs forever. > > We fix this by disabling IRQs when configuring OEVTEN in > dwc3_otg_init(). > > Signed-off-by: Roger Quadroscan't you just merge this patch into the one which introduced the bug to start with ? > --- > drivers/usb/dwc3/core.c | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 684010c..654aebf 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -921,6 +921,7 @@ static int dwc3_drd_init(struct dwc3 *dwc) > int ret, id, vbus; > struct usb_otg_caps *otgcaps = >otg_config.otg_caps; > u32 reg; > + unsigned long flags; > > otgcaps->otg_rev = 0; > otgcaps->hnp_support = false; > @@ -993,6 +994,8 @@ try_otg_core: > goto error; > } > > + spin_lock_irqsave(>lock, flags); > + > /* we need to set OTG to get events from OTG core */ > dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); > /* GUSB2PHYCFG0.SusPHY=0 */ > @@ -1018,6 +1021,8 @@ try_otg_core: > /* OCTL.PeriMode = 1 */ > dwc3_writel(dwc->regs, DWC3_OCTL, DWC3_OCTL_PERIMODE); > > + spin_unlock_irqrestore(>lock, flags); > + > dwc3_otg_fsm_sync(dwc); > usb_otg_sync_inputs(dwc->fsm); > > -- > 2.1.4 > -- balbi signature.asc Description: Digital signature
Re: [PATCH v4 9/9] usb: dwc3: core: don't break during suspend/resume while we're dual-role
On Wed, Sep 02, 2015 at 05:24:24PM +0300, Roger Quadros wrote: > We can't rely just on dr_mode to decide if we're in host or gadget > mode when we're configured as otg/dual-role. So while dr_mode is > OTG, we find out from the otg state machine if we're in host > or gadget mode and take the necessary actions during suspend/resume. > > Also make sure that we disable OTG irq and events during system suspend > so that we don't lockup the system during system suspend/resume. > > Signed-off-by: Roger Quadros> --- > drivers/usb/dwc3/core.c | 27 +-- > 1 file changed, 9 insertions(+), 18 deletions(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 654aebf..25891e3 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -1455,18 +1455,15 @@ static int dwc3_suspend(struct device *dev) > dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL); > dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT); > dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); > + dwc3_writel(dwc->regs, DWC3_OEVTEN, 0); > + disable_irq(dwc->otg_irq); you don't need disable_irq() here. In fact, it causes problems since you're calling it with IRQs disabled. > } > > - switch (dwc->dr_mode) { > - case USB_DR_MODE_PERIPHERAL: > - case USB_DR_MODE_OTG: > + if (dwc->dr_mode == USB_DR_MODE_PERIPHERAL || > + ((dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->fsm->protocol == > PROTO_GADGET))) > dwc3_gadget_suspend(dwc); > - /* FALLTHROUGH */ > - case USB_DR_MODE_HOST: > - default: > - dwc3_event_buffers_cleanup(dwc); > - break; > - } > + > + dwc3_event_buffers_cleanup(dwc); > > dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); > spin_unlock_irqrestore(>lock, flags); > @@ -1506,18 +1503,12 @@ static int dwc3_resume(struct device *dev) > dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl); > dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt); > dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); > + enable_irq(dwc->otg_irq); > } > > - switch (dwc->dr_mode) { > - case USB_DR_MODE_PERIPHERAL: > - case USB_DR_MODE_OTG: > + if (dwc->dr_mode == USB_DR_MODE_PERIPHERAL || > + ((dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->fsm->protocol == > PROTO_GADGET))) > dwc3_gadget_resume(dwc); > - /* FALLTHROUGH */ > - case USB_DR_MODE_HOST: > - default: > - /* do nothing */ > - break; > - } > > spin_unlock_irqrestore(>lock, flags); > > -- > 2.1.4 > -- balbi signature.asc Description: Digital signature
[PATCH v4 6/9] usb: dwc3: save/restore OTG registers during suspend/resume
Without this we loose OTG controller register context and malfunction after a system suspend-resume. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.c | 17 + drivers/usb/dwc3/core.h | 6 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 632ee53..684010c 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -56,6 +56,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); + dwc->current_mode = mode; dwc3_writel(dwc->regs, DWC3_GCTL, reg); } @@ -1443,6 +1444,14 @@ static int dwc3_suspend(struct device *dev) spin_lock_irqsave(>lock, flags); + /* Save OTG state only if we're really using it */ + if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) { + dwc->ocfg = dwc3_readl(dwc->regs, DWC3_OCFG); + dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL); + dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT); + dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); + } + switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_OTG: @@ -1486,6 +1495,14 @@ static int dwc3_resume(struct device *dev) dwc3_event_buffers_setup(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); + /* Restore OTG state only if we're really using it */ + if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) { + dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg); + dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl); + dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt); + dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); + } + switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_OTG: diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 129ef37..1115ce0 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -737,6 +737,7 @@ struct dwc3_scratchpad_array { * @regs: base address for our registers * @regs_size: address space size * @oevten: otg interrupt enable mask copy + * @current_mode: current mode of operation written to PRTCAPDIR * @nr_scratch: number of scratch buffers * @num_event_buffers: calculated number of event buffers * @u1u2: only used on revisions <1.83a for workaround @@ -858,9 +859,12 @@ struct dwc3 { /* used for suspend/resume */ u32 dcfg; u32 gctl; - + u32 ocfg; + u32 octl; + u32 oevt; u32 oevten; + u32 current_mode; u32 nr_scratch; u32 num_event_buffers; u32 u1u2; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 8/9] usb: dwc3: core: Prevent otg events from disabling themselves
There is a race happening during dwc3_drd_init() that causes otg events to get disabled. This is what happens. dwc3_otg_irq() happens immediately when PRTCAP is set to OTG, even though OEVTEN is 0. This is because BIT 31 IRQ of OEVT can't be disabled by OEVTEN. We configure OEVTEN in dwc3_otg_init() but dwc3_otg_irq() has already saved OEVTEN as 0 into dwc->oevten. So finally when dwc3_irq_thread_irq() is called we save 0 into OEVTEN thus disabling OTG irqs forever. We fix this by disabling IRQs when configuring OEVTEN in dwc3_otg_init(). Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 684010c..654aebf 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -921,6 +921,7 @@ static int dwc3_drd_init(struct dwc3 *dwc) int ret, id, vbus; struct usb_otg_caps *otgcaps = >otg_config.otg_caps; u32 reg; + unsigned long flags; otgcaps->otg_rev = 0; otgcaps->hnp_support = false; @@ -993,6 +994,8 @@ try_otg_core: goto error; } + spin_lock_irqsave(>lock, flags); + /* we need to set OTG to get events from OTG core */ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); /* GUSB2PHYCFG0.SusPHY=0 */ @@ -1018,6 +1021,8 @@ try_otg_core: /* OCTL.PeriMode = 1 */ dwc3_writel(dwc->regs, DWC3_OCTL, DWC3_OCTL_PERIMODE); + spin_unlock_irqrestore(>lock, flags); + dwc3_otg_fsm_sync(dwc); usb_otg_sync_inputs(dwc->fsm); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 7/9] usb: dwc3: gadget: Fix suspend/resume during dual-role mode
Gdget controller might not be always active during suspend/ resume when we are operating in dual-role/otg mode. Check if we're active and only if we are then perform necessary actions during suspend/resume. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/gadget.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1148ec8..ec6112d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2792,6 +2792,9 @@ void dwc3_gadget_exit(struct dwc3 *dwc) int dwc3_gadget_suspend(struct dwc3 *dwc) { + if (!dwc->gadget_driver) + return 0; + if (dwc->pullups_connected) { dwc3_gadget_disable_irq(dwc); dwc3_gadget_run_stop(dwc, true, true); @@ -2810,6 +2813,9 @@ int dwc3_gadget_resume(struct dwc3 *dwc) struct dwc3_ep *dep; int ret; + if (!dwc->gadget_driver) + return 0; + /* Start with SuperSpeed Default */ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 9/9] usb: dwc3: core: don't break during suspend/resume while we're dual-role
We can't rely just on dr_mode to decide if we're in host or gadget mode when we're configured as otg/dual-role. So while dr_mode is OTG, we find out from the otg state machine if we're in host or gadget mode and take the necessary actions during suspend/resume. Also make sure that we disable OTG irq and events during system suspend so that we don't lockup the system during system suspend/resume. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.c | 27 +-- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 654aebf..25891e3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1455,18 +1455,15 @@ static int dwc3_suspend(struct device *dev) dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL); dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT); dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); + dwc3_writel(dwc->regs, DWC3_OEVTEN, 0); + disable_irq(dwc->otg_irq); } - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + if (dwc->dr_mode == USB_DR_MODE_PERIPHERAL || + ((dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->fsm->protocol == PROTO_GADGET))) dwc3_gadget_suspend(dwc); - /* FALLTHROUGH */ - case USB_DR_MODE_HOST: - default: - dwc3_event_buffers_cleanup(dwc); - break; - } + + dwc3_event_buffers_cleanup(dwc); dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); spin_unlock_irqrestore(>lock, flags); @@ -1506,18 +1503,12 @@ static int dwc3_resume(struct device *dev) dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl); dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt); dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); + enable_irq(dwc->otg_irq); } - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + if (dwc->dr_mode == USB_DR_MODE_PERIPHERAL || + ((dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->fsm->protocol == PROTO_GADGET))) dwc3_gadget_resume(dwc); - /* FALLTHROUGH */ - case USB_DR_MODE_HOST: - default: - /* do nothing */ - break; - } spin_unlock_irqrestore(>lock, flags); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 3/9] usb: dwc3: dwc3-omap: Make the wrapper interrupt shared
On Wed, Sep 02, 2015 at 05:24:18PM +0300, Roger Quadros wrote: > The wrapper interrupt is shared with OTG core so mark it IRQF_SHARED. > > Signed-off-by: Roger Quadros> --- > drivers/usb/dwc3/dwc3-omap.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c > index a5a1b7c..b18f2a3 100644 > --- a/drivers/usb/dwc3/dwc3-omap.c > +++ b/drivers/usb/dwc3/dwc3-omap.c > @@ -506,8 +506,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) > reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); > omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); > > - ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, > - "dwc3-omap", omap); > + ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, IRQF_SHARED, > +"dwc3-omap", omap); looks like only first line needs to change > if (ret) { > dev_err(dev, "failed to request IRQ #%d --> %d\n", > omap->irq, ret); > -- > 2.1.4 > -- balbi signature.asc Description: Digital signature
Re: [PATCH v4 1/9] usb: dwc3: add dual-role support
Hi, On Wed, Sep 02, 2015 at 05:24:16PM +0300, Roger Quadros wrote: > Register with the USB OTG core. Since we don't support > OTG yet we just work as a dual-role device even > if device tree says "otg". > > Use extcon framework to get VBUS/ID cable events and > kick the OTG state machine. > > Signed-off-by: Roger Quadros> --- > drivers/usb/dwc3/core.c | 174 > ++- > drivers/usb/dwc3/core.h | 7 ++ > drivers/usb/dwc3/platform_data.h | 1 + > 3 files changed, 181 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 064123e..2e36a9b 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -704,6 +704,152 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) > return 0; > } > > +/* - Dual-Role management > --- */ > + > +static void dwc3_drd_fsm_sync(struct dwc3 *dwc) > +{ > + int id, vbus; > + > + /* get ID */ > + id = extcon_get_cable_state(dwc->edev, "USB-HOST"); > + /* Host means ID == 0 */ > + id = !id; > + > + /* get VBUS */ > + vbus = extcon_get_cable_state(dwc->edev, "USB"); > + dev_dbg(dwc->dev, "id %d vbus %d\n", id, vbus); tracepoint please. We don't want this driver to use dev_(v)?db anymore. Ditto to all others. > + > + dwc->fsm->id = id; > + dwc->fsm->b_sess_vld = vbus; > + usb_otg_sync_inputs(dwc->fsm); > +} > + > +static int dwc3_drd_start_host(struct otg_fsm *fsm, int on) > +{ > + struct device *dev = usb_otg_fsm_to_dev(fsm); > + struct dwc3 *dwc = dev_get_drvdata(dev); how about adding a usb_otg_get_drvdata(fsm) ? > + dev_dbg(dwc->dev, "%s: %d\n", __func__, on); > + if (on) { > + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); > + /* start the HCD */ > + usb_otg_start_host(fsm, true); > + } else { > + /* stop the HCD */ > + usb_otg_start_host(fsm, false); > + } This can be simplified. if (on) dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); usb_otg_start_host(fsm, on); > + > + return 0; > +} > + > +static int dwc3_drd_start_gadget(struct otg_fsm *fsm, int on) > +{ > + struct device *dev = usb_otg_fsm_to_dev(fsm); > + struct dwc3 *dwc = dev_get_drvdata(dev); > + > + dev_dbg(dwc->dev, "%s: %d\n", __func__, on); > + if (on) { > + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); > + dwc3_event_buffers_setup(dwc); > + > + /* start the UDC */ > + usb_otg_start_gadget(fsm, true); > + } else { > + /* stop the UDC */ > + usb_otg_start_gadget(fsm, false); > + } likewise: if (on) { dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); dwc3_event_buffers_setup(dwc); } usb_otg_start_gadget(fsm, on); > + return 0; > +} > + > +static struct otg_fsm_ops dwc3_drd_ops = { > + .start_host = dwc3_drd_start_host, > + .start_gadget = dwc3_drd_start_gadget, > +}; > + > +static int dwc3_drd_notifier(struct notifier_block *nb, > + unsigned long event, void *ptr) > +{ > + struct dwc3 *dwc = container_of(nb, struct dwc3, otg_nb); > + > + dwc3_drd_fsm_sync(dwc); > + > + return NOTIFY_DONE; > +} > + > +static int dwc3_drd_init(struct dwc3 *dwc) > +{ > + int ret, id, vbus; > + struct usb_otg_caps *otgcaps = >otg_config.otg_caps; > + > + otgcaps->otg_rev = 0; > + otgcaps->hnp_support = false; > + otgcaps->srp_support = false; > + otgcaps->adp_support = false; > + dwc->otg_config.fsm_ops = _drd_ops; > + > + if (!dwc->edev) { > + dev_err(dwc->dev, "No extcon device found for OTG mode\n"); > + return -ENODEV; > + } > + > + dwc->otg_nb.notifier_call = dwc3_drd_notifier; > + ret = extcon_register_notifier(dwc->edev, EXTCON_USB, >otg_nb); > + if (ret < 0) { > + dev_err(dwc->dev, "Couldn't register USB cable notifier\n"); > + return -ENODEV; > + } > + > + ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, > +>otg_nb); > + if (ret < 0) { > + dev_err(dwc->dev, "Couldn't register USB-HOST cable > notifier\n"); > + ret = -ENODEV; > + goto extcon_fail; > + } > + > + /* sanity check id & vbus states */ > + id = extcon_get_cable_state(dwc->edev, "USB-HOST"); > + vbus = extcon_get_cable_state(dwc->edev, "USB"); > + if (id < 0 || vbus < 0) { > + dev_err(dwc->dev, "Invalid USB cable state. id %d, vbus %d\n", > + id, vbus); > + ret = -ENODEV; > + goto fail; > + } > + > + /* register as DRD device with OTG core */ > + dwc->fsm = usb_otg_register(dwc->dev, >otg_config); > + if (IS_ERR(dwc->fsm)) { > + ret =
Re: [PATCH v4 4/9] usb: dwc3: core: Adapt to named interrupts
On Wed, Sep 02, 2015 at 05:24:19PM +0300, Roger Quadros wrote: > From: Felipe Balbi> > Add support to use interrupt names, > > Following are the interrupt names > > Peripheral Interrupt - peripheral > HOST Interrupt - host > OTG Interrupt - otg > > [Roger Q] > - If any of these are missing we use the > first available IRQ resource so that we don't > break with older DTBs. this is what original commit did: commit ecd5f71cfd663bcd4efd2f29824acd8b2ba9715d Author: Felipe Balbi Date: Fri Jan 3 13:49:38 2014 -0600 usb: dwc3: cleanup IRQ resources In order to make it easier for the driver to figure out which modes of operation it has, and because some dwc3 integrations have rather fuzzy IRQ routing, we now require three different IRQ numbers (peripheral, host, otg). In order to do that and maintain backwards compatibility, we still maintain support for the old IRQ resource name, but if you *really* want to have proper peripheral/host/otg support, you should make sure your resources are correct. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 60580a01cdd2..1f01031873b7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -556,10 +556,22 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) static int dwc3_core_init_mode(struct dwc3 *dwc) { struct device *dev = dwc->dev; + struct platform_device *pdev = to_platform_device(dev); int ret; switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: + dwc->gadget_irq = platform_get_irq_byname(pdev, "dwc3_peripheral"); + if (dwc->gadget_irq < 0) { + dwc->gadget_irq = platform_get_irq_byname(pdev, "dwc_usb3"); + if (dwc->gadget_irq < 0) { + dev_err(dev, "missing IRQ\n"); + return dwc->gadget_irq; + } else { + dev_warn(dev, "dwc_usb3 resource is deprecated\n"); + } + } + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { @@ -568,6 +580,22 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; case USB_DR_MODE_HOST: + dwc->xhci_irq = platform_get_irq_byname(pdev, "dwc3_host"); + if (dwc->xhci_irq < 0) { + dwc->xhci_irq = platform_get_irq_byname(pdev, "dwc_usb3"); + if (dwc->xhci_irq < 0) { + dev_err(dev, "missing Host IRQ\n"); + return dwc->xhci_irq; + } else { + dev_warn(dev, "dwc_usb3 resource is deprecated\n"); + } + + dwc->xhci_resources[1].start = dwc->xhci_irq; + dwc->xhci_resources[1].end = dwc->xhci_irq; + dwc->xhci_resources[1].flags = IORESOURCE_IRQ; + dwc->xhci_resources[1].name = "xhci"; + } + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { @@ -576,6 +604,28 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; case USB_DR_MODE_OTG: + dwc->gadget_irq = platform_get_irq_byname(pdev, "dwc3_peripheral"); + if (dwc->gadget_irq < 0) { + dwc->gadget_irq = platform_get_irq_byname(pdev, "dwc_usb3"); + if (dwc->gadget_irq < 0) { + dev_err(dev, "missing IRQ\n"); + return dwc->gadget_irq; + } else { + dev_warn(dev, "dwc_usb3 resource is deprecated\n"); + } + + dwc->xhci_irq = dwc->gadget_irq; + dwc->otg_irq = dwc->gadget_irq; + } else { + dwc->xhci_irq = platform_get_irq_byname(pdev, "dwc3_host"); + if (dwc->xhci_irq < 0) { + dev_err(dev, "missing Host IRQ\n"); + return dwc->xhci_irq; + } + + dwc->otg_irq = platform_get_irq_byname(pdev, "dwc3_otg"); + } + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); ret = dwc3_otg_init(dwc); if (ret) { @@ -647,18 +697,6 @@ static int dwc3_probe(struct platform_device *pdev) dwc->mem = mem; dwc->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "missing IRQ\n"); - return -ENODEV; -
Re: [RFC PATCH 1/1] usb: misc: usbtest: add bulk queue test
On Wed, 2 Sep 2015, Peter Chen wrote: > The bulk queue tests are used to show 'best performance' for bulk > transfer, we are often asked this question by users. > > It's result should be very close to IC simulation, in order > to get that, the device side should also need to prepare enough > queue. > > We have got the 'best performance' (IN: ~41MB, OUT: ~39MB) at i.mx platform > (USB2, ARM Cortex A9) with below command: > > Host side: > modprobe usbtest > ./testusb -a -t 27 -g 64 -s 16384 > ./testusb -a -t 28 -g 64 -s 16384 > Gadget side: > modprobe g_zero loopdefault=1 qlen=64 buflen=16384 > > Signed-off-by: Peter Chen> --- > > I am not sure if it is good to reuse iso structure, so I take > it as RFC. If reuse is accepted, I will rename the iso > structures to common one. > > drivers/usb/misc/usbtest.c | 88 > -- > 1 file changed, 69 insertions(+), 19 deletions(-) > > diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c > index ad6dd4a..f1faeb9 100644 > --- a/drivers/usb/misc/usbtest.c > +++ b/drivers/usb/misc/usbtest.c > @@ -17,6 +17,7 @@ > static int override_alt = -1; > module_param_named(alt, override_alt, int, 0644); > MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection"); > +static void iso_callback(struct urb *urb); > > /*-*/ > > @@ -239,7 +240,8 @@ static struct urb *usbtest_alloc_urb( > unsigned long bytes, > unsignedtransfer_flags, > unsignedoffset, > - u8 bInterval) > + u8 bInterval, > + boolqueue_callback) Should this be named "is_iso" instead? It would be be more clear. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 3/9] usb: dwc3: dwc3-omap: Make the wrapper interrupt shared
The wrapper interrupt is shared with OTG core so mark it IRQF_SHARED. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/dwc3-omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index a5a1b7c..b18f2a3 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -506,8 +506,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); - ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, - "dwc3-omap", omap); + ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, IRQF_SHARED, + "dwc3-omap", omap); if (ret) { dev_err(dev, "failed to request IRQ #%d --> %d\n", omap->irq, ret); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 0/9] usb: dwc3: add dual-role support
Hi, This series adds dual role support to dwc3 controller driver. Series depends on [1] for core OTG/dual-role support. Patches are based on greg/usb-next. Tested on am437x-gp-evm and dra7-evm after platform related patches are applied. Those are available at [2]. [1] core OTG/DRD support - http://thread.gmane.org/gmane.linux.kernel/2025239 [2] platform support - http://thread.gmane.org/gmane.linux.usb.general/127898 cheers, -roger Felipe Balbi (1): usb: dwc3: core: Adapt to named interrupts Roger Quadros (8): usb: dwc3: add dual-role support usb: dwc3: core.h: add some register definitions usb: dwc3: dwc3-omap: Make the wrapper interrupt shared usb: dwc3: core: make dual-role work with OTG irq usb: dwc3: save/restore OTG registers during suspend/resume usb: dwc3: gadget: Fix suspend/resume during dual-role mode usb: dwc3: core: Prevent otg events from disabling themselves usb: dwc3: core: don't break during suspend/resume while we're dual-role drivers/usb/dwc3/core.c | 422 +-- drivers/usb/dwc3/core.h | 103 ++ drivers/usb/dwc3/dwc3-omap.c | 4 +- drivers/usb/dwc3/gadget.c| 8 +- drivers/usb/dwc3/platform_data.h | 1 + 5 files changed, 516 insertions(+), 22 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 5/9] usb: dwc3: core: make dual-role work with OTG irq
If the ID pin event is not available over extcon then we rely on the OTG controller to provide us ID and VBUS information. We still don't support any OTG features but just dual-role operation. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.c | 217 drivers/usb/dwc3/core.h | 3 + 2 files changed, 205 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 38b31df..632ee53 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -704,6 +704,63 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) return 0; } +/* Get OTG events and sync it to OTG fsm */ +static void dwc3_otg_fsm_sync(struct dwc3 *dwc) +{ + u32 reg; + int id, vbus; + + reg = dwc3_readl(dwc->regs, DWC3_OSTS); + dev_dbg(dwc->dev, "otgstatus 0x%x\n", reg); + + id = !!(reg & DWC3_OSTS_CONIDSTS); + vbus = !!(reg & DWC3_OSTS_BSESVLD); + + if (id != dwc->fsm->id || vbus != dwc->fsm->b_sess_vld) { + dev_dbg(dwc->dev, "id %d vbus %d\n", id, vbus); + dwc->fsm->id = id; + dwc->fsm->b_sess_vld = vbus; + usb_otg_sync_inputs(dwc->fsm); + } +} + +static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc) +{ + struct dwc3 *dwc = _dwc; + unsigned long flags; + irqreturn_t ret = IRQ_NONE; + + spin_lock_irqsave(>lock, flags); + dwc3_otg_fsm_sync(dwc); + /* unmask interrupts */ + dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); + spin_unlock_irqrestore(>lock, flags); + + return ret; +} + +static irqreturn_t dwc3_otg_irq(int irq, void *_dwc) +{ + struct dwc3 *dwc = _dwc; + irqreturn_t ret = IRQ_NONE; + u32 reg; + + spin_lock(>lock); + + reg = dwc3_readl(dwc->regs, DWC3_OEVT); + if (reg) { + dwc3_writel(dwc->regs, DWC3_OEVT, reg); + /* mask interrupts till processed */ + dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); + dwc3_writel(dwc->regs, DWC3_OEVTEN, 0); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(>lock); + + return ret; +} + /* - Dual-Role management --- */ static void dwc3_drd_fsm_sync(struct dwc3 *dwc) @@ -728,15 +785,44 @@ static int dwc3_drd_start_host(struct otg_fsm *fsm, int on) { struct device *dev = usb_otg_fsm_to_dev(fsm); struct dwc3 *dwc = dev_get_drvdata(dev); + u32 reg; dev_dbg(dwc->dev, "%s: %d\n", __func__, on); + if (dwc->edev) { + if (on) { + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); + /* start the HCD */ + usb_otg_start_host(fsm, true); + } else { + /* stop the HCD */ + usb_otg_start_host(fsm, false); + } + + return 0; + } + + /* switch OTG core */ if (on) { - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); + /* OCTL.PeriMode = 0 */ + reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg &= ~DWC3_OCTL_PERIMODE; + dwc3_writel(dwc->regs, DWC3_OCTL, reg); + /* unconditionally turn on VBUS */ + reg |= DWC3_OCTL_PRTPWRCTL; + dwc3_writel(dwc->regs, DWC3_OCTL, reg); /* start the HCD */ usb_otg_start_host(fsm, true); } else { /* stop the HCD */ usb_otg_start_host(fsm, false); + /* turn off VBUS */ + reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg &= ~DWC3_OCTL_PRTPWRCTL; + dwc3_writel(dwc->regs, DWC3_OCTL, reg); + /* OCTL.PeriMode = 1 */ + reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg |= DWC3_OCTL_PERIMODE; + dwc3_writel(dwc->regs, DWC3_OCTL, reg); } return 0; @@ -746,15 +832,48 @@ static int dwc3_drd_start_gadget(struct otg_fsm *fsm, int on) { struct device *dev = usb_otg_fsm_to_dev(fsm); struct dwc3 *dwc = dev_get_drvdata(dev); + u32 reg; dev_dbg(dwc->dev, "%s: %d\n", __func__, on); - if (on) { - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); + if (on) dwc3_event_buffers_setup(dwc); + if (dwc->edev) { + if (on) { + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); + usb_otg_start_gadget(fsm, true); + } else { + usb_otg_start_gadget(fsm, false); + } + + return 0; + } + + /* switch OTG core */ + if (on) { + /* OCTL.PeriMode = 1 */ + reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg |= DWC3_OCTL_PERIMODE; +
[PATCH v4 4/9] usb: dwc3: core: Adapt to named interrupts
From: Felipe BalbiAdd support to use interrupt names, Following are the interrupt names Peripheral Interrupt - peripheral HOST Interrupt - host OTG Interrupt - otg [Roger Q] - If any of these are missing we use the first available IRQ resource so that we don't break with older DTBs. - Use gadget_irq in gadget driver. Signed-off-by: Felipe Balbi Signed-off-by: Roger Quadros --- drivers/usb/dwc3/core.c | 12 drivers/usb/dwc3/core.h | 7 +++ drivers/usb/dwc3/gadget.c | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2e36a9b..38b31df 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -958,6 +958,18 @@ static int dwc3_probe(struct platform_device *pdev) dwc->xhci_resources[1].flags = res->flags; dwc->xhci_resources[1].name = res->name; + dwc->otg_irq = platform_get_irq_byname(pdev, "otg"); + if (dwc->otg_irq < 0) + dwc->otg_irq = res->start; + + dwc->gadget_irq = platform_get_irq_byname(pdev, "peripheral"); + if (dwc->gadget_irq < 0) + dwc->gadget_irq = res->start; + + dwc->xhci_irq = platform_get_irq_byname(pdev, "host"); + if (dwc->xhci_irq < 0) + dwc->xhci_irq = res->start; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4b85330..bd32cb2 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -742,6 +742,9 @@ struct dwc3_scratchpad_array { * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents * @dr_mode: requested mode of operation + * @xhci_irq: IRQ number for XHCI IRQs + * @gadget_irq: IRQ number for Peripheral IRQs + * @otg_irq: IRQ number for OTG IRQs * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -847,6 +850,10 @@ struct dwc3 { enum usb_dr_modedr_mode; + int gadget_irq; + int xhci_irq; + int otg_irq; + /* used for suspend/resume */ u32 dcfg; u32 gctl; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0c25704..1148ec8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1533,7 +1533,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, int irq; u32 reg; - irq = platform_get_irq(to_platform_device(dwc->dev), 0); + irq = dwc->gadget_irq; ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, IRQF_SHARED, "dwc3", dwc); if (ret) { -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 1/9] usb: dwc3: add dual-role support
Register with the USB OTG core. Since we don't support OTG yet we just work as a dual-role device even if device tree says "otg". Use extcon framework to get VBUS/ID cable events and kick the OTG state machine. Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.c | 174 ++- drivers/usb/dwc3/core.h | 7 ++ drivers/usb/dwc3/platform_data.h | 1 + 3 files changed, 181 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 064123e..2e36a9b 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -704,6 +704,152 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) return 0; } +/* - Dual-Role management --- */ + +static void dwc3_drd_fsm_sync(struct dwc3 *dwc) +{ + int id, vbus; + + /* get ID */ + id = extcon_get_cable_state(dwc->edev, "USB-HOST"); + /* Host means ID == 0 */ + id = !id; + + /* get VBUS */ + vbus = extcon_get_cable_state(dwc->edev, "USB"); + dev_dbg(dwc->dev, "id %d vbus %d\n", id, vbus); + + dwc->fsm->id = id; + dwc->fsm->b_sess_vld = vbus; + usb_otg_sync_inputs(dwc->fsm); +} + +static int dwc3_drd_start_host(struct otg_fsm *fsm, int on) +{ + struct device *dev = usb_otg_fsm_to_dev(fsm); + struct dwc3 *dwc = dev_get_drvdata(dev); + + dev_dbg(dwc->dev, "%s: %d\n", __func__, on); + if (on) { + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); + /* start the HCD */ + usb_otg_start_host(fsm, true); + } else { + /* stop the HCD */ + usb_otg_start_host(fsm, false); + } + + return 0; +} + +static int dwc3_drd_start_gadget(struct otg_fsm *fsm, int on) +{ + struct device *dev = usb_otg_fsm_to_dev(fsm); + struct dwc3 *dwc = dev_get_drvdata(dev); + + dev_dbg(dwc->dev, "%s: %d\n", __func__, on); + if (on) { + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_event_buffers_setup(dwc); + + /* start the UDC */ + usb_otg_start_gadget(fsm, true); + } else { + /* stop the UDC */ + usb_otg_start_gadget(fsm, false); + } + + return 0; +} + +static struct otg_fsm_ops dwc3_drd_ops = { + .start_host = dwc3_drd_start_host, + .start_gadget = dwc3_drd_start_gadget, +}; + +static int dwc3_drd_notifier(struct notifier_block *nb, +unsigned long event, void *ptr) +{ + struct dwc3 *dwc = container_of(nb, struct dwc3, otg_nb); + + dwc3_drd_fsm_sync(dwc); + + return NOTIFY_DONE; +} + +static int dwc3_drd_init(struct dwc3 *dwc) +{ + int ret, id, vbus; + struct usb_otg_caps *otgcaps = >otg_config.otg_caps; + + otgcaps->otg_rev = 0; + otgcaps->hnp_support = false; + otgcaps->srp_support = false; + otgcaps->adp_support = false; + dwc->otg_config.fsm_ops = _drd_ops; + + if (!dwc->edev) { + dev_err(dwc->dev, "No extcon device found for OTG mode\n"); + return -ENODEV; + } + + dwc->otg_nb.notifier_call = dwc3_drd_notifier; + ret = extcon_register_notifier(dwc->edev, EXTCON_USB, >otg_nb); + if (ret < 0) { + dev_err(dwc->dev, "Couldn't register USB cable notifier\n"); + return -ENODEV; + } + + ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, + >otg_nb); + if (ret < 0) { + dev_err(dwc->dev, "Couldn't register USB-HOST cable notifier\n"); + ret = -ENODEV; + goto extcon_fail; + } + + /* sanity check id & vbus states */ + id = extcon_get_cable_state(dwc->edev, "USB-HOST"); + vbus = extcon_get_cable_state(dwc->edev, "USB"); + if (id < 0 || vbus < 0) { + dev_err(dwc->dev, "Invalid USB cable state. id %d, vbus %d\n", + id, vbus); + ret = -ENODEV; + goto fail; + } + + /* register as DRD device with OTG core */ + dwc->fsm = usb_otg_register(dwc->dev, >otg_config); + if (IS_ERR(dwc->fsm)) { + ret = PTR_ERR(dwc->fsm); + if (ret == -ENOTSUPP) + dev_err(dwc->dev, "CONFIG_USB_OTG needed for dual-role\n"); + else + dev_err(dwc->dev, "Failed to register with OTG core\n"); + + goto fail; + } + + dwc3_drd_fsm_sync(dwc); + + return 0; +fail: + extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST, >otg_nb); +extcon_fail: + extcon_unregister_notifier(dwc->edev, EXTCON_USB, >otg_nb); + + return ret; +} + +static void dwc3_drd_exit(struct dwc3 *dwc) +{ + usb_otg_unregister(dwc->dev); + extcon_unregister_notifier(dwc->edev,
[PATCH v4 2/9] usb: dwc3: core.h: add some register definitions
Add OTG and GHWPARAMS6 register definitions Signed-off-by: Roger Quadros--- drivers/usb/dwc3/core.h | 82 + 1 file changed, 82 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5ca2b25..4b85330 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -173,6 +173,15 @@ #define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) #define DWC3_GCTL_DSBLCLKGTNG (1 << 0) +/* Global Status Register */ +#define DWC3_GSTS_OTG_IP (1 << 10) +#define DWC3_GSTS_BC_IP(1 << 9) +#define DWC3_GSTS_ADP_IP (1 << 8) +#define DWC3_GSTS_HOST_IP (1 << 7) +#define DWC3_GSTS_DEVICE_IP(1 << 6) +#define DWC3_GSTS_CSR_TIMEOUT (1 << 5) +#define DWC3_GSTS_BUS_ERR_ADDR_VLD (1 << 4) + /* Global USB2 PHY Configuration Register */ #define DWC3_GUSB2PHYCFG_PHYSOFTRST(1 << 31) #define DWC3_GUSB2PHYCFG_SUSPHY(1 << 6) @@ -234,6 +243,11 @@ #define DWC3_MAX_HIBER_SCRATCHBUFS 15 /* Global HWPARAMS6 Register */ +#define DWC3_GHWPARAMS6_BCSUPPORT (1 << 14) +#define DWC3_GHWPARAMS6_OTG3SUPPORT(1 << 13) +#define DWC3_GHWPARAMS6_ADPSUPPORT (1 << 12) +#define DWC3_GHWPARAMS6_HNPSUPPORT (1 << 11) +#define DWC3_GHWPARAMS6_SRPSUPPORT (1 << 10) #define DWC3_GHWPARAMS6_EN_FPGA(1 << 7) /* Device Configuration Register */ @@ -393,6 +407,74 @@ #define DWC3_DEPCMD_TYPE_BULK 2 #define DWC3_DEPCMD_TYPE_INTR 3 +/* OTG Configuration Register */ +#define DWC3_OCFG_DISPWRCUTTOFF(1 << 5) +#define DWC3_OCFG_HIBDISMASK (1 << 4) +#define DWC3_OCFG_SFTRSTMASK (1 << 3) +#define DWC3_OCFG_OTGVERSION (1 << 2) +#define DWC3_OCFG_HNPCAP (1 << 1) +#define DWC3_OCFG_SRPCAP (1 << 0) + +/* OTG CTL Register */ +#define DWC3_OCTL_OTG3GOERR(1 << 7) +#define DWC3_OCTL_PERIMODE (1 << 6) +#define DWC3_OCTL_PRTPWRCTL(1 << 5) +#define DWC3_OCTL_HNPREQ (1 << 4) +#define DWC3_OCTL_SESREQ (1 << 3) +#define DWC3_OCTL_TERMSELIDPULSE (1 << 2) +#define DWC3_OCTL_DEVSETHNPEN (1 << 1) +#define DWC3_OCTL_HSTSETHNPEN (1 << 0) + +/* OTG Event Register */ +#define DWC3_OEVT_DEVICEMODE (1 << 31) +#define DWC3_OEVT_XHCIRUNSTPSET(1 << 27) +#define DWC3_OEVT_DEVRUNSTPSET (1 << 26) +#define DWC3_OEVT_HIBENTRY (1 << 25) +#define DWC3_OEVT_CONIDSTSCHNG (1 << 24) +#define DWC3_OEVT_HRRCONFNOTIF (1 << 23) +#define DWC3_OEVT_HRRINITNOTIF (1 << 22) +#define DWC3_OEVT_ADEVIDLE (1 << 21) +#define DWC3_OEVT_ADEVBHOSTEND (1 << 20) +#define DWC3_OEVT_ADEVHOST (1 << 19) +#define DWC3_OEVT_ADEVHNPCHNG (1 << 18) +#define DWC3_OEVT_ADEVSRPDET (1 << 17) +#define DWC3_OEVT_ADEVSESSENDDET (1 << 16) +#define DWC3_OEVT_BDEVBHOSTEND (1 << 11) +#define DWC3_OEVT_BDEVHNPCHNG (1 << 10) +#define DWC3_OEVT_BDEVSESSVLDDET (1 << 9) +#define DWC3_OEVT_BDEVVBUSCHNG (1 << 8) +#define DWC3_OEVT_BSESSVLD (1 << 3) +#define DWC3_OEVT_HSTNEGSTS(1 << 2) +#define DWC3_OEVT_SESREQSTS(1 << 1) +#define DWC3_OEVT_ERROR(1 << 0) + +/* OTG Event Enable Register */ +#define DWC3_OEVTEN_XHCIRUNSTPSETEN(1 << 27) +#define DWC3_OEVTEN_DEVRUNSTPSETEN (1 << 26) +#define DWC3_OEVTEN_HIBENTRYEN (1 << 25) +#define DWC3_OEVTEN_CONIDSTSCHNGEN (1 << 24) +#define DWC3_OEVTEN_HRRCONFNOTIFEN (1 << 23) +#define DWC3_OEVTEN_HRRINITNOTIFEN (1 << 22) +#define DWC3_OEVTEN_ADEVIDLEEN (1 << 21) +#define DWC3_OEVTEN_ADEVBHOSTENDEN (1 << 20) +#define DWC3_OEVTEN_ADEVHOSTEN (1 << 19) +#define DWC3_OEVTEN_ADEVHNPCHNGEN (1 << 18) +#define DWC3_OEVTEN_ADEVSRPDETEN (1 << 17) +#define DWC3_OEVTEN_ADEVSESSENDDETEN (1 << 16) +#define DWC3_OEVTEN_BDEVHOSTENDEN (1 << 11) +#define DWC3_OEVTEN_BDEVHNPCHNGEN (1 << 10) +#define DWC3_OEVTEN_BDEVSESSVLDDETEN (1 << 9) +#define DWC3_OEVTEN_BDEVVBUSCHNGE (1 << 8) + +/* OTG Status Register */ +#define DWC3_OSTS_DEVRUNSTP(1 << 13) +#define DWC3_OSTS_XHCIRUNSTP (1 << 12) +#define DWC3_OSTS_PERIPHERALSTATE (1 << 4) +#define DWC3_OSTS_XHCIPRTPOWER (1 << 3) +#define DWC3_OSTS_BSESVLD (1 << 2) +#define DWC3_OSTS_VBUSVLD (1 << 1) +#define DWC3_OSTS_CONIDSTS (1 << 0) + /* Structures */ struct dwc3_trb; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 5/9] usb: dwc3: core: make dual-role work with OTG irq
Hi, On Wed, Sep 02, 2015 at 05:24:20PM +0300, Roger Quadros wrote: > If the ID pin event is not available over extcon > then we rely on the OTG controller to provide us ID and VBUS > information. > > We still don't support any OTG features but just > dual-role operation. > > Signed-off-by: Roger Quadros> --- > drivers/usb/dwc3/core.c | 217 > > drivers/usb/dwc3/core.h | 3 + > 2 files changed, 205 insertions(+), 15 deletions(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 38b31df..632ee53 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -704,6 +704,63 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) > return 0; > } > > +/* Get OTG events and sync it to OTG fsm */ > +static void dwc3_otg_fsm_sync(struct dwc3 *dwc) > +{ > + u32 reg; > + int id, vbus; > + > + reg = dwc3_readl(dwc->regs, DWC3_OSTS); > + dev_dbg(dwc->dev, "otgstatus 0x%x\n", reg); > + > + id = !!(reg & DWC3_OSTS_CONIDSTS); > + vbus = !!(reg & DWC3_OSTS_BSESVLD); > + > + if (id != dwc->fsm->id || vbus != dwc->fsm->b_sess_vld) { > + dev_dbg(dwc->dev, "id %d vbus %d\n", id, vbus); > + dwc->fsm->id = id; > + dwc->fsm->b_sess_vld = vbus; > + usb_otg_sync_inputs(dwc->fsm); > + } this guy shouldn't try to filter events here. That's what the FSM should be doing. > +} > + > +static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc) > +{ > + struct dwc3 *dwc = _dwc; > + unsigned long flags; > + irqreturn_t ret = IRQ_NONE; this IRQ will be disabled pretty quickly. You *always* return IRQ_NONE > + spin_lock_irqsave(>lock, flags); if you cache current OSTS in dwc3, you can use that instead and change this to a spin_lock() instead of disabling IRQs here. This device's IRQs are already masked anyway. > + dwc3_otg_fsm_sync(dwc); > + /* unmask interrupts */ > + dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); > + spin_unlock_irqrestore(>lock, flags); > + > + return ret; > +} > + > +static irqreturn_t dwc3_otg_irq(int irq, void *_dwc) > +{ > + struct dwc3 *dwc = _dwc; > + irqreturn_t ret = IRQ_NONE; > + u32 reg; > + > + spin_lock(>lock); this seems unnecessary, we're already in hardirq with IRQs disabled. What sort of race could we have ? (in fact, this also needs change in dwc3/gadget.c). > + > + reg = dwc3_readl(dwc->regs, DWC3_OEVT); > + if (reg) { > + dwc3_writel(dwc->regs, DWC3_OEVT, reg); > + /* mask interrupts till processed */ > + dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); > + dwc3_writel(dwc->regs, DWC3_OEVTEN, 0); > + ret = IRQ_WAKE_THREAD; > + } > + > + spin_unlock(>lock); > + > + return ret; > +} > + > /* - Dual-Role management > --- */ > > static void dwc3_drd_fsm_sync(struct dwc3 *dwc) > @@ -728,15 +785,44 @@ static int dwc3_drd_start_host(struct otg_fsm *fsm, int > on) > { > struct device *dev = usb_otg_fsm_to_dev(fsm); > struct dwc3 *dwc = dev_get_drvdata(dev); > + u32 reg; > > dev_dbg(dwc->dev, "%s: %d\n", __func__, on); > + if (dwc->edev) { > + if (on) { > + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); > + /* start the HCD */ > + usb_otg_start_host(fsm, true); > + } else { > + /* stop the HCD */ > + usb_otg_start_host(fsm, false); > + } if (on) dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); usb_otg_start_host(fsm, on); > + > + return 0; > + } > + > + /* switch OTG core */ > if (on) { > - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); > + /* OCTL.PeriMode = 0 */ > + reg = dwc3_readl(dwc->regs, DWC3_OCTL); > + reg &= ~DWC3_OCTL_PERIMODE; > + dwc3_writel(dwc->regs, DWC3_OCTL, reg); > + /* unconditionally turn on VBUS */ > + reg |= DWC3_OCTL_PRTPWRCTL; > + dwc3_writel(dwc->regs, DWC3_OCTL, reg); > /* start the HCD */ > usb_otg_start_host(fsm, true); > } else { > /* stop the HCD */ > usb_otg_start_host(fsm, false); > + /* turn off VBUS */ > + reg = dwc3_readl(dwc->regs, DWC3_OCTL); > + reg &= ~DWC3_OCTL_PRTPWRCTL; > + dwc3_writel(dwc->regs, DWC3_OCTL, reg); > + /* OCTL.PeriMode = 1 */ > + reg = dwc3_readl(dwc->regs, DWC3_OCTL); > + reg |= DWC3_OCTL_PERIMODE; > + dwc3_writel(dwc->regs, DWC3_OCTL, reg); > } it looks like you're not really following the fluxchart from SNPS documentation, see Figure 11-4 on section 11.1.4.5 > @@ -746,15 +832,48
Re: [PATCH v4 6/9] usb: dwc3: save/restore OTG registers during suspend/resume
On Wed, Sep 02, 2015 at 05:24:21PM +0300, Roger Quadros wrote: > Without this we loose OTG controller register context and malfunction > after a system suspend-resume. > > Signed-off-by: Roger Quadros> --- > drivers/usb/dwc3/core.c | 17 + > drivers/usb/dwc3/core.h | 6 +- > 2 files changed, 22 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 632ee53..684010c 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -56,6 +56,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) > reg = dwc3_readl(dwc->regs, DWC3_GCTL); > reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); > reg |= DWC3_GCTL_PRTCAPDIR(mode); > + dwc->current_mode = mode; > dwc3_writel(dwc->regs, DWC3_GCTL, reg); > } > > @@ -1443,6 +1444,14 @@ static int dwc3_suspend(struct device *dev) > > spin_lock_irqsave(>lock, flags); > > + /* Save OTG state only if we're really using it */ > + if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) { > + dwc->ocfg = dwc3_readl(dwc->regs, DWC3_OCFG); > + dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL); > + dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT); oevt is what you use to clear pending IRQs, which means that ... > + dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN); > + } > + > switch (dwc->dr_mode) { > case USB_DR_MODE_PERIPHERAL: > case USB_DR_MODE_OTG: > @@ -1486,6 +1495,14 @@ static int dwc3_resume(struct device *dev) > dwc3_event_buffers_setup(dwc); > dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); > > + /* Restore OTG state only if we're really using it */ > + if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) { > + dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg); > + dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl); > + dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt); ... you could be clearing pending IRQs right here. > + dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten); > + } > + > switch (dwc->dr_mode) { > case USB_DR_MODE_PERIPHERAL: > case USB_DR_MODE_OTG: > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 129ef37..1115ce0 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -737,6 +737,7 @@ struct dwc3_scratchpad_array { > * @regs: base address for our registers > * @regs_size: address space size > * @oevten: otg interrupt enable mask copy > + * @current_mode: current mode of operation written to PRTCAPDIR > * @nr_scratch: number of scratch buffers > * @num_event_buffers: calculated number of event buffers > * @u1u2: only used on revisions <1.83a for workaround > @@ -858,9 +859,12 @@ struct dwc3 { > /* used for suspend/resume */ > u32 dcfg; > u32 gctl; > - > + u32 ocfg; > + u32 octl; > + u32 oevt; > u32 oevten; > > + u32 current_mode; > u32 nr_scratch; > u32 num_event_buffers; > u32 u1u2; > -- > 2.1.4 > -- balbi signature.asc Description: Digital signature