Re: [PATCH 2/5] USB: io_ti: use serial->interface for messages in download_fw

2015-09-02 Thread Oliver Neukum
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"

2015-09-02 Thread Masakazu Mokuno
Hi,

On Mon, 31 Aug 2015 11:54:13 -0500
Felipe Balbi  wrote:

> 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

2015-09-02 Thread Peter Chen
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

2015-09-02 Thread Pascal Huerst
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

2015-09-02 Thread Sergei Shtylyov

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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread John Youn
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

2015-09-02 Thread Nikhil Badola
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

2015-09-02 Thread Nikhil Badola
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

2015-09-02 Thread Nikhil Badola
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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Rodolfo Labiapari Mansur
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

2015-09-02 Thread Pascal Huerst
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

2015-09-02 Thread Alan Stern
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

2015-09-02 Thread Felipe Balbi
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"

2015-09-02 Thread Felipe Balbi
On Wed, Sep 02, 2015 at 05:09:39PM +0900, Masakazu Mokuno wrote:
> Hi,
> 
> On Mon, 31 Aug 2015 11:54:13 -0500
> Felipe Balbi  wrote:
> 
> > 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

2015-09-02 Thread Sergei Shtylyov

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

2015-09-02 Thread Sergei Shtylyov

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

2015-09-02 Thread Felipe Balbi
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 Quadros 

can'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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Alan Stern
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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.

- 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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Roger Quadros
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

2015-09-02 Thread Felipe Balbi
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

2015-09-02 Thread Felipe Balbi
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