Re: dwc2 (on Meson8b) doesn't detect "hot-plugged" USB devices

2018-07-04 Thread Martin Blumenstingl
On Wed, Jul 4, 2018 at 4:16 PM Martin Blumenstingl
 wrote:
[...]
> unfortunately it seems that plugging in seems to fill the kmsg buffer
> instantly, so I cannot (at least I don't know how - do you have any
> idea how to get around this?) get the information from the second
> where I'm plugging in the thumb drive
> I attached everything I have
I forgot to mention: I switched boards this time - my previous logs
were from a Meson8m2 board
to rule out that the board itself is faulty I switched to an Odroid-C1
(Meson8b) this time -> there's a 4-port USB hub hard-wired on the
Odroid-C1 which you can see in the kernel logs (just in case you are
wondering)
--
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: dwc2 (on Meson8b) doesn't detect "hot-plugged" USB devices

2018-07-04 Thread Martin Blumenstingl
Hello Arthur, Hello Minas,

On Wed, Jul 4, 2018 at 1:43 PM Artur Petrosyan
 wrote:
>
> Hello Martin,
>
> On 7/4/2018 01:39, Martin Blumenstingl wrote:
> > Hello Minas,
> >
> > On Thu, May 10, 2018 at 11:44 AM Martin Blumenstingl
> >  wrote:
> >>
> >> Hello Minas,
> >>
> >> On Mon, May 7, 2018 at 3:27 PM, Minas Harutyunyan
> >>  wrote:
> >>> Hi Martin,
> >>>
> >>> On 5/7/2018 12:28 AM, Martin Blumenstingl wrote:
> >>>> Hello,
> >>>>
> >>>> I was a bit surprised to see that hot-plugging USB devices on Amlogic
> >>>> Meson8b (for example: Odroid-C1) is broken.
> >>>> to be fair: I *think* it worked before, but I cannot guarantee it nor
> >>>> can I say when it broke
> >>>>
> >>>> all examples below are from an Odroid-C1 board with Amlogic Meson8b 
> >>>> (S805) SoC.
> >>>> this connects a (fixed, soldered down) 4-port USB hub to the dwc2
> >>>> controller (which is in "host" mode)
> >>>>
> >>>> during boot I see:
> >>>> [1.651687] dwc2 c90c.usb: c90c.usb supply vusb_d not
> >>>> found, using dummy regulator
> >>>> [1.654434] dwc2 c90c.usb: c90c.usb supply vusb_a not
> >>>> found, using dummy regulator
> >>>> [1.732374] dwc2 c90c.usb: dwc2_check_params: Invalid parameter 
> >>>> lpm=1
> >>>> [1.733526] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
> >>>> lpm_clock_gating=1
> >>>> [1.741427] dwc2 c90c.usb: dwc2_check_params: Invalid parameter 
> >>>> besl=1
> >>>> [1.748305] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
> >>>> hird_threshold_en=1
> >>>> [1.756491] dwc2 c90c.usb: DWC OTG Controller
> >>>> [1.760993] dwc2 c90c.usb: new USB bus registered, assigned bus 
> >>>> number 1
> >>>> [1.768046] dwc2 c90c.usb: irq 24, io mem 0xc90c
> >>>> [1.773947] hub 1-0:1.0: USB hub found
> >>>> [1.777063] hub 1-0:1.0: 1 port detected
> >>>> ...
> >>>> [2.212432] usb 1-1: new high-speed USB device number 2 using dwc2
> >>>> [2.464742] hub 1-1:1.0: USB hub found
> >>>> [2.465118] hub 1-1:1.0: 4 ports detected
> >>>>
> >>>> if a USB device is plugged into one of the four USB ports during boot
> >>>> then it is detected automatically.
> >>>> if I plug in devices later they are not detected automatically (I have
> >>>> to run "lsusb -v" due to some reason, then hot-plugged devices are
> >>>> being detected)
> >>>> un-plugging USB devices is recognized instantly (no "lsusb" trickery
> >>>> is required)
> >>>>
> >>>> is this a known issue? how can I help debugging?
> >>>> any help is appreciated!
> >>>>
> >>>> below is the output of all dwc2 debugfs files.
> >>>>
> >>>>
> >>>> Regards
> >>>> Martin
> >>>>
> >>>>
> >>>> [rootodroidc1 c90c.usb]# cat dr_mode
> >>>> host
> >>>> [rootodroidc1 c90c.usb]# cat fifo
> >>>> Non-periodic FIFOs:
> >>>> RXFIFO: Size 0
> >>>> NPTXFIFO: Size 0, Start 0x
> >>>>
> >>>> Periodic TXFIFOs:
> >>>> [rootodroidc1 c90c.usb]# cat hw_params
> >>>> op_mode   : 5
> >>>> arch  : 2
> >>>> dma_desc_enable   : 1
> >>>> enable_dynamic_fifo   : 1
> >>>> en_multiple_tx_fifo   : 0
> >>>> rx_fifo_size  : 2048
> >>>> host_nperio_tx_fifo_size  : 2048
> >>>> dev_nperio_tx_fifo_size   : 0
> >>>> host_perio_tx_fifo_size   : 2048
> >>>> nperio_tx_q_depth : 4
> >>>> host_perio_tx_q_depth : 4
> >>>> dev_token_q_depth : 8
> >>>> max_transfer_size : 524287
> >>>> max_packet_count  : 1023
> >>>> host_channels : 16
> >>>> hs_phy_type   : 1
> >>>> fs_phy_type   : 0
&g

Re: dwc2 (on Meson8b) doesn't detect "hot-plugged" USB devices

2018-07-03 Thread Martin Blumenstingl
Hello Minas,

On Thu, May 10, 2018 at 11:44 AM Martin Blumenstingl
 wrote:
>
> Hello Minas,
>
> On Mon, May 7, 2018 at 3:27 PM, Minas Harutyunyan
>  wrote:
> > Hi Martin,
> >
> > On 5/7/2018 12:28 AM, Martin Blumenstingl wrote:
> >> Hello,
> >>
> >> I was a bit surprised to see that hot-plugging USB devices on Amlogic
> >> Meson8b (for example: Odroid-C1) is broken.
> >> to be fair: I *think* it worked before, but I cannot guarantee it nor
> >> can I say when it broke
> >>
> >> all examples below are from an Odroid-C1 board with Amlogic Meson8b (S805) 
> >> SoC.
> >> this connects a (fixed, soldered down) 4-port USB hub to the dwc2
> >> controller (which is in "host" mode)
> >>
> >> during boot I see:
> >> [1.651687] dwc2 c90c.usb: c90c.usb supply vusb_d not
> >> found, using dummy regulator
> >> [1.654434] dwc2 c90c.usb: c90c.usb supply vusb_a not
> >> found, using dummy regulator
> >> [1.732374] dwc2 c90c.usb: dwc2_check_params: Invalid parameter 
> >> lpm=1
> >> [1.733526] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
> >> lpm_clock_gating=1
> >> [1.741427] dwc2 c90c.usb: dwc2_check_params: Invalid parameter 
> >> besl=1
> >> [1.748305] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
> >> hird_threshold_en=1
> >> [1.756491] dwc2 c90c.usb: DWC OTG Controller
> >> [1.760993] dwc2 c90c.usb: new USB bus registered, assigned bus 
> >> number 1
> >> [1.768046] dwc2 c90c.usb: irq 24, io mem 0xc90c
> >> [1.773947] hub 1-0:1.0: USB hub found
> >> [1.777063] hub 1-0:1.0: 1 port detected
> >> ...
> >> [2.212432] usb 1-1: new high-speed USB device number 2 using dwc2
> >> [2.464742] hub 1-1:1.0: USB hub found
> >> [2.465118] hub 1-1:1.0: 4 ports detected
> >>
> >> if a USB device is plugged into one of the four USB ports during boot
> >> then it is detected automatically.
> >> if I plug in devices later they are not detected automatically (I have
> >> to run "lsusb -v" due to some reason, then hot-plugged devices are
> >> being detected)
> >> un-plugging USB devices is recognized instantly (no "lsusb" trickery
> >> is required)
> >>
> >> is this a known issue? how can I help debugging?
> >> any help is appreciated!
> >>
> >> below is the output of all dwc2 debugfs files.
> >>
> >>
> >> Regards
> >> Martin
> >>
> >>
> >> [rootodroidc1 c90c.usb]# cat dr_mode
> >> host
> >> [rootodroidc1 c90c.usb]# cat fifo
> >> Non-periodic FIFOs:
> >> RXFIFO: Size 0
> >> NPTXFIFO: Size 0, Start 0x
> >>
> >> Periodic TXFIFOs:
> >> [rootodroidc1 c90c.usb]# cat hw_params
> >> op_mode   : 5
> >> arch  : 2
> >> dma_desc_enable   : 1
> >> enable_dynamic_fifo   : 1
> >> en_multiple_tx_fifo   : 0
> >> rx_fifo_size  : 2048
> >> host_nperio_tx_fifo_size  : 2048
> >> dev_nperio_tx_fifo_size   : 0
> >> host_perio_tx_fifo_size   : 2048
> >> nperio_tx_q_depth : 4
> >> host_perio_tx_q_depth : 4
> >> dev_token_q_depth : 8
> >> max_transfer_size : 524287
> >> max_packet_count  : 1023
> >> host_channels : 16
> >> hs_phy_type   : 1
> >> fs_phy_type   : 0
> >> i2c_enable: 0
> >> num_dev_ep: 2
> >> num_dev_perio_in_ep   : 0
> >> total_fifo_size   : 1984
> >> power_optimized   : 1
> >> utmi_phy_data_width   : 1
> >> snpsid: 0x4f54310a
> >> dev_ep_dirs   : 0x0
> >> [rootodroidc1 c90c.usb]# cat params
> >> otg_cap   : 2
> >> dma_desc_enable   : 0
> >> dma_desc_fs_enable: 0
> >> speed : 0
> >> enable_dynamic_fifo   : 1
> >> en_multiple_tx_fifo   : 0
> >> host_rx_fifo_size : 512
> >> host_nperio_tx_fifo_size  : 500
> >> host_perio_tx_fifo_size   : 500
> >> max_

Re: [PATCH 1/1] usb: chipidea: host: fix disconnection detect issue

2018-06-06 Thread Martin Blumenstingl
Hi Peter, Hi Mats,

On Wed, Jun 6, 2018 at 4:04 AM, Peter Chen  wrote:
> The commit 4e88d4c08301 ("usb: add a flag to skip PHY
> initialization to struct usb_hcd") delete the assignment
> for hcd->usb_phy, it causes usb_phy_notify_connect{disconnect)
> are not called, the USB PHY driver is not notified of hot plug
> event, then the disconnection will not be detected by hardware.
ouch, I totally missed that
thank you for taking time for bisecting, debugging and fixing this!

> Fixes: 4e88d4c08301 ("usb: add a flag to skip PHY initialization
>     to struct usb_hcd")
> Cc: Martin Blumenstingl 
> Reported-by: Mats Karrman 
> Signed-off-by: Peter Chen 
Acked-by: Martin Blumenstingl 

> ---
>  drivers/usb/chipidea/host.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index af45aa3222b5..4638d9b066be 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -124,8 +124,11 @@ static int host_start(struct ci_hdrc *ci)
>
> hcd->power_budget = ci->platdata->power_budget;
> hcd->tpl_support = ci->platdata->tpl_support;
> -   if (ci->phy || ci->usb_phy)
> +   if (ci->phy || ci->usb_phy) {
> hcd->skip_phy_initialization = 1;
> +   if (ci->usb_phy)
> +   hcd->usb_phy = ci->usb_phy;
> +   }
>
> ehci = hcd_to_ehci(hcd);
> ehci->caps = ci->hw_bank.cap;
> --
> 2.14.1
>
--
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: dwc2 (on Meson8b) doesn't detect "hot-plugged" USB devices

2018-05-10 Thread Martin Blumenstingl
Hello Minas,

On Mon, May 7, 2018 at 3:27 PM, Minas Harutyunyan
<minas.harutyun...@synopsys.com> wrote:
> Hi Martin,
>
> On 5/7/2018 12:28 AM, Martin Blumenstingl wrote:
>> Hello,
>>
>> I was a bit surprised to see that hot-plugging USB devices on Amlogic
>> Meson8b (for example: Odroid-C1) is broken.
>> to be fair: I *think* it worked before, but I cannot guarantee it nor
>> can I say when it broke
>>
>> all examples below are from an Odroid-C1 board with Amlogic Meson8b (S805) 
>> SoC.
>> this connects a (fixed, soldered down) 4-port USB hub to the dwc2
>> controller (which is in "host" mode)
>>
>> during boot I see:
>> [1.651687] dwc2 c90c.usb: c90c.usb supply vusb_d not
>> found, using dummy regulator
>> [1.654434] dwc2 c90c.usb: c90c.usb supply vusb_a not
>> found, using dummy regulator
>> [1.732374] dwc2 c90c.usb: dwc2_check_params: Invalid parameter lpm=1
>> [1.733526] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
>> lpm_clock_gating=1
>> [1.741427] dwc2 c90c.usb: dwc2_check_params: Invalid parameter besl=1
>> [1.748305] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
>> hird_threshold_en=1
>> [1.756491] dwc2 c90c.usb: DWC OTG Controller
>> [1.760993] dwc2 c90c.usb: new USB bus registered, assigned bus 
>> number 1
>> [1.768046] dwc2 c90c.usb: irq 24, io mem 0xc90c
>> [1.773947] hub 1-0:1.0: USB hub found
>> [1.777063] hub 1-0:1.0: 1 port detected
>> ...
>> [2.212432] usb 1-1: new high-speed USB device number 2 using dwc2
>> [2.464742] hub 1-1:1.0: USB hub found
>> [2.465118] hub 1-1:1.0: 4 ports detected
>>
>> if a USB device is plugged into one of the four USB ports during boot
>> then it is detected automatically.
>> if I plug in devices later they are not detected automatically (I have
>> to run "lsusb -v" due to some reason, then hot-plugged devices are
>> being detected)
>> un-plugging USB devices is recognized instantly (no "lsusb" trickery
>> is required)
>>
>> is this a known issue? how can I help debugging?
>> any help is appreciated!
>>
>> below is the output of all dwc2 debugfs files.
>>
>>
>> Regards
>> Martin
>>
>>
>> [rootodroidc1 c90c.usb]# cat dr_mode
>> host
>> [rootodroidc1 c90c.usb]# cat fifo
>> Non-periodic FIFOs:
>> RXFIFO: Size 0
>> NPTXFIFO: Size 0, Start 0x
>>
>> Periodic TXFIFOs:
>> [rootodroidc1 c90c.usb]# cat hw_params
>> op_mode   : 5
>> arch  : 2
>> dma_desc_enable   : 1
>> enable_dynamic_fifo   : 1
>> en_multiple_tx_fifo   : 0
>> rx_fifo_size  : 2048
>> host_nperio_tx_fifo_size  : 2048
>> dev_nperio_tx_fifo_size   : 0
>> host_perio_tx_fifo_size   : 2048
>> nperio_tx_q_depth : 4
>> host_perio_tx_q_depth : 4
>> dev_token_q_depth : 8
>> max_transfer_size : 524287
>> max_packet_count  : 1023
>> host_channels : 16
>> hs_phy_type   : 1
>> fs_phy_type   : 0
>> i2c_enable: 0
>> num_dev_ep: 2
>> num_dev_perio_in_ep   : 0
>> total_fifo_size   : 1984
>> power_optimized   : 1
>> utmi_phy_data_width   : 1
>> snpsid: 0x4f54310a
>> dev_ep_dirs   : 0x0
>> [rootodroidc1 c90c.usb]# cat params
>> otg_cap   : 2
>> dma_desc_enable   : 0
>> dma_desc_fs_enable: 0
>> speed : 0
>> enable_dynamic_fifo   : 1
>> en_multiple_tx_fifo   : 0
>> host_rx_fifo_size : 512
>> host_nperio_tx_fifo_size  : 500
>> host_perio_tx_fifo_size   : 500
>> max_transfer_size : 524287
>> max_packet_count  : 1023
>> host_channels : 16
>> phy_type  : 1
>> phy_utmi_width: 16
>> phy_ulpi_ddr  : 0
>> phy_ulpi_ext_vbus : 0
>> i2c_enable: 0
>> ulpi_fs_ls: 0
>> host_support_fs_ls_low_power  : 0
>> host_ls_low_power_phy_clk : 0
>> ts_dline  : 0
>> reload_ctl: 1
>> ahbcfg  

dwc2 (on Meson8b) doesn't detect "hot-plugged" USB devices

2018-05-06 Thread Martin Blumenstingl
Hello,

I was a bit surprised to see that hot-plugging USB devices on Amlogic
Meson8b (for example: Odroid-C1) is broken.
to be fair: I *think* it worked before, but I cannot guarantee it nor
can I say when it broke

all examples below are from an Odroid-C1 board with Amlogic Meson8b (S805) SoC.
this connects a (fixed, soldered down) 4-port USB hub to the dwc2
controller (which is in "host" mode)

during boot I see:
[1.651687] dwc2 c90c.usb: c90c.usb supply vusb_d not
found, using dummy regulator
[1.654434] dwc2 c90c.usb: c90c.usb supply vusb_a not
found, using dummy regulator
[1.732374] dwc2 c90c.usb: dwc2_check_params: Invalid parameter lpm=1
[1.733526] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
lpm_clock_gating=1
[1.741427] dwc2 c90c.usb: dwc2_check_params: Invalid parameter besl=1
[1.748305] dwc2 c90c.usb: dwc2_check_params: Invalid parameter
hird_threshold_en=1
[1.756491] dwc2 c90c.usb: DWC OTG Controller
[1.760993] dwc2 c90c.usb: new USB bus registered, assigned bus number 1
[1.768046] dwc2 c90c.usb: irq 24, io mem 0xc90c
[1.773947] hub 1-0:1.0: USB hub found
[1.777063] hub 1-0:1.0: 1 port detected
...
[2.212432] usb 1-1: new high-speed USB device number 2 using dwc2
[2.464742] hub 1-1:1.0: USB hub found
[2.465118] hub 1-1:1.0: 4 ports detected

if a USB device is plugged into one of the four USB ports during boot
then it is detected automatically.
if I plug in devices later they are not detected automatically (I have
to run "lsusb -v" due to some reason, then hot-plugged devices are
being detected)
un-plugging USB devices is recognized instantly (no "lsusb" trickery
is required)

is this a known issue? how can I help debugging?
any help is appreciated!

below is the output of all dwc2 debugfs files.


Regards
Martin


[rootodroidc1 c90c.usb]# cat dr_mode
host
[rootodroidc1 c90c.usb]# cat fifo
Non-periodic FIFOs:
RXFIFO: Size 0
NPTXFIFO: Size 0, Start 0x

Periodic TXFIFOs:
[rootodroidc1 c90c.usb]# cat hw_params
op_mode   : 5
arch  : 2
dma_desc_enable   : 1
enable_dynamic_fifo   : 1
en_multiple_tx_fifo   : 0
rx_fifo_size  : 2048
host_nperio_tx_fifo_size  : 2048
dev_nperio_tx_fifo_size   : 0
host_perio_tx_fifo_size   : 2048
nperio_tx_q_depth : 4
host_perio_tx_q_depth : 4
dev_token_q_depth : 8
max_transfer_size : 524287
max_packet_count  : 1023
host_channels : 16
hs_phy_type   : 1
fs_phy_type   : 0
i2c_enable: 0
num_dev_ep: 2
num_dev_perio_in_ep   : 0
total_fifo_size   : 1984
power_optimized   : 1
utmi_phy_data_width   : 1
snpsid: 0x4f54310a
dev_ep_dirs   : 0x0
[rootodroidc1 c90c.usb]# cat params
otg_cap   : 2
dma_desc_enable   : 0
dma_desc_fs_enable: 0
speed : 0
enable_dynamic_fifo   : 1
en_multiple_tx_fifo   : 0
host_rx_fifo_size : 512
host_nperio_tx_fifo_size  : 500
host_perio_tx_fifo_size   : 500
max_transfer_size : 524287
max_packet_count  : 1023
host_channels : 16
phy_type  : 1
phy_utmi_width: 16
phy_ulpi_ddr  : 0
phy_ulpi_ext_vbus : 0
i2c_enable: 0
ulpi_fs_ls: 0
host_support_fs_ls_low_power  : 0
host_ls_low_power_phy_clk : 0
ts_dline  : 0
reload_ctl: 1
ahbcfg: 0xa
uframe_sched  : 0
external_id_pin_ctl   : 0
power_down: 1
lpm   : 0
lpm_clock_gating  : 0
besl  : 0
hird_threshold_en : 0
hird_threshold: 4
host_dma  : 1
g_dma : 0
g_dma_desc: 0
g_rx_fifo_size: 0
g_np_tx_fifo_size : 0
g_tx_fifo_size[0] : 0
g_tx_fifo_size[1] : 0
g_tx_fifo_size[2] : 0
g_tx_fifo_size[3] : 0
g_tx_fifo_size[4] : 0
g_tx_fifo_size[5] : 0
g_tx_fifo_size[6] : 0
g_tx_fifo_size[7] : 0
g_tx_fifo_size[8] : 0
g_tx_fifo_size[9] : 0
g_tx_fifo_size[10]: 0
g_tx_fifo_size[11]: 0
g_tx_fifo_size[12]: 0
g_tx_fifo_size[13]: 0
g_tx_fifo_size[14]: 0
g_tx_fifo_size[15]: 0
[rootodroidc1 c90c.usb]# cat state
DCFG=0x, DCTL=0x, DSTS=0x
DIEPMSK=0x, DOEPMASK=0x
GINTMSK=0xf000, GINTSTS=0x0001
DAINTMSK=0x, DAINT=0x

Re: [PATCH v2 2/2] usb: dwc3: support clocks and resets for DWC3 core

2018-04-28 Thread Martin Blumenstingl
(adding Yixun from Amlogic to this mail)

On Sat, Apr 28, 2018 at 4:41 AM, Masahiro Yamada
<yamada.masah...@socionext.com> wrote:
> Hi Martin,
>
>
> 2018-04-24 2:44 GMT+09:00 Martin Blumenstingl
> <martin.blumensti...@googlemail.com>:
>> Hello,
>>
>> On Thu, Apr 19, 2018 at 1:03 PM, Masahiro Yamada
>> <yamada.masah...@socionext.com> wrote:
>>> Historically, the clocks and resets are handled on the glue layer
>>> side instead of the DWC3 core.  For simple cases, dwc3-of-simple.c
>>> takes care of arbitrary number of clocks and resets.  The DT node
>>> structure typically looks like as follows:
>>>
>>>   dwc3-glue {
>>>   compatible = "foo,dwc3";
>>>   clocks = ...;
>>>   resets = ...;
>>>   ...
>>>
>>>   dwc3 {
>>>   compatible = "snps,dwc3";
>>>   ...
>>>   };
>>>   }
>>>
>>> By supporting the clocks and the reset in the dwc3/core.c, it will
>>> be turned into a single node:
>>>
>>>   dwc3 {
>>>   compatible = "foo,dwc3", "snps,dwc3";
>>>   clocks = ...;
>>>   resets = ...;
>>>   ...
>>>   }
>>>
>>> This commit adds the binding of clocks and resets specific to this IP.
>>> The number of clocks should generally be the same across SoCs, it is
>>> just some SoCs either tie clocks together or do not provide software
>>> control of some of the clocks.
>>>
>>> I took the clock names from the Synopsys datasheet: "ref" (ref_clk),
>>> "bus_early" (bus_clk_early), and "suspend" (suspend_clk).
>> looking at the code: this could mean that dwc3-exynos.c can be removed
>> mid-term (assuming the PHY and regulator handling can be
>> moved/removed/changed)
>>
>> does the datasheet state anything about the clock speeds? from
>> Documentation/devicetree/bindings/usb/dwc3-xilinx.txt:
>> "bus_clk" Master/Core clock, have to be >= 125 MHz for SS operation
>> and >= 60MHz for HS operation
>>
>>> I found only one reset line in the datasheet, hence the reset-names
>>> property is omitted.
>> does the datasheet state whether this is a level or a pulsed reset line?
>> on Amlogic Meson GXL, GXM and AXG SoCs we use a pulsed (and shared)
>> reset line (see ff0a632f08759e "usb: dwc3: of-simple: add support for
>> shared and pulsed reset lines") because the reset line is shared
>> between various components (USB2 PHY, USB3 PHY, dwc3 controller, ...)
>> your current approach (having a vendor-specific "foo,dwc3" binding
>> along with the generic "snps,dwc3") would allow having
>> per-"of_device_id" settings which could indicate whether the reset
>> lines are level or pulsed reset if these are "implementation specific"
>
> Let me ask a question about your reset controller.
> (drivers/reset/reset-meson.c)
>
> All reset ID supports .reset, .assert, .deassert
> Is this correct?
as far as I know: yes (though I have only ever verified this with the
Ethernet controller's reset line)

>
> I believe you and I use the same DWC3 core IP.
this is possible - but I am not sure since I don't have access to
Amlogic's internal resources where this should be documented (my
knowledge mostly comes from reading Amlogic's out-of-tree kernel code
and porting that to mainline)

>
> I suspect the difference is in the reset controller side.
>
> In my case, the reset line is asserted by default.
> (that is, all FFs in the RTL are put into the initial state
> on power-on)
> That's why only reset_deassert() will work for me, I think.
>
> What about your case?  Is the reset line in deassert state on power-on?
> Then, the reset must be explicitly pulsed to put FFs into
> the initial state.  Is this correct?
let me give you a bit of context first:
the Amlogic Meson AXG, GXL and GXM SoCs have one reset line for "USB
components". this is shared among:
- the dwc3 controller
- (depending on the SoC) 2 or 3 USB2 PHYs
- a USB3 PHY
- some OTG detection logic within the registers of the USB3 PHY

(there is also a gate clock which is assigned to the same components)

based on my tests I believe that the reset line is "de-asserted" (=
USB components are working) by default.
asserting that reset line should stop the state machine of all USB
components. de-asserting it again should bring all USB components into
a defined state.
(I'm not sure though if these are HW defaults or if th

Re: [PATCH v2 2/2] usb: dwc3: support clocks and resets for DWC3 core

2018-04-23 Thread Martin Blumenstingl
Hello,

On Thu, Apr 19, 2018 at 1:03 PM, Masahiro Yamada
 wrote:
> Historically, the clocks and resets are handled on the glue layer
> side instead of the DWC3 core.  For simple cases, dwc3-of-simple.c
> takes care of arbitrary number of clocks and resets.  The DT node
> structure typically looks like as follows:
>
>   dwc3-glue {
>   compatible = "foo,dwc3";
>   clocks = ...;
>   resets = ...;
>   ...
>
>   dwc3 {
>   compatible = "snps,dwc3";
>   ...
>   };
>   }
>
> By supporting the clocks and the reset in the dwc3/core.c, it will
> be turned into a single node:
>
>   dwc3 {
>   compatible = "foo,dwc3", "snps,dwc3";
>   clocks = ...;
>   resets = ...;
>   ...
>   }
>
> This commit adds the binding of clocks and resets specific to this IP.
> The number of clocks should generally be the same across SoCs, it is
> just some SoCs either tie clocks together or do not provide software
> control of some of the clocks.
>
> I took the clock names from the Synopsys datasheet: "ref" (ref_clk),
> "bus_early" (bus_clk_early), and "suspend" (suspend_clk).
looking at the code: this could mean that dwc3-exynos.c can be removed
mid-term (assuming the PHY and regulator handling can be
moved/removed/changed)

does the datasheet state anything about the clock speeds? from
Documentation/devicetree/bindings/usb/dwc3-xilinx.txt:
"bus_clk" Master/Core clock, have to be >= 125 MHz for SS operation
and >= 60MHz for HS operation

> I found only one reset line in the datasheet, hence the reset-names
> property is omitted.
does the datasheet state whether this is a level or a pulsed reset line?
on Amlogic Meson GXL, GXM and AXG SoCs we use a pulsed (and shared)
reset line (see ff0a632f08759e "usb: dwc3: of-simple: add support for
shared and pulsed reset lines") because the reset line is shared
between various components (USB2 PHY, USB3 PHY, dwc3 controller, ...)
your current approach (having a vendor-specific "foo,dwc3" binding
along with the generic "snps,dwc3") would allow having
per-"of_device_id" settings which could indicate whether the reset
lines are level or pulsed reset if these are "implementation specific"

> Supporting those clocks and resets is the requirement for new platforms.
just to confirm:
with this series your goal is to replace the wrapper node which is
needed due to dwc3-of-simple.c ?
would other drivers which currently create a wrapper node (like
dwc3-keystone.c) keep their wrapper node or do you have any plans for
removing it for the other "wrapper" drivers too?

> Enforcing the new binding breaks existing platforms since they specify
> clocks and resets in their glue layer node, but nothing in the core
> node.  I listed such exceptional cases in the DT binding.  The driver
> code is loosened up to accept no clock/reset.  This change is based
> on the discussion [1].
(snip)

Regards
Martin
--
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 usb v6 6/6] usb: core: phy: add the SPDX-License-Identifier and include guard

2018-04-22 Thread Martin Blumenstingl
Hi Greg,

On Sun, Apr 22, 2018 at 3:01 PM, Greg KH <gre...@linuxfoundation.org> wrote:
> On Wed, Apr 18, 2018 at 09:39:51PM +0200, Martin Blumenstingl wrote:
>> This clarifies the license of the code. While here also add an include
>> guard to the header file.
>>
>> Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the 
>> HCD")
>> Suggested-by: Masahiro Yamada <yamada.masah...@socionext.com>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>>  drivers/usb/core/phy.h | 12 
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
>> index bbc969383074..88a3c037e9df 100644
>> --- a/drivers/usb/core/phy.h
>> +++ b/drivers/usb/core/phy.h
>> @@ -1,3 +1,13 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>
> Do you _really_ mean GPLv2 or anything later?
drivers/usb/core/hcd.c uses the same license identifier
that code is much more "valuable" than my few lines which manage a
list of PHYs - so I'm fine with "GPLv2 or anything later"

> I have to ask...
if you see any problems with this (for example that phy.h couldn't be
used from some special module with another license, ...) then please
let me know


Regards
Martin
--
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 0/3] USB: musb: dsps: phy fix and DT-topology support

2018-04-19 Thread Martin Blumenstingl
Hello Johan,

On Thu, Apr 19, 2018 at 9:43 AM, Johan Hovold <jo...@kernel.org> wrote:
> On Wed, Apr 18, 2018 at 09:18:30PM +0200, Martin Blumenstingl wrote:
>> Hi Johan,
>>
>> On Fri, Apr 13, 2018 at 5:15 PM, Johan Hovold <jo...@kernel.org> wrote:
>> > I've been carrying a patch out-of-tree since my work on improving the
>> > USB device-tree support which is needed to be able to describe USB
>> > topologies for musb based controllers.
>> >
>> > This patch, which associates the platform controller device with the
>> > glue device device-tree node, did not play well with the recent changes
>> > which added generic phy support to USB core however.
>> I'm the one who added this
>>
>> > Like the recent dwc2 regression fixed by Arnd after the device-tree
>> > #phy-cell changes, the generic phy code in USB core can now also fail
>> > indefinitly with -EPROBE_DEFER when the controller uses a legacy USB
>> > phy.
>> >
>> > The second patch addresses this for musb, which handles its own (legacy
>> > and generic) phys, but something more may possibly now be needed for
>> > other platforms with legacy phys.
>> I'm not sure if I understand the problem yet - could you please
>> explain with your words what "legacy PHYs" are and how the "conflict"
>> with the PHY handling in USB core?
>>
>> I am aware of two PHY subsystems:
>> - drivers/phy
>> -- also called "generic PHY framework"
>> -- uses a "phys" property
>
> Right, and these are sometimes referred to as generic PHYs, as opposed
> to...
>
>> - drivers/usb/phy
>> -- also called "USB PHY framework"
>> -- AFAIK this should not be used for new drivers
>
> ...the legacy ones.
>
>> -- uses an "usb-phy" property
>
> This is unfortunately not always the case however; some legacy USB phys
> are also referred to using a "phys" property...
oh, I was not aware of that. this explains the issue you're seeing...
thank you for the explanation!

>> the new PHY handling in USB core only parses the "phys" property and
>> thus should not conflict with "usb-phy" (the legacy property)
>
>> however, I probably missed something so I'd appreciate an explanation
>> how things can break
>
> ...and that is the problem. Specifically, since last fall when a number
> of legacy-phy nodes had a #phy-cells property added to them (to silence
> DTC warnings), the generic PHY subsubsystem can now return -EPROBE_DEFER
> indefinitely when looking up a phy as it finds a matching device-tree
> node, but for which there will never be a generic phy registered (since
> it's handled by a legacy-phy driver).
>
> I referred to Arnd's workaround for "usb-nop-xceiv" devices
>
> b7563e2796f8 ("phy: work around 'phys' references to
> usb-nop-xceiv devices")
>
> which has some more background on this.
thank you for this pointer too

> So if we have any other host controllers out there using
> "phys"-properties with legacy phys other than "usb-nop-xceiv", then
> these will now fail to register (with -EPROBE_DEFER) unless
> hcd->skip_phy_initialization is set (or we blacklist them as well in the
> generic phy code).
>
> I'm not aware of any further examples, but we're sure to find out soon
> enough if there are.
>
> Perhaps we should blacklist also "ti,am335x-usb-phy" in the generic phy
> code even if hcd->skip_phy_initialization is still needed for musb for
> the time being anyway.
>
> Johan


Regards
Martin
--
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 usb v6 0/6] usb/core/phy fixes for v4.17

2018-04-18 Thread Martin Blumenstingl
This is a follow-up to my previous series "initialize (multiple) PHYs
for a HCD": [0].

Roger Quadros reported [1] that it "is breaking low power cases on TI
SoCs when USB is in host mode". He further explains that "Not doing the
phy_exit() here [when entering suspend] leaves the clocks enabled on
our SoC and we're no longer able to reach low power states on system
suspend."
Chunfeng Yun from Mediatek noted [2] that we cannot unconditionally call
phy_exit while entering system suspend, because this would "disconnect
plugged devices on MTK platforms, due to re-initialize u2 phys when
resume"

In the discussion (which followed Roger's bug report: [1]) Roger,
Chunfeng and me came to the conclusion that we can fix suspend on the
TI SoCs without breaking it on the Mediatek SoCs by extending the
suspend and resume code in usb/core/phy.c by checking whether the USB
controller can wake up the system (which is the case for the Mediatek
MTU3 controller, but now for the dwc3 controller used on the TI SoCs):
- if the controller can wake up the system (Mediatek MTU3 use-case) we
  only call usb_phy_roothub_power_off (which calls phy_power_off) when
  entering system suspend
- if the controller however cannot wake up the system (dwc3 on TI SoCs)
  we additionally call usb_phy_roothub_exit (which calls phy_exit) when
  entering system suspend
- (we undo the previous steps during system resume)

The goal of this series is to fix the issue reported by Roger without
breaking suspend/resume on the Mediatek SoCs.
Since I neither have a TI nor a Mediatek device I am sending this as
RFC. I have tested it on an Amlogic Meson GXM board (Khadas VIM2) which
does NOT support suspend/resume yet.

Additionally Stefan Wahren reported [7] that booting on a Raspberry Pi
with CONFIG_GENERIC_PHY being disabled (which is the case for
bcm2835_defconfig) breaks USB. A fix for this is also included.


changes since v5 at [9]
- rebased on top of v4.17-rc1
- added Keerthy's Tested-by to the first three patches (thank you!)
- fixed a checkpatch warning (which was introduced in v4.17-rc1's
  checkpatch.pl) in patch #6 by using "/* SPDX-License-Identifier"
  instead of "// SPDX-License-Identifier"

changes since v4 at [8]
- updated series title since it now includes fixes for other
  functionality than suspend
- rebased on top of f8cf2f16a7c95a from Linus' tree -> I will re-send
  an updated version once v4.17-rc1 is out, I just sent it early to
  get some feedback early!
- included patch [3] "usb: core: phy: fix return value of
  usb_phy_roothub_exit()" in this series
- fix the logic if CONFIG_GENERIC_PHY is disabled (as reported by
  Stefan Wahren, new patch #4)
- two minor coding style fixes as suggested by Masahiro Yamada (new
  patches #4 and #5)

changes since RFC v3 at [6]:
- added Chunfeng Yun's Tested-by and Roger Quadros' Reviewed-by (thank
  you!)
- dropped RFC prefix

changes since RFC v2 at [5]:
- add missing INIT_LIST_HEAD call in usb_phy_roothub_add_phy (affects
  patch #1 - spotted by Roger Quadros, thank you!)
- fixed swapped conditions using device_may_wakeup() in
  usb_phy_roothub_resume because we need to call usb_phy_roothub_init
  if the controller cannot wake up the device (affects patch #2, spotted
  by Chunfeng Yun, thank you!)
- simplified the error condition to "undo" usb_phy_roothub_init if
  usb_phy_roothub_power_on failed in usb_phy_roothub_resume (suggested
  by Chunfeng Yun)
- updated the commit message (using Roger's wording) because (quote from
  Roger "it doesn't prevent the system from entering suspend but just
  prevents the system from reaching lowest power levels in the suspend
  state."

Changes since RFC v1 (blob attachments) at [4]:
- use device_may_wakeup instead of device_can_wakeup as suggested by
  Roger Quadros
- use the controller device from hcd->self.controller as suggested by
  Chunfeng Yun
- compile time fixes thanks to Roger Quadros
- if usb_phy_roothub_power_on in usb_phy_roothub_resume failes then
  we now call usb_phy_roothub_exit to keep the PHYs in the correct
  state if usb_phy_roothub_resume partially failed


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006599.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006737.html
[2] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006758.html
[3] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
[4] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006794.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006820.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006847.html
[7] https://www.spinics.net/lists/linux-usb/msg167472.html
[8] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006882.html
[9] http://lists.infradead.org/pipermail/linux-amlogic/2018-April/007009.html

Martin Blumenstingl (6):
  usb: core

[PATCH usb v6 6/6] usb: core: phy: add the SPDX-License-Identifier and include guard

2018-04-18 Thread Martin Blumenstingl
This clarifies the license of the code. While here also add an include
guard to the header file.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Suggested-by: Masahiro Yamada <yamada.masah...@socionext.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index bbc969383074..88a3c037e9df 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -1,3 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * USB roothub wrapper
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumensti...@googlemail.com>
+ */
+
+#ifndef __USB_CORE_PHY_H_
+#define __USB_CORE_PHY_H_
+
 struct device;
 struct usb_phy_roothub;
 
@@ -13,3 +23,5 @@ int usb_phy_roothub_suspend(struct device *controller_dev,
struct usb_phy_roothub *phy_roothub);
 int usb_phy_roothub_resume(struct device *controller_dev,
   struct usb_phy_roothub *phy_roothub);
+
+#endif /* __USB_CORE_PHY_H_ */
-- 
2.17.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 usb v6 4/6] usb: core: phy: make it a no-op if CONFIG_GENERIC_PHY is disabled

2018-04-18 Thread Martin Blumenstingl
If the generic PHY support is disabled the stub of devm_of_phy_get_by_index
returns ENOSYS. This corner case isn't handled properly by
usb_phy_roothub_add_phy and at least breaks USB support on Raspberry Pi
(bcm2835_defconfig):

dwc2 2098.usb: dwc2_hcd_init() FAILED, returning -38
dwc2: probe of 2098.usb failed with error -38

Let usb_phy_roothub_alloc() return in case CONFIG_GENERIC_PHY is
disabled to fix this issue (compilers might even be smart enough to
optimize away most of the code within usb_phy_roothub_alloc and
usb_phy_roothub_add_phy if CONFIG_GENERIC_PHY is disabled). All
existing usb_phy_roothub_* functions are already NULL-safe, so no
special handling is required there.

Fixes: 07dbff0ddbd8 ("usb: core: add a wrapper for the USB PHYs on the HCD")
Reported-by: Stefan Wahren <stefan.wah...@i2se.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index a39d9bb26a4f..9879767452a2 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -50,6 +50,9 @@ struct usb_phy_roothub *usb_phy_roothub_alloc(struct device 
*dev)
struct usb_phy_roothub *phy_roothub;
int i, num_phys, err;
 
+   if (!IS_ENABLED(CONFIG_GENERIC_PHY))
+   return NULL;
+
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
  "#phy-cells");
if (num_phys <= 0)
-- 
2.17.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 usb v6 3/6] usb: core: use phy_exit during suspend if wake up is not supported

2018-04-18 Thread Martin Blumenstingl
If the USB controller can wake up the system (which is the case for
example with the Mediatek USB3 IP) then we must not call phy_exit during
suspend to ensure that the USB controller doesn't have to re-enumerate
the devices during resume.
However, if the USB controller cannot wake up the system (which is the
case for example on various TI platforms using a dwc3 controller) then
we must call phy_exit during suspend. Otherwise the PHY driver keeps the
clocks enabled, which prevents the system from reaching the lowest power
levels in the suspend state.

Solve this by introducing two new functions in the PHY wrapper which are
dedicated to the suspend and resume handling.
If the controller can wake up the system the new usb_phy_roothub_suspend
function will simply call usb_phy_roothub_power_off. However, if wake up
is not supported by the controller it will also call
usb_phy_roothub_exit.
The also new usb_phy_roothub_resume function takes care of calling
usb_phy_roothub_init (if the controller can't wake up the system) in
addition to usb_phy_roothub_power_on.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Fixes: 178a0bce05cbc1 ("usb: core: hcd: integrate the PHY wrapper into the HCD 
core")
Reported-by: Roger Quadros <rog...@ti.com>
Suggested-by: Roger Quadros <rog...@ti.com>
Suggested-by: Chunfeng Yun <chunfeng@mediatek.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Chunfeng Yun <chunfeng@mediatek.com>
Reviewed-by: Roger Quadros <rog...@ti.com>
Tested-by: Keerthy <j-keer...@ti.com>
---
 drivers/usb/core/hcd.c |  8 +---
 drivers/usb/core/phy.c | 35 +++
 drivers/usb/core/phy.h |  5 +
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 15b0418e3b6a..78bae4ecd68b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2262,7 +2262,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
hcd->state = HC_STATE_SUSPENDED;
 
if (!PMSG_IS_AUTO(msg))
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev,
+   hcd->phy_roothub);
 
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
@@ -2302,7 +2303,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
 
if (!PMSG_IS_AUTO(msg)) {
-   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   status = usb_phy_roothub_resume(hcd->self.sysdev,
+   hcd->phy_roothub);
if (status)
return status;
}
@@ -2344,7 +2346,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 44f008cda7a8..a39d9bb26a4f 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -157,3 +157,38 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub 
*phy_roothub)
phy_power_off(roothub_entry->phy);
 }
 EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
+
+int usb_phy_roothub_suspend(struct device *controller_dev,
+   struct usb_phy_roothub *phy_roothub)
+{
+   usb_phy_roothub_power_off(phy_roothub);
+
+   /* keep the PHYs initialized so the device can wake up the system */
+   if (device_may_wakeup(controller_dev))
+   return 0;
+
+   return usb_phy_roothub_exit(phy_roothub);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend);
+
+int usb_phy_roothub_resume(struct device *controller_dev,
+  struct usb_phy_roothub *phy_roothub)
+{
+   int err;
+
+   /* if the device can't wake up the system _exit was called */
+   if (!device_may_wakeup(controller_dev)) {
+   err = usb_phy_roothub_init(phy_roothub);
+   if (err)
+   return err;
+   }
+
+   err = usb_phy_roothub_power_on(phy_roothub);
+
+   /* undo _init if _power_on failed */
+   if (err && !device_may_wakeup(controller_dev))
+   usb_phy_roothub_exit(phy_roothub);
+
+   return err;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_resume);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index eb31253201ad..60901d44 100644
--- a/drive

[PATCH usb v6 5/6] usb: core: phy: add missing forward declaration for "struct device"

2018-04-18 Thread Martin Blumenstingl
Currently hcd.c is the only consumer of the usb_phy_roothub logic. This
already includes the required header files so struct device is known.
However, future consumers might not know about struct device.
Add a forward declaration for struct device to fix potential future
consumers which don't include any of the struct device API headers.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Suggested-by: Masahiro Yamada <yamada.masah...@socionext.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index 60901d44..bbc969383074 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -1,3 +1,4 @@
+struct device;
 struct usb_phy_roothub;
 
 struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev);
-- 
2.17.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 usb v6 2/6] usb: core: split usb_phy_roothub_{init,alloc}

2018-04-18 Thread Martin Blumenstingl
Before this patch usb_phy_roothub_init served two purposes (from a
caller's point of view - like hcd.c):
- parsing the PHYs and allocating the list entries
- calling phy_init on each list entry

While this worked so far it has one disadvantage: if we need to call
phy_init for each PHY instance then the existing code cannot be re-used.
Solve this by splitting off usb_phy_roothub_alloc which only parses the
PHYs and allocates the list entries.
usb_phy_roothub_init then gets a struct usb_phy_roothub and only calls
phy_init on each PHY instance (along with the corresponding cleanup if
that failed somewhere).

This is a preparation step for adding proper suspend support for some
hardware that requires phy_exit to be called during suspend and phy_init
to be called during resume.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Chunfeng Yun <chunfeng@mediatek.com>
Reviewed-by: Roger Quadros <rog...@ti.com>
Tested-by: Keerthy <j-keer...@ti.com>
---
 drivers/usb/core/hcd.c | 10 +---
 drivers/usb/core/phy.c | 53 +-
 drivers/usb/core/phy.h |  4 +++-
 3 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..15b0418e3b6a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2758,12 +2758,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
 
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
-   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
retval = PTR_ERR(hcd->phy_roothub);
-   goto err_phy_roothub_init;
+   goto err_phy_roothub_alloc;
}
 
+   retval = usb_phy_roothub_init(hcd->phy_roothub);
+   if (retval)
+   goto err_phy_roothub_alloc;
+
retval = usb_phy_roothub_power_on(hcd->phy_roothub);
if (retval)
goto err_usb_phy_roothub_power_on;
@@ -2936,7 +2940,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_phy_roothub_power_off(hcd->phy_roothub);
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
-err_phy_roothub_init:
+err_phy_roothub_alloc:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index f19aaa3c899c..44f008cda7a8 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -19,19 +19,6 @@ struct usb_phy_roothub {
struct list_headlist;
 };
 
-static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
-{
-   struct usb_phy_roothub *roothub_entry;
-
-   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
-   if (!roothub_entry)
-   return ERR_PTR(-ENOMEM);
-
-   INIT_LIST_HEAD(_entry->list);
-
-   return roothub_entry;
-}
-
 static int usb_phy_roothub_add_phy(struct device *dev, int index,
   struct list_head *list)
 {
@@ -45,9 +32,11 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return PTR_ERR(phy);
}
 
-   roothub_entry = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(roothub_entry))
-   return PTR_ERR(roothub_entry);
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(_entry->list);
 
roothub_entry->phy = phy;
 
@@ -56,11 +45,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return 0;
 }
 
-struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
 {
struct usb_phy_roothub *phy_roothub;
-   struct usb_phy_roothub *roothub_entry;
-   struct list_head *head;
int i, num_phys, err;
 
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
@@ -68,16 +55,31 @@ struct usb_phy_roothub *usb_phy_roothub_init(struct device 
*dev)
if (num_phys <= 0)
return NULL;
 
-   phy_roothub = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(phy_roothub))
-   return phy_roothub;
+   phy_roothub = devm_kzalloc(dev, sizeof(*phy_roothub), GFP_KERNEL);
+   if (!phy_roothub)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_roothub->list);
 
for (i = 0; i < num_phys; i++) {
err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
if (err)
-   g

[PATCH usb v6 1/6] usb: core: phy: fix return value of usb_phy_roothub_exit()

2018-04-18 Thread Martin Blumenstingl
usb_phy_roothub_exit() should return the error code from the phy_exit()
call if exiting the PHY failed.
However, since a wrong variable is used usb_phy_roothub_exit() currently
always returns 0, even if one of the phy_exit calls returned an error.
Clang also reports this bug:
kernel/drivers/usb/core/phy.c:114:8: warning: explicitly assigning value of
variable of type 'int' to itself [-Wself-assign] error, forbidden
warning: phy.c:114

Fix this by assigning the error code from phy_exit() to the "ret"
variable to propagate the error correctly.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
Tested-by: Keerthy <j-keer...@ti.com>
---
 drivers/usb/core/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 09b7c43c0ea4..f19aaa3c899c 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -111,7 +111,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub 
*phy_roothub)
list_for_each_entry(roothub_entry, head, list) {
err = phy_exit(roothub_entry->phy);
if (err)
-   ret = ret;
+   ret = err;
}
 
return ret;
-- 
2.17.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: [PATCH 0/3] USB: musb: dsps: phy fix and DT-topology support

2018-04-18 Thread Martin Blumenstingl
Hi Johan,

On Fri, Apr 13, 2018 at 5:15 PM, Johan Hovold  wrote:
> I've been carrying a patch out-of-tree since my work on improving the
> USB device-tree support which is needed to be able to describe USB
> topologies for musb based controllers.
>
> This patch, which associates the platform controller device with the
> glue device device-tree node, did not play well with the recent changes
> which added generic phy support to USB core however.
I'm the one who added this

> Like the recent dwc2 regression fixed by Arnd after the device-tree
> #phy-cell changes, the generic phy code in USB core can now also fail
> indefinitly with -EPROBE_DEFER when the controller uses a legacy USB
> phy.
>
> The second patch addresses this for musb, which handles its own (legacy
> and generic) phys, but something more may possibly now be needed for
> other platforms with legacy phys.
I'm not sure if I understand the problem yet - could you please
explain with your words what "legacy PHYs" are and how the "conflict"
with the PHY handling in USB core?

I am aware of two PHY subsystems:
- drivers/phy
-- also called "generic PHY framework"
-- uses a "phys" property
- drivers/usb/phy
-- also called "USB PHY framework"
-- AFAIK this should not be used for new drivers
-- uses an "usb-phy" property

the new PHY handling in USB core only parses the "phys" property and
thus should not conflict with "usb-phy" (the legacy property)

however, I probably missed something so I'd appreciate an explanation
how things can break

> In the process of debugging this, I stumbled over another issue which
> caused the dsps legacy phy init two be called twice on every probe and
> which is fixed by the first patch.
>
> Johan
>
>
> Johan Hovold (3):
>   USB: musb: dsps: drop duplicate phy initialisation
>   USB: musb: host: prevent core phy initialisation
>   USB: musb: dsps: propagate device-tree node
>
>  drivers/usb/musb/musb_dsps.c | 3 +--
>  drivers/usb/musb/musb_host.c | 1 +
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> --
> 2.17.0
>

Regards
Martin
--
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 usb v5 6/6] usb: core: phy: add the SPDX-License-Identifier and include guard

2018-04-08 Thread Martin Blumenstingl
This clarifies the license of the code. While here also add an include
guard to the header file.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Suggested-by: Masahiro Yamada <yamada.masah...@socionext.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index bbc969383074..8451a7e88d38 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -1,3 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * USB roothub wrapper
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumensti...@googlemail.com>
+ */
+
+#ifndef __USB_CORE_PHY_H_
+#define __USB_CORE_PHY_H_
+
 struct device;
 struct usb_phy_roothub;
 
@@ -13,3 +23,5 @@ int usb_phy_roothub_suspend(struct device *controller_dev,
struct usb_phy_roothub *phy_roothub);
 int usb_phy_roothub_resume(struct device *controller_dev,
   struct usb_phy_roothub *phy_roothub);
+
+#endif /* __USB_CORE_PHY_H_ */
-- 
2.17.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 usb v5 4/6] usb: core: phy: make it a no-op if CONFIG_GENERIC_PHY is disabled

2018-04-08 Thread Martin Blumenstingl
If the generic PHY support is disabled the stub of devm_of_phy_get_by_index
returns ENOSYS. This corner case isn't handled properly by
usb_phy_roothub_add_phy and at least breaks USB support on Raspberry Pi
(bcm2835_defconfig):

dwc2 2098.usb: dwc2_hcd_init() FAILED, returning -38
dwc2: probe of 2098.usb failed with error -38

Let usb_phy_roothub_alloc() return in case CONFIG_GENERIC_PHY is
disabled to fix this issue (compilers might even be smart enough to
optimize away most of the code within usb_phy_roothub_alloc and
usb_phy_roothub_add_phy if CONFIG_GENERIC_PHY is disabled). All
existing usb_phy_roothub_* functions are already NULL-safe, so no
special handling is required there.

Fixes: 07dbff0ddbd8 ("usb: core: add a wrapper for the USB PHYs on the HCD")
Reported-by: Stefan Wahren <stefan.wah...@i2se.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index a39d9bb26a4f..9879767452a2 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -50,6 +50,9 @@ struct usb_phy_roothub *usb_phy_roothub_alloc(struct device 
*dev)
struct usb_phy_roothub *phy_roothub;
int i, num_phys, err;
 
+   if (!IS_ENABLED(CONFIG_GENERIC_PHY))
+   return NULL;
+
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
  "#phy-cells");
if (num_phys <= 0)
-- 
2.17.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 usb v5 5/6] usb: core: phy: add missing forward declaration for "struct device"

2018-04-08 Thread Martin Blumenstingl
Currently hcd.c is the only consumer of the usb_phy_roothub logic. This
already includes the required header files so struct device is known.
However, future consumers might not know about struct device.
Add a forward declaration for struct device to fix potential future
consumers which don't include any of the struct device API headers.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Suggested-by: Masahiro Yamada <yamada.masah...@socionext.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index 60901d44..bbc969383074 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -1,3 +1,4 @@
+struct device;
 struct usb_phy_roothub;
 
 struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev);
-- 
2.17.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 usb v5 0/6] usb/core/phy fixes for v4.17

2018-04-08 Thread Martin Blumenstingl
This is a follow-up to my previous series "initialize (multiple) PHYs
for a HCD": [0].

Roger Quadros reported [1] that it "is breaking low power cases on TI
SoCs when USB is in host mode". He further explains that "Not doing the
phy_exit() here [when entering suspend] leaves the clocks enabled on
our SoC and we're no longer able to reach low power states on system
suspend."
Chunfeng Yun from Mediatek noted [2] that we cannot unconditionally call
phy_exit while entering system suspend, because this would "disconnect
plugged devices on MTK platforms, due to re-initialize u2 phys when
resume"

In the discussion (which followed Roger's bug report: [1]) Roger,
Chunfeng and me came to the conclusion that we can fix suspend on the
TI SoCs without breaking it on the Mediatek SoCs by extending the
suspend and resume code in usb/core/phy.c by checking whether the USB
controller can wake up the system (which is the case for the Mediatek
MTU3 controller, but now for the dwc3 controller used on the TI SoCs):
- if the controller can wake up the system (Mediatek MTU3 use-case) we
  only call usb_phy_roothub_power_off (which calls phy_power_off) when
  entering system suspend
- if the controller however cannot wake up the system (dwc3 on TI SoCs)
  we additionally call usb_phy_roothub_exit (which calls phy_exit) when
  entering system suspend
- (we undo the previous steps during system resume)

The goal of this series is to fix the issue reported by Roger without
breaking suspend/resume on the Mediatek SoCs.
Since I neither have a TI nor a Mediatek device I am sending this as
RFC. I have tested it on an Amlogic Meson GXM board (Khadas VIM2) which
does NOT support suspend/resume yet.

Additionally Stefan Wahren reported [7] that booting on a Raspberry Pi
with CONFIG_GENERIC_PHY being disabled (which is the case for
bcm2835_defconfig) breaks USB. A fix for this is also included.


changes since v4 at [8]
- updated series title since it now includes fixes for other
  functionality than suspend
- rebased on top of f8cf2f16a7c95a from Linus' tree -> I will re-send
  an updated version once v4.17-rc1 is out, I just sent it early to
  get some feedback early!
- included patch [3] "usb: core: phy: fix return value of
  usb_phy_roothub_exit()" in this series
- fix the logic if CONFIG_GENERIC_PHY is disabled (as reported by
  Stefan Wahren, new patch #4)
- two minor coding style fixes as suggested by Masahiro Yamada (new
  patches #4 and #5)

changes since RFC v3 at [6]:
- added Chunfeng Yun's Tested-by and Roger Quadros' Reviewed-by (thank
  you!)
- dropped RFC prefix

changes since RFC v2 at [5]:
- add missing INIT_LIST_HEAD call in usb_phy_roothub_add_phy (affects
  patch #1 - spotted by Roger Quadros, thank you!)
- fixed swapped conditions using device_may_wakeup() in
  usb_phy_roothub_resume because we need to call usb_phy_roothub_init
  if the controller cannot wake up the device (affects patch #2, spotted
  by Chunfeng Yun, thank you!)
- simplified the error condition to "undo" usb_phy_roothub_init if
  usb_phy_roothub_power_on failed in usb_phy_roothub_resume (suggested
  by Chunfeng Yun)
- updated the commit message (using Roger's wording) because (quote from
  Roger "it doesn't prevent the system from entering suspend but just
  prevents the system from reaching lowest power levels in the suspend
  state."

Changes since RFC v1 (blob attachments) at [4]:
- use device_may_wakeup instead of device_can_wakeup as suggested by
  Roger Quadros
- use the controller device from hcd->self.controller as suggested by
  Chunfeng Yun
- compile time fixes thanks to Roger Quadros
- if usb_phy_roothub_power_on in usb_phy_roothub_resume failes then
  we now call usb_phy_roothub_exit to keep the PHYs in the correct
  state if usb_phy_roothub_resume partially failed


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006599.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006737.html
[2] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006758.html
[3] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
[4] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006794.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006820.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006847.html
[7] https://www.spinics.net/lists/linux-usb/msg167472.html
[8] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006882.html


Martin Blumenstingl (6):
  usb: core: phy: fix return value of usb_phy_roothub_exit()
  usb: core: split usb_phy_roothub_{init,alloc}
  usb: core: use phy_exit during suspend if wake up is not supported
  usb: core: phy: make it a no-op if CONFIG_GENERIC_PHY is disabled
  usb: core: phy: add missing forward declaration for "struct device"
  usb: core: phy: add the SPDX-License-Identifier

[PATCH usb v5 1/6] usb: core: phy: fix return value of usb_phy_roothub_exit()

2018-04-08 Thread Martin Blumenstingl
usb_phy_roothub_exit() should return the error code from the phy_exit()
call if exiting the PHY failed.
However, since a wrong variable is used usb_phy_roothub_exit() currently
always returns 0, even if one of the phy_exit calls returned an error.
Clang also reports this bug:
kernel/drivers/usb/core/phy.c:114:8: warning: explicitly assigning value of
variable of type 'int' to itself [-Wself-assign] error, forbidden
warning: phy.c:114

Fix this by assigning the error code from phy_exit() to the "ret"
variable to propagate the error correctly.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
---
 drivers/usb/core/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 09b7c43c0ea4..f19aaa3c899c 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -111,7 +111,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub 
*phy_roothub)
list_for_each_entry(roothub_entry, head, list) {
err = phy_exit(roothub_entry->phy);
if (err)
-   ret = ret;
+   ret = err;
}
 
return ret;
-- 
2.17.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 usb v5 2/6] usb: core: split usb_phy_roothub_{init,alloc}

2018-04-08 Thread Martin Blumenstingl
Before this patch usb_phy_roothub_init served two purposes (from a
caller's point of view - like hcd.c):
- parsing the PHYs and allocating the list entries
- calling phy_init on each list entry

While this worked so far it has one disadvantage: if we need to call
phy_init for each PHY instance then the existing code cannot be re-used.
Solve this by splitting off usb_phy_roothub_alloc which only parses the
PHYs and allocates the list entries.
usb_phy_roothub_init then gets a struct usb_phy_roothub and only calls
phy_init on each PHY instance (along with the corresponding cleanup if
that failed somewhere).

This is a preparation step for adding proper suspend support for some
hardware that requires phy_exit to be called during suspend and phy_init
to be called during resume.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Chunfeng Yun <chunfeng@mediatek.com>
Reviewed-by: Roger Quadros <rog...@ti.com>
---
 drivers/usb/core/hcd.c | 10 +---
 drivers/usb/core/phy.c | 53 +-
 drivers/usb/core/phy.h |  4 +++-
 3 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..15b0418e3b6a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2758,12 +2758,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
 
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
-   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
retval = PTR_ERR(hcd->phy_roothub);
-   goto err_phy_roothub_init;
+   goto err_phy_roothub_alloc;
}
 
+   retval = usb_phy_roothub_init(hcd->phy_roothub);
+   if (retval)
+   goto err_phy_roothub_alloc;
+
retval = usb_phy_roothub_power_on(hcd->phy_roothub);
if (retval)
goto err_usb_phy_roothub_power_on;
@@ -2936,7 +2940,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_phy_roothub_power_off(hcd->phy_roothub);
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
-err_phy_roothub_init:
+err_phy_roothub_alloc:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index f19aaa3c899c..44f008cda7a8 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -19,19 +19,6 @@ struct usb_phy_roothub {
struct list_headlist;
 };
 
-static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
-{
-   struct usb_phy_roothub *roothub_entry;
-
-   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
-   if (!roothub_entry)
-   return ERR_PTR(-ENOMEM);
-
-   INIT_LIST_HEAD(_entry->list);
-
-   return roothub_entry;
-}
-
 static int usb_phy_roothub_add_phy(struct device *dev, int index,
   struct list_head *list)
 {
@@ -45,9 +32,11 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return PTR_ERR(phy);
}
 
-   roothub_entry = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(roothub_entry))
-   return PTR_ERR(roothub_entry);
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(_entry->list);
 
roothub_entry->phy = phy;
 
@@ -56,11 +45,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return 0;
 }
 
-struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
 {
struct usb_phy_roothub *phy_roothub;
-   struct usb_phy_roothub *roothub_entry;
-   struct list_head *head;
int i, num_phys, err;
 
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
@@ -68,16 +55,31 @@ struct usb_phy_roothub *usb_phy_roothub_init(struct device 
*dev)
if (num_phys <= 0)
return NULL;
 
-   phy_roothub = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(phy_roothub))
-   return phy_roothub;
+   phy_roothub = devm_kzalloc(dev, sizeof(*phy_roothub), GFP_KERNEL);
+   if (!phy_roothub)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_roothub->list);
 
for (i = 0; i < num_phys; i++) {
err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
if (err)
-   goto err_out;
+   return ERR_PTR(err);

[PATCH usb v5 3/6] usb: core: use phy_exit during suspend if wake up is not supported

2018-04-08 Thread Martin Blumenstingl
If the USB controller can wake up the system (which is the case for
example with the Mediatek USB3 IP) then we must not call phy_exit during
suspend to ensure that the USB controller doesn't have to re-enumerate
the devices during resume.
However, if the USB controller cannot wake up the system (which is the
case for example on various TI platforms using a dwc3 controller) then
we must call phy_exit during suspend. Otherwise the PHY driver keeps the
clocks enabled, which prevents the system from reaching the lowest power
levels in the suspend state.

Solve this by introducing two new functions in the PHY wrapper which are
dedicated to the suspend and resume handling.
If the controller can wake up the system the new usb_phy_roothub_suspend
function will simply call usb_phy_roothub_power_off. However, if wake up
is not supported by the controller it will also call
usb_phy_roothub_exit.
The also new usb_phy_roothub_resume function takes care of calling
usb_phy_roothub_init (if the controller can't wake up the system) in
addition to usb_phy_roothub_power_on.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Fixes: 178a0bce05cbc1 ("usb: core: hcd: integrate the PHY wrapper into the HCD 
core")
Reported-by: Roger Quadros <rog...@ti.com>
Suggested-by: Roger Quadros <rog...@ti.com>
Suggested-by: Chunfeng Yun <chunfeng@mediatek.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Chunfeng Yun <chunfeng@mediatek.com>
Reviewed-by: Roger Quadros <rog...@ti.com>
---
 drivers/usb/core/hcd.c |  8 +---
 drivers/usb/core/phy.c | 35 +++
 drivers/usb/core/phy.h |  5 +
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 15b0418e3b6a..78bae4ecd68b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2262,7 +2262,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
hcd->state = HC_STATE_SUSPENDED;
 
if (!PMSG_IS_AUTO(msg))
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev,
+   hcd->phy_roothub);
 
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
@@ -2302,7 +2303,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
 
if (!PMSG_IS_AUTO(msg)) {
-   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   status = usb_phy_roothub_resume(hcd->self.sysdev,
+   hcd->phy_roothub);
if (status)
return status;
}
@@ -2344,7 +2346,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 44f008cda7a8..a39d9bb26a4f 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -157,3 +157,38 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub 
*phy_roothub)
phy_power_off(roothub_entry->phy);
 }
 EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
+
+int usb_phy_roothub_suspend(struct device *controller_dev,
+   struct usb_phy_roothub *phy_roothub)
+{
+   usb_phy_roothub_power_off(phy_roothub);
+
+   /* keep the PHYs initialized so the device can wake up the system */
+   if (device_may_wakeup(controller_dev))
+   return 0;
+
+   return usb_phy_roothub_exit(phy_roothub);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend);
+
+int usb_phy_roothub_resume(struct device *controller_dev,
+  struct usb_phy_roothub *phy_roothub)
+{
+   int err;
+
+   /* if the device can't wake up the system _exit was called */
+   if (!device_may_wakeup(controller_dev)) {
+   err = usb_phy_roothub_init(phy_roothub);
+   if (err)
+   return err;
+   }
+
+   err = usb_phy_roothub_power_on(phy_roothub);
+
+   /* undo _init if _power_on failed */
+   if (err && !device_may_wakeup(controller_dev))
+   usb_phy_roothub_exit(phy_roothub);
+
+   return err;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_resume);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index eb31253201ad..60901d44 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -7,3

Re: [PATCH] Usb: core: Correct self assignment in phy.c

2018-04-07 Thread Martin Blumenstingl
Hello,

thank you for finding this!

On Sat, Apr 7, 2018 at 1:04 AM, Rishabh Bhatnagar
 wrote:
> In file drivers/usb/core/phy.c line 114, ret variable is assigned to
> itself. The following error was observed:
>
> kernel/drivers/usb/core/phy.c:114:8: warning: explicitly assigning value of
> variable of type 'int' to itself [-Wself-assign] error, forbidden
> warning: phy.c:114
> This error was found when compiling with Clang. Change it to ret = err.
I found the same bug myself two weeks ago and already sent a patch: [0]
it has not made it to Greg's tree yet. Greg asked me to re-send that
patch along with some others after -rc1 is out: [1]

> Fixes: commit 07dbff0ddbd8 ("usb: core: add a wrapper for the USB PHYs on the 
> HCD")
> Signed-off-by: Rishabh Bhatnagar 
would you like me to add your Acked-by or Signed-off-by to my patch?

> ---
>  drivers/usb/core/phy.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
> index 09b7c43..f19aaa3 100644
> --- a/drivers/usb/core/phy.c
> +++ b/drivers/usb/core/phy.c
> @@ -111,7 +111,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub 
> *phy_roothub)
> list_for_each_entry(roothub_entry, head, list) {
> err = phy_exit(roothub_entry->phy);
> if (err)
> -   ret = ret;
> +   ret = err;
> }
>
> return ret;
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>


Regards
Martin


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-April/006977.html
--
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-next PATCH v11 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-04-05 Thread Martin Blumenstingl
On Fri, Apr 6, 2018 at 5:48 AM, Masahiro Yamada
<yamada.masah...@socionext.com> wrote:
> 2018-04-06 5:04 GMT+09:00 Martin Blumenstingl
> <martin.blumensti...@googlemail.com>:
>> Hello,
>>
>> (great to hear that this might be useful on Socionext SoCs as well :))
>>
>> On Wed, Apr 4, 2018 at 2:10 PM, Masahiro Yamada
>> <yamada.masah...@socionext.com> wrote:
>>> 2018-03-04 6:43 GMT+09:00 Martin Blumenstingl
>>> <martin.blumensti...@googlemail.com>:
>>>> Many SoC platforms have separate devices for the USB PHY which are
>>>> registered through the generic PHY framework. These PHYs have to be
>>>> enabled to make the USB controller actually work. They also have to be
>>>> disabled again on shutdown/suspend.
>>>>
>>>> Currently (at least) the following HCI platform drivers are using custom
>>>> code to obtain all PHYs via devicetree for the roothub/controller and
>>>> disable/enable them when required:
>>>> - ehci-platform.c has ehci_platform_power_{on,off}
>>>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>>>> - ohci-platform.c has ohci_platform_power_{on,off}
>>>>
>>>> With this new wrapper the USB PHYs can be specified directly in the
>>>> USB controller's devicetree node (just like on the drivers listed
>>>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>>>> correctly once this is wired up correctly. These SoCs use a dwc3
>>>> controller and require all USB PHYs to be initialized (if one of the USB
>>>> PHYs it not initialized then none of USB port works at all).
>>>>
>>>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>>>> Tested-by: Yixun Lan <yixun@amlogic.com>
>>>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>>>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>>>> ---
>>>>  drivers/usb/core/Makefile |   2 +-
>>>>  drivers/usb/core/phy.c| 158 
>>>> ++
>>>>  drivers/usb/core/phy.h|   7 ++
>>>>  3 files changed, 166 insertions(+), 1 deletion(-)
>>>>  create mode 100644 drivers/usb/core/phy.c
>>>>  create mode 100644 drivers/usb/core/phy.h
>>>>
>>>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>>>> index 92c9cefb4317..18e874b0441e 100644
>>>> --- a/drivers/usb/core/Makefile
>>>> +++ b/drivers/usb/core/Makefile
>>>> @@ -6,7 +6,7 @@
>>>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>>>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>>>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>>>> -usbcore-y += port.o
>>>> +usbcore-y += phy.o port.o
>>>>
>>>>  usbcore-$(CONFIG_OF)   += of.o
>>>>  usbcore-$(CONFIG_USB_PCI)  += hcd-pci.o
>>>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>>>> new file mode 100644
>>>> index ..09b7c43c0ea4
>>>> --- /dev/null
>>>> +++ b/drivers/usb/core/phy.c
>>>> @@ -0,0 +1,158 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/*
>>>> + * A wrapper for multiple PHYs which passes all phy_* function calls to
>>>> + * multiple (actual) PHY devices. This is comes handy when initializing
>>>> + * all PHYs on a HCD and to keep them all in the same state.
>>>> + *
>>>> + * Copyright (C) 2018 Martin Blumenstingl 
>>>> <martin.blumensti...@googlemail.com>
>>>> + */
>>>> +
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +
>>>> +#include "phy.h"
>>>> +
>>>> +struct usb_phy_roothub {
>>>> +   struct phy  *phy;
>>>> +   struct list_headlist;
>>>> +};
>>>> +
>>>> +static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
>>>> +{
>>>> +   struct usb_phy_roothub *roothub_entry;
>>>> +
>>>> +   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), 
>>>> GFP_KERNEL);
>>>> +   if (!roothub_entry)
>>>> +   return ERR_PTR(-ENOMEM);
>>>> +
>>>> +   INIT_LIST_HEAD(_entry->list);
>>

Re: [PATCH usb-next v4 0/2] fix HCD PHY suspend handling

2018-04-05 Thread Martin Blumenstingl
Hi Greg,

On Thu, Apr 5, 2018 at 3:38 PM, Greg KH <gre...@linuxfoundation.org> wrote:
> On Thu, Apr 05, 2018 at 11:47:11AM +0300, Roger Quadros wrote:
>> Greg,
>>
>> On 28/03/18 00:26, Martin Blumenstingl wrote:
>> > This is a follow-up to my previous series "initialize (multiple) PHYs
>> > for a HCD": [0].
>> >
>> > Roger Quadros reported [1] that it "is breaking low power cases on TI
>> > SoCs when USB is in host mode". He further explains that "Not doing the
>> > phy_exit() here [when entering suspend] leaves the clocks enabled on
>> > our SoC and we're no longer able to reach low power states on system
>> > suspend."
>> > Chunfeng Yun from Mediatek noted [2] that we cannot unconditionally call
>> > phy_exit while entering system suspend, because this would "disconnect
>> > plugged devices on MTK platforms, due to re-initialize u2 phys when
>> > resume"
>> >
>> > In the discussion (which followed Roger's bug report: [1]) Roger,
>> > Chunfeng and me came to the conclusion that we can fix suspend on the
>> > TI SoCs without breaking it on the Mediatek SoCs by extending the
>> > suspend and resume code in usb/core/phy.c by checking whether the USB
>> > controller can wake up the system (which is the case for the Mediatek
>> > MTU3 controller, but now for the dwc3 controller used on the TI SoCs):
>> > - if the controller can wake up the system (Mediatek MTU3 use-case) we
>> >   only call usb_phy_roothub_power_off (which calls phy_power_off) when
>> >   entering system suspend
>> > - if the controller however cannot wake up the system (dwc3 on TI SoCs)
>> >   we additionally call usb_phy_roothub_exit (which calls phy_exit) when
>> >   entering system suspend
>> > - (we undo the previous steps during system resume)
>> >
>> > The goal of this series is to fix the issue reported by Roger without
>> > breaking suspend/resume on the Mediatek SoCs.
>> > Since I neither have a TI nor a Mediatek device I am sending this as
>> > RFC. I have tested it on an Amlogic Meson GXM board (Khadas VIM2) which
>> > does NOT support suspend/resume yet.
>> >
>> > this should be applied on top of [3] "usb: core: phy: fix return value
>> > of usb_phy_roothub_exit()" (even though there's no strict dependency,
>> > this is the order I wrote the patches in).
>> >
>> > changes since RFC v3 at [6]:
>> > - added Chunfeng Yun's Tested-by and Roger Quadros' Reviewed-by (thank
>> >   you!)
>> > - dropped RFC prefix
>> >
>> > changes since RFC v2 at [5]:
>> > - add missing INIT_LIST_HEAD call in usb_phy_roothub_add_phy (affects
>> >   patch #1 - spotted by Roger Quadros, thank you!)
>> > - fixed swapped conditions using device_may_wakeup() in
>> >   usb_phy_roothub_resume because we need to call usb_phy_roothub_init
>> >   if the controller cannot wake up the device (affects patch #2, spotted
>> >   by Chunfeng Yun, thank you!)
>> > - simplified the error condition to "undo" usb_phy_roothub_init if
>> >   usb_phy_roothub_power_on failed in usb_phy_roothub_resume (suggested
>> >   by Chunfeng Yun)
>> > - updated the commit message (using Roger's wording) because (quote from
>> >   Roger "it doesn't prevent the system from entering suspend but just
>> >   prevents the system from reaching lowest power levels in the suspend
>> >   state."
>> >
>> > Changes since RFC v1 (blob attachments) at [4]:
>> > - use device_may_wakeup instead of device_can_wakeup as suggested by
>> >   Roger Quadros
>> > - use the controller device from hcd->self.controller as suggested by
>> >   Chunfeng Yun
>> > - compile time fixes thanks to Roger Quadros
>> > - if usb_phy_roothub_power_on in usb_phy_roothub_resume failes then
>> >   we now call usb_phy_roothub_exit to keep the PHYs in the correct
>> >   state if usb_phy_roothub_resume partially failed
>> >
>> >
>> > [0] 
>> > http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006599.html
>> > [1] 
>> > http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006737.html
>> > [2] 
>> > http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006758.html
>> > [3] 
>> > http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
>> > [4] 
>> > http://lists.infradead.org/pipermail/linux-amlogic/

Re: [usb-next PATCH v11 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-04-05 Thread Martin Blumenstingl
Hello,

(great to hear that this might be useful on Socionext SoCs as well :))

On Wed, Apr 4, 2018 at 2:10 PM, Masahiro Yamada
<yamada.masah...@socionext.com> wrote:
> 2018-03-04 6:43 GMT+09:00 Martin Blumenstingl
> <martin.blumensti...@googlemail.com>:
>> Many SoC platforms have separate devices for the USB PHY which are
>> registered through the generic PHY framework. These PHYs have to be
>> enabled to make the USB controller actually work. They also have to be
>> disabled again on shutdown/suspend.
>>
>> Currently (at least) the following HCI platform drivers are using custom
>> code to obtain all PHYs via devicetree for the roothub/controller and
>> disable/enable them when required:
>> - ehci-platform.c has ehci_platform_power_{on,off}
>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>> - ohci-platform.c has ohci_platform_power_{on,off}
>>
>> With this new wrapper the USB PHYs can be specified directly in the
>> USB controller's devicetree node (just like on the drivers listed
>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>> correctly once this is wired up correctly. These SoCs use a dwc3
>> controller and require all USB PHYs to be initialized (if one of the USB
>> PHYs it not initialized then none of USB port works at all).
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> Tested-by: Yixun Lan <yixun@amlogic.com>
>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>> ---
>>  drivers/usb/core/Makefile |   2 +-
>>  drivers/usb/core/phy.c| 158 
>> ++
>>  drivers/usb/core/phy.h|   7 ++
>>  3 files changed, 166 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/usb/core/phy.c
>>  create mode 100644 drivers/usb/core/phy.h
>>
>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>> index 92c9cefb4317..18e874b0441e 100644
>> --- a/drivers/usb/core/Makefile
>> +++ b/drivers/usb/core/Makefile
>> @@ -6,7 +6,7 @@
>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>> -usbcore-y += port.o
>> +usbcore-y += phy.o port.o
>>
>>  usbcore-$(CONFIG_OF)   += of.o
>>  usbcore-$(CONFIG_USB_PCI)  += hcd-pci.o
>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>> new file mode 100644
>> index ..09b7c43c0ea4
>> --- /dev/null
>> +++ b/drivers/usb/core/phy.c
>> @@ -0,0 +1,158 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * A wrapper for multiple PHYs which passes all phy_* function calls to
>> + * multiple (actual) PHY devices. This is comes handy when initializing
>> + * all PHYs on a HCD and to keep them all in the same state.
>> + *
>> + * Copyright (C) 2018 Martin Blumenstingl 
>> <martin.blumensti...@googlemail.com>
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include "phy.h"
>> +
>> +struct usb_phy_roothub {
>> +   struct phy  *phy;
>> +   struct list_headlist;
>> +};
>> +
>> +static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
>> +{
>> +   struct usb_phy_roothub *roothub_entry;
>> +
>> +   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), 
>> GFP_KERNEL);
>> +   if (!roothub_entry)
>> +   return ERR_PTR(-ENOMEM);
>> +
>> +   INIT_LIST_HEAD(_entry->list);
>> +
>> +   return roothub_entry;
>> +}
>> +
>> +static int usb_phy_roothub_add_phy(struct device *dev, int index,
>> +  struct list_head *list)
>> +{
>> +   struct usb_phy_roothub *roothub_entry;
>> +   struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
>> +
>> +   if (IS_ERR_OR_NULL(phy)) {
>> +   if (!phy || PTR_ERR(phy) == -ENODEV)
>> +   return 0;
>> +   else
>> +   return PTR_ERR(phy);
>> +   }
>> +
>> +   roothub_entry = usb_phy_roothub_alloc(dev);
>> +   if (IS_ERR(roothub_entry))
>> +   return PTR_ERR(roothub_entry);
>> +
>> +   roothub_entry->phy = phy;
>> +
>> +   list_add_tail(_entry->list, list);
>&

Re: [PATCH] usb: core: phy: Fix usb_phy_roothub_add_phy if GENERIC_PHY=n

2018-03-31 Thread Martin Blumenstingl
Hello Stefan,

On Sat, Mar 31, 2018 at 9:28 PM, Stefan Wahren  wrote:
> If the generic PHY support is disabled the stub of devm_of_phy_get_by_index
> returns ENOSYS. This corner case isn't handled properly by
> usb_phy_roothub_add_phy and at least breaks USB support on Raspberry Pi
> (bcm2835_defconfig):
>
> dwc2 2098.usb: dwc2_hcd_init() FAILED, returning -38
> dwc2: probe of 2098.usb failed with error -38
thank you for reporting and proposing a fix!

> Fixes: 07dbff0ddbd8 ("usb: core: add a wrapper for the USB PHYs on the HCD")
> Signed-off-by: Stefan Wahren 
> ---
>  drivers/usb/core/phy.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
> index 09b7c43..c89e9be 100644
> --- a/drivers/usb/core/phy.c
> +++ b/drivers/usb/core/phy.c
> @@ -39,7 +39,7 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
> index,
> struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
>
> if (IS_ERR_OR_NULL(phy)) {
> -   if (!phy || PTR_ERR(phy) == -ENODEV)
> +   if (!phy || PTR_ERR(phy) == -ENODEV || PTR_ERR(phy) == 
> -ENOSYS)
> return 0;
> else
> return PTR_ERR(phy);
> --
> 2.7.4
I have three patches pending, one of them (the patch from [1]) touches
the same function:
- "usb: core: phy: fix return value of usb_phy_roothub_exit()" [0]
- "usb: core: split usb_phy_roothub_{init, alloc}" [1]
- "usb: core: use phy_exit during suspend if wake up is not supported" [2]

maybe we should make it more explicit that the whole code is only
useful if CONFIG_GENERIC_PHY is enabled
what do you think about adding the following two lines at the
beginning of usb_phy_roothub_alloc (after patch [1] is applied, before
this function was basically called usb_phy_roothub_init)
if (!IS_ENABLED(CONFIG_GENERIC_PHY))
return NULL;

this should even allow the compiler to optimize away some unused code


Regards
Martin


[0] https://patchwork.kernel.org/patch/10306053/
[1] https://patchwork.kernel.org/patch/10311701/
[2] https://patchwork.kernel.org/patch/10311703/
--
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 usb-next v4 1/2] usb: core: split usb_phy_roothub_{init,alloc}

2018-03-27 Thread Martin Blumenstingl
Before this patch usb_phy_roothub_init served two purposes (from a
caller's point of view - like hcd.c):
- parsing the PHYs and allocating the list entries
- calling phy_init on each list entry

While this worked so far it has one disadvantage: if we need to call
phy_init for each PHY instance then the existing code cannot be re-used.
Solve this by splitting off usb_phy_roothub_alloc which only parses the
PHYs and allocates the list entries.
usb_phy_roothub_init then gets a struct usb_phy_roothub and only calls
phy_init on each PHY instance (along with the corresponding cleanup if
that failed somewhere).

This is a preparation step for adding proper suspend support for some
hardware that requires phy_exit to be called during suspend and phy_init
to be called during resume.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Chunfeng Yun <chunfeng@mediatek.com>
Reviewed-by: Roger Quadros <rog...@ti.com>
---
 drivers/usb/core/hcd.c | 10 +++---
 drivers/usb/core/phy.c | 53 +-
 drivers/usb/core/phy.h |  4 +++-
 3 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..15b0418e3b6a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2758,12 +2758,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
 
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
-   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
retval = PTR_ERR(hcd->phy_roothub);
-   goto err_phy_roothub_init;
+   goto err_phy_roothub_alloc;
}
 
+   retval = usb_phy_roothub_init(hcd->phy_roothub);
+   if (retval)
+   goto err_phy_roothub_alloc;
+
retval = usb_phy_roothub_power_on(hcd->phy_roothub);
if (retval)
goto err_usb_phy_roothub_power_on;
@@ -2936,7 +2940,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_phy_roothub_power_off(hcd->phy_roothub);
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
-err_phy_roothub_init:
+err_phy_roothub_alloc:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index f19aaa3c899c..44f008cda7a8 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -19,19 +19,6 @@ struct usb_phy_roothub {
struct list_headlist;
 };
 
-static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
-{
-   struct usb_phy_roothub *roothub_entry;
-
-   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
-   if (!roothub_entry)
-   return ERR_PTR(-ENOMEM);
-
-   INIT_LIST_HEAD(_entry->list);
-
-   return roothub_entry;
-}
-
 static int usb_phy_roothub_add_phy(struct device *dev, int index,
   struct list_head *list)
 {
@@ -45,9 +32,11 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return PTR_ERR(phy);
}
 
-   roothub_entry = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(roothub_entry))
-   return PTR_ERR(roothub_entry);
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(_entry->list);
 
roothub_entry->phy = phy;
 
@@ -56,11 +45,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return 0;
 }
 
-struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
 {
struct usb_phy_roothub *phy_roothub;
-   struct usb_phy_roothub *roothub_entry;
-   struct list_head *head;
int i, num_phys, err;
 
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
@@ -68,16 +55,31 @@ struct usb_phy_roothub *usb_phy_roothub_init(struct device 
*dev)
if (num_phys <= 0)
return NULL;
 
-   phy_roothub = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(phy_roothub))
-   return phy_roothub;
+   phy_roothub = devm_kzalloc(dev, sizeof(*phy_roothub), GFP_KERNEL);
+   if (!phy_roothub)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_roothub->list);
 
for (i = 0; i < num_phys; i++) {
err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
if (err)
-   goto err_out;
+   

[PATCH usb-next v4 2/2] usb: core: use phy_exit during suspend if wake up is not supported

2018-03-27 Thread Martin Blumenstingl
If the USB controller can wake up the system (which is the case for
example with the Mediatek USB3 IP) then we must not call phy_exit during
suspend to ensure that the USB controller doesn't have to re-enumerate
the devices during resume.
However, if the USB controller cannot wake up the system (which is the
case for example on various TI platforms using a dwc3 controller) then
we must call phy_exit during suspend. Otherwise the PHY driver keeps the
clocks enabled, which prevents the system from reaching the lowest power
levels in the suspend state.

Solve this by introducing two new functions in the PHY wrapper which are
dedicated to the suspend and resume handling.
If the controller can wake up the system the new usb_phy_roothub_suspend
function will simply call usb_phy_roothub_power_off. However, if wake up
is not supported by the controller it will also call
usb_phy_roothub_exit.
The also new usb_phy_roothub_resume function takes care of calling
usb_phy_roothub_init (if the controller can't wake up the system) in
addition to usb_phy_roothub_power_on.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Fixes: 178a0bce05cbc1 ("usb: core: hcd: integrate the PHY wrapper into the HCD 
core")
Reported-by: Roger Quadros <rog...@ti.com>
Suggested-by: Roger Quadros <rog...@ti.com>
Suggested-by: Chunfeng Yun <chunfeng@mediatek.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Chunfeng Yun <chunfeng@mediatek.com>
Reviewed-by: Roger Quadros <rog...@ti.com>
---
 drivers/usb/core/hcd.c |  8 +---
 drivers/usb/core/phy.c | 35 +++
 drivers/usb/core/phy.h |  5 +
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 15b0418e3b6a..78bae4ecd68b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2262,7 +2262,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
hcd->state = HC_STATE_SUSPENDED;
 
if (!PMSG_IS_AUTO(msg))
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev,
+   hcd->phy_roothub);
 
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
@@ -2302,7 +2303,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
 
if (!PMSG_IS_AUTO(msg)) {
-   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   status = usb_phy_roothub_resume(hcd->self.sysdev,
+   hcd->phy_roothub);
if (status)
return status;
}
@@ -2344,7 +2346,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 44f008cda7a8..a39d9bb26a4f 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -157,3 +157,38 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub 
*phy_roothub)
phy_power_off(roothub_entry->phy);
 }
 EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
+
+int usb_phy_roothub_suspend(struct device *controller_dev,
+   struct usb_phy_roothub *phy_roothub)
+{
+   usb_phy_roothub_power_off(phy_roothub);
+
+   /* keep the PHYs initialized so the device can wake up the system */
+   if (device_may_wakeup(controller_dev))
+   return 0;
+
+   return usb_phy_roothub_exit(phy_roothub);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend);
+
+int usb_phy_roothub_resume(struct device *controller_dev,
+  struct usb_phy_roothub *phy_roothub)
+{
+   int err;
+
+   /* if the device can't wake up the system _exit was called */
+   if (!device_may_wakeup(controller_dev)) {
+   err = usb_phy_roothub_init(phy_roothub);
+   if (err)
+   return err;
+   }
+
+   err = usb_phy_roothub_power_on(phy_roothub);
+
+   /* undo _init if _power_on failed */
+   if (err && !device_may_wakeup(controller_dev))
+   usb_phy_roothub_exit(phy_roothub);
+
+   return err;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_resume);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index eb31253201ad..60901d44 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -7,3

[PATCH usb-next v4 0/2] fix HCD PHY suspend handling

2018-03-27 Thread Martin Blumenstingl
This is a follow-up to my previous series "initialize (multiple) PHYs
for a HCD": [0].

Roger Quadros reported [1] that it "is breaking low power cases on TI
SoCs when USB is in host mode". He further explains that "Not doing the
phy_exit() here [when entering suspend] leaves the clocks enabled on
our SoC and we're no longer able to reach low power states on system
suspend."
Chunfeng Yun from Mediatek noted [2] that we cannot unconditionally call
phy_exit while entering system suspend, because this would "disconnect
plugged devices on MTK platforms, due to re-initialize u2 phys when
resume"

In the discussion (which followed Roger's bug report: [1]) Roger,
Chunfeng and me came to the conclusion that we can fix suspend on the
TI SoCs without breaking it on the Mediatek SoCs by extending the
suspend and resume code in usb/core/phy.c by checking whether the USB
controller can wake up the system (which is the case for the Mediatek
MTU3 controller, but now for the dwc3 controller used on the TI SoCs):
- if the controller can wake up the system (Mediatek MTU3 use-case) we
  only call usb_phy_roothub_power_off (which calls phy_power_off) when
  entering system suspend
- if the controller however cannot wake up the system (dwc3 on TI SoCs)
  we additionally call usb_phy_roothub_exit (which calls phy_exit) when
  entering system suspend
- (we undo the previous steps during system resume)

The goal of this series is to fix the issue reported by Roger without
breaking suspend/resume on the Mediatek SoCs.
Since I neither have a TI nor a Mediatek device I am sending this as
RFC. I have tested it on an Amlogic Meson GXM board (Khadas VIM2) which
does NOT support suspend/resume yet.

this should be applied on top of [3] "usb: core: phy: fix return value
of usb_phy_roothub_exit()" (even though there's no strict dependency,
this is the order I wrote the patches in).

changes since RFC v3 at [6]:
- added Chunfeng Yun's Tested-by and Roger Quadros' Reviewed-by (thank
  you!)
- dropped RFC prefix

changes since RFC v2 at [5]:
- add missing INIT_LIST_HEAD call in usb_phy_roothub_add_phy (affects
  patch #1 - spotted by Roger Quadros, thank you!)
- fixed swapped conditions using device_may_wakeup() in
  usb_phy_roothub_resume because we need to call usb_phy_roothub_init
  if the controller cannot wake up the device (affects patch #2, spotted
  by Chunfeng Yun, thank you!)
- simplified the error condition to "undo" usb_phy_roothub_init if
  usb_phy_roothub_power_on failed in usb_phy_roothub_resume (suggested
  by Chunfeng Yun)
- updated the commit message (using Roger's wording) because (quote from
  Roger "it doesn't prevent the system from entering suspend but just
  prevents the system from reaching lowest power levels in the suspend
  state."

Changes since RFC v1 (blob attachments) at [4]:
- use device_may_wakeup instead of device_can_wakeup as suggested by
  Roger Quadros
- use the controller device from hcd->self.controller as suggested by
  Chunfeng Yun
- compile time fixes thanks to Roger Quadros
- if usb_phy_roothub_power_on in usb_phy_roothub_resume failes then
  we now call usb_phy_roothub_exit to keep the PHYs in the correct
  state if usb_phy_roothub_resume partially failed


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006599.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006737.html
[2] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006758.html
[3] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
[4] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006794.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006820.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006847.html

Martin Blumenstingl (2):
  usb: core: split usb_phy_roothub_{init,alloc}
  usb: core: use phy_exit during suspend if wake up is not supported

 drivers/usb/core/hcd.c | 18 +++
 drivers/usb/core/phy.c | 88 +++---
 drivers/usb/core/phy.h |  9 +-
 3 files changed, 82 insertions(+), 33 deletions(-)

-- 
2.16.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


[RFC usb-next v3 2/2] usb: core: use phy_exit during suspend if wake up is not supported

2018-03-26 Thread Martin Blumenstingl
If the USB controller can wake up the system (which is the case for
example with the Mediatek USB3 IP) then we must not call phy_exit during
suspend to ensure that the USB controller doesn't have to re-enumerate
the devices during resume.
However, if the USB controller cannot wake up the system (which is the
case for example on various TI platforms using a dwc3 controller) then
we must call phy_exit during suspend. Otherwise the PHY driver keeps the
clocks enabled, which prevents the system from reaching the lowest power
levels in the suspend state.

Solve this by introducing two new functions in the PHY wrapper which are
dedicated to the suspend and resume handling.
If the controller can wake up the system the new usb_phy_roothub_suspend
function will simply call usb_phy_roothub_power_off. However, if wake up
is not supported by the controller it will also call
usb_phy_roothub_exit.
The also new usb_phy_roothub_resume function takes care of calling
usb_phy_roothub_init (if the controller can't wake up the system) in
addition to usb_phy_roothub_power_on.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Fixes: 178a0bce05cbc1 ("usb: core: hcd: integrate the PHY wrapper into the HCD 
core")
Reported-by: Roger Quadros <rog...@ti.com>
Suggested-by: Roger Quadros <rog...@ti.com>
Suggested-by: Chunfeng Yun <chunfeng@mediatek.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c |  8 +---
 drivers/usb/core/phy.c | 35 +++
 drivers/usb/core/phy.h |  5 +
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 15b0418e3b6a..78bae4ecd68b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2262,7 +2262,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
hcd->state = HC_STATE_SUSPENDED;
 
if (!PMSG_IS_AUTO(msg))
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev,
+   hcd->phy_roothub);
 
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
@@ -2302,7 +2303,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
 
if (!PMSG_IS_AUTO(msg)) {
-   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   status = usb_phy_roothub_resume(hcd->self.sysdev,
+   hcd->phy_roothub);
if (status)
return status;
}
@@ -2344,7 +2346,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 44f008cda7a8..a39d9bb26a4f 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -157,3 +157,38 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub 
*phy_roothub)
phy_power_off(roothub_entry->phy);
 }
 EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
+
+int usb_phy_roothub_suspend(struct device *controller_dev,
+   struct usb_phy_roothub *phy_roothub)
+{
+   usb_phy_roothub_power_off(phy_roothub);
+
+   /* keep the PHYs initialized so the device can wake up the system */
+   if (device_may_wakeup(controller_dev))
+   return 0;
+
+   return usb_phy_roothub_exit(phy_roothub);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend);
+
+int usb_phy_roothub_resume(struct device *controller_dev,
+  struct usb_phy_roothub *phy_roothub)
+{
+   int err;
+
+   /* if the device can't wake up the system _exit was called */
+   if (!device_may_wakeup(controller_dev)) {
+   err = usb_phy_roothub_init(phy_roothub);
+   if (err)
+   return err;
+   }
+
+   err = usb_phy_roothub_power_on(phy_roothub);
+
+   /* undo _init if _power_on failed */
+   if (err && !device_may_wakeup(controller_dev))
+   usb_phy_roothub_exit(phy_roothub);
+
+   return err;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_resume);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index eb31253201ad..60901d44 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -7,3 +7,8 @@ int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub);
 
 int usb_phy_roothub_power_on(

[RFC usb-next v3 0/2] fix HCD PHY suspend handling

2018-03-26 Thread Martin Blumenstingl
This is a follow-up to my previous series "initialize (multiple) PHYs
for a HCD": [0].

Roger Quadros reported [1] that it "is breaking low power cases on TI
SoCs when USB is in host mode". He further explains that "Not doing the
phy_exit() here [when entering suspend] leaves the clocks enabled on
our SoC and we're no longer able to reach low power states on system
suspend."
Chunfeng Yun from Mediatek noted [2] that we cannot unconditionally call
phy_exit while entering system suspend, because this would "disconnect
plugged devices on MTK platforms, due to re-initialize u2 phys when
resume"

In the discussion (which followed Roger's bug report: [1]) Roger,
Chunfeng and me came to the conclusion that we can fix suspend on the
TI SoCs without breaking it on the Mediatek SoCs by extending the
suspend and resume code in usb/core/phy.c by checking whether the USB
controller can wake up the system (which is the case for the Mediatek
MTU3 controller, but now for the dwc3 controller used on the TI SoCs):
- if the controller can wake up the system (Mediatek MTU3 use-case) we
  only call usb_phy_roothub_power_off (which calls phy_power_off) when
  entering system suspend
- if the controller however cannot wake up the system (dwc3 on TI SoCs)
  we additionally call usb_phy_roothub_exit (which calls phy_exit) when
  entering system suspend
- (we undo the previous steps during system resume)

The goal of this series is to fix the issue reported by Roger without
breaking suspend/resume on the Mediatek SoCs.
Since I neither have a TI nor a Mediatek device I am sending this as
RFC. I have tested it on an Amlogic Meson GXM board (Khadas VIM2) which
does NOT support suspend/resume yet.

this should be applied on top of [3] "usb: core: phy: fix return value
of usb_phy_roothub_exit()" (even though there's no strict dependency,
this is the order I wrote the patches in).


changes since RFC v2 at [5]:
- add missing INIT_LIST_HEAD call in usb_phy_roothub_add_phy (affects
  patch #1 - spotted by Roger Quadros, thank you!)
- fixed swapped conditions using device_may_wakeup() in
  usb_phy_roothub_resume because we need to call usb_phy_roothub_init
  if the controller cannot wake up the device (affects patch #2, spotted
  by Chunfeng Yun, thank you!)
- simplified the error condition to "undo" usb_phy_roothub_init if
  usb_phy_roothub_power_on failed in usb_phy_roothub_resume (suggested
  by Chunfeng Yun)
- updated the commit message (using Roger's wording) because (quote from
  Roger "it doesn't prevent the system from entering suspend but just
  prevents the system from reaching lowest power levels in the suspend
  state."

Changes since RFC v1 (blob attachments) at [4]:
- use device_may_wakeup instead of device_can_wakeup as suggested by
  Roger Quadros
- use the controller device from hcd->self.controller as suggested by
  Chunfeng Yun
- compile time fixes thanks to Roger Quadros
- if usb_phy_roothub_power_on in usb_phy_roothub_resume failes then
  we now call usb_phy_roothub_exit to keep the PHYs in the correct
  state if usb_phy_roothub_resume partially failed


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006599.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006737.html
[2] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006758.html
[3] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
[4] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006794.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006820.html

Martin Blumenstingl (2):
  usb: core: split usb_phy_roothub_{init,alloc}
  usb: core: use phy_exit during suspend if wake up is not supported

 drivers/usb/core/hcd.c | 18 +++
 drivers/usb/core/phy.c | 88 +++---
 drivers/usb/core/phy.h |  9 +-
 3 files changed, 82 insertions(+), 33 deletions(-)

-- 
2.16.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


[RFC usb-next v3 1/2] usb: core: split usb_phy_roothub_{init,alloc}

2018-03-26 Thread Martin Blumenstingl
Before this patch usb_phy_roothub_init served two purposes (from a
caller's point of view - like hcd.c):
- parsing the PHYs and allocating the list entries
- calling phy_init on each list entry

While this worked so far it has one disadvantage: if we need to call
phy_init for each PHY instance then the existing code cannot be re-used.
Solve this by splitting off usb_phy_roothub_alloc which only parses the
PHYs and allocates the list entries.
usb_phy_roothub_init then gets a struct usb_phy_roothub and only calls
phy_init on each PHY instance (along with the corresponding cleanup if
that failed somewhere).

This is a preparation step for adding proper suspend support for some
hardware that requires phy_exit to be called during suspend and phy_init
to be called during resume.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c | 10 +++---
 drivers/usb/core/phy.c | 53 +-
 drivers/usb/core/phy.h |  4 +++-
 3 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..15b0418e3b6a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2758,12 +2758,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
 
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
-   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
retval = PTR_ERR(hcd->phy_roothub);
-   goto err_phy_roothub_init;
+   goto err_phy_roothub_alloc;
}
 
+   retval = usb_phy_roothub_init(hcd->phy_roothub);
+   if (retval)
+   goto err_phy_roothub_alloc;
+
retval = usb_phy_roothub_power_on(hcd->phy_roothub);
if (retval)
goto err_usb_phy_roothub_power_on;
@@ -2936,7 +2940,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_phy_roothub_power_off(hcd->phy_roothub);
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
-err_phy_roothub_init:
+err_phy_roothub_alloc:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index f19aaa3c899c..44f008cda7a8 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -19,19 +19,6 @@ struct usb_phy_roothub {
struct list_headlist;
 };
 
-static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
-{
-   struct usb_phy_roothub *roothub_entry;
-
-   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
-   if (!roothub_entry)
-   return ERR_PTR(-ENOMEM);
-
-   INIT_LIST_HEAD(_entry->list);
-
-   return roothub_entry;
-}
-
 static int usb_phy_roothub_add_phy(struct device *dev, int index,
   struct list_head *list)
 {
@@ -45,9 +32,11 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return PTR_ERR(phy);
}
 
-   roothub_entry = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(roothub_entry))
-   return PTR_ERR(roothub_entry);
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(_entry->list);
 
roothub_entry->phy = phy;
 
@@ -56,11 +45,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return 0;
 }
 
-struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
 {
struct usb_phy_roothub *phy_roothub;
-   struct usb_phy_roothub *roothub_entry;
-   struct list_head *head;
int i, num_phys, err;
 
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
@@ -68,16 +55,31 @@ struct usb_phy_roothub *usb_phy_roothub_init(struct device 
*dev)
if (num_phys <= 0)
return NULL;
 
-   phy_roothub = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(phy_roothub))
-   return phy_roothub;
+   phy_roothub = devm_kzalloc(dev, sizeof(*phy_roothub), GFP_KERNEL);
+   if (!phy_roothub)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_roothub->list);
 
for (i = 0; i < num_phys; i++) {
err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
if (err)
-   goto err_out;
+   return ERR_PTR(err);
}
 
+   return phy_roothub;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_alloc);
+
+int usb_p

Re: [RFC usb-next v2 1/2] usb: core: split usb_phy_roothub_{init,alloc}

2018-03-26 Thread Martin Blumenstingl
Hi Chunfeng,

On Mon, Mar 26, 2018 at 5:37 AM, Chunfeng Yun <chunfeng@mediatek.com> wrote:
> On Sat, 2018-03-24 at 15:21 +0100, Martin Blumenstingl wrote:
>> Before this patch usb_phy_roothub_init served two purposes (from a
>> caller's point of view - like hcd.c):
>> - parsing the PHYs and allocating the list entries
>> - calling phy_init on each list entry
>>
>> While this worked so far it has one disadvantage: if we need to call
>> phy_init for each PHY instance then the existing code cannot be re-used.
>> Solve this by splitting off usb_phy_roothub_alloc which only parses the
>> PHYs and allocates the list entries.
>> usb_phy_roothub_init then gets a struct usb_phy_roothub and only calls
>> phy_init on each PHY instance (along with the corresponding cleanup if
>> that failed somewhere).
>>
>> This is a preparation step for adding proper suspend support for some
>> hardware that requires phy_exit to be called during suspend and phy_init
>> to be called during resume.
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>>  drivers/usb/core/hcd.c | 10 +++---
>>  drivers/usb/core/phy.c | 51 
>> +-
>>  drivers/usb/core/phy.h |  4 +++-
>>  3 files changed, 35 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
>> index 777036ae6367..15b0418e3b6a 100644
>> --- a/drivers/usb/core/hcd.c
>> +++ b/drivers/usb/core/hcd.c
>> @@ -2758,12 +2758,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
>>   }
>>
>>   if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
>> - hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
>> + hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
>>   if (IS_ERR(hcd->phy_roothub)) {
>>   retval = PTR_ERR(hcd->phy_roothub);
>> - goto err_phy_roothub_init;
>> + goto err_phy_roothub_alloc;
>>   }
>>
>> + retval = usb_phy_roothub_init(hcd->phy_roothub);
>> + if (retval)
>> + goto err_phy_roothub_alloc;
>> +
>>   retval = usb_phy_roothub_power_on(hcd->phy_roothub);
>>   if (retval)
>>   goto err_usb_phy_roothub_power_on;
>> @@ -2936,7 +2940,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
>>   usb_phy_roothub_power_off(hcd->phy_roothub);
>>  err_usb_phy_roothub_power_on:
>>   usb_phy_roothub_exit(hcd->phy_roothub);
>> -err_phy_roothub_init:
>> +err_phy_roothub_alloc:
>>   if (hcd->remove_phy && hcd->usb_phy) {
>>   usb_phy_shutdown(hcd->usb_phy);
>>   usb_put_phy(hcd->usb_phy);
>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>> index f19aaa3c899c..d1861c5a74de 100644
>> --- a/drivers/usb/core/phy.c
>> +++ b/drivers/usb/core/phy.c
>> @@ -19,19 +19,6 @@ struct usb_phy_roothub {
>>   struct list_headlist;
>>  };
>>
>> -static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
>> -{
>> - struct usb_phy_roothub *roothub_entry;
>> -
>> - roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
>> - if (!roothub_entry)
>> - return ERR_PTR(-ENOMEM);
>> -
>> - INIT_LIST_HEAD(_entry->list);
>> -
>> - return roothub_entry;
>> -}
>> -
>>  static int usb_phy_roothub_add_phy(struct device *dev, int index,
>>  struct list_head *list)
>>  {
>> @@ -45,9 +32,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
>> index,
>>   return PTR_ERR(phy);
>>   }
>
>>
>> - roothub_entry = usb_phy_roothub_alloc(dev);
>> - if (IS_ERR(roothub_entry))
>> - return PTR_ERR(roothub_entry);
>> + roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
>> + if (!roothub_entry)
>> + return -ENOMEM;
>>
>>   roothub_entry->phy = phy;
>>
>> @@ -56,11 +43,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, 
>> int index,
>>   return 0;
>>  }
>>
>> -struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
>> +struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
>>  {
>>   struct usb_phy_ro

Re: [PATCH usb-next v1] usb: core: phy: fix return value of usb_phy_roothub_exit()

2018-03-26 Thread Martin Blumenstingl
Hi Chunfeng,

On Mon, Mar 26, 2018 at 5:43 AM, Chunfeng Yun <chunfeng@mediatek.com> wrote:
> On Sat, 2018-03-24 at 14:56 +0100, Martin Blumenstingl wrote:
>> usb_phy_roothub_exit() should return the error code from the phy_exit()
>> call if exiting the PHY failed.
>> However, since a wrong variable is used usb_phy_roothub_exit() currently
>> always returns 0, even if one of the phy_exit calls returned an error.
>> Fix this by assigning the error code from phy_exit() to the "ret"
>> variable to propagate the error correctly.
>>
>> Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the 
>> HCD")
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>>  drivers/usb/core/phy.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>> index 09b7c43c0ea4..f19aaa3c899c 100644
>> --- a/drivers/usb/core/phy.c
>> +++ b/drivers/usb/core/phy.c
>> @@ -111,7 +111,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub 
>> *phy_roothub)
>>   list_for_each_entry(roothub_entry, head, list) {
>>   err = phy_exit(roothub_entry->phy);
>>   if (err)
>> - ret = ret;
>> + ret = err;
> Need break the loop?
in the original implementation I decided not to break the loop here so
phy_exit is called for all PHYs -> only the problematic ones will
remain initialized
(in the _power_on implementation we can try to fix the state by adding
a break and then calling _power_off for all PHYs before the "broken"
one where _power_on failed)

also if phy_exit fails then something is probably very wrong

do you have any specific use-case in mind where the missing break
could be a problem?

>>   }
>>
>>   return ret;
>
>


Regards
Martin
--
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 usb-next v2 1/2] usb: core: split usb_phy_roothub_{init,alloc}

2018-03-24 Thread Martin Blumenstingl
Before this patch usb_phy_roothub_init served two purposes (from a
caller's point of view - like hcd.c):
- parsing the PHYs and allocating the list entries
- calling phy_init on each list entry

While this worked so far it has one disadvantage: if we need to call
phy_init for each PHY instance then the existing code cannot be re-used.
Solve this by splitting off usb_phy_roothub_alloc which only parses the
PHYs and allocates the list entries.
usb_phy_roothub_init then gets a struct usb_phy_roothub and only calls
phy_init on each PHY instance (along with the corresponding cleanup if
that failed somewhere).

This is a preparation step for adding proper suspend support for some
hardware that requires phy_exit to be called during suspend and phy_init
to be called during resume.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c | 10 +++---
 drivers/usb/core/phy.c | 51 +-
 drivers/usb/core/phy.h |  4 +++-
 3 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..15b0418e3b6a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2758,12 +2758,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
 
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
-   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
retval = PTR_ERR(hcd->phy_roothub);
-   goto err_phy_roothub_init;
+   goto err_phy_roothub_alloc;
}
 
+   retval = usb_phy_roothub_init(hcd->phy_roothub);
+   if (retval)
+   goto err_phy_roothub_alloc;
+
retval = usb_phy_roothub_power_on(hcd->phy_roothub);
if (retval)
goto err_usb_phy_roothub_power_on;
@@ -2936,7 +2940,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_phy_roothub_power_off(hcd->phy_roothub);
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
-err_phy_roothub_init:
+err_phy_roothub_alloc:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index f19aaa3c899c..d1861c5a74de 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -19,19 +19,6 @@ struct usb_phy_roothub {
struct list_headlist;
 };
 
-static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
-{
-   struct usb_phy_roothub *roothub_entry;
-
-   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
-   if (!roothub_entry)
-   return ERR_PTR(-ENOMEM);
-
-   INIT_LIST_HEAD(_entry->list);
-
-   return roothub_entry;
-}
-
 static int usb_phy_roothub_add_phy(struct device *dev, int index,
   struct list_head *list)
 {
@@ -45,9 +32,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return PTR_ERR(phy);
}
 
-   roothub_entry = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(roothub_entry))
-   return PTR_ERR(roothub_entry);
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return -ENOMEM;
 
roothub_entry->phy = phy;
 
@@ -56,11 +43,9 @@ static int usb_phy_roothub_add_phy(struct device *dev, int 
index,
return 0;
 }
 
-struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
 {
struct usb_phy_roothub *phy_roothub;
-   struct usb_phy_roothub *roothub_entry;
-   struct list_head *head;
int i, num_phys, err;
 
num_phys = of_count_phandle_with_args(dev->of_node, "phys",
@@ -68,16 +53,31 @@ struct usb_phy_roothub *usb_phy_roothub_init(struct device 
*dev)
if (num_phys <= 0)
return NULL;
 
-   phy_roothub = usb_phy_roothub_alloc(dev);
-   if (IS_ERR(phy_roothub))
-   return phy_roothub;
+   phy_roothub = devm_kzalloc(dev, sizeof(*phy_roothub), GFP_KERNEL);
+   if (!phy_roothub)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_roothub->list);
 
for (i = 0; i < num_phys; i++) {
err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
if (err)
-   goto err_out;
+   return ERR_PTR(err);
}
 
+   return phy_roothub;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_alloc);
+
+int usb_phy_roothub_init(struct usb_phy_root

[RFC usb-next v2 0/2] fix HCD PHY suspend handling

2018-03-24 Thread Martin Blumenstingl
This is a follow-up to my previous series "initialize (multiple) PHYs
for a HCD": [0].

Roger Quadros reported [1] that it "is breaking low power cases on TI
SoCs when USB is in host mode". He further explains that "Not doing the
phy_exit() here [when entering suspend] leaves the clocks enabled on
our SoC and we're no longer able to reach low power states on system
suspend."
Chunfeng Yun from Mediatek noted [2] that we cannot unconditionally call
phy_exit while entering system suspend, because this would "disconnect
plugged devices on MTK platforms, due to re-initialize u2 phys when
resume"

In the discussion (which followed Roger's bug report: [1]) Roger,
Chunfeng and me came to the conclusion that we can fix suspend on the
TI SoCs without breaking it on the Mediatek SoCs by extending the
suspend and resume code in usb/core/phy.c by checking whether the USB
controller can wake up the system (which is the case for the Mediatek
MTU3 controller, but now for the dwc3 controller used on the TI SoCs):
- if the controller can wake up the system (Mediatek MTU3 use-case) we
  only call usb_phy_roothub_power_off (which calls phy_power_off) when
  entering system suspend
- if the controller however cannot wake up the system (dwc3 on TI SoCs)
  we additionally call usb_phy_roothub_exit (which calls phy_exit) when
  entering system suspend
- (we undo the previous steps during system resume)

The goal of this series is to fix the issue reported by Roger without
breaking suspend/resume on the Mediatek SoCs.
Since I neither have a TI nor a Mediatek device I am sending this as
RFC. I have tested it on an Amlogic Meson GXM board (Khadas VIM2) which
does NOT support suspend/resume yet.

this should be applied on top of [3] "usb: core: phy: fix return value
of usb_phy_roothub_exit()" (even though there's no strict dependency,
this is the order I wrote the patches in).

Changes since v1 (blob attachments) at [4]:
- use device_may_wakeup instead of device_can_wakeup as suggested by
  Roger Quadros
- use the controller device from hcd->self.controller as suggested by
  Chunfeng Yun
- compile time fixes thanks to Roger Quadros
- if usb_phy_roothub_power_on in usb_phy_roothub_resume failes then
  we now call usb_phy_roothub_exit to keep the PHYs in the correct
  state if usb_phy_roothub_resume partially failed


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006599.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006737.html
[2] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006758.html
[3] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006819.html
[4] http://lists.infradead.org/pipermail/linux-amlogic/2018-March/006794.html


Martin Blumenstingl (2):
  usb: core: split usb_phy_roothub_{init,alloc}
  usb: core: use phy_exit during suspend if wake up is not supported

 drivers/usb/core/hcd.c | 18 +++
 drivers/usb/core/phy.c | 88 +++---
 drivers/usb/core/phy.h |  9 +-
 3 files changed, 82 insertions(+), 33 deletions(-)

-- 
2.16.2

--
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 usb-next v2 2/2] usb: core: use phy_exit during suspend if wake up is not supported

2018-03-24 Thread Martin Blumenstingl
If the USB controller can wake up the system (which is the case for
example with the Mediatek USB3 IP) then we must not call phy_exit during
suspend to ensure that the USB controller doesn't have to re-enumerate
the devices during resume.
However, if the USB controller cannot wake up the system (which is the
case for example on various TI platforms using a dwc3 controller) then
we must call phy_exit during suspend. Otherwise the PHY driver keeps the
clocks enabled, which prevents the system from entering the suspend
state.

Solve this by introducing two new functions in the PHY wrapper which are
dedicated to the suspend and resume handling.
If the controller can wake up the system the new usb_phy_roothub_suspend
function will simply call usb_phy_roothub_power_off. However, if wake up
is not supported by the controller it will also call
usb_phy_roothub_exit.
The also new usb_phy_roothub_resume function takes care of calling
usb_phy_roothub_init (if the controller can't wake up the system) in
addition to usb_phy_roothub_power_on.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Fixes: 178a0bce05cbc1 ("usb: core: hcd: integrate the PHY wrapper into the HCD 
core")
Reported-by: Roger Quadros <rog...@ti.com>
Suggested-by: Roger Quadros <rog...@ti.com>
Suggested-by: Chunfeng Yun <chunfeng@mediatek.com>
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c |  8 +---
 drivers/usb/core/phy.c | 37 +
 drivers/usb/core/phy.h |  5 +
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 15b0418e3b6a..78bae4ecd68b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2262,7 +2262,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
hcd->state = HC_STATE_SUSPENDED;
 
if (!PMSG_IS_AUTO(msg))
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev,
+   hcd->phy_roothub);
 
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
@@ -2302,7 +2303,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
 
if (!PMSG_IS_AUTO(msg)) {
-   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   status = usb_phy_roothub_resume(hcd->self.sysdev,
+   hcd->phy_roothub);
if (status)
return status;
}
@@ -2344,7 +2346,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
-   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index d1861c5a74de..e794cbee97e9 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -155,3 +155,40 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub 
*phy_roothub)
phy_power_off(roothub_entry->phy);
 }
 EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
+
+int usb_phy_roothub_suspend(struct device *controller_dev,
+   struct usb_phy_roothub *phy_roothub)
+{
+   usb_phy_roothub_power_off(phy_roothub);
+
+   /* keep the PHYs initialized so the device can wake up the system */
+   if (device_may_wakeup(controller_dev))
+   return 0;
+
+   return usb_phy_roothub_exit(phy_roothub);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend);
+
+int usb_phy_roothub_resume(struct device *controller_dev,
+  struct usb_phy_roothub *phy_roothub)
+{
+   int err;
+
+   /* if the device can't wake up the system _exit was called */
+   if (device_may_wakeup(controller_dev)) {
+   err = usb_phy_roothub_init(phy_roothub);
+   if (err)
+   return err;
+   }
+
+   err = usb_phy_roothub_power_on(phy_roothub);
+   if (err) {
+   if (device_may_wakeup(controller_dev))
+   usb_phy_roothub_exit(phy_roothub);
+
+   return err;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_resume);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index eb31253201ad..60901d44 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -7,3 +7,8 @@ int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub);
 
 int usb_phy_roothub_power_on(struct u

[PATCH usb-next v1] usb: core: phy: fix return value of usb_phy_roothub_exit()

2018-03-24 Thread Martin Blumenstingl
usb_phy_roothub_exit() should return the error code from the phy_exit()
call if exiting the PHY failed.
However, since a wrong variable is used usb_phy_roothub_exit() currently
always returns 0, even if one of the phy_exit calls returned an error.
Fix this by assigning the error code from phy_exit() to the "ret"
variable to propagate the error correctly.

Fixes: 07dbff0ddbd86c ("usb: core: add a wrapper for the USB PHYs on the HCD")
Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 09b7c43c0ea4..f19aaa3c899c 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -111,7 +111,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub 
*phy_roothub)
list_for_each_entry(roothub_entry, head, list) {
err = phy_exit(roothub_entry->phy);
if (err)
-   ret = ret;
+   ret = err;
}
 
return ret;
-- 
2.16.2

--
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 usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-03-24 Thread Martin Blumenstingl
Hi Roger,

On Wed, Mar 21, 2018 at 12:30 PM, Roger Quadros <rog...@ti.com> wrote:
> Martin,
>
> On 21/03/18 00:01, Martin Blumenstingl wrote:
>> Hi Roger, Hi Chunfeng,
>>
>> On Tue, Mar 20, 2018 at 1:04 PM, Chunfeng Yun <chunfeng@mediatek.com> 
>> wrote:
>>> Hi Martin & Roger:
>>>
>>> On Mon, 2018-03-19 at 17:12 +0100, Martin Blumenstingl wrote:
>>>> Hi Roger,
>>>>
>>>> On Mon, Mar 19, 2018 at 9:49 AM, Roger Quadros <rog...@ti.com> wrote:
>>>>> Hi,
>>>>>
>>>>> On 19/03/18 00:29, Martin Blumenstingl wrote:
>>>>>> Hi Roger,
>>>>>>
>>>>>> On Fri, Mar 16, 2018 at 3:32 PM, Roger Quadros <rog...@ti.com> wrote:
>>>>>>> +some TI folks
>>>>>>>
>>>>>>> Hi Martin,
>>>>>>>
>>>>>>> On 18/02/18 20:44, Martin Blumenstingl wrote:
>>>>>>>> Many SoC platforms have separate devices for the USB PHY which are
>>>>>>>> registered through the generic PHY framework. These PHYs have to be
>>>>>>>> enabled to make the USB controller actually work. They also have to be
>>>>>>>> disabled again on shutdown/suspend.
>>>>>>>>
>>>>>>>> Currently (at least) the following HCI platform drivers are using 
>>>>>>>> custom
>>>>>>>> code to obtain all PHYs via devicetree for the roothub/controller and
>>>>>>>> disable/enable them when required:
>>>>>>>> - ehci-platform.c has ehci_platform_power_{on,off}
>>>>>>>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>>>>>>>> - ohci-platform.c has ohci_platform_power_{on,off}
>>>>>>>>
>>>>>>>> With this new wrapper the USB PHYs can be specified directly in the
>>>>>>>> USB controller's devicetree node (just like on the drivers listed
>>>>>>>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>>>>>>>> correctly once this is wired up correctly. These SoCs use a dwc3
>>>>>>>> controller and require all USB PHYs to be initialized (if one of the 
>>>>>>>> USB
>>>>>>>> PHYs it not initialized then none of USB port works at all).
>>>>>>>>
>>>>>>>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>>>>>>>> Tested-by: Yixun Lan <yixun@amlogic.com>
>>>>>>>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>>>>>>>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>>>>>>>
>>>>>>> This patch is breaking low power cases on TI SoCs when USB is in host 
>>>>>>> mode.
>>>>>>> I'll explain why below.
>>>>>> based on your explanation and reading the TI PHY drivers I am assuming
>>>>>> that the affected SoCs are using the "phy-omap-usb2" driver
>>>>>>
>>>>> yes and phy-ti-pipe3 as well i.e. "ti,phy-usb3" and "ti,omap-usb3"
>>>> I missed that, thanks
>>>>
>>>>>>>> ---
>>>>>>>>  drivers/usb/core/Makefile |   2 +-
>>>>>>>>  drivers/usb/core/phy.c| 158 
>>>>>>>> ++
>>>>>>>>  drivers/usb/core/phy.h|   7 ++
>>>>>>>>  3 files changed, 166 insertions(+), 1 deletion(-)
>>>>>>>>  create mode 100644 drivers/usb/core/phy.c
>>>>>>>>  create mode 100644 drivers/usb/core/phy.h
>>>>>>>>
>>>>>>>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>>>>>>>> index 92c9cefb4317..18e874b0441e 100644
>>>>>>>> --- a/drivers/usb/core/Makefile
>>>>>>>> +++ b/drivers/usb/core/Makefile
>>>>>>>> @@ -6,7 +6,7 @@
>>>>>>>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>>>>>>>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>>>>>>>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>>>>>>>> -usbcore-y += port.o
>>>>&

Re: [PATCH usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-03-20 Thread Martin Blumenstingl
Hi Roger, Hi Chunfeng,

On Tue, Mar 20, 2018 at 1:04 PM, Chunfeng Yun <chunfeng@mediatek.com> wrote:
> Hi Martin & Roger:
>
> On Mon, 2018-03-19 at 17:12 +0100, Martin Blumenstingl wrote:
>> Hi Roger,
>>
>> On Mon, Mar 19, 2018 at 9:49 AM, Roger Quadros <rog...@ti.com> wrote:
>> > Hi,
>> >
>> > On 19/03/18 00:29, Martin Blumenstingl wrote:
>> >> Hi Roger,
>> >>
>> >> On Fri, Mar 16, 2018 at 3:32 PM, Roger Quadros <rog...@ti.com> wrote:
>> >>> +some TI folks
>> >>>
>> >>> Hi Martin,
>> >>>
>> >>> On 18/02/18 20:44, Martin Blumenstingl wrote:
>> >>>> Many SoC platforms have separate devices for the USB PHY which are
>> >>>> registered through the generic PHY framework. These PHYs have to be
>> >>>> enabled to make the USB controller actually work. They also have to be
>> >>>> disabled again on shutdown/suspend.
>> >>>>
>> >>>> Currently (at least) the following HCI platform drivers are using custom
>> >>>> code to obtain all PHYs via devicetree for the roothub/controller and
>> >>>> disable/enable them when required:
>> >>>> - ehci-platform.c has ehci_platform_power_{on,off}
>> >>>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>> >>>> - ohci-platform.c has ohci_platform_power_{on,off}
>> >>>>
>> >>>> With this new wrapper the USB PHYs can be specified directly in the
>> >>>> USB controller's devicetree node (just like on the drivers listed
>> >>>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>> >>>> correctly once this is wired up correctly. These SoCs use a dwc3
>> >>>> controller and require all USB PHYs to be initialized (if one of the USB
>> >>>> PHYs it not initialized then none of USB port works at all).
>> >>>>
>> >>>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> >>>> Tested-by: Yixun Lan <yixun@amlogic.com>
>> >>>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>> >>>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>> >>>
>> >>> This patch is breaking low power cases on TI SoCs when USB is in host 
>> >>> mode.
>> >>> I'll explain why below.
>> >> based on your explanation and reading the TI PHY drivers I am assuming
>> >> that the affected SoCs are using the "phy-omap-usb2" driver
>> >>
>> > yes and phy-ti-pipe3 as well i.e. "ti,phy-usb3" and "ti,omap-usb3"
>> I missed that, thanks
>>
>> >>>> ---
>> >>>>  drivers/usb/core/Makefile |   2 +-
>> >>>>  drivers/usb/core/phy.c| 158 
>> >>>> ++
>> >>>>  drivers/usb/core/phy.h|   7 ++
>> >>>>  3 files changed, 166 insertions(+), 1 deletion(-)
>> >>>>  create mode 100644 drivers/usb/core/phy.c
>> >>>>  create mode 100644 drivers/usb/core/phy.h
>> >>>>
>> >>>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>> >>>> index 92c9cefb4317..18e874b0441e 100644
>> >>>> --- a/drivers/usb/core/Makefile
>> >>>> +++ b/drivers/usb/core/Makefile
>> >>>> @@ -6,7 +6,7 @@
>> >>>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>> >>>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>> >>>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>> >>>> -usbcore-y += port.o
>> >>>> +usbcore-y += phy.o port.o
>> >>>>
>> >>>>  usbcore-$(CONFIG_OF) += of.o
>> >>>>  usbcore-$(CONFIG_USB_PCI)+= hcd-pci.o
>> >>>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>> >>>> new file mode 100644
>> >>>> index ..09b7c43c0ea4
>> >>>> --- /dev/null
>> >>>> +++ b/drivers/usb/core/phy.c
>> >>>> @@ -0,0 +1,158 @@
>> >>>> +// SPDX-License-Identifier: GPL-2.0+
>> >>>> +/*
>> >>>> + * A wrapper for multiple PHYs which passes all phy_* function calls to
>> >>>&g

Re: [PATCH usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-03-20 Thread Martin Blumenstingl
Hello Kishon,

On Tue, Mar 20, 2018 at 12:27 PM, Kishon Vijay Abraham I <kis...@ti.com> wrote:
> Hi,
>
> On Monday 19 March 2018 09:42 PM, Martin Blumenstingl wrote:
>> Hi Roger,
>>
>> On Mon, Mar 19, 2018 at 9:49 AM, Roger Quadros <rog...@ti.com> wrote:
>>> Hi,
>>>
>>> On 19/03/18 00:29, Martin Blumenstingl wrote:
>>>> Hi Roger,
>>>>
>>>> On Fri, Mar 16, 2018 at 3:32 PM, Roger Quadros <rog...@ti.com> wrote:
>>>>> +some TI folks
>>>>>
>>>>> Hi Martin,
>>>>>
>>>>> On 18/02/18 20:44, Martin Blumenstingl wrote:
>>>>>> Many SoC platforms have separate devices for the USB PHY which are
>>>>>> registered through the generic PHY framework. These PHYs have to be
>>>>>> enabled to make the USB controller actually work. They also have to be
>>>>>> disabled again on shutdown/suspend.
>>>>>>
>>>>>> Currently (at least) the following HCI platform drivers are using custom
>>>>>> code to obtain all PHYs via devicetree for the roothub/controller and
>>>>>> disable/enable them when required:
>>>>>> - ehci-platform.c has ehci_platform_power_{on,off}
>>>>>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>>>>>> - ohci-platform.c has ohci_platform_power_{on,off}
>>>>>>
>>>>>> With this new wrapper the USB PHYs can be specified directly in the
>>>>>> USB controller's devicetree node (just like on the drivers listed
>>>>>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>>>>>> correctly once this is wired up correctly. These SoCs use a dwc3
>>>>>> controller and require all USB PHYs to be initialized (if one of the USB
>>>>>> PHYs it not initialized then none of USB port works at all).
>>>>>>
>>>>>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>>>>>> Tested-by: Yixun Lan <yixun@amlogic.com>
>>>>>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>>>>>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>>>>>
>>>>> This patch is breaking low power cases on TI SoCs when USB is in host 
>>>>> mode.
>>>>> I'll explain why below.
>>>> based on your explanation and reading the TI PHY drivers I am assuming
>>>> that the affected SoCs are using the "phy-omap-usb2" driver
>>>>
>>> yes and phy-ti-pipe3 as well i.e. "ti,phy-usb3" and "ti,omap-usb3"
>> I missed that, thanks
>>
>>>>>> ---
>>>>>>  drivers/usb/core/Makefile |   2 +-
>>>>>>  drivers/usb/core/phy.c| 158 
>>>>>> ++
>>>>>>  drivers/usb/core/phy.h|   7 ++
>>>>>>  3 files changed, 166 insertions(+), 1 deletion(-)
>>>>>>  create mode 100644 drivers/usb/core/phy.c
>>>>>>  create mode 100644 drivers/usb/core/phy.h
>>>>>>
>>>>>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>>>>>> index 92c9cefb4317..18e874b0441e 100644
>>>>>> --- a/drivers/usb/core/Makefile
>>>>>> +++ b/drivers/usb/core/Makefile
>>>>>> @@ -6,7 +6,7 @@
>>>>>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>>>>>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>>>>>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>>>>>> -usbcore-y += port.o
>>>>>> +usbcore-y += phy.o port.o
>>>>>>
>>>>>>  usbcore-$(CONFIG_OF) += of.o
>>>>>>  usbcore-$(CONFIG_USB_PCI)+= hcd-pci.o
>>>>>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>>>>>> new file mode 100644
>>>>>> index ..09b7c43c0ea4
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/usb/core/phy.c
>>>>>> @@ -0,0 +1,158 @@
>>>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>>>> +/*
>>>>>> + * A wrapper for multiple PHYs which passes all phy_* function calls to
>>>>>> + * multiple (actual) PHY devices. This is comes handy when initializing
>&g

Re: [PATCH usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-03-19 Thread Martin Blumenstingl
Hi Roger,

On Mon, Mar 19, 2018 at 9:49 AM, Roger Quadros <rog...@ti.com> wrote:
> Hi,
>
> On 19/03/18 00:29, Martin Blumenstingl wrote:
>> Hi Roger,
>>
>> On Fri, Mar 16, 2018 at 3:32 PM, Roger Quadros <rog...@ti.com> wrote:
>>> +some TI folks
>>>
>>> Hi Martin,
>>>
>>> On 18/02/18 20:44, Martin Blumenstingl wrote:
>>>> Many SoC platforms have separate devices for the USB PHY which are
>>>> registered through the generic PHY framework. These PHYs have to be
>>>> enabled to make the USB controller actually work. They also have to be
>>>> disabled again on shutdown/suspend.
>>>>
>>>> Currently (at least) the following HCI platform drivers are using custom
>>>> code to obtain all PHYs via devicetree for the roothub/controller and
>>>> disable/enable them when required:
>>>> - ehci-platform.c has ehci_platform_power_{on,off}
>>>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>>>> - ohci-platform.c has ohci_platform_power_{on,off}
>>>>
>>>> With this new wrapper the USB PHYs can be specified directly in the
>>>> USB controller's devicetree node (just like on the drivers listed
>>>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>>>> correctly once this is wired up correctly. These SoCs use a dwc3
>>>> controller and require all USB PHYs to be initialized (if one of the USB
>>>> PHYs it not initialized then none of USB port works at all).
>>>>
>>>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>>>> Tested-by: Yixun Lan <yixun@amlogic.com>
>>>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>>>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>>>
>>> This patch is breaking low power cases on TI SoCs when USB is in host mode.
>>> I'll explain why below.
>> based on your explanation and reading the TI PHY drivers I am assuming
>> that the affected SoCs are using the "phy-omap-usb2" driver
>>
> yes and phy-ti-pipe3 as well i.e. "ti,phy-usb3" and "ti,omap-usb3"
I missed that, thanks

>>>> ---
>>>>  drivers/usb/core/Makefile |   2 +-
>>>>  drivers/usb/core/phy.c| 158 
>>>> ++
>>>>  drivers/usb/core/phy.h|   7 ++
>>>>  3 files changed, 166 insertions(+), 1 deletion(-)
>>>>  create mode 100644 drivers/usb/core/phy.c
>>>>  create mode 100644 drivers/usb/core/phy.h
>>>>
>>>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>>>> index 92c9cefb4317..18e874b0441e 100644
>>>> --- a/drivers/usb/core/Makefile
>>>> +++ b/drivers/usb/core/Makefile
>>>> @@ -6,7 +6,7 @@
>>>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>>>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>>>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>>>> -usbcore-y += port.o
>>>> +usbcore-y += phy.o port.o
>>>>
>>>>  usbcore-$(CONFIG_OF) += of.o
>>>>  usbcore-$(CONFIG_USB_PCI)+= hcd-pci.o
>>>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>>>> new file mode 100644
>>>> index ..09b7c43c0ea4
>>>> --- /dev/null
>>>> +++ b/drivers/usb/core/phy.c
>>>> @@ -0,0 +1,158 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/*
>>>> + * A wrapper for multiple PHYs which passes all phy_* function calls to
>>>> + * multiple (actual) PHY devices. This is comes handy when initializing
>>>> + * all PHYs on a HCD and to keep them all in the same state.
>>>> + *
>>>> + * Copyright (C) 2018 Martin Blumenstingl 
>>>> <martin.blumensti...@googlemail.com>
>>>> + */
>>>> +
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +
>>>> +#include "phy.h"
>>>> +
>>>> +struct usb_phy_roothub {
>>>> + struct phy  *phy;
>>>> + struct list_headlist;
>>>> +};
>>>> +
>>>> +static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
>>>> +{
>>>> + struct usb_phy_roothub *roothub_entry;
>>>> +
>>>> +

Re: [PATCH usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-03-18 Thread Martin Blumenstingl
Hi Roger,

On Fri, Mar 16, 2018 at 3:32 PM, Roger Quadros <rog...@ti.com> wrote:
> +some TI folks
>
> Hi Martin,
>
> On 18/02/18 20:44, Martin Blumenstingl wrote:
>> Many SoC platforms have separate devices for the USB PHY which are
>> registered through the generic PHY framework. These PHYs have to be
>> enabled to make the USB controller actually work. They also have to be
>> disabled again on shutdown/suspend.
>>
>> Currently (at least) the following HCI platform drivers are using custom
>> code to obtain all PHYs via devicetree for the roothub/controller and
>> disable/enable them when required:
>> - ehci-platform.c has ehci_platform_power_{on,off}
>> - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
>> - ohci-platform.c has ohci_platform_power_{on,off}
>>
>> With this new wrapper the USB PHYs can be specified directly in the
>> USB controller's devicetree node (just like on the drivers listed
>> above). This allows SoCs like the Amlogic Meson GXL family to operate
>> correctly once this is wired up correctly. These SoCs use a dwc3
>> controller and require all USB PHYs to be initialized (if one of the USB
>> PHYs it not initialized then none of USB port works at all).
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> Tested-by: Yixun Lan <yixun@amlogic.com>
>> Cc: Neil Armstrong <narmstr...@baylibre.com>
>> Cc: Chunfeng Yun <chunfeng@mediatek.com>
>
> This patch is breaking low power cases on TI SoCs when USB is in host mode.
> I'll explain why below.
based on your explanation and reading the TI PHY drivers I am assuming
that the affected SoCs are using the "phy-omap-usb2" driver

>> ---
>>  drivers/usb/core/Makefile |   2 +-
>>  drivers/usb/core/phy.c| 158 
>> ++
>>  drivers/usb/core/phy.h|   7 ++
>>  3 files changed, 166 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/usb/core/phy.c
>>  create mode 100644 drivers/usb/core/phy.h
>>
>> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
>> index 92c9cefb4317..18e874b0441e 100644
>> --- a/drivers/usb/core/Makefile
>> +++ b/drivers/usb/core/Makefile
>> @@ -6,7 +6,7 @@
>>  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
>>  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
>>  usbcore-y += devio.o notify.o generic.o quirks.o devices.o
>> -usbcore-y += port.o
>> +usbcore-y += phy.o port.o
>>
>>  usbcore-$(CONFIG_OF) += of.o
>>  usbcore-$(CONFIG_USB_PCI)+= hcd-pci.o
>> diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
>> new file mode 100644
>> index ..09b7c43c0ea4
>> --- /dev/null
>> +++ b/drivers/usb/core/phy.c
>> @@ -0,0 +1,158 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * A wrapper for multiple PHYs which passes all phy_* function calls to
>> + * multiple (actual) PHY devices. This is comes handy when initializing
>> + * all PHYs on a HCD and to keep them all in the same state.
>> + *
>> + * Copyright (C) 2018 Martin Blumenstingl 
>> <martin.blumensti...@googlemail.com>
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include "phy.h"
>> +
>> +struct usb_phy_roothub {
>> + struct phy  *phy;
>> + struct list_headlist;
>> +};
>> +
>> +static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
>> +{
>> + struct usb_phy_roothub *roothub_entry;
>> +
>> + roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
>> + if (!roothub_entry)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + INIT_LIST_HEAD(_entry->list);
>> +
>> + return roothub_entry;
>> +}
>> +
>> +static int usb_phy_roothub_add_phy(struct device *dev, int index,
>> +struct list_head *list)
>> +{
>> + struct usb_phy_roothub *roothub_entry;
>> + struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
>> +
>> + if (IS_ERR_OR_NULL(phy)) {
>> + if (!phy || PTR_ERR(phy) == -ENODEV)
>> + return 0;
>> + else
>> + return PTR_ERR(phy);
>> + }
>> +
>> + roothub_entry = usb_phy_roothub_alloc(dev);
>> + if (IS_ERR(roothub_entry))
>> + return PTR_ERR(roothub_entry);
>>

Re: [PATCH usb-next v2 0/3] DWC3 support for Amlogic Meson AXG and GXL SoCs

2018-03-03 Thread Martin Blumenstingl
Hello Felipe, Hello Greg,

On Tue, Feb 20, 2018 at 11:39 PM, Martin Blumenstingl
<martin.blumensti...@googlemail.com> wrote:
> Hello Felipe,
>
> On Sun, Feb 11, 2018 at 10:15 PM, Martin Blumenstingl
> <martin.blumensti...@googlemail.com> wrote:
>> Amlogic Meson AXG and GXL SoCs can use the dwc3-of-simple with little
>> modifications. These SoCs use:
>> - a gate clock for the USB components (DWC3, USB PHYs)
>> - a reset line which is shared across all USB components (DWC3, USB2 and
>>   USB3 PHYs, OTG detection logic inside the USB3 PHY registers)
>> - a reset pulse to trigger the reset
>> - depending on the SoC two or more PHYs (AXG: 1x USB2 and 1x USB3 PHY,
>>   GXL: 2x USB2 and 1x USB3 PHY)
>>
>> This extends the dwc3-of-simple so it supports (depending on the
>> platform) shared and level resets. Additionally it adds new bindings
>> for the Amlogic Meson AXG and GXL SoCs, along with the documentation
>> (dt-bindings).
>>
>> NOTE: for full support on Amlogic Meson GXL SoCs my other series called
>> "initialize (multiple) PHYs for a HCD" (see [0] for v8 of that series)
>> is required. However, there is no direct dependency on that series.
>> Especially since Meson AXG doesn't need it (since it only has one USB2
>> and one USB3 PHY, which is already supported by the current dwc3 driver,
>> unlike the 2x USB2 and 1x USB3 PHYs on Meson GXL).
>> So I believe that this series can still be merged, even if the other
>> patchset is not ready yet.
>>
>>
>> changes since v1 at [1]:
>> - use of_device_is_compatible() instead of struct dwc3_of_simple_params
>>   as requested by Felipe Balbi (affects PATCH #2 and #3)
>> - added Rob's Acked-by to the dt-bindings patch
>> - added Yixun Lan's Tested-by to the whole series as he tested this
>>   successfully (along with other patches) on the Amlogic Meson AXG SoC
>>
>>
>> [0] 
>> http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html
>> [1] 
>> http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006286.html
>>
>> Martin Blumenstingl (3):
>>   dt-bindings: usb: add support for dwc3 controller on Amlogic Meson GX
>>   usb: dwc3: of-simple: add support for shared and pulsed reset lines
>>   usb: dwc3: of-simple: add support for the Amlogic Meson GXL and AXG
>> SoCs
> could you please let me know if you spotted any problems, code-style
> issues in v2 or whether you are waiting for feedback from another
> maintainer?
> in case everything is fine: will you take this series through your tree?
could you please let me know how this series is supposed to land in
the next kernel release:
- Felipe, will you take it through your usb tree (which contains many
other dwc2/dwc3 driver changes)?
- Greg, will you take it through your usb-next tree?
- should Kevin apply it to his linux-amlogic tree (drivers branch,
which goes to the the arm-soc tree)?

as noted in the cover-letter Meson AXG support does not depend on any
other series


Regards
Martin
--
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-next PATCH v11 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-03-03 Thread Martin Blumenstingl
Many SoC platforms have separate devices for the USB PHY which are
registered through the generic PHY framework. These PHYs have to be
enabled to make the USB controller actually work. They also have to be
disabled again on shutdown/suspend.

Currently (at least) the following HCI platform drivers are using custom
code to obtain all PHYs via devicetree for the roothub/controller and
disable/enable them when required:
- ehci-platform.c has ehci_platform_power_{on,off}
- xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
- ohci-platform.c has ohci_platform_power_{on,off}

With this new wrapper the USB PHYs can be specified directly in the
USB controller's devicetree node (just like on the drivers listed
above). This allows SoCs like the Amlogic Meson GXL family to operate
correctly once this is wired up correctly. These SoCs use a dwc3
controller and require all USB PHYs to be initialized (if one of the USB
PHYs it not initialized then none of USB port works at all).

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
Cc: Neil Armstrong <narmstr...@baylibre.com>
Cc: Chunfeng Yun <chunfeng@mediatek.com>
---
 drivers/usb/core/Makefile |   2 +-
 drivers/usb/core/phy.c| 158 ++
 drivers/usb/core/phy.h|   7 ++
 3 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/core/phy.c
 create mode 100644 drivers/usb/core/phy.h

diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 92c9cefb4317..18e874b0441e 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -6,7 +6,7 @@
 usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
 usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
 usbcore-y += devio.o notify.o generic.o quirks.o devices.o
-usbcore-y += port.o
+usbcore-y += phy.o port.o
 
 usbcore-$(CONFIG_OF)   += of.o
 usbcore-$(CONFIG_USB_PCI)  += hcd-pci.o
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
new file mode 100644
index ..09b7c43c0ea4
--- /dev/null
+++ b/drivers/usb/core/phy.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * A wrapper for multiple PHYs which passes all phy_* function calls to
+ * multiple (actual) PHY devices. This is comes handy when initializing
+ * all PHYs on a HCD and to keep them all in the same state.
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumensti...@googlemail.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "phy.h"
+
+struct usb_phy_roothub {
+   struct phy  *phy;
+   struct list_headlist;
+};
+
+static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
+{
+   struct usb_phy_roothub *roothub_entry;
+
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_entry->list);
+
+   return roothub_entry;
+}
+
+static int usb_phy_roothub_add_phy(struct device *dev, int index,
+  struct list_head *list)
+{
+   struct usb_phy_roothub *roothub_entry;
+   struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
+
+   if (IS_ERR_OR_NULL(phy)) {
+   if (!phy || PTR_ERR(phy) == -ENODEV)
+   return 0;
+   else
+   return PTR_ERR(phy);
+   }
+
+   roothub_entry = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(roothub_entry))
+   return PTR_ERR(roothub_entry);
+
+   roothub_entry->phy = phy;
+
+   list_add_tail(_entry->list, list);
+
+   return 0;
+}
+
+struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+{
+   struct usb_phy_roothub *phy_roothub;
+   struct usb_phy_roothub *roothub_entry;
+   struct list_head *head;
+   int i, num_phys, err;
+
+   num_phys = of_count_phandle_with_args(dev->of_node, "phys",
+ "#phy-cells");
+   if (num_phys <= 0)
+   return NULL;
+
+   phy_roothub = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(phy_roothub))
+   return phy_roothub;
+
+   for (i = 0; i < num_phys; i++) {
+   err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
+   if (err)
+   goto err_out;
+   }
+
+   head = _roothub->list;
+
+   list_for_each_entry(roothub_entry, head, list) {
+   err = phy_init(roothub_entry->phy);
+   if (err)
+   goto err_exit_phys;
+   }
+
+   return phy_roothub;
+
+err_exit_phys:
+   list_for_each_entry_continue_reverse(roothub_entry, head, list)
+   phy_exit(roothub_entry->phy);
+
+err_out:
+   return ERR_PTR(err);
+}
+EXPORT_SYMB

[usb-next PATCH v11 5/8] usb: host: xhci-mtk: remove custom USB PHY handling

2018-03-03 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the xhci-mtk driver as the core
HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/host/xhci-mtk.c | 98 +
 1 file changed, 2 insertions(+), 96 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index b0ab4d5e2751..7334da9e9779 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -352,62 +351,6 @@ static const struct xhci_driver_overrides 
xhci_mtk_overrides __initconst = {
 
 static struct hc_driver __read_mostly xhci_mtk_hc_driver;
 
-static int xhci_mtk_phy_init(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_init(mtk->phys[i]);
-   if (ret)
-   goto exit_phy;
-   }
-   return 0;
-
-exit_phy:
-   for (; i > 0; i--)
-   phy_exit(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static int xhci_mtk_phy_exit(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_exit(mtk->phys[i]);
-
-   return 0;
-}
-
-static int xhci_mtk_phy_power_on(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_power_on(mtk->phys[i]);
-   if (ret)
-   goto power_off_phy;
-   }
-   return 0;
-
-power_off_phy:
-   for (; i > 0; i--)
-   phy_power_off(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static void xhci_mtk_phy_power_off(struct xhci_hcd_mtk *mtk)
-{
-   unsigned int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_power_off(mtk->phys[i]);
-}
-
 static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
 {
int ret;
@@ -488,8 +431,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
-   struct phy *phy;
-   int phy_num;
int ret = -ENODEV;
int irq;
 
@@ -529,16 +470,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
return ret;
}
 
-   mtk->num_phys = of_count_phandle_with_args(node,
-   "phys", "#phy-cells");
-   if (mtk->num_phys > 0) {
-   mtk->phys = devm_kcalloc(dev, mtk->num_phys,
-   sizeof(*mtk->phys), GFP_KERNEL);
-   if (!mtk->phys)
-   return -ENOMEM;
-   } else {
-   mtk->num_phys = 0;
-   }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
device_enable_async_suspend(dev);
@@ -596,23 +527,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
mtk->has_ippc = false;
}
 
-   for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
-   phy = devm_of_phy_get_by_index(dev, node, phy_num);
-   if (IS_ERR(phy)) {
-   ret = PTR_ERR(phy);
-   goto put_usb2_hcd;
-   }
-   mtk->phys[phy_num] = phy;
-   }
-
-   ret = xhci_mtk_phy_init(mtk);
-   if (ret)
-   goto put_usb2_hcd;
-
-   ret = xhci_mtk_phy_power_on(mtk);
-   if (ret)
-   goto exit_phys;
-
device_init_wakeup(dev, true);
 
xhci = hcd_to_xhci(hcd);
@@ -630,7 +544,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
dev_name(dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
-   goto power_off_phys;
+   goto disable_device_wakeup;
}
 
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -653,13 +567,9 @@ static int xhci_mtk_probe(struct platform_device *pdev)
xhci_mtk_sch_exit(mtk);
usb_put_hcd(xhci->shared_hcd);
 
-power_off_phys:
-   xhci_mtk_phy_power_off(mtk);
+disable_device_wakeup:
device_init_wakeup(dev, false);
 
-exit_phys:
-   xhci_mtk_phy_exit(mtk);
-
 put_usb2_hcd:
usb_put_hcd(hcd);
 
@@ -682,8 +592,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
usb_remove_hcd(xhci->shared_hcd);
-   xhci_mtk_phy_power_off(mtk);
-   xhci_mtk_phy_exit(mtk);
device_init_wakeup(>dev, false);
 
usb_remove_hcd(hcd);
@@ -718,7 +626,6 @@ static int __maybe_unused xhci_mtk_suspend(struct device 
*de

[usb-next PATCH v11 1/8] dt-bindings: usb: add the documentation for USB HCDs

2018-03-03 Thread Martin Blumenstingl
A USB HCD may have several PHYs which need to be configured before the
the HCD starts working.
This adds the documentation for such a USB HCD as well as a reference to
the new "usb-hcd.txt" from all bindings that implement a USB HCD which
support one USB PHY per port.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Reviewed-by: Rob Herring <r...@kernel.org>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 5 -
 Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 5 -
 Documentation/devicetree/bindings/usb/usb-ehci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-hcd.txt   | 9 +
 Documentation/devicetree/bindings/usb/usb-ohci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-uhci.txt  | 3 +++
 Documentation/devicetree/bindings/usb/usb-xhci.txt  | 5 +
 7 files changed, 33 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/usb-hcd.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
index 88d9f4a4b280..266c2d917a28 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
@@ -32,7 +32,7 @@ Required properties:
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA
 
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
 
 Optional properties:
  - wakeup-source : enable USB remote wakeup;
@@ -52,6 +52,9 @@ Optional properties:
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  - imod-interval-ns: default interrupt moderation interval is 5000ns
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example:
 usb30: usb@1127 {
compatible = "mediatek,mt8173-xhci";
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index d589a1ef96a1..3382b5cb471d 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
@@ -17,7 +17,7 @@ Required properties:
  - clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dam_ck";
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
  - dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
 
@@ -53,6 +53,9 @@ Optional properties:
  - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Sub-nodes:
 The xhci should be added as subnode to mtu3 as shown in the following example
 if host mode is enabled. The DT binding details of xhci can be found in:
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt 
b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index 3efde12b5d68..0f1b75386207 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -16,10 +16,12 @@ Optional properties:
  - has-transaction-translator : boolean, set this if EHCI have a Transaction
Translator built into the root hub.
  - clocks : a list of phandle + clock specifier pairs
- - phys : phandle + phy specifier pair
- - phy-names : "usb"
+ - phys : see usb-hcd.txt in the current directory
  - resets : phandle + reset specifier pair
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example (Sequoia 440EPx):
 ehci@e300 {
   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.txt 
b/Documentation/devicetree/bindings/usb/usb-hcd.txt
new file mode 100644
index ..50529b838c9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.txt
@@ -0,0 +1,9 @@
+Generic USB HCD (Host Controller Device) Properties
+
+Optional properties:
+- phys: a list of all USB PHYs on this HCD
+
+Example:
+{
+   phys = <_phy1>, <_phy1>;
+   };
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt 
b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 09e70c875bc6..a8d2103d1f3d 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -13,10 +13,12 @@ Optional properties:
 - remote-wakeup-connected: remote wakeup is wired on the 

[usb-next PATCH v11 4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core

2018-03-03 Thread Martin Blumenstingl
This integrates the PHY wrapper into the core hcd infrastructure.
Multiple PHYs which are part of the HCD's device tree node are now
managed (= powered on/off when needed), by the new usb_phy_roothub code.

Suspend and resume is also supported, however not for
runtime/auto-suspend (which is triggered for example when no devices are
connected to the USB bus). This is needed on some SoCs (for example
Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend
then devices which are plugged in afterwards are not seen by the host.

One example where this is required is the Amlogic GXL and GXM SoCs:
They are using a dwc3 USB controller with up to three ports enabled on
the internal roothub. Each port has it's own PHY which must be enabled
(if one of the PHYs is left disabled then none of the USB ports works at
all).
The new logic works on the Amlogic GXL and GXM SoCs because the dwc3
driver internally creates a xhci-hcd which then registers a HCD which
then triggers our new PHY wrapper.

USB controller drivers can opt out of this by setting
"skip_phy_initialization" in struct usb_hcd to true. This is identical
to how it works for a single USB PHY, so the "multiple PHY" handling is
disabled for drivers that opted out of the management logic of a single
PHY.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
Acked-by: Chunfeng Yun <chunfeng@mediatek.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 drivers/usb/core/hcd.c  | 31 +++
 include/linux/usb/hcd.h |  1 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f2307470a31e..32797c25ac3b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -37,6 +37,7 @@
 #include 
 
 #include "usb.h"
+#include "phy.h"
 
 
 /*-*/
@@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
 
+   if (!PMSG_IS_AUTO(msg))
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
charbuffer[6];
@@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, 
pm_message_t msg)
dev_dbg(>dev, "skipped %s of dead bus\n", "resume");
return 0;
}
+
+   if (!PMSG_IS_AUTO(msg)) {
+   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (status)
+   return status;
+   }
+
if (!hcd->driver->bus_resume)
return -ENOENT;
if (HCD_RH_RUNNING(hcd))
@@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
+   usb_phy_roothub_power_off(hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
@@ -2769,6 +2781,18 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
+   if (!hcd->skip_phy_initialization) {
+   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   if (IS_ERR(hcd->phy_roothub)) {
+   retval = PTR_ERR(hcd->phy_roothub);
+   goto err_phy_roothub_init;
+   }
+
+   retval = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (retval)
+   goto err_usb_phy_roothub_power_on;
+   }
+
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
/* Keep old behaviour if authorized_default is not in [0, 1]. */
@@ -2933,6 +2957,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_register_bus:
hcd_buffer_destroy(hcd);
 err_create_buf:
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+err_usb_phy_roothub_power_on:
+   usb_phy_roothub_exit(hcd->phy_roothub);
+err_phy_roothub_init:
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy);
phy_exit(hcd->phy);
@@ -3017,6 +3045,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_deregister_bus(>self);
hcd_buffer_destroy(hcd);
 
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_exit(hcd->phy_roothub);
+
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy

[usb-next PATCH v11 6/8] usb: host: ehci-platform: remove custom USB PHY handling

2018-03-03 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ehci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
---
 drivers/usb/host/ehci-platform.c | 55 +++-
 1 file changed, 4 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b91eea8c73ae..4c306fb6b069 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -44,8 +43,6 @@
 struct ehci_platform_priv {
struct clk *clks[EHCI_MAX_CLKS];
struct reset_control *rsts;
-   struct phy **phys;
-   int num_phys;
bool reset_on_resume;
 };
 
@@ -80,7 +77,7 @@ static int ehci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -88,24 +85,8 @@ static int ehci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -117,12 +98,7 @@ static void ehci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -149,7 +125,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct usb_ehci_pdata *pdata = dev_get_platdata(>dev);
struct ehci_platform_priv *priv;
struct ehci_hcd *ehci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -202,29 +178,6 @@ static int ehci_platform_probe(struct platform_device *dev)
  "has-transaction-translator"))
hcd->has_tt = 1;
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->skip_phy_initialization = 1;
-   }
-   }
-
for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -306,7 +259,7 @@ static int ehci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_put_hcd:
+
   

[usb-next PATCH v11 8/8] usb: core: hcd: remove support for initializing a single PHY

2018-03-03 Thread Martin Blumenstingl
With the new PHY wrapper in place we can now handle multiple PHYs.
Remove the code which handles only one generic PHY as this is now
covered (with support for multiple PHYs as well as suspend/resume
support) by the new PHY wrapper.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c  | 37 -
 include/linux/usb/hcd.h |  1 -
 2 files changed, 38 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 32797c25ac3b..5a92d8f7c484 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2757,30 +2757,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
-   struct phy *phy = phy_get(hcd->self.sysdev, "usb");
-
-   if (IS_ERR(phy)) {
-   retval = PTR_ERR(phy);
-   if (retval == -EPROBE_DEFER)
-   goto err_phy;
-   } else {
-   retval = phy_init(phy);
-   if (retval) {
-   phy_put(phy);
-   goto err_phy;
-   }
-   retval = phy_power_on(phy);
-   if (retval) {
-   phy_exit(phy);
-   phy_put(phy);
-   goto err_phy;
-   }
-   hcd->phy = phy;
-   hcd->remove_phy = 1;
-   }
-   }
-
if (!hcd->skip_phy_initialization) {
hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
@@ -2961,13 +2937,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
 err_phy_roothub_init:
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
-err_phy:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
@@ -3048,12 +3017,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_phy_roothub_power_off(hcd->phy_roothub);
usb_phy_roothub_exit(hcd->phy_roothub);
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index a042675e03ba..aef50cb2ed1b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -103,7 +103,6 @@ struct usb_hcd {
 * other external phys should be software-transparent
 */
struct usb_phy  *usb_phy;
-   struct phy  *phy;
struct usb_phy_roothub  *phy_roothub;
 
/* Flags that need to be manipulated atomically because they can
-- 
2.16.2

--
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-next PATCH v11 7/8] usb: host: ohci-platform: remove custom USB PHY handling

2018-03-03 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ohci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
---
 drivers/usb/host/ohci-platform.c | 56 
 1 file changed, 5 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 62ef36a9333f..65a1c3fdc88c 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -21,7 +21,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -38,8 +38,6 @@
 struct ohci_platform_priv {
struct clk *clks[OHCI_MAX_CLKS];
struct reset_control *resets;
-   struct phy **phys;
-   int num_phys;
 };
 
 static const char hcd_name[] = "ohci-platform";
@@ -48,7 +46,7 @@ static int ohci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -56,24 +54,8 @@ static int ohci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -85,12 +67,7 @@ static void ohci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -117,7 +94,7 @@ static int ohci_platform_probe(struct platform_device *dev)
struct usb_ohci_pdata *pdata = dev_get_platdata(>dev);
struct ohci_platform_priv *priv;
struct ohci_hcd *ohci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -169,29 +146,6 @@ static int ohci_platform_probe(struct platform_device *dev)
of_property_read_u32(dev->dev.of_node, "num-ports",
 >num_ports);
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->skip_phy_initialization = 1;
-   }
-   }
-
for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -277,7 +231,7 @@ static int ohci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
   

[usb-next PATCH v11 2/8] usb: add a flag to skip PHY initialization to struct usb_hcd

2018-03-03 Thread Martin Blumenstingl
The USB HCD core driver parses the device-tree node for "phys" and
"usb-phys" properties. It also manages the power state of these PHYs
automatically.
However, drivers may opt-out of this behavior by setting "phy" or
"usb_phy" in struct usb_hcd to a non-null value. An example where this
is required is the "Qualcomm USB2 controller", implemented by the
chipidea driver. The hardware requires that the PHY is only powered on
after the "reset completed" event from the controller is received.

A follow-up patch will allow the USB HCD core driver to manage more than
one PHY. Add a new "skip_phy_initialization" bitflag to struct usb_hcd
so drivers can opt-out of any PHY management provided by the USB HCD
core driver.

This also updates the existing drivers so they use the new flag if they
want to opt out of the PHY management provided by the USB HCD core
driver. This means that for these drivers the new "multiple PHY"
handling (which will be added in a follow-up patch) will be disabled as
well.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Peter Chen <peter.c...@nxp.com>
---
 drivers/usb/chipidea/host.c  | 6 ++
 drivers/usb/core/hcd.c   | 4 ++--
 drivers/usb/host/ehci-fsl.c  | 2 ++
 drivers/usb/host/ehci-platform.c | 4 ++--
 drivers/usb/host/ehci-tegra.c| 1 +
 drivers/usb/host/ohci-omap.c | 1 +
 drivers/usb/host/ohci-platform.c | 4 ++--
 drivers/usb/host/xhci-plat.c | 1 +
 include/linux/usb/hcd.h  | 6 ++
 9 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 19d60ed7e41f..af45aa3222b5 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -124,10 +124,8 @@ static int host_start(struct ci_hdrc *ci)
 
hcd->power_budget = ci->platdata->power_budget;
hcd->tpl_support = ci->platdata->tpl_support;
-   if (ci->phy)
-   hcd->phy = ci->phy;
-   else
-   hcd->usb_phy = ci->usb_phy;
+   if (ci->phy || ci->usb_phy)
+   hcd->skip_phy_initialization = 1;
 
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fc32391a34d5..f2307470a31e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2727,7 +2727,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
 
-   if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
+   if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0);
 
if (IS_ERR(phy)) {
@@ -2745,7 +2745,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
+   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
struct phy *phy = phy_get(hcd->self.sysdev, "usb");
 
if (IS_ERR(phy)) {
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index c5094cb88cd5..0a9fd2022acf 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -155,6 +155,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
retval = -ENODEV;
goto err2;
}
+
+   hcd->skip_phy_initialization = 1;
}
 #endif
return retval;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b065a960adc2..b91eea8c73ae 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -219,9 +219,9 @@ static int ehci_platform_probe(struct platform_device *dev)
if (IS_ERR(priv->phys[phy_num])) {
err = PTR_ERR(priv->phys[phy_num]);
goto err_put_hcd;
-   } else if (!hcd->phy) {
+   } else {
/* Avoiding phy_get() in usb_add_hcd() */
-   hcd->phy = priv->phys[phy_num];
+   hcd->skip_phy_initialization = 1;
}
}
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c809f7d2f08f..a6f4389f7e88 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -461,6 +461,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_clk_en;
}
hcd->usb_phy = u_phy;
+   hcd->skip_phy_initialization = 1;
 
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvid

[usb-next PATCH v11 0/8] initialize (multiple) PHYs for a HCD

2018-03-03 Thread Martin Blumenstingl
 (see [0]). please wait for an ACK
  from Rob on this one to make sure that we're not introducing some
  broken binding (as discussed with Arnd: [7])
- added Alan Stern's ACK on PATCH #3
- added Neil's Tested-by on PATCH #2 and #3

Changes since RfC v5 at [5]:
- dropped RfC prefix
- removed noisy dev_err if no roothub node was found (spotted by
  Xiaolong Ye's kbuild test robot - thank you for that!)
- moved the call to usb_phy_roothub_power_off() within
  hcd_bus_suspend() to make sure that the PHYs are turned off
  if the "race with a root-hub wakeup event" condition is met (in
  this case the PHYs are turned on again, with the old code we did
  break the PHYs internal ref-counting because we never turned the
  PHYs off before turning them on again in case of that special
  "race with a root-hub wakeup event").
  additionally we're not handling the status returned by
  usb_phy_roothub_power_off() anymore (the bus is already turned off
  and we tried to turn off all PHYs as well - only the PHYs which
  failed to power off will stay in the current state).
  thanks to Alan Stern for the suggestion
- removed return value from usb_phy_roothub_power_off() because none
  of my code uses it anymore. thanks to Alan Stern for the suggestion

Changes since v4 at [4]:
- renamed the subject of the cover-letter (old name was:
  "initialize (multiple) PHYs in xhci-plat")
- back into RFC status (see below for the reasons)
- dropped Tested-by from Chunfeng Yun (same reasons as RFC status)
- reworded cover-letter and commit messages from "platform-roothub"
  to "roothub PHY wrapper"
- moved code from drivers/usb/host/platform-roothub.* to
  drivers/usb/core/phy.* and the changes to
  drivers/usb/host/xhci-plat.c to drivers/usb/core/hcd.c as suggested
  by Mathias Nyman (as a benefit this will enable the new logic for
  non-xHCI controllers as well - however this was not tested yet)
- rename the structs, function names, etc from platform_roothub_* to
  usb_phy_roothub*

Changes since RFCv3 at [3]:
- moved the DT binding change from patch #3 to patch #1 as suggested
  by Rob Herring (and slightly adjusted the commit message to account
  for that)
- added Tested-by from Chunfeng Yun (who confirmed that the whole
  concept and implementation works fine on Mediatek SoCs - many thanks
  again!) to patch #2
- added Rob Herring's ACK to patches 1 and 3
- dropped RFC status (RFCv3 -> PATCH v4)

Changes since RFCv2 at [2]:
- split phy_{init,exit} and phy_power_{on,off} handling. up until RFCv2
  I called phy_init plus phy_power_on in platform_roothub_power_on and
  phy_power_off plus phy_exit in platform_roothub_power_off. However,
  Chunfeng Yun (a Mediatek SoC developer - many thanks for testing my
  series and providing great feedback) reported that only using
  phy_power_off (and omitting phy_exit) during system suspend fixes an
  issue where USB devices would be re-enumerated when resuming. His
  original problem description: "In order to keep link state on mt8173,
  we just power off all phys(not exit) when system enter suspend, then
  power on them again (needn't init, otherwise device will be
  disconnected) when system resume, this can avoid re-enumerating
  device.". This fix affects patch #2 and #3 as we now have
  platform_roothub_init (which calls phy_init internally),
  platform_roothub_power_on (which calls phy_power_on internally),
  platform_roothub_power_off (which calls phy_power_off internally) and
  platform_roothub_exit (which calls phy_exit internally). suspend and
  resume only call platform_roothub_power_{on,off} to prevent the issue
  described by Chunfeng Yun (unfortunately I cannot test this because
  the Amlogic platform currently does not support system suspend).
- dropped two struct forward declarations from platform-roothub.h which
  are not used in the header file (thanks to Chunfeng Yun for spotting
  this)

Changes since RFCv1 at [1]:
- split the usb-xhci dt-binding documentation into a separate patch
- fixed a typo ("usb-phy" -> "phys" in the dt-binding example)
- rebased to apply against latest usb-next


[0] http://lists.infradead.org/pipermail/linux-amlogic/2016-November/001818.html
[1] http://marc.info/?l=linux-usb=148414866303604=2
[2] https://www.spinics.net/lists/linux-usb/msg158967.html
[3] https://www.spinics.net/lists/devicetree/msg190426.html
[4] 
http://lists.infradead.org/pipermail/linux-amlogic/2017-September/004685.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/004924.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005049.html
[7] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005121.html
[8] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005124.html
[9] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005192.html
[10] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html
[11] htt

Re: [PATCH usb-next v2 0/3] DWC3 support for Amlogic Meson AXG and GXL SoCs

2018-02-20 Thread Martin Blumenstingl
Hello Felipe,

On Sun, Feb 11, 2018 at 10:15 PM, Martin Blumenstingl
<martin.blumensti...@googlemail.com> wrote:
> Amlogic Meson AXG and GXL SoCs can use the dwc3-of-simple with little
> modifications. These SoCs use:
> - a gate clock for the USB components (DWC3, USB PHYs)
> - a reset line which is shared across all USB components (DWC3, USB2 and
>   USB3 PHYs, OTG detection logic inside the USB3 PHY registers)
> - a reset pulse to trigger the reset
> - depending on the SoC two or more PHYs (AXG: 1x USB2 and 1x USB3 PHY,
>   GXL: 2x USB2 and 1x USB3 PHY)
>
> This extends the dwc3-of-simple so it supports (depending on the
> platform) shared and level resets. Additionally it adds new bindings
> for the Amlogic Meson AXG and GXL SoCs, along with the documentation
> (dt-bindings).
>
> NOTE: for full support on Amlogic Meson GXL SoCs my other series called
> "initialize (multiple) PHYs for a HCD" (see [0] for v8 of that series)
> is required. However, there is no direct dependency on that series.
> Especially since Meson AXG doesn't need it (since it only has one USB2
> and one USB3 PHY, which is already supported by the current dwc3 driver,
> unlike the 2x USB2 and 1x USB3 PHYs on Meson GXL).
> So I believe that this series can still be merged, even if the other
> patchset is not ready yet.
>
>
> changes since v1 at [1]:
> - use of_device_is_compatible() instead of struct dwc3_of_simple_params
>   as requested by Felipe Balbi (affects PATCH #2 and #3)
> - added Rob's Acked-by to the dt-bindings patch
> - added Yixun Lan's Tested-by to the whole series as he tested this
>   successfully (along with other patches) on the Amlogic Meson AXG SoC
>
>
> [0] 
> http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html
> [1] 
> http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006286.html
>
> Martin Blumenstingl (3):
>   dt-bindings: usb: add support for dwc3 controller on Amlogic Meson GX
>   usb: dwc3: of-simple: add support for shared and pulsed reset lines
>   usb: dwc3: of-simple: add support for the Amlogic Meson GXL and AXG
> SoCs
could you please let me know if you spotted any problems, code-style
issues in v2 or whether you are waiting for feedback from another
maintainer?
in case everything is fine: will you take this series through your tree?


Regards
Martin
--
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 usb-next v10 2/8] usb: add a flag to skip PHY initialization to struct usb_hcd

2018-02-18 Thread Martin Blumenstingl
The USB HCD core driver parses the device-tree node for "phys" and
"usb-phys" properties. It also manages the power state of these PHYs
automatically.
However, drivers may opt-out of this behavior by setting "phy" or
"usb_phy" in struct usb_hcd to a non-null value. An example where this
is required is the "Qualcomm USB2 controller", implemented by the
chipidea driver. The hardware requires that the PHY is only powered on
after the "reset completed" event from the controller is received.

A follow-up patch will allow the USB HCD core driver to manage more than
one PHY. Add a new "skip_phy_initialization" bitflag to struct usb_hcd
so drivers can opt-out of any PHY management provided by the USB HCD
core driver.

This also updates the existing drivers so they use the new flag if they
want to opt out of the PHY management provided by the USB HCD core
driver. This means that for these drivers the new "multiple PHY"
handling (which will be added in a follow-up patch) will be disabled as
well.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/chipidea/host.c  | 6 ++
 drivers/usb/core/hcd.c   | 4 ++--
 drivers/usb/host/ehci-fsl.c  | 2 ++
 drivers/usb/host/ehci-platform.c | 4 ++--
 drivers/usb/host/ehci-tegra.c| 1 +
 drivers/usb/host/ohci-omap.c | 1 +
 drivers/usb/host/ohci-platform.c | 4 ++--
 drivers/usb/host/xhci-plat.c | 1 +
 include/linux/usb/hcd.h  | 6 ++
 9 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 19d60ed7e41f..af45aa3222b5 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -124,10 +124,8 @@ static int host_start(struct ci_hdrc *ci)
 
hcd->power_budget = ci->platdata->power_budget;
hcd->tpl_support = ci->platdata->tpl_support;
-   if (ci->phy)
-   hcd->phy = ci->phy;
-   else
-   hcd->usb_phy = ci->usb_phy;
+   if (ci->phy || ci->usb_phy)
+   hcd->skip_phy_initialization = 1;
 
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fc32391a34d5..f2307470a31e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2727,7 +2727,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
 
-   if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
+   if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0);
 
if (IS_ERR(phy)) {
@@ -2745,7 +2745,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
+   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
struct phy *phy = phy_get(hcd->self.sysdev, "usb");
 
if (IS_ERR(phy)) {
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index c5094cb88cd5..0a9fd2022acf 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -155,6 +155,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
retval = -ENODEV;
goto err2;
}
+
+   hcd->skip_phy_initialization = 1;
}
 #endif
return retval;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b065a960adc2..b91eea8c73ae 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -219,9 +219,9 @@ static int ehci_platform_probe(struct platform_device *dev)
if (IS_ERR(priv->phys[phy_num])) {
err = PTR_ERR(priv->phys[phy_num]);
goto err_put_hcd;
-   } else if (!hcd->phy) {
+   } else {
/* Avoiding phy_get() in usb_add_hcd() */
-   hcd->phy = priv->phys[phy_num];
+   hcd->skip_phy_initialization = 1;
}
}
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c809f7d2f08f..a6f4389f7e88 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -461,6 +461,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_clk_en;
}
hcd->usb_phy = u_phy;
+   hcd->skip_phy_initialization = 1;
 
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvidia,needs-double-reset");
diff --git a

[PATCH usb-next v10 7/8] usb: host: ohci-platform: remove custom USB PHY handling

2018-02-18 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ohci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
---
 drivers/usb/host/ohci-platform.c | 56 
 1 file changed, 5 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 62ef36a9333f..65a1c3fdc88c 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -21,7 +21,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -38,8 +38,6 @@
 struct ohci_platform_priv {
struct clk *clks[OHCI_MAX_CLKS];
struct reset_control *resets;
-   struct phy **phys;
-   int num_phys;
 };
 
 static const char hcd_name[] = "ohci-platform";
@@ -48,7 +46,7 @@ static int ohci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -56,24 +54,8 @@ static int ohci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -85,12 +67,7 @@ static void ohci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -117,7 +94,7 @@ static int ohci_platform_probe(struct platform_device *dev)
struct usb_ohci_pdata *pdata = dev_get_platdata(>dev);
struct ohci_platform_priv *priv;
struct ohci_hcd *ohci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -169,29 +146,6 @@ static int ohci_platform_probe(struct platform_device *dev)
of_property_read_u32(dev->dev.of_node, "num-ports",
 >num_ports);
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->skip_phy_initialization = 1;
-   }
-   }
-
for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -277,7 +231,7 @@ static int ohci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
   

[PATCH usb-next v10 5/8] usb: host: xhci-mtk: remove custom USB PHY handling

2018-02-18 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the xhci-mtk driver as the core
HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/host/xhci-mtk.c | 98 +
 1 file changed, 2 insertions(+), 96 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index b0ab4d5e2751..7334da9e9779 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -352,62 +351,6 @@ static const struct xhci_driver_overrides 
xhci_mtk_overrides __initconst = {
 
 static struct hc_driver __read_mostly xhci_mtk_hc_driver;
 
-static int xhci_mtk_phy_init(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_init(mtk->phys[i]);
-   if (ret)
-   goto exit_phy;
-   }
-   return 0;
-
-exit_phy:
-   for (; i > 0; i--)
-   phy_exit(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static int xhci_mtk_phy_exit(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_exit(mtk->phys[i]);
-
-   return 0;
-}
-
-static int xhci_mtk_phy_power_on(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_power_on(mtk->phys[i]);
-   if (ret)
-   goto power_off_phy;
-   }
-   return 0;
-
-power_off_phy:
-   for (; i > 0; i--)
-   phy_power_off(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static void xhci_mtk_phy_power_off(struct xhci_hcd_mtk *mtk)
-{
-   unsigned int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_power_off(mtk->phys[i]);
-}
-
 static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
 {
int ret;
@@ -488,8 +431,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
-   struct phy *phy;
-   int phy_num;
int ret = -ENODEV;
int irq;
 
@@ -529,16 +470,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
return ret;
}
 
-   mtk->num_phys = of_count_phandle_with_args(node,
-   "phys", "#phy-cells");
-   if (mtk->num_phys > 0) {
-   mtk->phys = devm_kcalloc(dev, mtk->num_phys,
-   sizeof(*mtk->phys), GFP_KERNEL);
-   if (!mtk->phys)
-   return -ENOMEM;
-   } else {
-   mtk->num_phys = 0;
-   }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
device_enable_async_suspend(dev);
@@ -596,23 +527,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
mtk->has_ippc = false;
}
 
-   for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
-   phy = devm_of_phy_get_by_index(dev, node, phy_num);
-   if (IS_ERR(phy)) {
-   ret = PTR_ERR(phy);
-   goto put_usb2_hcd;
-   }
-   mtk->phys[phy_num] = phy;
-   }
-
-   ret = xhci_mtk_phy_init(mtk);
-   if (ret)
-   goto put_usb2_hcd;
-
-   ret = xhci_mtk_phy_power_on(mtk);
-   if (ret)
-   goto exit_phys;
-
device_init_wakeup(dev, true);
 
xhci = hcd_to_xhci(hcd);
@@ -630,7 +544,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
dev_name(dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
-   goto power_off_phys;
+   goto disable_device_wakeup;
}
 
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -653,13 +567,9 @@ static int xhci_mtk_probe(struct platform_device *pdev)
xhci_mtk_sch_exit(mtk);
usb_put_hcd(xhci->shared_hcd);
 
-power_off_phys:
-   xhci_mtk_phy_power_off(mtk);
+disable_device_wakeup:
device_init_wakeup(dev, false);
 
-exit_phys:
-   xhci_mtk_phy_exit(mtk);
-
 put_usb2_hcd:
usb_put_hcd(hcd);
 
@@ -682,8 +592,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
usb_remove_hcd(xhci->shared_hcd);
-   xhci_mtk_phy_power_off(mtk);
-   xhci_mtk_phy_exit(mtk);
device_init_wakeup(>dev, false);
 
usb_remove_hcd(hcd);
@@ -718,7 +626,6 @@ static int __maybe_unused xhci_mtk_suspend(struct device 
*de

[PATCH usb-next v10 1/8] dt-bindings: usb: add the documentation for USB HCDs

2018-02-18 Thread Martin Blumenstingl
A USB HCD may have several PHYs which need to be configured before the
the HCD starts working.
This adds the documentation for such a USB HCD as well as a reference to
the new "usb-hcd.txt" from all bindings that implement a USB HCD which
support one USB PHY per port.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Reviewed-by: Rob Herring <r...@kernel.org>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 5 -
 Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 5 -
 Documentation/devicetree/bindings/usb/usb-ehci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-hcd.txt   | 9 +
 Documentation/devicetree/bindings/usb/usb-ohci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-uhci.txt  | 3 +++
 Documentation/devicetree/bindings/usb/usb-xhci.txt  | 5 +
 7 files changed, 33 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/usb-hcd.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
index 88d9f4a4b280..266c2d917a28 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
@@ -32,7 +32,7 @@ Required properties:
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA
 
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
 
 Optional properties:
  - wakeup-source : enable USB remote wakeup;
@@ -52,6 +52,9 @@ Optional properties:
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  - imod-interval-ns: default interrupt moderation interval is 5000ns
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example:
 usb30: usb@1127 {
compatible = "mediatek,mt8173-xhci";
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index d589a1ef96a1..3382b5cb471d 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
@@ -17,7 +17,7 @@ Required properties:
  - clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dam_ck";
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
  - dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
 
@@ -53,6 +53,9 @@ Optional properties:
  - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Sub-nodes:
 The xhci should be added as subnode to mtu3 as shown in the following example
 if host mode is enabled. The DT binding details of xhci can be found in:
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt 
b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index 3efde12b5d68..0f1b75386207 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -16,10 +16,12 @@ Optional properties:
  - has-transaction-translator : boolean, set this if EHCI have a Transaction
Translator built into the root hub.
  - clocks : a list of phandle + clock specifier pairs
- - phys : phandle + phy specifier pair
- - phy-names : "usb"
+ - phys : see usb-hcd.txt in the current directory
  - resets : phandle + reset specifier pair
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example (Sequoia 440EPx):
 ehci@e300 {
   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.txt 
b/Documentation/devicetree/bindings/usb/usb-hcd.txt
new file mode 100644
index ..50529b838c9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.txt
@@ -0,0 +1,9 @@
+Generic USB HCD (Host Controller Device) Properties
+
+Optional properties:
+- phys: a list of all USB PHYs on this HCD
+
+Example:
+{
+   phys = <_phy1>, <_phy1>;
+   };
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt 
b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 09e70c875bc6..a8d2103d1f3d 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -13,10 +13,12 @@ Optional properties:
 - remote-wakeup-connected: remote wakeup is wired on the 

[PATCH usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-02-18 Thread Martin Blumenstingl
Many SoC platforms have separate devices for the USB PHY which are
registered through the generic PHY framework. These PHYs have to be
enabled to make the USB controller actually work. They also have to be
disabled again on shutdown/suspend.

Currently (at least) the following HCI platform drivers are using custom
code to obtain all PHYs via devicetree for the roothub/controller and
disable/enable them when required:
- ehci-platform.c has ehci_platform_power_{on,off}
- xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
- ohci-platform.c has ohci_platform_power_{on,off}

With this new wrapper the USB PHYs can be specified directly in the
USB controller's devicetree node (just like on the drivers listed
above). This allows SoCs like the Amlogic Meson GXL family to operate
correctly once this is wired up correctly. These SoCs use a dwc3
controller and require all USB PHYs to be initialized (if one of the USB
PHYs it not initialized then none of USB port works at all).

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
Cc: Neil Armstrong <narmstr...@baylibre.com>
Cc: Chunfeng Yun <chunfeng@mediatek.com>
---
 drivers/usb/core/Makefile |   2 +-
 drivers/usb/core/phy.c| 158 ++
 drivers/usb/core/phy.h|   7 ++
 3 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/core/phy.c
 create mode 100644 drivers/usb/core/phy.h

diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 92c9cefb4317..18e874b0441e 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -6,7 +6,7 @@
 usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
 usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
 usbcore-y += devio.o notify.o generic.o quirks.o devices.o
-usbcore-y += port.o
+usbcore-y += phy.o port.o
 
 usbcore-$(CONFIG_OF)   += of.o
 usbcore-$(CONFIG_USB_PCI)  += hcd-pci.o
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
new file mode 100644
index ..09b7c43c0ea4
--- /dev/null
+++ b/drivers/usb/core/phy.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * A wrapper for multiple PHYs which passes all phy_* function calls to
+ * multiple (actual) PHY devices. This is comes handy when initializing
+ * all PHYs on a HCD and to keep them all in the same state.
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumensti...@googlemail.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "phy.h"
+
+struct usb_phy_roothub {
+   struct phy  *phy;
+   struct list_headlist;
+};
+
+static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
+{
+   struct usb_phy_roothub *roothub_entry;
+
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_entry->list);
+
+   return roothub_entry;
+}
+
+static int usb_phy_roothub_add_phy(struct device *dev, int index,
+  struct list_head *list)
+{
+   struct usb_phy_roothub *roothub_entry;
+   struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
+
+   if (IS_ERR_OR_NULL(phy)) {
+   if (!phy || PTR_ERR(phy) == -ENODEV)
+   return 0;
+   else
+   return PTR_ERR(phy);
+   }
+
+   roothub_entry = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(roothub_entry))
+   return PTR_ERR(roothub_entry);
+
+   roothub_entry->phy = phy;
+
+   list_add_tail(_entry->list, list);
+
+   return 0;
+}
+
+struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+{
+   struct usb_phy_roothub *phy_roothub;
+   struct usb_phy_roothub *roothub_entry;
+   struct list_head *head;
+   int i, num_phys, err;
+
+   num_phys = of_count_phandle_with_args(dev->of_node, "phys",
+ "#phy-cells");
+   if (num_phys <= 0)
+   return NULL;
+
+   phy_roothub = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(phy_roothub))
+   return phy_roothub;
+
+   for (i = 0; i < num_phys; i++) {
+   err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
+   if (err)
+   goto err_out;
+   }
+
+   head = _roothub->list;
+
+   list_for_each_entry(roothub_entry, head, list) {
+   err = phy_init(roothub_entry->phy);
+   if (err)
+   goto err_exit_phys;
+   }
+
+   return phy_roothub;
+
+err_exit_phys:
+   list_for_each_entry_continue_reverse(roothub_entry, head, list)
+   phy_exit(roothub_entry->phy);
+
+err_out:
+   return ERR_PTR(err);
+}
+EXPORT_SYMB

[PATCH usb-next v10 8/8] usb: core: hcd: remove support for initializing a single PHY

2018-02-18 Thread Martin Blumenstingl
With the new PHY wrapper in place we can now handle multiple PHYs.
Remove the code which handles only one generic PHY as this is now
covered (with support for multiple PHYs as well as suspend/resume
support) by the new PHY wrapper.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c  | 37 -
 include/linux/usb/hcd.h |  1 -
 2 files changed, 38 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 32797c25ac3b..5a92d8f7c484 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2757,30 +2757,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
-   struct phy *phy = phy_get(hcd->self.sysdev, "usb");
-
-   if (IS_ERR(phy)) {
-   retval = PTR_ERR(phy);
-   if (retval == -EPROBE_DEFER)
-   goto err_phy;
-   } else {
-   retval = phy_init(phy);
-   if (retval) {
-   phy_put(phy);
-   goto err_phy;
-   }
-   retval = phy_power_on(phy);
-   if (retval) {
-   phy_exit(phy);
-   phy_put(phy);
-   goto err_phy;
-   }
-   hcd->phy = phy;
-   hcd->remove_phy = 1;
-   }
-   }
-
if (!hcd->skip_phy_initialization) {
hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
@@ -2961,13 +2937,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
 err_phy_roothub_init:
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
-err_phy:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
@@ -3048,12 +3017,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_phy_roothub_power_off(hcd->phy_roothub);
usb_phy_roothub_exit(hcd->phy_roothub);
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index a042675e03ba..aef50cb2ed1b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -103,7 +103,6 @@ struct usb_hcd {
 * other external phys should be software-transparent
 */
struct usb_phy  *usb_phy;
-   struct phy  *phy;
struct usb_phy_roothub  *phy_roothub;
 
/* Flags that need to be manipulated atomically because they can
-- 
2.16.1

--
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 usb-next v10 0/8] initialize (multiple) PHYs for a HCD

2018-02-18 Thread Martin Blumenstingl
tern's ACK on PATCH #3
- added Neil's Tested-by on PATCH #2 and #3

Changes since RfC v5 at [5]:
- dropped RfC prefix
- removed noisy dev_err if no roothub node was found (spotted by
  Xiaolong Ye's kbuild test robot - thank you for that!)
- moved the call to usb_phy_roothub_power_off() within
  hcd_bus_suspend() to make sure that the PHYs are turned off
  if the "race with a root-hub wakeup event" condition is met (in
  this case the PHYs are turned on again, with the old code we did
  break the PHYs internal ref-counting because we never turned the
  PHYs off before turning them on again in case of that special
  "race with a root-hub wakeup event").
  additionally we're not handling the status returned by
  usb_phy_roothub_power_off() anymore (the bus is already turned off
  and we tried to turn off all PHYs as well - only the PHYs which
  failed to power off will stay in the current state).
  thanks to Alan Stern for the suggestion
- removed return value from usb_phy_roothub_power_off() because none
  of my code uses it anymore. thanks to Alan Stern for the suggestion

Changes since v4 at [4]:
- renamed the subject of the cover-letter (old name was:
  "initialize (multiple) PHYs in xhci-plat")
- back into RFC status (see below for the reasons)
- dropped Tested-by from Chunfeng Yun (same reasons as RFC status)
- reworded cover-letter and commit messages from "platform-roothub"
  to "roothub PHY wrapper"
- moved code from drivers/usb/host/platform-roothub.* to
  drivers/usb/core/phy.* and the changes to
  drivers/usb/host/xhci-plat.c to drivers/usb/core/hcd.c as suggested
  by Mathias Nyman (as a benefit this will enable the new logic for
  non-xHCI controllers as well - however this was not tested yet)
- rename the structs, function names, etc from platform_roothub_* to
  usb_phy_roothub*

Changes since RFCv3 at [3]:
- moved the DT binding change from patch #3 to patch #1 as suggested
  by Rob Herring (and slightly adjusted the commit message to account
  for that)
- added Tested-by from Chunfeng Yun (who confirmed that the whole
  concept and implementation works fine on Mediatek SoCs - many thanks
  again!) to patch #2
- added Rob Herring's ACK to patches 1 and 3
- dropped RFC status (RFCv3 -> PATCH v4)

Changes since RFCv2 at [2]:
- split phy_{init,exit} and phy_power_{on,off} handling. up until RFCv2
  I called phy_init plus phy_power_on in platform_roothub_power_on and
  phy_power_off plus phy_exit in platform_roothub_power_off. However,
  Chunfeng Yun (a Mediatek SoC developer - many thanks for testing my
  series and providing great feedback) reported that only using
  phy_power_off (and omitting phy_exit) during system suspend fixes an
  issue where USB devices would be re-enumerated when resuming. His
  original problem description: "In order to keep link state on mt8173,
  we just power off all phys(not exit) when system enter suspend, then
  power on them again (needn't init, otherwise device will be
  disconnected) when system resume, this can avoid re-enumerating
  device.". This fix affects patch #2 and #3 as we now have
  platform_roothub_init (which calls phy_init internally),
  platform_roothub_power_on (which calls phy_power_on internally),
  platform_roothub_power_off (which calls phy_power_off internally) and
  platform_roothub_exit (which calls phy_exit internally). suspend and
  resume only call platform_roothub_power_{on,off} to prevent the issue
  described by Chunfeng Yun (unfortunately I cannot test this because
  the Amlogic platform currently does not support system suspend).
- dropped two struct forward declarations from platform-roothub.h which
  are not used in the header file (thanks to Chunfeng Yun for spotting
  this)

Changes since RFCv1 at [1]:
- split the usb-xhci dt-binding documentation into a separate patch
- fixed a typo ("usb-phy" -> "phys" in the dt-binding example)
- rebased to apply against latest usb-next


[0] http://lists.infradead.org/pipermail/linux-amlogic/2016-November/001818.html
[1] http://marc.info/?l=linux-usb=148414866303604=2
[2] https://www.spinics.net/lists/linux-usb/msg158967.html
[3] https://www.spinics.net/lists/devicetree/msg190426.html
[4] 
http://lists.infradead.org/pipermail/linux-amlogic/2017-September/004685.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/004924.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005049.html
[7] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005121.html
[8] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005124.html
[9] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005192.html
[10] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html
[11] https://marc.info/?l=linux-usb=151683941207898=2
[12] 
http://lists.infradead.org/pipermail/linux-amlogic/2018-February/006412.html

Martin Blumenstingl (8):
  dt-bindi

[PATCH usb-next v10 4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core

2018-02-18 Thread Martin Blumenstingl
This integrates the PHY wrapper into the core hcd infrastructure.
Multiple PHYs which are part of the HCD's device tree node are now
managed (= powered on/off when needed), by the new usb_phy_roothub code.

Suspend and resume is also supported, however not for
runtime/auto-suspend (which is triggered for example when no devices are
connected to the USB bus). This is needed on some SoCs (for example
Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend
then devices which are plugged in afterwards are not seen by the host.

One example where this is required is the Amlogic GXL and GXM SoCs:
They are using a dwc3 USB controller with up to three ports enabled on
the internal roothub. Each port has it's own PHY which must be enabled
(if one of the PHYs is left disabled then none of the USB ports works at
all).
The new logic works on the Amlogic GXL and GXM SoCs because the dwc3
driver internally creates a xhci-hcd which then registers a HCD which
then triggers our new PHY wrapper.

USB controller drivers can opt out of this by setting
"skip_phy_initialization" in struct usb_hcd to true. This is identical
to how it works for a single USB PHY, so the "multiple PHY" handling is
disabled for drivers that opted out of the management logic of a single
PHY.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
Acked-by: Chunfeng Yun <chunfeng@mediatek.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 drivers/usb/core/hcd.c  | 31 +++
 include/linux/usb/hcd.h |  1 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f2307470a31e..32797c25ac3b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -37,6 +37,7 @@
 #include 
 
 #include "usb.h"
+#include "phy.h"
 
 
 /*-*/
@@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
 
+   if (!PMSG_IS_AUTO(msg))
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
charbuffer[6];
@@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, 
pm_message_t msg)
dev_dbg(>dev, "skipped %s of dead bus\n", "resume");
return 0;
}
+
+   if (!PMSG_IS_AUTO(msg)) {
+   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (status)
+   return status;
+   }
+
if (!hcd->driver->bus_resume)
return -ENOENT;
if (HCD_RH_RUNNING(hcd))
@@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
+   usb_phy_roothub_power_off(hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
@@ -2769,6 +2781,18 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
+   if (!hcd->skip_phy_initialization) {
+   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   if (IS_ERR(hcd->phy_roothub)) {
+   retval = PTR_ERR(hcd->phy_roothub);
+   goto err_phy_roothub_init;
+   }
+
+   retval = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (retval)
+   goto err_usb_phy_roothub_power_on;
+   }
+
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
/* Keep old behaviour if authorized_default is not in [0, 1]. */
@@ -2933,6 +2957,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_register_bus:
hcd_buffer_destroy(hcd);
 err_create_buf:
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+err_usb_phy_roothub_power_on:
+   usb_phy_roothub_exit(hcd->phy_roothub);
+err_phy_roothub_init:
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy);
phy_exit(hcd->phy);
@@ -3017,6 +3045,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_deregister_bus(>self);
hcd_buffer_destroy(hcd);
 
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_exit(hcd->phy_roothub);
+
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy

[PATCH usb-next v10 6/8] usb: host: ehci-platform: remove custom USB PHY handling

2018-02-18 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ehci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
---
 drivers/usb/host/ehci-platform.c | 55 +++-
 1 file changed, 4 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b91eea8c73ae..4c306fb6b069 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -44,8 +43,6 @@
 struct ehci_platform_priv {
struct clk *clks[EHCI_MAX_CLKS];
struct reset_control *rsts;
-   struct phy **phys;
-   int num_phys;
bool reset_on_resume;
 };
 
@@ -80,7 +77,7 @@ static int ehci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -88,24 +85,8 @@ static int ehci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -117,12 +98,7 @@ static void ehci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -149,7 +125,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct usb_ehci_pdata *pdata = dev_get_platdata(>dev);
struct ehci_platform_priv *priv;
struct ehci_hcd *ehci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -202,29 +178,6 @@ static int ehci_platform_probe(struct platform_device *dev)
  "has-transaction-translator"))
hcd->has_tt = 1;
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->skip_phy_initialization = 1;
-   }
-   }
-
for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -306,7 +259,7 @@ static int ehci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_put_hcd:
+
   

Re: [PATCH usb-next v9 2/8] usb: add a flag to skip PHY initialization to struct usb_hcd

2018-02-12 Thread Martin Blumenstingl
Hi Alan,

On Mon, Feb 12, 2018 at 4:15 PM, Alan Stern <st...@rowland.harvard.edu> wrote:
> On Sun, 11 Feb 2018, Martin Blumenstingl wrote:
>
>> The USB HCD core driver parses the device-tree node for "phys" and
>> "usb-phys" properties. It also manages the power state of these PHYs
>> automatically.
>> However, drivers may opt-out of this behavior by setting "phy" or
>> "usb_phy" in struct usb_hcd to a non-null value. An example where this
>> is required is the "Qualcomm USB2 controller", implemented by the
>> chipidea driver. The hardware requires that the PHY is only powered on
>> after the "reset completed" event from the controller is received.
>>
>> A follow-up patch will allow the USB HCD core driver to manage more than
>> one PHY. Add a new "bool skip_phy_initialization" field to struct
>> usb_hcd so drivers can opt-out of any PHY management provided by the USB
>> HCD core driver. The new field will be used in that patch as well.
>>
>> This also updates the existing drivers so they use the new flag if they
>> want to opt out of the PHY management provided by the USB HCD core
>> driver. This means that for these drivers the new "multiple PHY"
>> handling (which will be added in a follow-up patch) will be disabled as
>> well.
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>
>> --- a/include/linux/usb/hcd.h
>> +++ b/include/linux/usb/hcd.h
>> @@ -98,6 +98,12 @@ struct usb_hcd {
>>*/
>>   const struct hc_driver  *driver;/* hw-specific hooks */
>>
>> + /*
>> +  * do not manage the PHY state in the HCD core, instead let the driver
>> +  * handle this (for example if the PHY can only be turned on after a
>> +  * specific event)
>> +  */
>> + bool skip_phy_initialization;
>
> Instead of declaring this as a bool at some random location in the
> structure, it would be better to make this a bitflag along with the
> other ones that get set at registration.  For example, it could come
> right after the remove_phy flag.
I'll move it to the other bitflags as suggested - thanks for pointing this out!

just to save you from reviewing this over and over again:
- I'll move the skip_phy_initialization field below remove_phy
- it's new definition will be "unsigned skip_phy_initialization:1"
- do you see any issues with the rest of the patch (the "concept" of
using a flag to skip all kinds of PHY initialization)?


Regards
Martin
--
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 usb-next v2 2/3] usb: dwc3: of-simple: add support for shared and pulsed reset lines

2018-02-11 Thread Martin Blumenstingl
Some SoCs (such as Amlogic Meson GXL for example) share the reset line
with other components (in case of the Meson GXL example there's a shared
reset line between the USB2 PHYs, USB3 PHYs and the dwc3 controller).
Additionally SoC implementations may prefer a reset pulse over level
resets.

For now this falls back to the old defaults, which are:
- reset lines are exclusive
- level resets are being used

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 drivers/usb/dwc3/dwc3-of-simple.c | 23 +--
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
b/drivers/usb/dwc3/dwc3-of-simple.c
index 7ae0eefc7cc7..d2e4928c8d62 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -27,6 +27,7 @@ struct dwc3_of_simple {
struct clk  **clks;
int num_clocks;
struct reset_control*resets;
+   boolpulse_resets;
 };
 
 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
@@ -83,6 +84,7 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 
int ret;
int i;
+   boolshared_resets = false;
 
simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
if (!simple)
@@ -91,16 +93,22 @@ static int dwc3_of_simple_probe(struct platform_device 
*pdev)
platform_set_drvdata(pdev, simple);
simple->dev = dev;
 
-   simple->resets = of_reset_control_array_get_optional_exclusive(np);
+   simple->resets = of_reset_control_array_get(np, shared_resets, true);
if (IS_ERR(simple->resets)) {
ret = PTR_ERR(simple->resets);
dev_err(dev, "failed to get device resets, err=%d\n", ret);
return ret;
}
 
-   ret = reset_control_deassert(simple->resets);
-   if (ret)
-   goto err_resetc_put;
+   if (simple->pulse_resets) {
+   ret = reset_control_reset(simple->resets);
+   if (ret)
+   goto err_resetc_put;
+   } else {
+   ret = reset_control_deassert(simple->resets);
+   if (ret)
+   goto err_resetc_put;
+   }
 
ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
"clocks", "#clock-cells"));
@@ -124,7 +132,8 @@ static int dwc3_of_simple_probe(struct platform_device 
*pdev)
return 0;
 
 err_resetc_assert:
-   reset_control_assert(simple->resets);
+   if (!simple->pulse_resets)
+   reset_control_assert(simple->resets);
 
 err_resetc_put:
reset_control_put(simple->resets);
@@ -144,7 +153,9 @@ static int dwc3_of_simple_remove(struct platform_device 
*pdev)
clk_put(simple->clks[i]);
}
 
-   reset_control_assert(simple->resets);
+   if (!simple->pulse_resets)
+   reset_control_assert(simple->resets);
+
reset_control_put(simple->resets);
 
pm_runtime_put_sync(dev);
-- 
2.16.1

--
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 usb-next v2 3/3] usb: dwc3: of-simple: add support for the Amlogic Meson GXL and AXG SoCs

2018-02-11 Thread Martin Blumenstingl
Amlogic Meson GXL and AXG SoCs come with a (host-only) dwc3 USB
controller. To use this controller a clock has to be enabled and a reset
line has to be pulsed.
Enabling the clock works identical to other SoCs. However, the reset
line has to be pulsed (using reset_control_reset) instead of using a
level reset (reset_control_{assert,deassert}).

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 drivers/usb/dwc3/dwc3-of-simple.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
b/drivers/usb/dwc3/dwc3-of-simple.c
index d2e4928c8d62..66cdc79017cf 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -93,6 +93,12 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, simple);
simple->dev = dev;
 
+   if (of_device_is_compatible(np, "amlogic,meson-axg-dwc3") ||
+   of_device_is_compatible(np, "amlogic,meson-gxl-dwc3")) {
+   shared_resets = true;
+   simple->pulse_resets = true;
+   }
+
simple->resets = of_reset_control_array_get(np, shared_resets, true);
if (IS_ERR(simple->resets)) {
ret = PTR_ERR(simple->resets);
@@ -206,6 +212,8 @@ static const struct of_device_id of_dwc3_simple_match[] = {
{ .compatible = "xlnx,zynqmp-dwc3" },
{ .compatible = "cavium,octeon-7130-usb-uctl" },
{ .compatible = "sprd,sc9860-dwc3" },
+   { .compatible = "amlogic,meson-axg-dwc3" },
+   { .compatible = "amlogic,meson-gxl-dwc3" },
{ /* Sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
-- 
2.16.1

--
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 usb-next v2 0/3] DWC3 support for Amlogic Meson AXG and GXL SoCs

2018-02-11 Thread Martin Blumenstingl
Amlogic Meson AXG and GXL SoCs can use the dwc3-of-simple with little
modifications. These SoCs use:
- a gate clock for the USB components (DWC3, USB PHYs)
- a reset line which is shared across all USB components (DWC3, USB2 and
  USB3 PHYs, OTG detection logic inside the USB3 PHY registers)
- a reset pulse to trigger the reset
- depending on the SoC two or more PHYs (AXG: 1x USB2 and 1x USB3 PHY,
  GXL: 2x USB2 and 1x USB3 PHY)

This extends the dwc3-of-simple so it supports (depending on the
platform) shared and level resets. Additionally it adds new bindings
for the Amlogic Meson AXG and GXL SoCs, along with the documentation
(dt-bindings).

NOTE: for full support on Amlogic Meson GXL SoCs my other series called
"initialize (multiple) PHYs for a HCD" (see [0] for v8 of that series)
is required. However, there is no direct dependency on that series.
Especially since Meson AXG doesn't need it (since it only has one USB2
and one USB3 PHY, which is already supported by the current dwc3 driver,
unlike the 2x USB2 and 1x USB3 PHYs on Meson GXL).
So I believe that this series can still be merged, even if the other
patchset is not ready yet.


changes since v1 at [1]:
- use of_device_is_compatible() instead of struct dwc3_of_simple_params
  as requested by Felipe Balbi (affects PATCH #2 and #3)
- added Rob's Acked-by to the dt-bindings patch
- added Yixun Lan's Tested-by to the whole series as he tested this
  successfully (along with other patches) on the Amlogic Meson AXG SoC


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006286.html

Martin Blumenstingl (3):
  dt-bindings: usb: add support for dwc3 controller on Amlogic Meson GX
  usb: dwc3: of-simple: add support for shared and pulsed reset lines
  usb: dwc3: of-simple: add support for the Amlogic Meson GXL and AXG
SoCs

 .../devicetree/bindings/usb/amlogic,dwc3.txt   | 42 ++
 drivers/usb/dwc3/dwc3-of-simple.c  | 31 
 2 files changed, 67 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/amlogic,dwc3.txt

-- 
2.16.1

--
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 usb-next v2 1/3] dt-bindings: usb: add support for dwc3 controller on Amlogic Meson GX

2018-02-11 Thread Martin Blumenstingl
Amlogic Meson GX SoCs (GXL and AXG) come with a (host-only) dwc3 USB
controller. This requires a clock to be enabled and a reset line to be
pulsed to get the hardware into a known state.
Add the documentation for this IP block, similar to "qcom,dwc3.txt".

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Reviewed-by: Rob Herring <r...@kernel.org>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 .../devicetree/bindings/usb/amlogic,dwc3.txt   | 42 ++
 1 file changed, 42 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/amlogic,dwc3.txt

diff --git a/Documentation/devicetree/bindings/usb/amlogic,dwc3.txt 
b/Documentation/devicetree/bindings/usb/amlogic,dwc3.txt
new file mode 100644
index ..9a8b631904fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/amlogic,dwc3.txt
@@ -0,0 +1,42 @@
+Amlogic Meson GX DWC3 USB SoC controller
+
+Required properties:
+- compatible:  depending on the SoC this should contain one of:
+   * amlogic,meson-axg-dwc3
+   * amlogic,meson-gxl-dwc3
+- clocks:  a handle for the "USB general" clock
+- clock-names: must be "usb_general"
+- resets:  a handle for the shared "USB OTG" reset line
+- reset-names: must be "usb_otg"
+
+Required child node:
+A child node must exist to represent the core DWC3 IP block. The name of
+the node is not important. The content of the node is defined in dwc3.txt.
+
+PHY documentation is provided in the following places:
+- Documentation/devicetree/bindings/phy/meson-gxl-usb2-phy.txt
+- Documentation/devicetree/bindings/phy/meson-gxl-usb3-phy.txt
+
+Example device nodes:
+   usb0: usb@ff50 {
+   compatible = "amlogic,meson-axg-dwc3";
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+
+   clocks = < CLKID_USB>;
+   clock-names = "usb_general";
+   resets = < RESET_USB_OTG>;
+   reset-names = "usb_otg";
+
+   dwc3: dwc3@ff50 {
+   compatible = "snps,dwc3";
+   reg = <0x0 0xff50 0x0 0x10>;
+   interrupts = ;
+   dr_mode = "host";
+   maximum-speed = "high-speed";
+   snps,dis_u2_susphy_quirk;
+   phys = <_phy>, <_phy0>;
+   phy-names = "usb2-phy", "usb3-phy";
+   };
+   };
-- 
2.16.1

--
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 usb-next v9 5/8] usb: host: xhci-mtk: remove custom USB PHY handling

2018-02-11 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the xhci-mtk driver as the core
HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/host/xhci-mtk.c | 98 +
 1 file changed, 2 insertions(+), 96 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index b0ab4d5e2751..7334da9e9779 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -352,62 +351,6 @@ static const struct xhci_driver_overrides 
xhci_mtk_overrides __initconst = {
 
 static struct hc_driver __read_mostly xhci_mtk_hc_driver;
 
-static int xhci_mtk_phy_init(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_init(mtk->phys[i]);
-   if (ret)
-   goto exit_phy;
-   }
-   return 0;
-
-exit_phy:
-   for (; i > 0; i--)
-   phy_exit(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static int xhci_mtk_phy_exit(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_exit(mtk->phys[i]);
-
-   return 0;
-}
-
-static int xhci_mtk_phy_power_on(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_power_on(mtk->phys[i]);
-   if (ret)
-   goto power_off_phy;
-   }
-   return 0;
-
-power_off_phy:
-   for (; i > 0; i--)
-   phy_power_off(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static void xhci_mtk_phy_power_off(struct xhci_hcd_mtk *mtk)
-{
-   unsigned int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_power_off(mtk->phys[i]);
-}
-
 static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
 {
int ret;
@@ -488,8 +431,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
-   struct phy *phy;
-   int phy_num;
int ret = -ENODEV;
int irq;
 
@@ -529,16 +470,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
return ret;
}
 
-   mtk->num_phys = of_count_phandle_with_args(node,
-   "phys", "#phy-cells");
-   if (mtk->num_phys > 0) {
-   mtk->phys = devm_kcalloc(dev, mtk->num_phys,
-   sizeof(*mtk->phys), GFP_KERNEL);
-   if (!mtk->phys)
-   return -ENOMEM;
-   } else {
-   mtk->num_phys = 0;
-   }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
device_enable_async_suspend(dev);
@@ -596,23 +527,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
mtk->has_ippc = false;
}
 
-   for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
-   phy = devm_of_phy_get_by_index(dev, node, phy_num);
-   if (IS_ERR(phy)) {
-   ret = PTR_ERR(phy);
-   goto put_usb2_hcd;
-   }
-   mtk->phys[phy_num] = phy;
-   }
-
-   ret = xhci_mtk_phy_init(mtk);
-   if (ret)
-   goto put_usb2_hcd;
-
-   ret = xhci_mtk_phy_power_on(mtk);
-   if (ret)
-   goto exit_phys;
-
device_init_wakeup(dev, true);
 
xhci = hcd_to_xhci(hcd);
@@ -630,7 +544,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
dev_name(dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
-   goto power_off_phys;
+   goto disable_device_wakeup;
}
 
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -653,13 +567,9 @@ static int xhci_mtk_probe(struct platform_device *pdev)
xhci_mtk_sch_exit(mtk);
usb_put_hcd(xhci->shared_hcd);
 
-power_off_phys:
-   xhci_mtk_phy_power_off(mtk);
+disable_device_wakeup:
device_init_wakeup(dev, false);
 
-exit_phys:
-   xhci_mtk_phy_exit(mtk);
-
 put_usb2_hcd:
usb_put_hcd(hcd);
 
@@ -682,8 +592,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
usb_remove_hcd(xhci->shared_hcd);
-   xhci_mtk_phy_power_off(mtk);
-   xhci_mtk_phy_exit(mtk);
device_init_wakeup(>dev, false);
 
usb_remove_hcd(hcd);
@@ -718,7 +626,6 @@ static int __maybe_unused xhci_mtk_suspend(struct device 
*de

[PATCH usb-next v9 6/8] usb: host: ehci-platform: remove custom USB PHY handling

2018-02-11 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ehci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
---
 drivers/usb/host/ehci-platform.c | 55 +++-
 1 file changed, 4 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 40fbc4925378..4c306fb6b069 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -44,8 +43,6 @@
 struct ehci_platform_priv {
struct clk *clks[EHCI_MAX_CLKS];
struct reset_control *rsts;
-   struct phy **phys;
-   int num_phys;
bool reset_on_resume;
 };
 
@@ -80,7 +77,7 @@ static int ehci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -88,24 +85,8 @@ static int ehci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -117,12 +98,7 @@ static void ehci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -149,7 +125,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct usb_ehci_pdata *pdata = dev_get_platdata(>dev);
struct ehci_platform_priv *priv;
struct ehci_hcd *ehci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -202,29 +178,6 @@ static int ehci_platform_probe(struct platform_device *dev)
  "has-transaction-translator"))
hcd->has_tt = 1;
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->skip_phy_initialization = true;
-   }
-   }
-
for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -306,7 +259,7 @@ static int ehci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_p

[PATCH usb-next v9 7/8] usb: host: ohci-platform: remove custom USB PHY handling

2018-02-11 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ohci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
---
 drivers/usb/host/ohci-platform.c | 56 
 1 file changed, 5 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index bd605e79ae7d..65a1c3fdc88c 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -21,7 +21,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -38,8 +38,6 @@
 struct ohci_platform_priv {
struct clk *clks[OHCI_MAX_CLKS];
struct reset_control *resets;
-   struct phy **phys;
-   int num_phys;
 };
 
 static const char hcd_name[] = "ohci-platform";
@@ -48,7 +46,7 @@ static int ohci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -56,24 +54,8 @@ static int ohci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -85,12 +67,7 @@ static void ohci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -117,7 +94,7 @@ static int ohci_platform_probe(struct platform_device *dev)
struct usb_ohci_pdata *pdata = dev_get_platdata(>dev);
struct ohci_platform_priv *priv;
struct ohci_hcd *ohci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -169,29 +146,6 @@ static int ohci_platform_probe(struct platform_device *dev)
of_property_read_u32(dev->dev.of_node, "num-ports",
 >num_ports);
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->skip_phy_initialization = true;
-   }
-   }
-
for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -277,7 +231,7 @@ static int ohci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
   

[PATCH usb-next v9 1/8] dt-bindings: usb: add the documentation for USB HCDs

2018-02-11 Thread Martin Blumenstingl
A USB HCD may have several PHYs which need to be configured before the
the HCD starts working.
This adds the documentation for such a USB HCD as well as a reference to
the new "usb-hcd.txt" from all bindings that implement a USB HCD which
support one USB PHY per port.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Reviewed-by: Rob Herring <r...@kernel.org>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 5 -
 Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 5 -
 Documentation/devicetree/bindings/usb/usb-ehci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-hcd.txt   | 9 +
 Documentation/devicetree/bindings/usb/usb-ohci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-uhci.txt  | 3 +++
 Documentation/devicetree/bindings/usb/usb-xhci.txt  | 5 +
 7 files changed, 33 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/usb-hcd.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
index 88d9f4a4b280..266c2d917a28 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
@@ -32,7 +32,7 @@ Required properties:
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA
 
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
 
 Optional properties:
  - wakeup-source : enable USB remote wakeup;
@@ -52,6 +52,9 @@ Optional properties:
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  - imod-interval-ns: default interrupt moderation interval is 5000ns
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example:
 usb30: usb@1127 {
compatible = "mediatek,mt8173-xhci";
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index d589a1ef96a1..3382b5cb471d 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
@@ -17,7 +17,7 @@ Required properties:
  - clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dam_ck";
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
  - dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
 
@@ -53,6 +53,9 @@ Optional properties:
  - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Sub-nodes:
 The xhci should be added as subnode to mtu3 as shown in the following example
 if host mode is enabled. The DT binding details of xhci can be found in:
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt 
b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index 3efde12b5d68..0f1b75386207 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -16,10 +16,12 @@ Optional properties:
  - has-transaction-translator : boolean, set this if EHCI have a Transaction
Translator built into the root hub.
  - clocks : a list of phandle + clock specifier pairs
- - phys : phandle + phy specifier pair
- - phy-names : "usb"
+ - phys : see usb-hcd.txt in the current directory
  - resets : phandle + reset specifier pair
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example (Sequoia 440EPx):
 ehci@e300 {
   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.txt 
b/Documentation/devicetree/bindings/usb/usb-hcd.txt
new file mode 100644
index ..50529b838c9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.txt
@@ -0,0 +1,9 @@
+Generic USB HCD (Host Controller Device) Properties
+
+Optional properties:
+- phys: a list of all USB PHYs on this HCD
+
+Example:
+{
+   phys = <_phy1>, <_phy1>;
+   };
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt 
b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 09e70c875bc6..a8d2103d1f3d 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -13,10 +13,12 @@ Optional properties:
 - remote-wakeup-connected: remote wakeup is wired on the 

[PATCH usb-next v9 4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core

2018-02-11 Thread Martin Blumenstingl
This integrates the PHY wrapper into the core hcd infrastructure.
Multiple PHYs which are part of the HCD's device tree node are now
managed (= powered on/off when needed), by the new usb_phy_roothub code.

Suspend and resume is also supported, however not for
runtime/auto-suspend (which is triggered for example when no devices are
connected to the USB bus). This is needed on some SoCs (for example
Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend
then devices which are plugged in afterwards are not seen by the host.

One example where this is required is the Amlogic GXL and GXM SoCs:
They are using a dwc3 USB controller with up to three ports enabled on
the internal roothub. Each port has it's own PHY which must be enabled
(if one of the PHYs is left disabled then none of the USB ports works at
all).
The new logic works on the Amlogic GXL and GXM SoCs because the dwc3
driver internally creates a xhci-hcd which then registers a HCD which
then triggers our new PHY wrapper.

USB controller drivers can opt out of this by setting
"skip_phy_initialization" in struct usb_hcd to true. This is identical
to how it works for a single USB PHY, so the "multiple PHY" handling is
disabled for drivers that opted out of the management logic of a single
PHY.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
Acked-by: Chunfeng Yun <chunfeng@mediatek.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
---
 drivers/usb/core/hcd.c  | 31 +++
 include/linux/usb/hcd.h |  1 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f2307470a31e..32797c25ac3b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -37,6 +37,7 @@
 #include 
 
 #include "usb.h"
+#include "phy.h"
 
 
 /*-*/
@@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
 
+   if (!PMSG_IS_AUTO(msg))
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
charbuffer[6];
@@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, 
pm_message_t msg)
dev_dbg(>dev, "skipped %s of dead bus\n", "resume");
return 0;
}
+
+   if (!PMSG_IS_AUTO(msg)) {
+   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (status)
+   return status;
+   }
+
if (!hcd->driver->bus_resume)
return -ENOENT;
if (HCD_RH_RUNNING(hcd))
@@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
+   usb_phy_roothub_power_off(hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
@@ -2769,6 +2781,18 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
+   if (!hcd->skip_phy_initialization) {
+   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   if (IS_ERR(hcd->phy_roothub)) {
+   retval = PTR_ERR(hcd->phy_roothub);
+   goto err_phy_roothub_init;
+   }
+
+   retval = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (retval)
+   goto err_usb_phy_roothub_power_on;
+   }
+
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
/* Keep old behaviour if authorized_default is not in [0, 1]. */
@@ -2933,6 +2957,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_register_bus:
hcd_buffer_destroy(hcd);
 err_create_buf:
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+err_usb_phy_roothub_power_on:
+   usb_phy_roothub_exit(hcd->phy_roothub);
+err_phy_roothub_init:
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy);
phy_exit(hcd->phy);
@@ -3017,6 +3045,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_deregister_bus(>self);
hcd_buffer_destroy(hcd);
 
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_exit(hcd->phy_roothub);
+
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy

[PATCH usb-next v9 2/8] usb: add a flag to skip PHY initialization to struct usb_hcd

2018-02-11 Thread Martin Blumenstingl
The USB HCD core driver parses the device-tree node for "phys" and
"usb-phys" properties. It also manages the power state of these PHYs
automatically.
However, drivers may opt-out of this behavior by setting "phy" or
"usb_phy" in struct usb_hcd to a non-null value. An example where this
is required is the "Qualcomm USB2 controller", implemented by the
chipidea driver. The hardware requires that the PHY is only powered on
after the "reset completed" event from the controller is received.

A follow-up patch will allow the USB HCD core driver to manage more than
one PHY. Add a new "bool skip_phy_initialization" field to struct
usb_hcd so drivers can opt-out of any PHY management provided by the USB
HCD core driver. The new field will be used in that patch as well.

This also updates the existing drivers so they use the new flag if they
want to opt out of the PHY management provided by the USB HCD core
driver. This means that for these drivers the new "multiple PHY"
handling (which will be added in a follow-up patch) will be disabled as
well.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/chipidea/host.c  | 5 +
 drivers/usb/core/hcd.c   | 4 ++--
 drivers/usb/host/ehci-fsl.c  | 2 ++
 drivers/usb/host/ehci-platform.c | 4 ++--
 drivers/usb/host/ehci-tegra.c| 1 +
 drivers/usb/host/ohci-omap.c | 1 +
 drivers/usb/host/ohci-platform.c | 4 ++--
 drivers/usb/host/xhci-plat.c | 1 +
 include/linux/usb/hcd.h  | 6 ++
 9 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 19d60ed7e41f..493ef826ef4c 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -124,10 +124,7 @@ static int host_start(struct ci_hdrc *ci)
 
hcd->power_budget = ci->platdata->power_budget;
hcd->tpl_support = ci->platdata->tpl_support;
-   if (ci->phy)
-   hcd->phy = ci->phy;
-   else
-   hcd->usb_phy = ci->usb_phy;
+   hcd->skip_phy_initialization = ci->phy || ci->usb_phy;
 
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fc32391a34d5..f2307470a31e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2727,7 +2727,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
 
-   if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
+   if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0);
 
if (IS_ERR(phy)) {
@@ -2745,7 +2745,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
+   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
struct phy *phy = phy_get(hcd->self.sysdev, "usb");
 
if (IS_ERR(phy)) {
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index c5094cb88cd5..009de5e4e136 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -155,6 +155,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
retval = -ENODEV;
goto err2;
}
+
+   hcd->skip_phy_initialization = true;
}
 #endif
return retval;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b065a960adc2..40fbc4925378 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -219,9 +219,9 @@ static int ehci_platform_probe(struct platform_device *dev)
if (IS_ERR(priv->phys[phy_num])) {
err = PTR_ERR(priv->phys[phy_num]);
goto err_put_hcd;
-   } else if (!hcd->phy) {
+   } else {
/* Avoiding phy_get() in usb_add_hcd() */
-   hcd->phy = priv->phys[phy_num];
+   hcd->skip_phy_initialization = true;
}
}
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c809f7d2f08f..9a8442a66b14 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -461,6 +461,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_clk_en;
}
hcd->usb_phy = u_phy;
+   hcd->skip_phy_initialization = true;
 
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvidia,nee

[PATCH usb-next v9 8/8] usb: core: hcd: remove support for initializing a single PHY

2018-02-11 Thread Martin Blumenstingl
With the new PHY wrapper in place we can now handle multiple PHYs.
Remove the code which handles only one generic PHY as this is now
covered (with support for multiple PHYs as well as suspend/resume
support) by the new PHY wrapper.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c  | 37 -
 include/linux/usb/hcd.h |  1 -
 2 files changed, 38 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 32797c25ac3b..5a92d8f7c484 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2757,30 +2757,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
-   struct phy *phy = phy_get(hcd->self.sysdev, "usb");
-
-   if (IS_ERR(phy)) {
-   retval = PTR_ERR(phy);
-   if (retval == -EPROBE_DEFER)
-   goto err_phy;
-   } else {
-   retval = phy_init(phy);
-   if (retval) {
-   phy_put(phy);
-   goto err_phy;
-   }
-   retval = phy_power_on(phy);
-   if (retval) {
-   phy_exit(phy);
-   phy_put(phy);
-   goto err_phy;
-   }
-   hcd->phy = phy;
-   hcd->remove_phy = 1;
-   }
-   }
-
if (!hcd->skip_phy_initialization) {
hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
@@ -2961,13 +2937,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
 err_phy_roothub_init:
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
-err_phy:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
@@ -3048,12 +3017,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_phy_roothub_power_off(hcd->phy_roothub);
usb_phy_roothub_exit(hcd->phy_roothub);
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index b85e3d4fb0c5..68694afd4a46 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -109,7 +109,6 @@ struct usb_hcd {
 * other external phys should be software-transparent
 */
struct usb_phy  *usb_phy;
-   struct phy  *phy;
struct usb_phy_roothub  *phy_roothub;
 
/* Flags that need to be manipulated atomically because they can
-- 
2.16.1

--
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 usb-next v9 0/8] initialize (multiple) PHYs for a HCD

2018-02-11 Thread Martin Blumenstingl
thub_power_off() within
  hcd_bus_suspend() to make sure that the PHYs are turned off
  if the "race with a root-hub wakeup event" condition is met (in
  this case the PHYs are turned on again, with the old code we did
  break the PHYs internal ref-counting because we never turned the
  PHYs off before turning them on again in case of that special
  "race with a root-hub wakeup event").
  additionally we're not handling the status returned by
  usb_phy_roothub_power_off() anymore (the bus is already turned off
  and we tried to turn off all PHYs as well - only the PHYs which
  failed to power off will stay in the current state).
  thanks to Alan Stern for the suggestion
- removed return value from usb_phy_roothub_power_off() because none
  of my code uses it anymore. thanks to Alan Stern for the suggestion

Changes since v4 at [4]:
- renamed the subject of the cover-letter (old name was:
  "initialize (multiple) PHYs in xhci-plat")
- back into RFC status (see below for the reasons)
- dropped Tested-by from Chunfeng Yun (same reasons as RFC status)
- reworded cover-letter and commit messages from "platform-roothub"
  to "roothub PHY wrapper"
- moved code from drivers/usb/host/platform-roothub.* to
  drivers/usb/core/phy.* and the changes to
  drivers/usb/host/xhci-plat.c to drivers/usb/core/hcd.c as suggested
  by Mathias Nyman (as a benefit this will enable the new logic for
  non-xHCI controllers as well - however this was not tested yet)
- rename the structs, function names, etc from platform_roothub_* to
  usb_phy_roothub*

Changes since RFCv3 at [3]:
- moved the DT binding change from patch #3 to patch #1 as suggested
  by Rob Herring (and slightly adjusted the commit message to account
  for that)
- added Tested-by from Chunfeng Yun (who confirmed that the whole
  concept and implementation works fine on Mediatek SoCs - many thanks
  again!) to patch #2
- added Rob Herring's ACK to patches 1 and 3
- dropped RFC status (RFCv3 -> PATCH v4)

Changes since RFCv2 at [2]:
- split phy_{init,exit} and phy_power_{on,off} handling. up until RFCv2
  I called phy_init plus phy_power_on in platform_roothub_power_on and
  phy_power_off plus phy_exit in platform_roothub_power_off. However,
  Chunfeng Yun (a Mediatek SoC developer - many thanks for testing my
  series and providing great feedback) reported that only using
  phy_power_off (and omitting phy_exit) during system suspend fixes an
  issue where USB devices would be re-enumerated when resuming. His
  original problem description: "In order to keep link state on mt8173,
  we just power off all phys(not exit) when system enter suspend, then
  power on them again (needn't init, otherwise device will be
  disconnected) when system resume, this can avoid re-enumerating
  device.". This fix affects patch #2 and #3 as we now have
  platform_roothub_init (which calls phy_init internally),
  platform_roothub_power_on (which calls phy_power_on internally),
  platform_roothub_power_off (which calls phy_power_off internally) and
  platform_roothub_exit (which calls phy_exit internally). suspend and
  resume only call platform_roothub_power_{on,off} to prevent the issue
  described by Chunfeng Yun (unfortunately I cannot test this because
  the Amlogic platform currently does not support system suspend).
- dropped two struct forward declarations from platform-roothub.h which
  are not used in the header file (thanks to Chunfeng Yun for spotting
  this)

Changes since RFCv1 at [1]:
- split the usb-xhci dt-binding documentation into a separate patch
- fixed a typo ("usb-phy" -> "phys" in the dt-binding example)
- rebased to apply against latest usb-next


[0] http://lists.infradead.org/pipermail/linux-amlogic/2016-November/001818.html
[1] http://marc.info/?l=linux-usb=148414866303604=2
[2] https://www.spinics.net/lists/linux-usb/msg158967.html
[3] https://www.spinics.net/lists/devicetree/msg190426.html
[4] 
http://lists.infradead.org/pipermail/linux-amlogic/2017-September/004685.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/004924.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005049.html
[7] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005121.html
[8] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005124.html
[9] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005192.html
[10] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html
[11] https://marc.info/?l=linux-usb=151683941207898=2

Martin Blumenstingl (8):
  dt-bindings: usb: add the documentation for USB HCDs
  usb: add a flag to skip PHY initialization to struct usb_hcd
  usb: core: add a wrapper for the USB PHYs on the HCD
  usb: core: hcd: integrate the PHY wrapper into the HCD core
  usb: host: xhci-mtk: remove custom USB PHY handling
  usb: host: ehci-platform: remove custom USB PHY handling
  usb: host: oh

[PATCH usb-next v9 3/8] usb: core: add a wrapper for the USB PHYs on the HCD

2018-02-11 Thread Martin Blumenstingl
Many SoC platforms have separate devices for the USB PHY which are
registered through the generic PHY framework. These PHYs have to be
enabled to make the USB controller actually work. They also have to be
disabled again on shutdown/suspend.

Currently (at least) the following HCI platform drivers are using custom
code to obtain all PHYs via devicetree for the roothub/controller and
disable/enable them when required:
- ehci-platform.c has ehci_platform_power_{on,off}
- xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
- ohci-platform.c has ohci_platform_power_{on,off}

With this new wrapper the USB PHYs can be specified directly in the
USB controller's devicetree node (just like on the drivers listed
above). This allows SoCs like the Amlogic Meson GXL family to operate
correctly once this is wired up correctly. These SoCs use a dwc3
controller and require all USB PHYs to be initialized (if one of the USB
PHYs it not initialized then none of USB port works at all).

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Tested-by: Yixun Lan <yixun@amlogic.com>
Cc: Neil Armstrong <narmstr...@baylibre.com>
Cc: Chunfeng Yun <chunfeng@mediatek.com>
---
 drivers/usb/core/Makefile |   2 +-
 drivers/usb/core/phy.c| 158 ++
 drivers/usb/core/phy.h|   7 ++
 3 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/core/phy.c
 create mode 100644 drivers/usb/core/phy.h

diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 92c9cefb4317..18e874b0441e 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -6,7 +6,7 @@
 usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
 usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
 usbcore-y += devio.o notify.o generic.o quirks.o devices.o
-usbcore-y += port.o
+usbcore-y += phy.o port.o
 
 usbcore-$(CONFIG_OF)   += of.o
 usbcore-$(CONFIG_USB_PCI)  += hcd-pci.o
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
new file mode 100644
index ..09b7c43c0ea4
--- /dev/null
+++ b/drivers/usb/core/phy.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * A wrapper for multiple PHYs which passes all phy_* function calls to
+ * multiple (actual) PHY devices. This is comes handy when initializing
+ * all PHYs on a HCD and to keep them all in the same state.
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumensti...@googlemail.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "phy.h"
+
+struct usb_phy_roothub {
+   struct phy  *phy;
+   struct list_headlist;
+};
+
+static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
+{
+   struct usb_phy_roothub *roothub_entry;
+
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_entry->list);
+
+   return roothub_entry;
+}
+
+static int usb_phy_roothub_add_phy(struct device *dev, int index,
+  struct list_head *list)
+{
+   struct usb_phy_roothub *roothub_entry;
+   struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
+
+   if (IS_ERR_OR_NULL(phy)) {
+   if (!phy || PTR_ERR(phy) == -ENODEV)
+   return 0;
+   else
+   return PTR_ERR(phy);
+   }
+
+   roothub_entry = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(roothub_entry))
+   return PTR_ERR(roothub_entry);
+
+   roothub_entry->phy = phy;
+
+   list_add_tail(_entry->list, list);
+
+   return 0;
+}
+
+struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+{
+   struct usb_phy_roothub *phy_roothub;
+   struct usb_phy_roothub *roothub_entry;
+   struct list_head *head;
+   int i, num_phys, err;
+
+   num_phys = of_count_phandle_with_args(dev->of_node, "phys",
+ "#phy-cells");
+   if (num_phys <= 0)
+   return NULL;
+
+   phy_roothub = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(phy_roothub))
+   return phy_roothub;
+
+   for (i = 0; i < num_phys; i++) {
+   err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
+   if (err)
+   goto err_out;
+   }
+
+   head = _roothub->list;
+
+   list_for_each_entry(roothub_entry, head, list) {
+   err = phy_init(roothub_entry->phy);
+   if (err)
+   goto err_exit_phys;
+   }
+
+   return phy_roothub;
+
+err_exit_phys:
+   list_for_each_entry_continue_reverse(roothub_entry, head, list)
+   phy_exit(roothub_entry->phy);
+
+err_out:
+   return ERR_PTR(err);
+}
+EXPORT_SYMB

Re: [RFC/RFT usb-next v1 5/6] usb: chipidea: do not set the "phy" field in struct usb_hcd

2018-02-04 Thread Martin Blumenstingl
Hi Peter,

On Mon, Jan 29, 2018 at 4:30 AM, Peter Chen <peter.c...@nxp.com> wrote:
>
>> >
>> >>
>> >> Now that usb_add_hcd parses all generic PHYs anyways the code which
>> >> skips initialization of a single PHY will go away.
>> >> Remove the code which sets struct usb_hcd's phy field from the
>> >> chipidea driver as this field will go away soon.
>> >>
>> >> Signed-off-by: Martin Blumenstingl
>> >> <martin.blumensti...@googlemail.com>
>> >> ---
>> >>  drivers/usb/chipidea/host.c | 4 +---
>> >>  1 file changed, 1 insertion(+), 3 deletions(-)
>> >>
>> >> diff --git a/drivers/usb/chipidea/host.c
>> >> b/drivers/usb/chipidea/host.c index 19d60ed7e41f..fc324767cb0f 100644
>> >> --- a/drivers/usb/chipidea/host.c
>> >> +++ b/drivers/usb/chipidea/host.c
>> >> @@ -124,9 +124,7 @@ static int host_start(struct ci_hdrc *ci)
>> >>
>> >>   hcd->power_budget = ci->platdata->power_budget;
>> >>   hcd->tpl_support = ci->platdata->tpl_support;
>> >> - if (ci->phy)
>> >> - hcd->phy = ci->phy;
>> >> - else
>> >> + if (!ci->phy)
>> >>   hcd->usb_phy = ci->usb_phy;
>> >>
>> >
>> > The reason hcd->phy is initialized by chipidea core is we do not need
>> > HCD core to touch PHY, and PHY operation is shared for both device and host
>> mode for chipidea.
>> Chunfeng wanted me to drop the mtu3 patch because I forgot about device mode 
>> in
>> the mtu3 driver.
>> however, the chipidea driver seems to be different because I'm not dropping 
>> the
>> whole phy_{init,power_on,power_off,exit} code from it, but only a "flag" 
>> that tells the
>> HCD core to skip managing the USB PHY
>>
>> > If I understand correct, your HCD core PHY wrapper patch set will do
>> > PHY operation if there is a "phy" node under controller's? If it is
>> > correct, you may supply one way to let the HCD core bypass phy operations 
>> > for
>> some USB controllers, eg dual-role controllers.
>> > Thanks.
>> could you please explain why the HCD core should not manage the the PHYs when
>> the chipidea driver is used?
>>
>> my understanding is that all phy_{init,power_on,power_off,exit}
>> operations are ref-counted internally in the PHY framework this means that 
>> if the
>> chipidea driver calls phy_{init,power_on} first then the same functions 
>> called from
>> within the HCD core are no-ops (except for the ref-counting) so I think it 
>> should not
>> change anything - however, I have no hardware to actually prove that.
>
> Martin, you design has no problem for most of cases, but some hardware needs 
> special
> sequence for phy control. I will give an example below.
great to hear that this should work for most devices!

>> it would be great if you could explain the issue behind this (and thereby 
>> answer the
>> question: why we would not want the HCD core to manage the PHY states)!
>>
>>
> Eg, taking Qualcomm USB2 controller as an example, it even does not allow 
> chipidea core
> to manage its power operation, see CI_HDRC_OVERRIDE_PHY_CONTROL at chipidea 
> driver
> (usb/chipidea/core.c). Its phy_power_on is called after ehci controller reset 
> has finished.
> (usb/chipidea/ci_hdrc_msm.c).
I see, thank you for explaining this!

what do you think about replacing the two following fields from struct usb_hcd:
  struct usb_phy *usb_phy;
  struct phy *phy;
with:
  /*
   * do not manage the PHY state in the HCD core, instead let the driver handle
   * this (for example if the PHY can only be turned on after a specific event)
   */
  bool skip_phy_initialization;

maybe I should also do this together with my other series which adds
the PHY wrapper to the HCD core (or even as a separate series, which
would be merged before this and the PHY wrapper series). what do you
think?


Regards
Martin
--
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 2/3] usb: dwc3: of-simple: add support for shared and pulsed reset lines

2018-02-03 Thread Martin Blumenstingl
Hi Felipe,

On Mon, Jan 29, 2018 at 9:18 AM, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Martin Blumenstingl <martin.blumensti...@googlemail.com> writes:
>> Some SoCs (such as Amlogic Meson GXL for example) share the reset line
>> with other components (in case of the Meson GXL example there's a shared
>> reset line between the USB2 PHYs, USB3 PHYs and the dwc3 controller).
>> Additionally SoC implementations may prefer a reset pulse over level
>> resets.
>>
>> Add an internal per-of_device_id struct which can be used to configure
>> whether the reset lines are shared and whether they use level or pulse
>> resets.
>>
>> For now this falls back to the old defaults, which are:
>> - reset lines are exclusive
>> - level resets are being used
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>>  drivers/usb/dwc3/dwc3-of-simple.c | 65 
>> ---
>>  1 file changed, 54 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
>> b/drivers/usb/dwc3/dwc3-of-simple.c
>> index 7ae0eefc7cc7..ceb9f0cd822a 100644
>> --- a/drivers/usb/dwc3/dwc3-of-simple.c
>> +++ b/drivers/usb/dwc3/dwc3-of-simple.c
>> @@ -22,11 +22,22 @@
>>  #include 
>>  #include 
>>
>> +/**
>> + * struct dwc3_of_simple_params - hardware specific parameters
>> + * @shared_resets: indicates that the resets are shared or exclusive
>> + * @pulse_resets: use a reset pulse instead of level based resets
>> + */
>> +struct dwc3_of_simple_params {
>> + boolshared_resets;
>> + boolpulse_resets;
>> +};
>> +
>>  struct dwc3_of_simple {
>>   struct device   *dev;
>>   struct clk  **clks;
>>   int num_clocks;
>>   struct reset_control*resets;
>> + const struct dwc3_of_simple_params  *params;
>
> instead, you can add these two fields here:
>
> bool shared_resets;
> bool pulse_resets;
>
> and ...
>
>> @@ -90,17 +101,26 @@ static int dwc3_of_simple_probe(struct platform_device 
>> *pdev)
>>
>>   platform_set_drvdata(pdev, simple);
>>   simple->dev = dev;
>> + simple->params = of_device_get_match_data(dev);
>>
>> - simple->resets = of_reset_control_array_get_optional_exclusive(np);
>> + simple->resets = of_reset_control_array_get(np,
>> + simple->params->shared_resets,
>> + true);
>
> wrap this with a of_device_is_compatible() check:
>
> if (of_device_is_compatible(dev->of_node, "foobar")) {
> simple->shared_resets = true;
> simple->pulse_resets = true;
> }
>
> or something like that. Then we don't need to add a new
> dwc3_of_simple_params for everybody.
sure, I can do this if that fits the coding style in the dwc3 driver better
in that case, do you still want me to keep patches #2 and #3 separate?

> Also, the why isn't the reset type (pulse vs level) handled by reset
> framework itself? Why does dwc3-of-simple need to know about it?
the Amlogic reset driver supports both, level resets and reset pulses
unfortunately the reset line is de-asserted by default, so to reset it
we would have to:
- assert it first
- then de-assert it again

however, the reset framework does not allow this for shared resets
(see reset_control_assert: it triggers a WARN_ON if we try to assert a
shared reset which has not been de-asserted yet)
together with the fact that there are reset controller hardware
implementations out there which don't support level resets I decided
to implement it as reset pulse


Regards
Martin
--
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 0/3] DWC3 support for Amlogic Meson AXG and GXL SoCs

2018-01-28 Thread Martin Blumenstingl
Amlogic Meson AXG and GXL SoCs can use the dwc3-of-simple with little
modifications. These SoCs use:
- a gate clock for the USB components (DWC3, USB PHYs)
- a reset line which is shared across all USB components (DWC3, USB2 and
  USB3 PHYs, OTG detection logic inside the USB3 PHY registers)
- a reset pulse to trigger the reset
- depending on the SoC two or more PHYs (AXG: 1x USB2 and 1x USB3 PHY,
  GXL: 2x USB2 and 1x USB3 PHY)

This extends the dwc3-of-simple so it supports (depending on the
platform) shared and level resets. Additionally it adds new bindings
for the Amlogic Meson AXG and GXL SoCs, along with the documentation
(dt-bindings).

NOTE: for full support on Amlogic Meson GXL SoCs my other series called
"initialize (multiple) PHYs for a HCD" (see [0] for v8 of that series)
is required. However, there is no direct dependency on that series.
Especially since Meson AXG doesn't need it (since it only has one USB2
and one USB3 PHY, which is already supported by the current dwc3 driver,
unlike the 2x USB2 and 1x USB3 PHYs on Meson GXL).
So I believe that this series can still be merged, even if the other
patchset is not ready yet.


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html


Martin Blumenstingl (3):
  dt-bindings: usb: add support for dwc3 controller on Amlogic Meson GX
  usb: dwc3: of-simple: add support for shared and pulsed reset lines
  usb: dwc3: of-simple: add support for the Amlogic Meson GXL and AXG
SoCs

 .../devicetree/bindings/usb/amlogic,dwc3.txt   | 42 
 drivers/usb/dwc3/dwc3-of-simple.c  | 78 +++---
 2 files changed, 109 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/amlogic,dwc3.txt

-- 
2.16.1

--
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] dt-bindings: usb: add support for dwc3 controller on Amlogic Meson GX

2018-01-28 Thread Martin Blumenstingl
Amlogic Meson GX SoCs (GXL and AXG) come with a (host-only) dwc3 USB
controller. This requires a clock to be enabled and a reset line to be
pulsed to get the hardware into a known state.
Add the documentation for this IP block, similar to "qcom,dwc3.txt".

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 .../devicetree/bindings/usb/amlogic,dwc3.txt   | 42 ++
 1 file changed, 42 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/amlogic,dwc3.txt

diff --git a/Documentation/devicetree/bindings/usb/amlogic,dwc3.txt 
b/Documentation/devicetree/bindings/usb/amlogic,dwc3.txt
new file mode 100644
index ..9a8b631904fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/amlogic,dwc3.txt
@@ -0,0 +1,42 @@
+Amlogic Meson GX DWC3 USB SoC controller
+
+Required properties:
+- compatible:  depending on the SoC this should contain one of:
+   * amlogic,meson-axg-dwc3
+   * amlogic,meson-gxl-dwc3
+- clocks:  a handle for the "USB general" clock
+- clock-names: must be "usb_general"
+- resets:  a handle for the shared "USB OTG" reset line
+- reset-names: must be "usb_otg"
+
+Required child node:
+A child node must exist to represent the core DWC3 IP block. The name of
+the node is not important. The content of the node is defined in dwc3.txt.
+
+PHY documentation is provided in the following places:
+- Documentation/devicetree/bindings/phy/meson-gxl-usb2-phy.txt
+- Documentation/devicetree/bindings/phy/meson-gxl-usb3-phy.txt
+
+Example device nodes:
+   usb0: usb@ff50 {
+   compatible = "amlogic,meson-axg-dwc3";
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+
+   clocks = < CLKID_USB>;
+   clock-names = "usb_general";
+   resets = < RESET_USB_OTG>;
+   reset-names = "usb_otg";
+
+   dwc3: dwc3@ff50 {
+   compatible = "snps,dwc3";
+   reg = <0x0 0xff50 0x0 0x10>;
+   interrupts = ;
+   dr_mode = "host";
+   maximum-speed = "high-speed";
+   snps,dis_u2_susphy_quirk;
+   phys = <_phy>, <_phy0>;
+   phy-names = "usb2-phy", "usb3-phy";
+   };
+   };
-- 
2.16.1

--
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] usb: dwc3: of-simple: add support for the Amlogic Meson GXL and AXG SoCs

2018-01-28 Thread Martin Blumenstingl
Amlogic Meson GXL and AXG SoCs come with a (host-only) dwc3 USB
controller. To use this controller a clock has to be enabled and a reset
line has to be pulsed.
Enabling the clock works identical to other SoCs. However, the reset
line has to be pulsed (using reset_control_reset) instead of using a
level reset (reset_control_{assert,deassert}).

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/dwc3/dwc3-of-simple.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
b/drivers/usb/dwc3/dwc3-of-simple.c
index ceb9f0cd822a..d9e4b8b09eaf 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -217,6 +217,11 @@ static const struct dwc3_of_simple_params 
dwc3_of_simple_default_params = {
.pulse_resets = false,
 };
 
+static const struct dwc3_of_simple_params dwc3_of_simple_amlogic_params = {
+   .shared_resets = true,
+   .pulse_resets = true,
+};
+
 static const struct of_device_id of_dwc3_simple_match[] = {
{
.compatible = "qcom,dwc3",
@@ -238,6 +243,14 @@ static const struct of_device_id of_dwc3_simple_match[] = {
.compatible = "sprd,sc9860-dwc3",
.data = _of_simple_default_params
},
+   {
+   .compatible = "amlogic,meson-axg-dwc3",
+   .data = _of_simple_amlogic_params
+   },
+   {
+   .compatible = "amlogic,meson-gxl-dwc3",
+   .data = _of_simple_amlogic_params
+   },
{ /* Sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
-- 
2.16.1

--
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] usb: dwc3: of-simple: add support for shared and pulsed reset lines

2018-01-28 Thread Martin Blumenstingl
Some SoCs (such as Amlogic Meson GXL for example) share the reset line
with other components (in case of the Meson GXL example there's a shared
reset line between the USB2 PHYs, USB3 PHYs and the dwc3 controller).
Additionally SoC implementations may prefer a reset pulse over level
resets.

Add an internal per-of_device_id struct which can be used to configure
whether the reset lines are shared and whether they use level or pulse
resets.

For now this falls back to the old defaults, which are:
- reset lines are exclusive
- level resets are being used

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/dwc3/dwc3-of-simple.c | 65 ---
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
b/drivers/usb/dwc3/dwc3-of-simple.c
index 7ae0eefc7cc7..ceb9f0cd822a 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -22,11 +22,22 @@
 #include 
 #include 
 
+/**
+ * struct dwc3_of_simple_params - hardware specific parameters
+ * @shared_resets: indicates that the resets are shared or exclusive
+ * @pulse_resets: use a reset pulse instead of level based resets
+ */
+struct dwc3_of_simple_params {
+   boolshared_resets;
+   boolpulse_resets;
+};
+
 struct dwc3_of_simple {
struct device   *dev;
struct clk  **clks;
int num_clocks;
struct reset_control*resets;
+   const struct dwc3_of_simple_params  *params;
 };
 
 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
@@ -90,17 +101,26 @@ static int dwc3_of_simple_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, simple);
simple->dev = dev;
+   simple->params = of_device_get_match_data(dev);
 
-   simple->resets = of_reset_control_array_get_optional_exclusive(np);
+   simple->resets = of_reset_control_array_get(np,
+   simple->params->shared_resets,
+   true);
if (IS_ERR(simple->resets)) {
ret = PTR_ERR(simple->resets);
dev_err(dev, "failed to get device resets, err=%d\n", ret);
return ret;
}
 
-   ret = reset_control_deassert(simple->resets);
-   if (ret)
-   goto err_resetc_put;
+   if (simple->params->pulse_resets) {
+   ret = reset_control_reset(simple->resets);
+   if (ret)
+   goto err_resetc_put;
+   } else {
+   ret = reset_control_deassert(simple->resets);
+   if (ret)
+   goto err_resetc_put;
+   }
 
ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
"clocks", "#clock-cells"));
@@ -124,7 +144,8 @@ static int dwc3_of_simple_probe(struct platform_device 
*pdev)
return 0;
 
 err_resetc_assert:
-   reset_control_assert(simple->resets);
+   if (!simple->params->pulse_resets)
+   reset_control_assert(simple->resets);
 
 err_resetc_put:
reset_control_put(simple->resets);
@@ -144,7 +165,9 @@ static int dwc3_of_simple_remove(struct platform_device 
*pdev)
clk_put(simple->clks[i]);
}
 
-   reset_control_assert(simple->resets);
+   if (!simple->params->pulse_resets)
+   reset_control_assert(simple->resets);
+
reset_control_put(simple->resets);
 
pm_runtime_put_sync(dev);
@@ -189,12 +212,32 @@ static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops 
= {
dwc3_of_simple_runtime_resume, NULL)
 };
 
+static const struct dwc3_of_simple_params dwc3_of_simple_default_params = {
+   .shared_resets = false,
+   .pulse_resets = false,
+};
+
 static const struct of_device_id of_dwc3_simple_match[] = {
-   { .compatible = "qcom,dwc3" },
-   { .compatible = "rockchip,rk3399-dwc3" },
-   { .compatible = "xlnx,zynqmp-dwc3" },
-   { .compatible = "cavium,octeon-7130-usb-uctl" },
-   { .compatible = "sprd,sc9860-dwc3" },
+   {
+   .compatible = "qcom,dwc3",
+   .data = _of_simple_default_params
+   },
+   {
+   .compatible = "rockchip,rk3399-dwc3",
+   .data = _of_simple_default_params
+   },
+   {
+   .compatible = "xlnx,zynqmp-dwc3",
+   .data = _of_simple_default_params
+   },
+   {
+   .compatible = "cavium,octeon-7130-usb-uctl",
+   .data = _of_simple_default_params
+   },
+   {
+   .compatible = "sprd,s

Re: [RFC/RFT usb-next v1 5/6] usb: chipidea: do not set the "phy" field in struct usb_hcd

2018-01-26 Thread Martin Blumenstingl
Hi Peter,

On Fri, Jan 26, 2018 at 10:06 AM, Peter Chen <peter.c...@nxp.com> wrote:
>
>>
>> Now that usb_add_hcd parses all generic PHYs anyways the code which skips
>> initialization of a single PHY will go away.
>> Remove the code which sets struct usb_hcd's phy field from the chipidea 
>> driver as
>> this field will go away soon.
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>>  drivers/usb/chipidea/host.c | 4 +---
>>  1 file changed, 1 insertion(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index
>> 19d60ed7e41f..fc324767cb0f 100644
>> --- a/drivers/usb/chipidea/host.c
>> +++ b/drivers/usb/chipidea/host.c
>> @@ -124,9 +124,7 @@ static int host_start(struct ci_hdrc *ci)
>>
>>   hcd->power_budget = ci->platdata->power_budget;
>>   hcd->tpl_support = ci->platdata->tpl_support;
>> - if (ci->phy)
>> - hcd->phy = ci->phy;
>> - else
>> + if (!ci->phy)
>>   hcd->usb_phy = ci->usb_phy;
>>
>
> The reason hcd->phy is initialized by chipidea core is we do not need HCD 
> core to
> touch PHY, and PHY operation is shared for both device and host mode for 
> chipidea.
Chunfeng wanted me to drop the mtu3 patch because I forgot about
device mode in the mtu3 driver.
however, the chipidea driver seems to be different because I'm not
dropping the whole phy_{init,power_on,power_off,exit} code from it,
but only a "flag" that tells the HCD core to skip managing the USB PHY

> If I understand correct, your HCD core PHY wrapper patch set will do PHY 
> operation if
> there is a "phy" node under controller's? If it is correct, you may supply 
> one way to let
> the HCD core bypass phy operations for some USB controllers, eg dual-role 
> controllers.
> Thanks.
could you please explain why the HCD core should not manage the the
PHYs when the chipidea driver is used?

my understanding is that all phy_{init,power_on,power_off,exit}
operations are ref-counted internally in the PHY framework
this means that if the chipidea driver calls phy_{init,power_on} first
then the same functions called from within the HCD core are no-ops
(except for the ref-counting)
so I think it should not change anything - however, I have no hardware
to actually prove that.
it would be great if you could explain the issue behind this (and
thereby answer the question: why we would not want the HCD core to
manage the PHY states)!


Regards
Martin
--
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: [RFC/RFT usb-next v1 1/6] usb: mtu3: remove custom USB PHY handling

2018-01-25 Thread Martin Blumenstingl
Hi,

On Thu, Jan 25, 2018 at 3:47 AM, Chunfeng Yun <chunfeng@mediatek.com> wrote:
> Hi,
>
> On Thu, 2018-01-25 at 01:16 +0100, Martin Blumenstingl wrote:
>> The new PHY wrapper is now wired up in the core HCD code. This means
>> that PHYs are now controlled (initialized, enabled, disabled, exited)
>> without requiring any host-driver specific code.
>> Remove the custom USB PHY handling from the mtu3 driver as the core HCD
>> code now handles this.
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
>> ---
>>  drivers/usb/mtu3/mtu3_plat.c | 101 
>> ---
>>  1 file changed, 101 deletions(-)
>>
>> diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
>> index 628d5ce356ca..a894ddf25bcd 100644
>> --- a/drivers/usb/mtu3/mtu3_plat.c
>> +++ b/drivers/usb/mtu3/mtu3_plat.c
>> @@ -44,62 +44,6 @@ int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 
>> ex_clks)
>>   return 0;
>>  }
>>
>> -static int ssusb_phy_init(struct ssusb_mtk *ssusb)
>> -{
>> - int i;
>> - int ret;
>> -
>> - for (i = 0; i < ssusb->num_phys; i++) {
>> - ret = phy_init(ssusb->phys[i]);
>> - if (ret)
>> - goto exit_phy;
>> - }
>> - return 0;
>> -
>> -exit_phy:
>> - for (; i > 0; i--)
>> - phy_exit(ssusb->phys[i - 1]);
>> -
>> - return ret;
>> -}
>> -
>> -static int ssusb_phy_exit(struct ssusb_mtk *ssusb)
>> -{
>> - int i;
>> -
>> - for (i = 0; i < ssusb->num_phys; i++)
>> - phy_exit(ssusb->phys[i]);
>> -
>> - return 0;
>> -}
>> -
>> -static int ssusb_phy_power_on(struct ssusb_mtk *ssusb)
>> -{
>> - int i;
>> - int ret;
>> -
>> - for (i = 0; i < ssusb->num_phys; i++) {
>> - ret = phy_power_on(ssusb->phys[i]);
>> - if (ret)
>> - goto power_off_phy;
>> - }
>> - return 0;
>> -
>> -power_off_phy:
>> - for (; i > 0; i--)
>> - phy_power_off(ssusb->phys[i - 1]);
>> -
>> - return ret;
>> -}
>> -
>> -static void ssusb_phy_power_off(struct ssusb_mtk *ssusb)
>> -{
>> - unsigned int i;
>> -
>> - for (i = 0; i < ssusb->num_phys; i++)
>> - phy_power_off(ssusb->phys[i]);
>> -}
>> -
>>  static int ssusb_clks_enable(struct ssusb_mtk *ssusb)
>>  {
>>   int ret;
>> @@ -162,24 +106,8 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
>>   if (ret)
>>   goto clks_err;
>>
>> - ret = ssusb_phy_init(ssusb);
>> - if (ret) {
>> - dev_err(ssusb->dev, "failed to init phy\n");
>> - goto phy_init_err;
>> - }
>> -
>> - ret = ssusb_phy_power_on(ssusb);
>> - if (ret) {
>> - dev_err(ssusb->dev, "failed to power on phy\n");
>> - goto phy_err;
>> - }
>> -
>>   return 0;
>>
>> -phy_err:
>> - ssusb_phy_exit(ssusb);
>> -phy_init_err:
>> - ssusb_clks_disable(ssusb);
>>  clks_err:
>>   regulator_disable(ssusb->vusb33);
>>  vusb33_err:
>> @@ -190,8 +118,6 @@ static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
>>  {
>>   ssusb_clks_disable(ssusb);
>>   regulator_disable(ssusb->vusb33);
>> - ssusb_phy_power_off(ssusb);
>> - ssusb_phy_exit(ssusb);
>>  }
>>
>>  static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb)
>> @@ -222,7 +148,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, 
>> struct ssusb_mtk *ssusb)
>>   struct device *dev = >dev;
>>   struct regulator *vbus;
>>   struct resource *res;
>> - int i;
>>   int ret;
>>
>>   ssusb->vusb33 = devm_regulator_get(>dev, "vusb33");
>> @@ -249,25 +174,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, 
>> struct ssusb_mtk *ssusb)
>>   if (IS_ERR(ssusb->dma_clk))
>>   return PTR_ERR(ssusb->dma_clk);
>>
>> - ssusb->num_phys = of_count_phandle_with_args(node,
>> - "phys", "#phy-cells");
>> - if (ssusb->num_phys > 0) {
>> - ssusb->phys = devm_kcalloc(dev, ssusb->num_phys,
>

[RFC/RFT usb-next v1 5/6] usb: chipidea: do not set the "phy" field in struct usb_hcd

2018-01-24 Thread Martin Blumenstingl
Now that usb_add_hcd parses all generic PHYs anyways the code which
skips initialization of a single PHY will go away.
Remove the code which sets struct usb_hcd's phy field from the chipidea
driver as this field will go away soon.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/chipidea/host.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 19d60ed7e41f..fc324767cb0f 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -124,9 +124,7 @@ static int host_start(struct ci_hdrc *ci)
 
hcd->power_budget = ci->platdata->power_budget;
hcd->tpl_support = ci->platdata->tpl_support;
-   if (ci->phy)
-   hcd->phy = ci->phy;
-   else
+   if (!ci->phy)
hcd->usb_phy = ci->usb_phy;
 
ehci = hcd_to_ehci(hcd);
-- 
2.16.1

--
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/RFT usb-next v1 6/6] usb: core: hcd: remove support for initializing a single PHY

2018-01-24 Thread Martin Blumenstingl
With the new PHY wrapper in place we can now handle multiple PHYs.
Remove the code which handles only one generic PHY as this is now
covered (with support for multiple PHYs as well as suspend/resume
support) by the new PHY wrapper.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/core/hcd.c  | 37 -
 include/linux/usb/hcd.h |  1 -
 2 files changed, 38 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fc99cddc117e..5d59e0b4d463 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2757,30 +2757,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
-   struct phy *phy = phy_get(hcd->self.sysdev, "usb");
-
-   if (IS_ERR(phy)) {
-   retval = PTR_ERR(phy);
-   if (retval == -EPROBE_DEFER)
-   goto err_phy;
-   } else {
-   retval = phy_init(phy);
-   if (retval) {
-   phy_put(phy);
-   goto err_phy;
-   }
-   retval = phy_power_on(phy);
-   if (retval) {
-   phy_exit(phy);
-   phy_put(phy);
-   goto err_phy;
-   }
-   hcd->phy = phy;
-   hcd->remove_phy = 1;
-   }
-   }
-
hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) {
retval = PTR_ERR(hcd->phy_roothub);
@@ -2959,13 +2935,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_usb_phy_roothub_power_on:
usb_phy_roothub_exit(hcd->phy_roothub);
 err_phy_roothub_init:
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
-err_phy:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
@@ -3046,12 +3015,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_phy_roothub_power_off(hcd->phy_roothub);
usb_phy_roothub_exit(hcd->phy_roothub);
 
-   if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
-   phy_power_off(hcd->phy);
-   phy_exit(hcd->phy);
-   phy_put(hcd->phy);
-   hcd->phy = NULL;
-   }
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 9e8fc9c5f394..e464c7384bd5 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -103,7 +103,6 @@ struct usb_hcd {
 * other external phys should be software-transparent
 */
struct usb_phy  *usb_phy;
-   struct phy  *phy;
struct usb_phy_roothub  *phy_roothub;
 
/* Flags that need to be manipulated atomically because they can
-- 
2.16.1

--
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/RFT usb-next v1 4/6] usb: host: ohci-platform: remove custom USB PHY handling

2018-01-24 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ohci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/host/ohci-platform.c | 56 
 1 file changed, 5 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 1e6c954f4b3f..65a1c3fdc88c 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -21,7 +21,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -38,8 +38,6 @@
 struct ohci_platform_priv {
struct clk *clks[OHCI_MAX_CLKS];
struct reset_control *resets;
-   struct phy **phys;
-   int num_phys;
 };
 
 static const char hcd_name[] = "ohci-platform";
@@ -48,7 +46,7 @@ static int ohci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -56,24 +54,8 @@ static int ohci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -85,12 +67,7 @@ static void ohci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -117,7 +94,7 @@ static int ohci_platform_probe(struct platform_device *dev)
struct usb_ohci_pdata *pdata = dev_get_platdata(>dev);
struct ohci_platform_priv *priv;
struct ohci_hcd *ohci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -169,29 +146,6 @@ static int ohci_platform_probe(struct platform_device *dev)
of_property_read_u32(dev->dev.of_node, "num-ports",
 >num_ports);
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else if (!hcd->phy) {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->phy = priv->phys[phy_num];
-   }
-   }
-
for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -277,7 +231,7 @@ static int ohci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_p

[RFC/RFT usb-next v1 0/6] remove driver-specific "multiple PHY" handling

2018-01-24 Thread Martin Blumenstingl
(this is the follow-up to my "initialize (multiple) PHYs for a HCD"
series from [0])

Various USB controller drivers parse the "phys" device-tree property and
grab all listed PHYs.
There is a lot of duplicate code around this in the various drivers:
- parse the "phys" property during .probe and save all PHYs in an array
- call phy_init and phy_power_on on all PHYs
- (where supported by the driver) call phy_power_off during .suspend and
  phy_power_on during .resume
- call phy_power_off and phy_exit during .remove

With [0] this functionality was moved to the core HCD driver, meaning
that all USB controller drivers now support this without having to
implement custom code for it.

Thus this series removes this code duplication.

The last two patches are a bit special:
- after patches #1-4 the chipidea driver is the last driver which sets
  the "phy" field of struct usb_hcd. remove this logic as the PHY
  wrapper (which is now part of the core HCD driver) manages the state
  of all PHYs anyways.
- the last patch removes the "phy" field from struct usb_hcd because
  nothing uses it anymore after the previous patches. it also removes
  the parsing and managing of a single PHY with the name "usb" as the
  new PHY wrapper parses all PHYs from the device-tree "phys" property
  anyways (so the PHY wrapper has the same functionality, except that it
  doesn't need the phy-name "usb" and it can manage more than one PHY)

preconditions for testing this series: all patches from [0] need to be
applied.
disclaimer: I don't have any hardware that uses any of the affected
drivers!


[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-January/006274.html

Martin Blumenstingl (6):
  usb: mtu3: remove custom USB PHY handling
  usb: host: xhci-mtk: remove custom USB PHY handling
  usb: host: ehci-platform: remove custom USB PHY handling
  usb: host: ohci-platform: remove custom USB PHY handling
  usb: chipidea: do not set the "phy" field in struct usb_hcd
  usb: core: hcd: remove support for initializing a single PHY

 drivers/usb/chipidea/host.c  |   4 +-
 drivers/usb/core/hcd.c   |  37 --
 drivers/usb/host/ehci-platform.c |  55 ++---
 drivers/usb/host/ohci-platform.c |  56 ++
 drivers/usb/host/xhci-mtk.c  |  98 +
 drivers/usb/mtu3/mtu3_plat.c | 101 ---
 include/linux/usb/hcd.h  |   1 -
 7 files changed, 12 insertions(+), 340 deletions(-)

-- 
2.16.1

--
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/RFT usb-next v1 3/6] usb: host: ehci-platform: remove custom USB PHY handling

2018-01-24 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the ehci-platform driver as the
core HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/host/ehci-platform.c | 55 +++-
 1 file changed, 4 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b065a960adc2..4c306fb6b069 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -44,8 +43,6 @@
 struct ehci_platform_priv {
struct clk *clks[EHCI_MAX_CLKS];
struct reset_control *rsts;
-   struct phy **phys;
-   int num_phys;
bool reset_on_resume;
 };
 
@@ -80,7 +77,7 @@ static int ehci_platform_power_on(struct platform_device *dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, ret, phy_num;
+   int clk, ret;
 
for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -88,24 +85,8 @@ static int ehci_platform_power_on(struct platform_device 
*dev)
goto err_disable_clks;
}
 
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   ret = phy_init(priv->phys[phy_num]);
-   if (ret)
-   goto err_exit_phy;
-   ret = phy_power_on(priv->phys[phy_num]);
-   if (ret) {
-   phy_exit(priv->phys[phy_num]);
-   goto err_exit_phy;
-   }
-   }
-
return 0;
 
-err_exit_phy:
-   while (--phy_num >= 0) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
 err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -117,12 +98,7 @@ static void ehci_platform_power_off(struct platform_device 
*dev)
 {
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
-   int clk, phy_num;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   phy_power_off(priv->phys[phy_num]);
-   phy_exit(priv->phys[phy_num]);
-   }
+   int clk;
 
for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -149,7 +125,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct usb_ehci_pdata *pdata = dev_get_platdata(>dev);
struct ehci_platform_priv *priv;
struct ehci_hcd *ehci;
-   int err, irq, phy_num, clk = 0;
+   int err, irq, clk = 0;
 
if (usb_disabled())
return -ENODEV;
@@ -202,29 +178,6 @@ static int ehci_platform_probe(struct platform_device *dev)
  "has-transaction-translator"))
hcd->has_tt = 1;
 
-   priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
-   "phys", "#phy-cells");
-
-   if (priv->num_phys > 0) {
-   priv->phys = devm_kcalloc(>dev, priv->num_phys,
-   sizeof(struct phy *), GFP_KERNEL);
-   if (!priv->phys)
-   return -ENOMEM;
-   } else
-   priv->num_phys = 0;
-
-   for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
-   priv->phys[phy_num] = devm_of_phy_get_by_index(
-   >dev, dev->dev.of_node, phy_num);
-   if (IS_ERR(priv->phys[phy_num])) {
-   err = PTR_ERR(priv->phys[phy_num]);
-   goto err_put_hcd;
-   } else if (!hcd->phy) {
-   /* Avoiding phy_get() in usb_add_hcd() */
-   hcd->phy = priv->phys[phy_num];
-   }
-   }
-
for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -306,7 +259,7 @@ static int ehci_platform_probe(struct platform_device *dev)
 err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_put_hcd:
+
if (pdata == _plat

[RFC/RFT usb-next v1 1/6] usb: mtu3: remove custom USB PHY handling

2018-01-24 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the mtu3 driver as the core HCD
code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/mtu3/mtu3_plat.c | 101 ---
 1 file changed, 101 deletions(-)

diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 628d5ce356ca..a894ddf25bcd 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -44,62 +44,6 @@ int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 ex_clks)
return 0;
 }
 
-static int ssusb_phy_init(struct ssusb_mtk *ssusb)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < ssusb->num_phys; i++) {
-   ret = phy_init(ssusb->phys[i]);
-   if (ret)
-   goto exit_phy;
-   }
-   return 0;
-
-exit_phy:
-   for (; i > 0; i--)
-   phy_exit(ssusb->phys[i - 1]);
-
-   return ret;
-}
-
-static int ssusb_phy_exit(struct ssusb_mtk *ssusb)
-{
-   int i;
-
-   for (i = 0; i < ssusb->num_phys; i++)
-   phy_exit(ssusb->phys[i]);
-
-   return 0;
-}
-
-static int ssusb_phy_power_on(struct ssusb_mtk *ssusb)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < ssusb->num_phys; i++) {
-   ret = phy_power_on(ssusb->phys[i]);
-   if (ret)
-   goto power_off_phy;
-   }
-   return 0;
-
-power_off_phy:
-   for (; i > 0; i--)
-   phy_power_off(ssusb->phys[i - 1]);
-
-   return ret;
-}
-
-static void ssusb_phy_power_off(struct ssusb_mtk *ssusb)
-{
-   unsigned int i;
-
-   for (i = 0; i < ssusb->num_phys; i++)
-   phy_power_off(ssusb->phys[i]);
-}
-
 static int ssusb_clks_enable(struct ssusb_mtk *ssusb)
 {
int ret;
@@ -162,24 +106,8 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
if (ret)
goto clks_err;
 
-   ret = ssusb_phy_init(ssusb);
-   if (ret) {
-   dev_err(ssusb->dev, "failed to init phy\n");
-   goto phy_init_err;
-   }
-
-   ret = ssusb_phy_power_on(ssusb);
-   if (ret) {
-   dev_err(ssusb->dev, "failed to power on phy\n");
-   goto phy_err;
-   }
-
return 0;
 
-phy_err:
-   ssusb_phy_exit(ssusb);
-phy_init_err:
-   ssusb_clks_disable(ssusb);
 clks_err:
regulator_disable(ssusb->vusb33);
 vusb33_err:
@@ -190,8 +118,6 @@ static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
 {
ssusb_clks_disable(ssusb);
regulator_disable(ssusb->vusb33);
-   ssusb_phy_power_off(ssusb);
-   ssusb_phy_exit(ssusb);
 }
 
 static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb)
@@ -222,7 +148,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, 
struct ssusb_mtk *ssusb)
struct device *dev = >dev;
struct regulator *vbus;
struct resource *res;
-   int i;
int ret;
 
ssusb->vusb33 = devm_regulator_get(>dev, "vusb33");
@@ -249,25 +174,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, 
struct ssusb_mtk *ssusb)
if (IS_ERR(ssusb->dma_clk))
return PTR_ERR(ssusb->dma_clk);
 
-   ssusb->num_phys = of_count_phandle_with_args(node,
-   "phys", "#phy-cells");
-   if (ssusb->num_phys > 0) {
-   ssusb->phys = devm_kcalloc(dev, ssusb->num_phys,
-   sizeof(*ssusb->phys), GFP_KERNEL);
-   if (!ssusb->phys)
-   return -ENOMEM;
-   } else {
-   ssusb->num_phys = 0;
-   }
-
-   for (i = 0; i < ssusb->num_phys; i++) {
-   ssusb->phys[i] = devm_of_phy_get_by_index(dev, node, i);
-   if (IS_ERR(ssusb->phys[i])) {
-   dev_err(dev, "failed to get phy-%d\n", i);
-   return PTR_ERR(ssusb->phys[i]);
-   }
-   }
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc");
ssusb->ippc_base = devm_ioremap_resource(dev, res);
if (IS_ERR(ssusb->ippc_base))
@@ -457,7 +363,6 @@ static int __maybe_unused mtu3_suspend(struct device *dev)
return 0;
 
ssusb_host_disable(ssusb, true);
-   ssusb_phy_power_off(ssusb);
ssusb_clks_disable(ssusb);
ssusb_wakeup_set(ssusb, true);
 
@@ -480,16 +385,10 @@ static int __maybe_unused mtu3_resume(struct device *dev)
if (ret)
goto clks_err;
 
-   ret = ssusb_phy_power_on(ssusb);
-   if (ret)
-   goto phy_err;

[RFC/RFT usb-next v1 2/6] usb: host: xhci-mtk: remove custom USB PHY handling

2018-01-24 Thread Martin Blumenstingl
The new PHY wrapper is now wired up in the core HCD code. This means
that PHYs are now controlled (initialized, enabled, disabled, exited)
without requiring any host-driver specific code.
Remove the custom USB PHY handling from the xhci-mtk driver as the core
HCD code now handles this.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 drivers/usb/host/xhci-mtk.c | 98 +
 1 file changed, 2 insertions(+), 96 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index b0ab4d5e2751..7334da9e9779 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -352,62 +351,6 @@ static const struct xhci_driver_overrides 
xhci_mtk_overrides __initconst = {
 
 static struct hc_driver __read_mostly xhci_mtk_hc_driver;
 
-static int xhci_mtk_phy_init(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_init(mtk->phys[i]);
-   if (ret)
-   goto exit_phy;
-   }
-   return 0;
-
-exit_phy:
-   for (; i > 0; i--)
-   phy_exit(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static int xhci_mtk_phy_exit(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_exit(mtk->phys[i]);
-
-   return 0;
-}
-
-static int xhci_mtk_phy_power_on(struct xhci_hcd_mtk *mtk)
-{
-   int i;
-   int ret;
-
-   for (i = 0; i < mtk->num_phys; i++) {
-   ret = phy_power_on(mtk->phys[i]);
-   if (ret)
-   goto power_off_phy;
-   }
-   return 0;
-
-power_off_phy:
-   for (; i > 0; i--)
-   phy_power_off(mtk->phys[i - 1]);
-
-   return ret;
-}
-
-static void xhci_mtk_phy_power_off(struct xhci_hcd_mtk *mtk)
-{
-   unsigned int i;
-
-   for (i = 0; i < mtk->num_phys; i++)
-   phy_power_off(mtk->phys[i]);
-}
-
 static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
 {
int ret;
@@ -488,8 +431,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
-   struct phy *phy;
-   int phy_num;
int ret = -ENODEV;
int irq;
 
@@ -529,16 +470,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
return ret;
}
 
-   mtk->num_phys = of_count_phandle_with_args(node,
-   "phys", "#phy-cells");
-   if (mtk->num_phys > 0) {
-   mtk->phys = devm_kcalloc(dev, mtk->num_phys,
-   sizeof(*mtk->phys), GFP_KERNEL);
-   if (!mtk->phys)
-   return -ENOMEM;
-   } else {
-   mtk->num_phys = 0;
-   }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
device_enable_async_suspend(dev);
@@ -596,23 +527,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
mtk->has_ippc = false;
}
 
-   for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
-   phy = devm_of_phy_get_by_index(dev, node, phy_num);
-   if (IS_ERR(phy)) {
-   ret = PTR_ERR(phy);
-   goto put_usb2_hcd;
-   }
-   mtk->phys[phy_num] = phy;
-   }
-
-   ret = xhci_mtk_phy_init(mtk);
-   if (ret)
-   goto put_usb2_hcd;
-
-   ret = xhci_mtk_phy_power_on(mtk);
-   if (ret)
-   goto exit_phys;
-
device_init_wakeup(dev, true);
 
xhci = hcd_to_xhci(hcd);
@@ -630,7 +544,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
dev_name(dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
-   goto power_off_phys;
+   goto disable_device_wakeup;
}
 
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -653,13 +567,9 @@ static int xhci_mtk_probe(struct platform_device *pdev)
xhci_mtk_sch_exit(mtk);
usb_put_hcd(xhci->shared_hcd);
 
-power_off_phys:
-   xhci_mtk_phy_power_off(mtk);
+disable_device_wakeup:
device_init_wakeup(dev, false);
 
-exit_phys:
-   xhci_mtk_phy_exit(mtk);
-
 put_usb2_hcd:
usb_put_hcd(hcd);
 
@@ -682,8 +592,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
usb_remove_hcd(xhci->shared_hcd);
-   xhci_mtk_phy_power_off(mtk);
-   xhci_mtk_phy_exit(mtk);
device_init_wakeup(>dev, false);
 
usb_remove_hcd(hcd);
@@ -718,7 +626,6 @@ static int __maybe_unused xhci_mtk_suspend(struct device 
*de

[RFC usb-next v8 3/3] usb: core: hcd: integrate the PHY wrapper into the HCD core

2018-01-24 Thread Martin Blumenstingl
This integrates the PHY wrapper into the core hcd infrastructure.
Multiple PHYs which are part of the HCD's device tree node are now
managed (= powered on/off when needed), by the new usb_phy_roothub code.

Suspend and resume is also supported, however not for
runtime/auto-suspend (which is triggered for example when no devices are
connected to the USB bus). This is needed on some SoCs (for example
Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend
then devices which are plugged in afterwards are not seen by the host.

One example where this is required is the Amlogic GXL and GXM SoCs:
They are using a dwc3 USB controller with up to three ports enabled on
the internal roothub. Each port has it's own PHY which must be enabled
(if one of the PHYs is left disabled then none of the USB ports works at
all).
The new logic works on the Amlogic GXL and GXM SoCs because the dwc3
driver internally creates a xhci-hcd which then registers a HCD which
then triggers our new PHY wrapper.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Acked-by: Alan Stern <st...@rowland.harvard.edu>
Acked-by: Chunfeng Yun <chunfeng@mediatek.com>
---
 drivers/usb/core/hcd.c  | 29 +
 include/linux/usb/hcd.h |  1 +
 2 files changed, 30 insertions(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fc32391a34d5..fc99cddc117e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -37,6 +37,7 @@
 #include 
 
 #include "usb.h"
+#include "phy.h"
 
 
 /*-*/
@@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, 
pm_message_t msg)
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
 
+   if (!PMSG_IS_AUTO(msg))
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
charbuffer[6];
@@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, 
pm_message_t msg)
dev_dbg(>dev, "skipped %s of dead bus\n", "resume");
return 0;
}
+
+   if (!PMSG_IS_AUTO(msg)) {
+   status = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (status)
+   return status;
+   }
+
if (!hcd->driver->bus_resume)
return -ENOENT;
if (HCD_RH_RUNNING(hcd))
@@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t 
msg)
}
} else {
hcd->state = old_state;
+   usb_phy_roothub_power_off(hcd->phy_roothub);
dev_dbg(>dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
@@ -2769,6 +2781,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
 
+   hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+   if (IS_ERR(hcd->phy_roothub)) {
+   retval = PTR_ERR(hcd->phy_roothub);
+   goto err_phy_roothub_init;
+   }
+
+   retval = usb_phy_roothub_power_on(hcd->phy_roothub);
+   if (retval)
+   goto err_usb_phy_roothub_power_on;
+
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
/* Keep old behaviour if authorized_default is not in [0, 1]. */
@@ -2933,6 +2955,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
 err_register_bus:
hcd_buffer_destroy(hcd);
 err_create_buf:
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+err_usb_phy_roothub_power_on:
+   usb_phy_roothub_exit(hcd->phy_roothub);
+err_phy_roothub_init:
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy);
phy_exit(hcd->phy);
@@ -3017,6 +3043,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_deregister_bus(>self);
hcd_buffer_destroy(hcd);
 
+   usb_phy_roothub_power_off(hcd->phy_roothub);
+   usb_phy_roothub_exit(hcd->phy_roothub);
+
if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
phy_power_off(hcd->phy);
phy_exit(hcd->phy);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 176900528822..9e8fc9c5f394 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -104,6 +104,7 @@ struct usb_hcd {
 */
struct usb_phy  *usb_phy;
struct phy  *phy;
+   struct usb_phy_roothub  *phy_roothub;
 
/* Flags that need to be manipulated atomically because they can
 * change while 

[RFC usb-next v8 0/3] initialize (multiple) PHYs for a HCD

2018-01-24 Thread Martin Blumenstingl
drivers/usb/core/phy.* and the changes to
  drivers/usb/host/xhci-plat.c to drivers/usb/core/hcd.c as suggested
  by Mathias Nyman (as a benefit this will enable the new logic for
  non-xHCI controllers as well - however this was not tested yet)
- rename the structs, function names, etc from platform_roothub_* to
  usb_phy_roothub*

Changes since RFCv3 at [3]:
- moved the DT binding change from patch #3 to patch #1 as suggested
  by Rob Herring (and slightly adjusted the commit message to account
  for that)
- added Tested-by from Chunfeng Yun (who confirmed that the whole
  concept and implementation works fine on Mediatek SoCs - many thanks
  again!) to patch #2
- added Rob Herring's ACK to patches 1 and 3
- dropped RFC status (RFCv3 -> PATCH v4)

Changes since RFCv2 at [2]:
- split phy_{init,exit} and phy_power_{on,off} handling. up until RFCv2
  I called phy_init plus phy_power_on in platform_roothub_power_on and
  phy_power_off plus phy_exit in platform_roothub_power_off. However,
  Chunfeng Yun (a Mediatek SoC developer - many thanks for testing my
  series and providing great feedback) reported that only using
  phy_power_off (and omitting phy_exit) during system suspend fixes an
  issue where USB devices would be re-enumerated when resuming. His
  original problem description: "In order to keep link state on mt8173,
  we just power off all phys(not exit) when system enter suspend, then
  power on them again (needn't init, otherwise device will be
  disconnected) when system resume, this can avoid re-enumerating
  device.". This fix affects patch #2 and #3 as we now have
  platform_roothub_init (which calls phy_init internally),
  platform_roothub_power_on (which calls phy_power_on internally),
  platform_roothub_power_off (which calls phy_power_off internally) and
  platform_roothub_exit (which calls phy_exit internally). suspend and
  resume only call platform_roothub_power_{on,off} to prevent the issue
  described by Chunfeng Yun (unfortunately I cannot test this because
  the Amlogic platform currently does not support system suspend).
- dropped two struct forward declarations from platform-roothub.h which
  are not used in the header file (thanks to Chunfeng Yun for spotting
  this)

Changes since RFCv1 at [1]:
- split the usb-xhci dt-binding documentation into a separate patch
- fixed a typo ("usb-phy" -> "phys" in the dt-binding example)
- rebased to apply against latest usb-next


[0] http://lists.infradead.org/pipermail/linux-amlogic/2016-November/001818.html
[1] http://marc.info/?l=linux-usb=148414866303604=2
[2] https://www.spinics.net/lists/linux-usb/msg158967.html
[3] https://www.spinics.net/lists/devicetree/msg190426.html
[4] 
http://lists.infradead.org/pipermail/linux-amlogic/2017-September/004685.html
[5] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/004924.html
[6] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005049.html
[7] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005121.html
[8] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005124.html
[9] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/005192.html

Martin Blumenstingl (3):
  dt-bindings: usb: add the documentation for USB HCDs
  usb: core: add a wrapper for the USB PHYs on the HCD
  usb: core: hcd: integrate the PHY wrapper into the HCD core

 .../devicetree/bindings/usb/mediatek,mtk-xhci.txt  |   5 +-
 .../devicetree/bindings/usb/mediatek,mtu3.txt  |   5 +-
 Documentation/devicetree/bindings/usb/usb-ehci.txt |   6 +-
 Documentation/devicetree/bindings/usb/usb-hcd.txt  |   9 ++
 Documentation/devicetree/bindings/usb/usb-ohci.txt |   6 +-
 Documentation/devicetree/bindings/usb/usb-uhci.txt |   3 +
 Documentation/devicetree/bindings/usb/usb-xhci.txt |   5 +
 drivers/usb/core/Makefile  |   2 +-
 drivers/usb/core/hcd.c |  29 
 drivers/usb/core/phy.c | 158 +
 drivers/usb/core/phy.h |   7 +
 include/linux/usb/hcd.h|   1 +
 12 files changed, 229 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/usb-hcd.txt
 create mode 100644 drivers/usb/core/phy.c
 create mode 100644 drivers/usb/core/phy.h

-- 
2.16.1

--
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 usb-next v8 1/3] dt-bindings: usb: add the documentation for USB HCDs

2018-01-24 Thread Martin Blumenstingl
A USB HCD may have several PHYs which need to be configured before the
the HCD starts working.
This adds the documentation for such a USB HCD as well as a reference to
the new "usb-hcd.txt" from all bindings that implement a USB HCD which
support one USB PHY per port.

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
---
 Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 5 -
 Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 5 -
 Documentation/devicetree/bindings/usb/usb-ehci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-hcd.txt   | 9 +
 Documentation/devicetree/bindings/usb/usb-ohci.txt  | 6 --
 Documentation/devicetree/bindings/usb/usb-uhci.txt  | 3 +++
 Documentation/devicetree/bindings/usb/usb-xhci.txt  | 5 +
 7 files changed, 33 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/usb-hcd.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
index 88d9f4a4b280..266c2d917a28 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
@@ -32,7 +32,7 @@ Required properties:
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA
 
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
 
 Optional properties:
  - wakeup-source : enable USB remote wakeup;
@@ -52,6 +52,9 @@ Optional properties:
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  - imod-interval-ns: default interrupt moderation interval is 5000ns
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example:
 usb30: usb@1127 {
compatible = "mediatek,mt8173-xhci";
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt 
b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index d589a1ef96a1..3382b5cb471d 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
@@ -17,7 +17,7 @@ Required properties:
  - clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dam_ck";
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
  - dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
 
@@ -53,6 +53,9 @@ Optional properties:
  - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Sub-nodes:
 The xhci should be added as subnode to mtu3 as shown in the following example
 if host mode is enabled. The DT binding details of xhci can be found in:
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt 
b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index 3efde12b5d68..0f1b75386207 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -16,10 +16,12 @@ Optional properties:
  - has-transaction-translator : boolean, set this if EHCI have a Transaction
Translator built into the root hub.
  - clocks : a list of phandle + clock specifier pairs
- - phys : phandle + phy specifier pair
- - phy-names : "usb"
+ - phys : see usb-hcd.txt in the current directory
  - resets : phandle + reset specifier pair
 
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
 Example (Sequoia 440EPx):
 ehci@e300 {
   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.txt 
b/Documentation/devicetree/bindings/usb/usb-hcd.txt
new file mode 100644
index ..50529b838c9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.txt
@@ -0,0 +1,9 @@
+Generic USB HCD (Host Controller Device) Properties
+
+Optional properties:
+- phys: a list of all USB PHYs on this HCD
+
+Example:
+{
+   phys = <_phy1>, <_phy1>;
+   };
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt 
b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 09e70c875bc6..a8d2103d1f3d 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -13,10 +13,12 @@ Optional properties:
 - remote-wakeup-connected: remote wakeup is wired on the platform
 - num-ports : u32, to override the detected port count
 - clocks : a list of phandle + cloc

[RFC usb-next v8 2/3] usb: core: add a wrapper for the USB PHYs on the HCD

2018-01-24 Thread Martin Blumenstingl
Many SoC platforms have separate devices for the USB PHY which are
registered through the generic PHY framework. These PHYs have to be
enabled to make the USB controller actually work. They also have to be
disabled again on shutdown/suspend.

Currently (at least) the following HCI platform drivers are using custom
code to obtain all PHYs via devicetree for the roothub/controller and
disable/enable them when required:
- ehci-platform.c has ehci_platform_power_{on,off}
- xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off}
- ohci-platform.c has ohci_platform_power_{on,off}

With this new wrapper the USB PHYs can be specified directly in the
USB controller's devicetree node (just like on the drivers listed
above). This allows SoCs like the Amlogic Meson GXL family to operate
correctly once this is wired up correctly. These SoCs use a dwc3
controller and require all USB PHYs to be initialized (if one of the USB
PHYs it not initialized then none of USB port works at all).

Signed-off-by: Martin Blumenstingl <martin.blumensti...@googlemail.com>
Cc: Neil Armstrong <narmstr...@baylibre.com>
Cc: Chunfeng Yun <chunfeng@mediatek.com>
---
 drivers/usb/core/Makefile |   2 +-
 drivers/usb/core/phy.c| 158 ++
 drivers/usb/core/phy.h|   7 ++
 3 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/core/phy.c
 create mode 100644 drivers/usb/core/phy.h

diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 92c9cefb4317..18e874b0441e 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -6,7 +6,7 @@
 usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
 usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
 usbcore-y += devio.o notify.o generic.o quirks.o devices.o
-usbcore-y += port.o
+usbcore-y += phy.o port.o
 
 usbcore-$(CONFIG_OF)   += of.o
 usbcore-$(CONFIG_USB_PCI)  += hcd-pci.o
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
new file mode 100644
index ..09b7c43c0ea4
--- /dev/null
+++ b/drivers/usb/core/phy.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * A wrapper for multiple PHYs which passes all phy_* function calls to
+ * multiple (actual) PHY devices. This is comes handy when initializing
+ * all PHYs on a HCD and to keep them all in the same state.
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumensti...@googlemail.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "phy.h"
+
+struct usb_phy_roothub {
+   struct phy  *phy;
+   struct list_headlist;
+};
+
+static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
+{
+   struct usb_phy_roothub *roothub_entry;
+
+   roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+   if (!roothub_entry)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_entry->list);
+
+   return roothub_entry;
+}
+
+static int usb_phy_roothub_add_phy(struct device *dev, int index,
+  struct list_head *list)
+{
+   struct usb_phy_roothub *roothub_entry;
+   struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
+
+   if (IS_ERR_OR_NULL(phy)) {
+   if (!phy || PTR_ERR(phy) == -ENODEV)
+   return 0;
+   else
+   return PTR_ERR(phy);
+   }
+
+   roothub_entry = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(roothub_entry))
+   return PTR_ERR(roothub_entry);
+
+   roothub_entry->phy = phy;
+
+   list_add_tail(_entry->list, list);
+
+   return 0;
+}
+
+struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+{
+   struct usb_phy_roothub *phy_roothub;
+   struct usb_phy_roothub *roothub_entry;
+   struct list_head *head;
+   int i, num_phys, err;
+
+   num_phys = of_count_phandle_with_args(dev->of_node, "phys",
+ "#phy-cells");
+   if (num_phys <= 0)
+   return NULL;
+
+   phy_roothub = usb_phy_roothub_alloc(dev);
+   if (IS_ERR(phy_roothub))
+   return phy_roothub;
+
+   for (i = 0; i < num_phys; i++) {
+   err = usb_phy_roothub_add_phy(dev, i, _roothub->list);
+   if (err)
+   goto err_out;
+   }
+
+   head = _roothub->list;
+
+   list_for_each_entry(roothub_entry, head, list) {
+   err = phy_init(roothub_entry->phy);
+   if (err)
+   goto err_exit_phys;
+   }
+
+   return phy_roothub;
+
+err_exit_phys:
+   list_for_each_entry_continue_reverse(roothub_entry, head, list)
+   phy_exit(roothub_entry->phy);
+
+err_out:
+   return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_init);
+
+int usb_phy_roothub_exi

  1   2   3   >