[PATCH] phy: stm32-usphyc: add mdelay(1) to fix timeout on some machines
Fabrice Gasnier
fabrice.gasnier at foss.st.com
Thu Feb 16 00:30:26 PST 2023
On 2/13/23 15:59, Michael Grzeschik wrote:
> Hi Fabrice,
>
> On Wed, Feb 01, 2023 at 05:20:11PM +0100, Fabrice Gasnier wrote:
>> On 1/24/23 21:45, Michael Grzeschik wrote:
>>> An mdelay of 1 seems to be necessary on some machines, since
>>
>> Hi Michael,
>>
>> Could you precise on which board ?
>
> It was reproducible on one of our lxa-mc1 boards.
>
>>> the monsel status does not seem to be accurate. On rare occasions just
>>> working with the phy after this pll check lead to no functional usb.
>>
>> Could you elaborate on the symptoms (provide some error logs) ?
>
> The symptom was, that the dwc2 controller was not resuming from polling
> on the soft reset done bit and so ran into a timeout. (dwc2:
> GRSTCTL_CSFTRST(GRSTCTL_CSFTRST_DONE))
>
> While debugging we found that the stm vendor uboot phy driver
> was just adding an predefined wait of 200us after setting
> the pll.
>
> https://github.com/STMicroelectronics/u-boot/blob/v2021.10-stm32mp/drivers/phy/phy-stm32-usbphyc.c#L257
>
> The comment for the PLL_INIT_TIME_US says that the value is based on the
> possible max pll lock latency and an additional phy init delay:
>
> /* max 100 us for PLL lock and 100 us for PHY init */
> #define PLL_INIT_TIME_US 200
>
> Reading the datasheet of the stm32mp1, the 100 us sure come from
> tLOCK in Table 41. USB_PLL characteristics. (Page 159)
>
> https://www.st.com/resource/en/datasheet/stm32mp157c.pdf
>
>
> In the mainline Kernel we have the set of lock monitor
> bits that are actually undefined in any register specs
> we read so far.
>
> /* STM32_USBPHYC_MONITOR bit fields */
> #define STM32_USBPHYC_MON_OUT GENMASK(3, 0)
> #define STM32_USBPHYC_MON_SEL GENMASK(8, 4)
> #define STM32_USBPHYC_MON_SEL_LOCKP 0x1F
> #define STM32_USBPHYC_MON_OUT_LOCKP BIT(3)
>
> So this will bring the maximum lock delay to its real
> delay.
Hi Michael,
Thanks for all detailed explanation.
I asked some improvements in the documentations in this area.
>
> But for the additional phy init delay, we are unsure where the 100us are
> coming from. So we could not really tell if the value makes sense at
> all. The assumption was to increase the delay, just to make sure that
> this will solve the issue for good.
>
>>> With this short mdelay this issue was not reported again.
>>>
>>> Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
>>> ---
>>> drivers/phy/st/phy-stm32-usbphyc.c | 9 +++++++++
>>> 1 file changed, 9 insertions(+)
>>>
>>> diff --git a/drivers/phy/st/phy-stm32-usbphyc.c
>>> b/drivers/phy/st/phy-stm32-usbphyc.c
>>> index 5bb9647b078f12..c452a0caceb9fa 100644
>>> --- a/drivers/phy/st/phy-stm32-usbphyc.c
>>> +++ b/drivers/phy/st/phy-stm32-usbphyc.c
>>> @@ -353,6 +353,15 @@ static int stm32_usbphyc_phy_init(struct phy *phy)
>>> goto pll_disable;
>>> }
>>>
>>> + /* This mdelay seems to be necessary on some machines, since the
>>> + * monsel status does not seem to be accurate. On rare occasions
>>> + * just working with the phy after this pll check the usb
>>> + * peripheral (e.g. on the dwc2) run into timeout issues and
>>> + * leading to no functional usb. With this short mdelay this
>>> + * issue was not reported again.
>>> + */
>>> + mdelay(1);
>>> +
>>
>> The USBPHYC provides two PHY interfaces:
>> - PHY port#1 is for USBH
>> - PHY port#2 can be assigned to USBH or DWC2.
>>
>> Adding some delay here, we'll hit twice this penalty (e.g. for USBH +
>> DWC2 or dual USBH) on all MP1 (MP13 & MP15) platforms.
>>
>> Could you try to narrow down the issue by adding some debug log in:
>> - stm32_usbphyc_phy_init
>> - stm32_usbphyc_clk48_prepare
>
> The whole issue is actually very easy to reproduce in the bootloader.
> So we already mainlined this patch to the barebox bootloader.
>
> So this patch is actually a port from the bootloader to make sure
> that the kernel does not run into the issue as well.
Kernel and u-boot drivers are both registering:
- a clock provider
clk_prepare ... -> stm32_usbphyc_clk48_prepare()
Currently, there's no wait loop NOR delay here
- a PHY provider (2 PHYs, e.g. 2 ports)
additional mdelay(1) will be hit twice, one time for DWC2, one for
EHCI/OHCI
Both in kernel and u-boot the clk_prepare() likely happens 1st, then
phy_init().
This is still unclear to me why an additional delay in PHY init, would
be necessary in your environment, with the kernel. Is there a real issue
in kernel ? Or is it more a caution, theoretical port from barebox ?
Still, If needed, I'd advice the delay to be applied only once, e.g. in
stm32_usbphyc_pll_enable(), just after PLLEN bit has been set (as in
u-boot). And rely on MON bits for each PHY init.
Regarding mdelay(): It would also be better to adopt usleep_range()
instead of busy loop.
stm32_usbphyc_set_bits(pll_reg, PLLEN);
+ /* Wait for maximum lock time */
+ usleep_range(200, 300);
+
return 0;
This way, delay will be hit upon clk_prepare, then polling the MON bits
in phy_init() may become a no-op. So, the delay would be hit only once
(instead of two times). If ever the phy_init() comes first in the
future, only the 1st call to one of the APIs will hit this delay.
Could you check if this solves the issue at your end ?
I had a look at barebox driver, same logic could apply there even if no
clock provider is registered.
>
> I bet your team at st can figure out a more reasonable value for the
> delay.
I'd recommend 200µs (min) as in u-boot.
Regards,
Fabrice
>
>>> usbphyc_phy->active = true;
>>>
>>> return 0;
>>
>
> Regards,
> Michael
>
More information about the linux-arm-kernel
mailing list