diff mbox

[6/9] usb: chipidea: add PTW and PTS handling

Message ID 1352909950-32555-7-git-send-email-m.grzeschik@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Grzeschik Nov. 14, 2012, 4:19 p.m. UTC
This patch makes it possible to configure the PTW and PTS bits inside
the portsc register for host and device mode before the driver starts
and the phy can be addressed as hardware implementation is designed.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/usb/chipidea/bits.h        |    3 +++
 drivers/usb/chipidea/ci.h          |    2 ++
 drivers/usb/chipidea/ci13xxx_imx.c |    1 +
 drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
 drivers/usb/chipidea/host.c        |    4 +++
 include/linux/usb/chipidea.h       |    9 +++++++
 6 files changed, 66 insertions(+)

Comments

Alexander Shishkin Nov. 16, 2012, 12:18 p.m. UTC | #1
Michael Grzeschik <m.grzeschik@pengutronix.de> writes:

> This patch makes it possible to configure the PTW and PTS bits inside
> the portsc register for host and device mode before the driver starts
> and the phy can be addressed as hardware implementation is designed.
>
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/usb/chipidea/bits.h        |    3 +++
>  drivers/usb/chipidea/ci.h          |    2 ++
>  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>  drivers/usb/chipidea/host.c        |    4 +++
>  include/linux/usb/chipidea.h       |    9 +++++++
>  6 files changed, 66 insertions(+)
>
> diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
> index 4b6ae3e..3cded5f 100644
> --- a/drivers/usb/chipidea/bits.h
> +++ b/drivers/usb/chipidea/bits.h
> @@ -48,6 +48,9 @@
>  #define PORTSC_SUSP           BIT(7)
>  #define PORTSC_HSP            BIT(9)
>  #define PORTSC_PTC            (0x0FUL << 16)
> +#define PORTSC_PTS            (BIT(31) | BIT(30))
> +#define PORTSC_PTW            BIT(28)
> +#define PORTSC_STS            BIT(29)
>  
>  /* DEVLC */
>  #define DEVLC_PSPD            (0x03UL << 25)
> diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
> index cd42b59..1439e51 100644
> --- a/drivers/usb/chipidea/ci.h
> +++ b/drivers/usb/chipidea/ci.h
> @@ -314,6 +314,8 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
>  	return (val & mask) >> ffs_nr(mask);
>  }
>  
> +void hw_portsc_configure(struct ci13xxx *ci);
> +
>  int hw_device_reset(struct ci13xxx *ci, u32 mode);
>  
>  int hw_port_test_set(struct ci13xxx *ci, u8 mode);
> diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
> index ee4dab0..a8257b8 100644
> --- a/drivers/usb/chipidea/ci13xxx_imx.c
> +++ b/drivers/usb/chipidea/ci13xxx_imx.c
> @@ -133,6 +133,7 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
>  		       CI13XXX_PULLUP_ON_VBUS |
>  		       CI13XXX_DISABLE_STREAMING |
>  		       CI13XXX_REGS_SHARED,
> +	ci13xxx_get_dr_flags(pdev->dev.of_node, pdata);

It will be a bit easier to read if this one and ci13xxx_get_dr_mode()
calls are next to one another. Also my comment about get_dr_mode()
probably applies here too.

Regards,
--
Alex
Alexander Shishkin Nov. 16, 2012, 12:45 p.m. UTC | #2
Michael Grzeschik <m.grzeschik@pengutronix.de> writes:

> This patch makes it possible to configure the PTW and PTS bits inside
> the portsc register for host and device mode before the driver starts
> and the phy can be addressed as hardware implementation is designed.
>
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/usb/chipidea/bits.h        |    3 +++
>  drivers/usb/chipidea/ci.h          |    2 ++
>  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>  drivers/usb/chipidea/host.c        |    4 +++
>  include/linux/usb/chipidea.h       |    9 +++++++
>  6 files changed, 66 insertions(+)
>
> diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
> index 4b6ae3e..3cded5f 100644
> --- a/drivers/usb/chipidea/bits.h
> +++ b/drivers/usb/chipidea/bits.h
> @@ -48,6 +48,9 @@
>  #define PORTSC_SUSP           BIT(7)
>  #define PORTSC_HSP            BIT(9)
>  #define PORTSC_PTC            (0x0FUL << 16)
> +#define PORTSC_PTS            (BIT(31) | BIT(30))
> +#define PORTSC_PTW            BIT(28)
> +#define PORTSC_STS            BIT(29)

Hm, my spec says these are actually in DEVLC register and only have this
meaning in device mode. And in portsc these bits fall in device address
bitfield. Can you refer me to your spec?

Regards,
--
Alex
Michael Grzeschik Nov. 16, 2012, 1:16 p.m. UTC | #3
On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
> 
> > This patch makes it possible to configure the PTW and PTS bits inside
> > the portsc register for host and device mode before the driver starts
> > and the phy can be addressed as hardware implementation is designed.
> >
> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> > ---
> >  drivers/usb/chipidea/bits.h        |    3 +++
> >  drivers/usb/chipidea/ci.h          |    2 ++
> >  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
> >  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
> >  drivers/usb/chipidea/host.c        |    4 +++
> >  include/linux/usb/chipidea.h       |    9 +++++++
> >  6 files changed, 66 insertions(+)
> >
> > diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
> > index 4b6ae3e..3cded5f 100644
> > --- a/drivers/usb/chipidea/bits.h
> > +++ b/drivers/usb/chipidea/bits.h
> > @@ -48,6 +48,9 @@
> >  #define PORTSC_SUSP           BIT(7)
> >  #define PORTSC_HSP            BIT(9)
> >  #define PORTSC_PTC            (0x0FUL << 16)
> > +#define PORTSC_PTS            (BIT(31) | BIT(30))
> > +#define PORTSC_PTW            BIT(28)
> > +#define PORTSC_STS            BIT(29)
> 
> Hm, my spec says these are actually in DEVLC register and only have this
> meaning in device mode. And in portsc these bits fall in device address
> bitfield. Can you refer me to your spec?

You can find it here:
http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
Page 4947

We as well do have the original documentation from Synopsys in which there
there is an DEVLC register in the index, but nowhere else in the Datasheet.

June 2011 - Doc.Rev. 2.40a
USB 2.0 High Speed Atlantic Controller

Unfortunately, its not possible for me to share this document.

Thanks,
Michael
Alexander Shishkin Nov. 16, 2012, 1:34 p.m. UTC | #4
Michael Grzeschik <mgr@pengutronix.de> writes:

> On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
>> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
>> 
>> > This patch makes it possible to configure the PTW and PTS bits inside
>> > the portsc register for host and device mode before the driver starts
>> > and the phy can be addressed as hardware implementation is designed.
>> >
>> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>> > ---
>> >  drivers/usb/chipidea/bits.h        |    3 +++
>> >  drivers/usb/chipidea/ci.h          |    2 ++
>> >  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>> >  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>> >  drivers/usb/chipidea/host.c        |    4 +++
>> >  include/linux/usb/chipidea.h       |    9 +++++++
>> >  6 files changed, 66 insertions(+)
>> >
>> > diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
>> > index 4b6ae3e..3cded5f 100644
>> > --- a/drivers/usb/chipidea/bits.h
>> > +++ b/drivers/usb/chipidea/bits.h
>> > @@ -48,6 +48,9 @@
>> >  #define PORTSC_SUSP           BIT(7)
>> >  #define PORTSC_HSP            BIT(9)
>> >  #define PORTSC_PTC            (0x0FUL << 16)
>> > +#define PORTSC_PTS            (BIT(31) | BIT(30))
>> > +#define PORTSC_PTW            BIT(28)
>> > +#define PORTSC_STS            BIT(29)
>> 
>> Hm, my spec says these are actually in DEVLC register and only have this
>> meaning in device mode. And in portsc these bits fall in device address
>> bitfield. Can you refer me to your spec?
>
> You can find it here:
> http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
> Page 4947

Oh, but see, the offset is 0x184, which in chipidea spec (the version
that I have) corresponds to DEVLC and not PORTSC. So in this driver's
terminology it's DEVLC too, at least currently.

So have you tested this code and did it make any difference?

> We as well do have the original documentation from Synopsys in which there
> there is an DEVLC register in the index, but nowhere else in the Datasheet.

Maybe it's a leftover from the old terminology, which would explain the
confusion.

> June 2011 - Doc.Rev. 2.40a
> USB 2.0 High Speed Atlantic Controller

Yes, mine is from 2009.

Regards,
--
Alex
Michael Grzeschik Nov. 16, 2012, 1:57 p.m. UTC | #5
On Fri, Nov 16, 2012 at 03:34:23PM +0200, Alexander Shishkin wrote:
> Michael Grzeschik <mgr@pengutronix.de> writes:
> 
> > On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
> >> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
> >> 
> >> > This patch makes it possible to configure the PTW and PTS bits inside
> >> > the portsc register for host and device mode before the driver starts
> >> > and the phy can be addressed as hardware implementation is designed.
> >> >
> >> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> >> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> >> > ---
> >> >  drivers/usb/chipidea/bits.h        |    3 +++
> >> >  drivers/usb/chipidea/ci.h          |    2 ++
> >> >  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
> >> >  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
> >> >  drivers/usb/chipidea/host.c        |    4 +++
> >> >  include/linux/usb/chipidea.h       |    9 +++++++
> >> >  6 files changed, 66 insertions(+)
> >> >
> >> > diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
> >> > index 4b6ae3e..3cded5f 100644
> >> > --- a/drivers/usb/chipidea/bits.h
> >> > +++ b/drivers/usb/chipidea/bits.h
> >> > @@ -48,6 +48,9 @@
> >> >  #define PORTSC_SUSP           BIT(7)
> >> >  #define PORTSC_HSP            BIT(9)
> >> >  #define PORTSC_PTC            (0x0FUL << 16)
> >> > +#define PORTSC_PTS            (BIT(31) | BIT(30))
> >> > +#define PORTSC_PTW            BIT(28)
> >> > +#define PORTSC_STS            BIT(29)
> >> 
> >> Hm, my spec says these are actually in DEVLC register and only have this
> >> meaning in device mode. And in portsc these bits fall in device address
> >> bitfield. Can you refer me to your spec?
> >
> > You can find it here:
> > http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
> > Page 4947
> 
> Oh, but see, the offset is 0x184, which in chipidea spec (the version
> that I have) corresponds to DEVLC and not PORTSC. So in this driver's
> terminology it's DEVLC too, at least currently.
> 
> So have you tested this code and did it make any difference?

Yes, i have tested this code with MX25, MX28, MX35 and MX53. In every
SoCs Datasheet the PORTSC register is defined on PORTBASE+0x184. Without
this proper configuration its not possible to communicate with the PHY.

> > We as well do have the original documentation from Synopsys in which there
> > there is an DEVLC register in the index, but nowhere else in the Datasheet.
> 
> Maybe it's a leftover from the old terminology, which would explain the
> confusion.

ACK

> > June 2011 - Doc.Rev. 2.40a
> > USB 2.0 High Speed Atlantic Controller
> Yes, mine is from 2009.

Probably worth to get updatet.

Michael
Alexander Shishkin Nov. 16, 2012, 2:06 p.m. UTC | #6
Michael Grzeschik <mgr@pengutronix.de> writes:

> On Fri, Nov 16, 2012 at 03:34:23PM +0200, Alexander Shishkin wrote:
>> Michael Grzeschik <mgr@pengutronix.de> writes:
>> 
>> > On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
>> >> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
>> >> 
>> >> > This patch makes it possible to configure the PTW and PTS bits inside
>> >> > the portsc register for host and device mode before the driver starts
>> >> > and the phy can be addressed as hardware implementation is designed.
>> >> >
>> >> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>> >> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>> >> > ---
>> >> >  drivers/usb/chipidea/bits.h        |    3 +++
>> >> >  drivers/usb/chipidea/ci.h          |    2 ++
>> >> >  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>> >> >  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>> >> >  drivers/usb/chipidea/host.c        |    4 +++
>> >> >  include/linux/usb/chipidea.h       |    9 +++++++
>> >> >  6 files changed, 66 insertions(+)
>> >> >
>> >> > diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
>> >> > index 4b6ae3e..3cded5f 100644
>> >> > --- a/drivers/usb/chipidea/bits.h
>> >> > +++ b/drivers/usb/chipidea/bits.h
>> >> > @@ -48,6 +48,9 @@
>> >> >  #define PORTSC_SUSP           BIT(7)
>> >> >  #define PORTSC_HSP            BIT(9)
>> >> >  #define PORTSC_PTC            (0x0FUL << 16)
>> >> > +#define PORTSC_PTS            (BIT(31) | BIT(30))
>> >> > +#define PORTSC_PTW            BIT(28)
>> >> > +#define PORTSC_STS            BIT(29)
>> >> 
>> >> Hm, my spec says these are actually in DEVLC register and only have this
>> >> meaning in device mode. And in portsc these bits fall in device address
>> >> bitfield. Can you refer me to your spec?
>> >
>> > You can find it here:
>> > http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
>> > Page 4947
>> 
>> Oh, but see, the offset is 0x184, which in chipidea spec (the version
>> that I have) corresponds to DEVLC and not PORTSC. So in this driver's
>> terminology it's DEVLC too, at least currently.
>> 
>> So have you tested this code and did it make any difference?
>
> Yes, i have tested this code with MX25, MX28, MX35 and MX53. In every
> SoCs Datasheet the PORTSC register is defined on PORTBASE+0x184. Without
> this proper configuration its not possible to communicate with the PHY.

No, I mean, you're writing DEVLC (using present driver's terminology)
bits to PORTSC register. It *shouldn't* work. I suppose, it does
something, but not exactly what you intended.

Regards,
--
Alex
Matthieu CASTET Nov. 16, 2012, 2:46 p.m. UTC | #7
Alexander Shishkin a écrit :
> Michael Grzeschik <mgr@pengutronix.de> writes:
> 
>> On Fri, Nov 16, 2012 at 03:34:23PM +0200, Alexander Shishkin wrote:
>>> Michael Grzeschik <mgr@pengutronix.de> writes:
>>>
>>>> On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
>>>>> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
>>>>>
>>>>>> This patch makes it possible to configure the PTW and PTS bits inside
>>>>>> the portsc register for host and device mode before the driver starts
>>>>>> and the phy can be addressed as hardware implementation is designed.
>>>>>>
>>>>>> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>>>>>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>>>>>> ---
>>>>>>  drivers/usb/chipidea/bits.h        |    3 +++
>>>>>>  drivers/usb/chipidea/ci.h          |    2 ++
>>>>>>  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>>>>>>  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>>>>>>  drivers/usb/chipidea/host.c        |    4 +++
>>>>>>  include/linux/usb/chipidea.h       |    9 +++++++
>>>>>>  6 files changed, 66 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
>>>>>> index 4b6ae3e..3cded5f 100644
>>>>>> --- a/drivers/usb/chipidea/bits.h
>>>>>> +++ b/drivers/usb/chipidea/bits.h
>>>>>> @@ -48,6 +48,9 @@
>>>>>>  #define PORTSC_SUSP           BIT(7)
>>>>>>  #define PORTSC_HSP            BIT(9)
>>>>>>  #define PORTSC_PTC            (0x0FUL << 16)
>>>>>> +#define PORTSC_PTS            (BIT(31) | BIT(30))
>>>>>> +#define PORTSC_PTW            BIT(28)
>>>>>> +#define PORTSC_STS            BIT(29)
>>>>> Hm, my spec says these are actually in DEVLC register and only have this
>>>>> meaning in device mode. And in portsc these bits fall in device address
>>>>> bitfield. Can you refer me to your spec?
>>>> You can find it here:
>>>> http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
>>>> Page 4947
>>> Oh, but see, the offset is 0x184, which in chipidea spec (the version
>>> that I have) corresponds to DEVLC and not PORTSC. So in this driver's
>>> terminology it's DEVLC too, at least currently.
>>>
>>> So have you tested this code and did it make any difference?
>> Yes, i have tested this code with MX25, MX28, MX35 and MX53. In every
>> SoCs Datasheet the PORTSC register is defined on PORTBASE+0x184. Without
>> this proper configuration its not possible to communicate with the PHY.
> 
> No, I mean, you're writing DEVLC (using present driver's terminology)
> bits to PORTSC register. It *shouldn't* work. I suppose, it does
> something, but not exactly what you intended.
> 
I confirm in our datasheet we have PTW, PTS, STS in this register  PORTSCx with
this mapping.

In later design that support lpm, these bits have to move in another register
because ehci 1.1 use them [1].

So this code should only do that when !ci->hw_bank.lpm.
In case of ci->hw_bank.lpm, I don't know the new register mapping.


Matthieu



[1]
/* EHCI 1.1 addendum */
#define PORTSC_SUSPEND_STS_ACK 0
#define PORTSC_SUSPEND_STS_NYET 1
#define PORTSC_SUSPEND_STS_STALL 2
#define PORTSC_SUSPEND_STS_ERR 3

#define PORT_DEV_ADDR   (0x7f<<25)      /* device address */
#define PORT_SSTS   (0x3<<23)       /* suspend status */
Alexander Shishkin Nov. 16, 2012, 3:39 p.m. UTC | #8
Matthieu CASTET <matthieu.castet@parrot.com> writes:

> Alexander Shishkin a écrit :
>> Michael Grzeschik <mgr@pengutronix.de> writes:
>> 
>>> On Fri, Nov 16, 2012 at 03:34:23PM +0200, Alexander Shishkin wrote:
>>>> Michael Grzeschik <mgr@pengutronix.de> writes:
>>>>
>>>>> On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
>>>>>> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
>>>>>>
>>>>>>> This patch makes it possible to configure the PTW and PTS bits inside
>>>>>>> the portsc register for host and device mode before the driver starts
>>>>>>> and the phy can be addressed as hardware implementation is designed.
>>>>>>>
>>>>>>> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>>>>>>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>>>>>>> ---
>>>>>>>  drivers/usb/chipidea/bits.h        |    3 +++
>>>>>>>  drivers/usb/chipidea/ci.h          |    2 ++
>>>>>>>  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>>>>>>>  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>>>>>>>  drivers/usb/chipidea/host.c        |    4 +++
>>>>>>>  include/linux/usb/chipidea.h       |    9 +++++++
>>>>>>>  6 files changed, 66 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
>>>>>>> index 4b6ae3e..3cded5f 100644
>>>>>>> --- a/drivers/usb/chipidea/bits.h
>>>>>>> +++ b/drivers/usb/chipidea/bits.h
>>>>>>> @@ -48,6 +48,9 @@
>>>>>>>  #define PORTSC_SUSP           BIT(7)
>>>>>>>  #define PORTSC_HSP            BIT(9)
>>>>>>>  #define PORTSC_PTC            (0x0FUL << 16)
>>>>>>> +#define PORTSC_PTS            (BIT(31) | BIT(30))
>>>>>>> +#define PORTSC_PTW            BIT(28)
>>>>>>> +#define PORTSC_STS            BIT(29)
>>>>>> Hm, my spec says these are actually in DEVLC register and only have this
>>>>>> meaning in device mode. And in portsc these bits fall in device address
>>>>>> bitfield. Can you refer me to your spec?
>>>>> You can find it here:
>>>>> http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
>>>>> Page 4947
>>>> Oh, but see, the offset is 0x184, which in chipidea spec (the version
>>>> that I have) corresponds to DEVLC and not PORTSC. So in this driver's
>>>> terminology it's DEVLC too, at least currently.
>>>>
>>>> So have you tested this code and did it make any difference?
>>> Yes, i have tested this code with MX25, MX28, MX35 and MX53. In every
>>> SoCs Datasheet the PORTSC register is defined on PORTBASE+0x184. Without
>>> this proper configuration its not possible to communicate with the PHY.
>> 
>> No, I mean, you're writing DEVLC (using present driver's terminology)
>> bits to PORTSC register. It *shouldn't* work. I suppose, it does
>> something, but not exactly what you intended.
>> 
> I confirm in our datasheet we have PTW, PTS, STS in this register  PORTSCx with
> this mapping.
>
> In later design that support lpm, these bits have to move in another register
> because ehci 1.1 use them [1].

Ahh, I didn't realize imxes were nolpm. Now it makes more sense. This
means that, as you suggested in the other mail, these portsc/devlc
accesses should be done conditionally based on ci->hw_bank.lpm.

Regards,
--
Alex
Michael Grzeschik Nov. 21, 2012, 3:57 p.m. UTC | #9
On Fri, Nov 16, 2012 at 05:39:42PM +0200, Alexander Shishkin wrote:
> Matthieu CASTET <matthieu.castet@parrot.com> writes:
> 
> > Alexander Shishkin a écrit :
> >> Michael Grzeschik <mgr@pengutronix.de> writes:
> >> 
> >>> On Fri, Nov 16, 2012 at 03:34:23PM +0200, Alexander Shishkin wrote:
> >>>> Michael Grzeschik <mgr@pengutronix.de> writes:
> >>>>
> >>>>> On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
> >>>>>> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
> >>>>>>
> >>>>>>> This patch makes it possible to configure the PTW and PTS bits inside
> >>>>>>> the portsc register for host and device mode before the driver starts
> >>>>>>> and the phy can be addressed as hardware implementation is designed.
> >>>>>>>
> >>>>>>> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> >>>>>>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> >>>>>>> ---
> >>>>>>>  drivers/usb/chipidea/bits.h        |    3 +++
> >>>>>>>  drivers/usb/chipidea/ci.h          |    2 ++
> >>>>>>>  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
> >>>>>>>  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
> >>>>>>>  drivers/usb/chipidea/host.c        |    4 +++
> >>>>>>>  include/linux/usb/chipidea.h       |    9 +++++++
> >>>>>>>  6 files changed, 66 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
> >>>>>>> index 4b6ae3e..3cded5f 100644
> >>>>>>> --- a/drivers/usb/chipidea/bits.h
> >>>>>>> +++ b/drivers/usb/chipidea/bits.h
> >>>>>>> @@ -48,6 +48,9 @@
> >>>>>>>  #define PORTSC_SUSP           BIT(7)
> >>>>>>>  #define PORTSC_HSP            BIT(9)
> >>>>>>>  #define PORTSC_PTC            (0x0FUL << 16)
> >>>>>>> +#define PORTSC_PTS            (BIT(31) | BIT(30))
> >>>>>>> +#define PORTSC_PTW            BIT(28)
> >>>>>>> +#define PORTSC_STS            BIT(29)
> >>>>>> Hm, my spec says these are actually in DEVLC register and only have this
> >>>>>> meaning in device mode. And in portsc these bits fall in device address
> >>>>>> bitfield. Can you refer me to your spec?
> >>>>> You can find it here:
> >>>>> http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
> >>>>> Page 4947
> >>>> Oh, but see, the offset is 0x184, which in chipidea spec (the version
> >>>> that I have) corresponds to DEVLC and not PORTSC. So in this driver's
> >>>> terminology it's DEVLC too, at least currently.
> >>>>
> >>>> So have you tested this code and did it make any difference?
> >>> Yes, i have tested this code with MX25, MX28, MX35 and MX53. In every
> >>> SoCs Datasheet the PORTSC register is defined on PORTBASE+0x184. Without
> >>> this proper configuration its not possible to communicate with the PHY.
> >> 
> >> No, I mean, you're writing DEVLC (using present driver's terminology)
> >> bits to PORTSC register. It *shouldn't* work. I suppose, it does
> >> something, but not exactly what you intended.
> >> 
> > I confirm in our datasheet we have PTW, PTS, STS in this register  PORTSCx with
> > this mapping.
> >
> > In later design that support lpm, these bits have to move in another register
> > because ehci 1.1 use them [1].
> 
> Ahh, I didn't realize imxes were nolpm. Now it makes more sense. This
> means that, as you suggested in the other mail, these portsc/devlc
> accesses should be done conditionally based on ci->hw_bank.lpm.

To handle lpm devices in this patch, we need some register layout of the
lpm core. Probably only te DEVLC register. Is there some documentation
available?

Regards,
Michael
Matthieu CASTET Nov. 21, 2012, 4:06 p.m. UTC | #10
Michael Grzeschik a écrit :
> On Fri, Nov 16, 2012 at 05:39:42PM +0200, Alexander Shishkin wrote:
>> Matthieu CASTET <matthieu.castet@parrot.com> writes:
>>
>>> Alexander Shishkin a écrit :
>>>> Michael Grzeschik <mgr@pengutronix.de> writes:
>>>>
>>>>> On Fri, Nov 16, 2012 at 03:34:23PM +0200, Alexander Shishkin wrote:
>>>>>> Michael Grzeschik <mgr@pengutronix.de> writes:
>>>>>>
>>>>>>> On Fri, Nov 16, 2012 at 02:45:39PM +0200, Alexander Shishkin wrote:
>>>>>>>> Michael Grzeschik <m.grzeschik@pengutronix.de> writes:
>>>>>>>>
>>>>>>>>> This patch makes it possible to configure the PTW and PTS bits inside
>>>>>>>>> the portsc register for host and device mode before the driver starts
>>>>>>>>> and the phy can be addressed as hardware implementation is designed.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>>>>>>>>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>>>>>>>>> ---
>>>>>>>>>  drivers/usb/chipidea/bits.h        |    3 +++
>>>>>>>>>  drivers/usb/chipidea/ci.h          |    2 ++
>>>>>>>>>  drivers/usb/chipidea/ci13xxx_imx.c |    1 +
>>>>>>>>>  drivers/usb/chipidea/core.c        |   47 ++++++++++++++++++++++++++++++++++++
>>>>>>>>>  drivers/usb/chipidea/host.c        |    4 +++
>>>>>>>>>  include/linux/usb/chipidea.h       |    9 +++++++
>>>>>>>>>  6 files changed, 66 insertions(+)
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
>>>>>>>>> index 4b6ae3e..3cded5f 100644
>>>>>>>>> --- a/drivers/usb/chipidea/bits.h
>>>>>>>>> +++ b/drivers/usb/chipidea/bits.h
>>>>>>>>> @@ -48,6 +48,9 @@
>>>>>>>>>  #define PORTSC_SUSP           BIT(7)
>>>>>>>>>  #define PORTSC_HSP            BIT(9)
>>>>>>>>>  #define PORTSC_PTC            (0x0FUL << 16)
>>>>>>>>> +#define PORTSC_PTS            (BIT(31) | BIT(30))
>>>>>>>>> +#define PORTSC_PTW            BIT(28)
>>>>>>>>> +#define PORTSC_STS            BIT(29)
>>>>>>>> Hm, my spec says these are actually in DEVLC register and only have this
>>>>>>>> meaning in device mode. And in portsc these bits fall in device address
>>>>>>>> bitfield. Can you refer me to your spec?
>>>>>>> You can find it here:
>>>>>>> http://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf?fpsp=1
>>>>>>> Page 4947
>>>>>> Oh, but see, the offset is 0x184, which in chipidea spec (the version
>>>>>> that I have) corresponds to DEVLC and not PORTSC. So in this driver's
>>>>>> terminology it's DEVLC too, at least currently.
>>>>>>
>>>>>> So have you tested this code and did it make any difference?
>>>>> Yes, i have tested this code with MX25, MX28, MX35 and MX53. In every
>>>>> SoCs Datasheet the PORTSC register is defined on PORTBASE+0x184. Without
>>>>> this proper configuration its not possible to communicate with the PHY.
>>>> No, I mean, you're writing DEVLC (using present driver's terminology)
>>>> bits to PORTSC register. It *shouldn't* work. I suppose, it does
>>>> something, but not exactly what you intended.
>>>>
>>> I confirm in our datasheet we have PTW, PTS, STS in this register  PORTSCx with
>>> this mapping.
>>>
>>> In later design that support lpm, these bits have to move in another register
>>> because ehci 1.1 use them [1].
>> Ahh, I didn't realize imxes were nolpm. Now it makes more sense. This
>> means that, as you suggested in the other mail, these portsc/devlc
>> accesses should be done conditionally based on ci->hw_bank.lpm.
> 
> To handle lpm devices in this patch, we need some register layout of the
> lpm core. Probably only te DEVLC register. Is there some documentation
> available?

In include/linux/usb/langwell_udc.h before it was removed, you could find the
mapping :

    u32 devlc;      /* control LPM and each USB port behavior */
/* bits 31:29, parallel transceiver select */
#define LPM_PTS(d)  (((d)>>29)&7)
#define LPM_STS     BIT(28) /* serial transceiver select */
#define LPM_PTW     BIT(27) /* parallel transceiver width */
#define LPM_PSPD(d) (((d)>>25)&3)   /* bits 26:25, port speed */
#define LPM_PSPD_MASK   (BIT(26) | BIT(25))
#define LPM_SPEED_FULL  0
#define LPM_SPEED_LOW   1
#define LPM_SPEED_HIGH  2
#define LPM_SRT     BIT(24) /* shorten reset time */
#define LPM_PFSC    BIT(23) /* port force full speed connect */
#define LPM_PHCD    BIT(22) /* PHY low power suspend clock disable */
#define LPM_STL     BIT(16) /* STALL reply to LPM token */
#define LPM_BA(d)   \
    (((d)>>1)&0x7ff)    /* bits 11:1, BmAttributes */
#define LPM_NYT_ACK BIT(0)  /* NYET/ACK reply to LPM token */
Peter Chen Nov. 27, 2012, 1:12 a.m. UTC | #11
On Wed, Nov 14, 2012 at 05:19:07PM +0100, Michael Grzeschik wrote:
>  /**
>   * hw_device_reset: resets chip (execute without interruption)
>   * @ci: the controller
> @@ -237,6 +256,8 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
>  	if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
>  		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
>  
> +	hw_portsc_configure(ci);
> +
>  	/* USBMODE should be configured step by step */
>  	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
>  	hw_write(ci, OP_USBMODE, USBMODE_CM, mode);
> @@ -522,6 +543,32 @@ void ci13xxx_remove_device(struct platform_device *pdev)
>  }
>  EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
>  
> +void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata)
> +{
> +	int interface = of_get_usbphy_mode(of_node);
> +
> +	switch (interface) {
> +	case USBPHY_INTERFACE_MODE_UTMI:
> +		pdata->flags |= CI13XXX_PORTSC_PTS_UTMI;
> +		break;
> +	case USBPHY_INTERFACE_MODE_UTMIW:
> +		pdata->flags |= CI13XXX_PORTSC_PTS_UTMI |
> +			CI13XXX_PORTSC_PTW_16BIT;
> +		break;
> +	case USBPHY_INTERFACE_MODE_ULPI:
> +		pdata->flags |= CI13XXX_PORTSC_PTS_ULPI;
> +		break;
> +	case USBPHY_INTERFACE_MODE_SERIAL:
> +		pdata->flags |= CI13XXX_PORTSC_PTS_FSLS;
> +		break;
> +	case USBPHY_INTERFACE_MODE_NA:
> +	default:
> +		pr_err("no phy interface defined\n");
> +	}
> +
> +}
> +EXPORT_SYMBOL_GPL(ci13xxx_get_dr_flags);
> +
>  void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata)
>  {
>  	const unsigned char *dr_mode;
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index ebff9f4..b23ee1d 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -106,6 +106,10 @@ static int host_start(struct ci13xxx *ci)
>  	if (usb_disabled())
>  		return -ENODEV;
>  
> +	hw_portsc_configure(ci);
> +
> +	mdelay(10);
is usleep_range ok?
Why host needs 10ms delay, but peripheral mode doesn't?

> +
>  	hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev));
>  	if (!hcd)
>  		return -ENOMEM;
> diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
> index 906d259..cafca23 100644
> --- a/include/linux/usb/chipidea.h
> +++ b/include/linux/usb/chipidea.h
> @@ -21,6 +21,12 @@ struct ci13xxx_platform_data {
>  #define CI13XXX_DISABLE_STREAMING	BIT(3)
>  #define CI13XXX_DR_MODE_HOST		BIT(4)
>  #define CI13XXX_DR_MODE_PERIPHERAL	BIT(5)
> +#define CI13XXX_PORTSC_PTW_8BIT		BIT(6)
> +#define CI13XXX_PORTSC_PTW_16BIT	BIT(7)
> +#define CI13XXX_PORTSC_PTS_UTMI		BIT(8)
> +#define CI13XXX_PORTSC_PTS_ULPI		BIT(9)
> +#define CI13XXX_PORTSC_PTS_FSLS		BIT(10)
> +
>  #define CI13XXX_DR_MODE_MASK \
>  	(CI13XXX_DR_MODE_HOST | CI13XXX_DR_MODE_PERIPHERAL)
>  
> @@ -42,4 +48,7 @@ void ci13xxx_remove_device(struct platform_device *pdev);
>  /* Parse of-tree "dr_mode" property */
>  void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
>  
> +/* Parse of-tree "flags" */
> +void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
> +
>  #endif
> -- 
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
Michael Grzeschik Nov. 27, 2012, 9:54 a.m. UTC | #12
On Tue, Nov 27, 2012 at 09:12:30AM +0800, Peter Chen wrote:
> On Wed, Nov 14, 2012 at 05:19:07PM +0100, Michael Grzeschik wrote:
> >  /**
> >   * hw_device_reset: resets chip (execute without interruption)
> >   * @ci: the controller
> > @@ -237,6 +256,8 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
> >  	if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
> >  		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
> >  
> > +	hw_portsc_configure(ci);
> > +

This can be dropped.

> >  	/* USBMODE should be configured step by step */
> >  	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
> >  	hw_write(ci, OP_USBMODE, USBMODE_CM, mode);
> > @@ -522,6 +543,32 @@ void ci13xxx_remove_device(struct platform_device *pdev)
> >  }
> >  EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
> >  
> > +void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata)
> > +{
> > +	int interface = of_get_usbphy_mode(of_node);
> > +
> > +	switch (interface) {
> > +	case USBPHY_INTERFACE_MODE_UTMI:
> > +		pdata->flags |= CI13XXX_PORTSC_PTS_UTMI;
> > +		break;
> > +	case USBPHY_INTERFACE_MODE_UTMIW:
> > +		pdata->flags |= CI13XXX_PORTSC_PTS_UTMI |
> > +			CI13XXX_PORTSC_PTW_16BIT;
> > +		break;
> > +	case USBPHY_INTERFACE_MODE_ULPI:
> > +		pdata->flags |= CI13XXX_PORTSC_PTS_ULPI;
> > +		break;
> > +	case USBPHY_INTERFACE_MODE_SERIAL:
> > +		pdata->flags |= CI13XXX_PORTSC_PTS_FSLS;
> > +		break;
> > +	case USBPHY_INTERFACE_MODE_NA:
> > +	default:
> > +		pr_err("no phy interface defined\n");
> > +	}
> > +
> > +}
> > +EXPORT_SYMBOL_GPL(ci13xxx_get_dr_flags);
> > +
> >  void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata)
> >  {
> >  	const unsigned char *dr_mode;
> > diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> > index ebff9f4..b23ee1d 100644
> > --- a/drivers/usb/chipidea/host.c
> > +++ b/drivers/usb/chipidea/host.c
> > @@ -106,6 +106,10 @@ static int host_start(struct ci13xxx *ci)
> >  	if (usb_disabled())
> >  		return -ENODEV;
> >  
> > +	hw_portsc_configure(ci);
> > +
> > +	mdelay(10);
> is usleep_range ok?

I will change that.

> Why host needs 10ms delay, but peripheral mode doesn't?

I didn't figure out why this is needed. However, we prefer to move this
hunk to be in ci_hdrc_probe just before ci_role_start gets called. So
hw_portsc_configure will be called only there in the beginning. As the
phy setup doesn't change, we need no further call and can take the delay
unconditionally of the role.

> > +
> >  	hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev));
> >  	if (!hcd)
> >  		return -ENOMEM;
> > diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
> > index 906d259..cafca23 100644
> > --- a/include/linux/usb/chipidea.h
> > +++ b/include/linux/usb/chipidea.h
> > @@ -21,6 +21,12 @@ struct ci13xxx_platform_data {
> >  #define CI13XXX_DISABLE_STREAMING	BIT(3)
> >  #define CI13XXX_DR_MODE_HOST		BIT(4)
> >  #define CI13XXX_DR_MODE_PERIPHERAL	BIT(5)
> > +#define CI13XXX_PORTSC_PTW_8BIT		BIT(6)
> > +#define CI13XXX_PORTSC_PTW_16BIT	BIT(7)
> > +#define CI13XXX_PORTSC_PTS_UTMI		BIT(8)
> > +#define CI13XXX_PORTSC_PTS_ULPI		BIT(9)
> > +#define CI13XXX_PORTSC_PTS_FSLS		BIT(10)
> > +
> >  #define CI13XXX_DR_MODE_MASK \
> >  	(CI13XXX_DR_MODE_HOST | CI13XXX_DR_MODE_PERIPHERAL)
> >  
> > @@ -42,4 +48,7 @@ void ci13xxx_remove_device(struct platform_device *pdev);
> >  /* Parse of-tree "dr_mode" property */
> >  void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
> >  
> > +/* Parse of-tree "flags" */
> > +void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
> > +
> >  #endif
> > -- 
> > 1.7.10.4
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
Peter Chen Nov. 28, 2012, 1:26 a.m. UTC | #13
On Tue, Nov 27, 2012 at 10:54:32AM +0100, Michael Grzeschik wrote:
> 
> I didn't figure out why this is needed. However, we prefer to move this
> hunk to be in ci_hdrc_probe just before ci_role_start gets called. So
> hw_portsc_configure will be called only there in the beginning. As the
> phy setup doesn't change, we need no further call and can take the delay
> unconditionally of the role.

I agree, as configure phy is common future, it is ok at ci_hdrc_probe.
Below initialization sequence is ok:

configure_phy
delay for phy stable
role_start(init)

> 
> > > +
> > >  	hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev));
> > >  	if (!hcd)
> > >  		return -ENOMEM;
> > > diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
> > > index 906d259..cafca23 100644
> > > --- a/include/linux/usb/chipidea.h
> > > +++ b/include/linux/usb/chipidea.h
> > > @@ -21,6 +21,12 @@ struct ci13xxx_platform_data {
> > >  #define CI13XXX_DISABLE_STREAMING	BIT(3)
> > >  #define CI13XXX_DR_MODE_HOST		BIT(4)
> > >  #define CI13XXX_DR_MODE_PERIPHERAL	BIT(5)
> > > +#define CI13XXX_PORTSC_PTW_8BIT		BIT(6)
> > > +#define CI13XXX_PORTSC_PTW_16BIT	BIT(7)
> > > +#define CI13XXX_PORTSC_PTS_UTMI		BIT(8)
> > > +#define CI13XXX_PORTSC_PTS_ULPI		BIT(9)
> > > +#define CI13XXX_PORTSC_PTS_FSLS		BIT(10)
> > > +
> > >  #define CI13XXX_DR_MODE_MASK \
> > >  	(CI13XXX_DR_MODE_HOST | CI13XXX_DR_MODE_PERIPHERAL)
> > >  
> > > @@ -42,4 +48,7 @@ void ci13xxx_remove_device(struct platform_device *pdev);
> > >  /* Parse of-tree "dr_mode" property */
> > >  void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
> > >  
> > > +/* Parse of-tree "flags" */
> > > +void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
> > > +
> > >  #endif
> > > -- 
> > > 1.7.10.4
> > > 
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>
diff mbox

Patch

diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 4b6ae3e..3cded5f 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -48,6 +48,9 @@ 
 #define PORTSC_SUSP           BIT(7)
 #define PORTSC_HSP            BIT(9)
 #define PORTSC_PTC            (0x0FUL << 16)
+#define PORTSC_PTS            (BIT(31) | BIT(30))
+#define PORTSC_PTW            BIT(28)
+#define PORTSC_STS            BIT(29)
 
 /* DEVLC */
 #define DEVLC_PSPD            (0x03UL << 25)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index cd42b59..1439e51 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -314,6 +314,8 @@  static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
 	return (val & mask) >> ffs_nr(mask);
 }
 
+void hw_portsc_configure(struct ci13xxx *ci);
+
 int hw_device_reset(struct ci13xxx *ci, u32 mode);
 
 int hw_port_test_set(struct ci13xxx *ci, u8 mode);
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index ee4dab0..a8257b8 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -133,6 +133,7 @@  static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
 		       CI13XXX_PULLUP_ON_VBUS |
 		       CI13XXX_DISABLE_STREAMING |
 		       CI13XXX_REGS_SHARED,
+	ci13xxx_get_dr_flags(pdev->dev.of_node, pdata);
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data) {
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 3e3e159..7e80f1b 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -68,6 +68,8 @@ 
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/chipidea.h>
+#include <linux/of_usbphy.h>
+#include <linux/phy.h>
 
 #include "ci.h"
 #include "udc.h"
@@ -213,6 +215,23 @@  static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
 	return 0;
 }
 
+void hw_portsc_configure(struct ci13xxx *ci)
+{
+	if (ci->platdata->flags & CI13XXX_PORTSC_PTW_16BIT)
+		hw_write(ci, OP_PORTSC, PORTSC_PTW, 0x1 << ffs_nr(PORTSC_PTW));
+
+	if (ci->platdata->flags & CI13XXX_PORTSC_PTS_UTMI) {
+		hw_write(ci, OP_PORTSC, PORTSC_PTS, 0x0 << ffs_nr(PORTSC_PTS));
+		hw_write(ci, OP_PORTSC, PORTSC_STS, 0x0 << ffs_nr(PORTSC_STS));
+	} else if (ci->platdata->flags & CI13XXX_PORTSC_PTS_ULPI) {
+		hw_write(ci, OP_PORTSC, PORTSC_PTS, 0x2 << ffs_nr(PORTSC_PTS));
+		hw_write(ci, OP_PORTSC, PORTSC_STS, 0x0 << ffs_nr(PORTSC_STS));
+	} else if (ci->platdata->flags & CI13XXX_PORTSC_PTS_FSLS) {
+		hw_write(ci, OP_PORTSC, PORTSC_PTS, 0x3 << ffs_nr(PORTSC_PTS));
+		hw_write(ci, OP_PORTSC, PORTSC_STS, 0x1 << ffs_nr(PORTSC_STS));
+	}
+}
+
 /**
  * hw_device_reset: resets chip (execute without interruption)
  * @ci: the controller
@@ -237,6 +256,8 @@  int hw_device_reset(struct ci13xxx *ci, u32 mode)
 	if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
 		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
 
+	hw_portsc_configure(ci);
+
 	/* USBMODE should be configured step by step */
 	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
 	hw_write(ci, OP_USBMODE, USBMODE_CM, mode);
@@ -522,6 +543,32 @@  void ci13xxx_remove_device(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
 
+void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata)
+{
+	int interface = of_get_usbphy_mode(of_node);
+
+	switch (interface) {
+	case USBPHY_INTERFACE_MODE_UTMI:
+		pdata->flags |= CI13XXX_PORTSC_PTS_UTMI;
+		break;
+	case USBPHY_INTERFACE_MODE_UTMIW:
+		pdata->flags |= CI13XXX_PORTSC_PTS_UTMI |
+			CI13XXX_PORTSC_PTW_16BIT;
+		break;
+	case USBPHY_INTERFACE_MODE_ULPI:
+		pdata->flags |= CI13XXX_PORTSC_PTS_ULPI;
+		break;
+	case USBPHY_INTERFACE_MODE_SERIAL:
+		pdata->flags |= CI13XXX_PORTSC_PTS_FSLS;
+		break;
+	case USBPHY_INTERFACE_MODE_NA:
+	default:
+		pr_err("no phy interface defined\n");
+	}
+
+}
+EXPORT_SYMBOL_GPL(ci13xxx_get_dr_flags);
+
 void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata)
 {
 	const unsigned char *dr_mode;
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index ebff9f4..b23ee1d 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -106,6 +106,10 @@  static int host_start(struct ci13xxx *ci)
 	if (usb_disabled())
 		return -ENODEV;
 
+	hw_portsc_configure(ci);
+
+	mdelay(10);
+
 	hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev));
 	if (!hcd)
 		return -ENOMEM;
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index 906d259..cafca23 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -21,6 +21,12 @@  struct ci13xxx_platform_data {
 #define CI13XXX_DISABLE_STREAMING	BIT(3)
 #define CI13XXX_DR_MODE_HOST		BIT(4)
 #define CI13XXX_DR_MODE_PERIPHERAL	BIT(5)
+#define CI13XXX_PORTSC_PTW_8BIT		BIT(6)
+#define CI13XXX_PORTSC_PTW_16BIT	BIT(7)
+#define CI13XXX_PORTSC_PTS_UTMI		BIT(8)
+#define CI13XXX_PORTSC_PTS_ULPI		BIT(9)
+#define CI13XXX_PORTSC_PTS_FSLS		BIT(10)
+
 #define CI13XXX_DR_MODE_MASK \
 	(CI13XXX_DR_MODE_HOST | CI13XXX_DR_MODE_PERIPHERAL)
 
@@ -42,4 +48,7 @@  void ci13xxx_remove_device(struct platform_device *pdev);
 /* Parse of-tree "dr_mode" property */
 void ci13xxx_get_dr_mode(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
 
+/* Parse of-tree "flags" */
+void ci13xxx_get_dr_flags(struct device_node *of_node, struct ci13xxx_platform_data *pdata);
+
 #endif