[Linux-stm32] stm32mp1xx: use of reg11, reg18 and vdd_usb rails
Sean Nyekjaer
sean at geanix.com
Mon Mar 4 23:59:34 PST 2024
Hi,
> On 4 Mar 2024, at 18.50, Fabrice Gasnier <fabrice.gasnier at foss.st.com> wrote:
>
> On 3/4/24 09:30, Sean Nyekjaer wrote:
>>
>>
>>> On 1 Mar 2024, at 18.58, Fabrice Gasnier <fabrice.gasnier at foss.st.com> wrote:
>>>
>>> On 3/1/24 15:41, Sean Nyekjaer wrote:
>>>> Hi all,
>>>>
>>>> We are using the osd32mp1 SIP module [0].
>>>> We are seeing some hardware get’s fried inside the SIP module.
>>>> It’s somewhat traced down to the usb controller/phy/regulator.
>>>>
>>>> With this device tree[1]. We have noticed during boot the reg18 is toggled on and off
>>>
>>> Dear Sean,
>>
>> Hi Fabrice,
>>
>>>
>>> I've tried to check what you've pointed out.
>>>
>>> The toggling happens when registering the PHY as a clock provider. The
>>> USB PHY has a PLL to provide clock for OTG and USBH. This clock gets
>>> registered to the clock framework, as they go through RCC.
>>>
>>> stm32_usbphyc_clk48_register() -> clk_hw_register()
>>>
>>> In order to properly be inserted into the clock tree, (e.g. RCC does
>>> some gating then) reparent operation requires the PLL (with its
>>> supplies) to be enabled. Once the reparent is completed, it requests to
>>> turn it OFF.
>>>
>>> That's the reason for the toggling.
>>
>> Also our conclusion. A rather complex setup.
>
> Hi Sean,
>
> That's needed for low power (e.g. suspend). You may find upon suspend,
> HCD driver calls phy_exit() but still needs to access registers, before
> clk_disable() gets called. The PHY clock on MP1 is still needed in
> between the two calls. Hence, the clock is exposed and used for this low
> power sequence.
Fortunately we are not using suspend :)
>
>>
>>>
>>>> without vdd_usb being turned off before reg18 as required in the data sheet[2], section 3.8.1:
>>>
>>> vdd_usb is problably (I haven't checked) a boot-on regulator, totally
>>> untouched when the toggling happens. It gets enabled in drivers later,
>>> during phy_power_on() or in dwc2 driver (stm id glue / usb33d cascaded
>>> then to pwr). So it isn't controlled before that.
>>
>> reg18 is boot-on because the BYPASS_REG1V8 is pulled low, reg18 is fed by VDD, which is has a lower PMIC ranking than vdd_usb/ldo4.
>> U-boot is actually powering off reg11, reg18 and vdd_usb(in the correct order). Before starting the kernel.
>
> So these regulators are all 'off', out of u-boot, before starting the
> kernel (toggling reg18 should then have no effect) ?
Yes they are all off, then reg18 is powered on and then vdd_usb.
reg18 is then briefly toggled. Because the clk framework is deactivating it.
>
> As you confirmed the above behavior (reg18 toggles on-off) during
> stm32_usbphyc_clk48_register(), how is the vdd_usb regulator "on" when
> booting the kernel ? I don't get it.
stm32-pwr.c is adding a consumer to the vdd_usb.
root at hostname:~# cat /sys/class/regulator/regulator.8/name
vdd_usb
root at hostname:~# cat /sys/class/regulator/regulator.8/num_users
4
root at hostname:~# cat /sys/class/regulator/regulator.8/regulator.17-SUPPLY/name
usb33
> (The clock reparent operation comes during USBPHYC driver probe, it
> doesn't involve vdd_usb, no consumer should have had an opportunity to
> enable vdd_usb before that).
See above.
>
> Please clarify the boot chain you're using. Is it on u-boot ? (SPL?
> TF-A? Is OPTEE involved ? ))
> I can't find the board DT in u-boot, is there some specific code / dts
> for this board in u-boot ?
No TF-A, no OPTEE.
I have copied the device tree from Linux.
>
> U-boot normally doesn't probe the USB during normal boot from sd-card
> for example. Hence, these regulators are normally untouched by u-boot.
>
> With stm32mp157c-dk2.dts, I can see when breaking boot (SPL config):
> STM32MP> regulator status
> Name Enabled uV mA Mode Status
> reg11 enabled 1100000 - - 0
> reg18 enabled 1800000 - - 0
> usb33 disabled 3300000 - - 0
> ...
> vdd_usb enabled 3300000 - - 0
>
> Please clarify the use case? I'd like to avoid any confusion.
> Or, USB is used in your case before booting ?
I’m USB booting from u-boot.
But it doesn’t make a difference with the toggling of reg18, if the initial state is on/off.
>
> In such case, after "usb start", or any other device class command in
> u-boot (ums, dfu...), all these regulators would be disabled in the end.
>
> Could you check and report "regulator status" command output in u-boot,
> before boot ?
Before booting the kernel u-boot will exit the usb stack and power off related regulators.
See here:
https://first.geanix.com/boot-linux.jpg
The Yellow line, is reg18 and the purple is vdd_usb.
If the initial state of reg18 is LOW doesn’t make a difference, as the toggling happens later :)
With my proposed fix (removing the vdd_3v3_usbfs, thus breaking otg)
https://first.geanix.com/boot-linux-good.jpg
Hope that clarifies.
>
>>
>>>
>>>> VDD3V3_USBHS must not be present unless VDDA1V8_REG is present, otherwise permanent
>>>> STM32MP157C/F damage could occur. Must be ensured by PMIC ranking order or with
>>>> external component in case of discrete component power supply implementation.
>>>>
>>>> It’s happens because the something is already uses the vdd_usb, it’s both the drivers/phy/st/phy-stm32-usbphyc.c
>>>> and drivers/regulator/stm32-pwr.c that consumes it.
>>>
>>> No (see above).
>>
>> Yes, the stm32-pwr.c consumes the vdd_usb, and blocks the dwc2 driver from powering it off.
>
> I don't understand the condition here: PWR regulators are in the middle
> of the power tree, in between PMIC and USBPHYC or dwc2 consumers. PWR
> doesn't / shouldn't enable vdd_usb on its own: it rather cascades
> enable/disable requests from consumers, to the parent regulator. This
> should happen after the toggling: e.g. after USBPHC driver probe (clk
> reparent), when consumers are initializing.
>
> Please clarify.
See above.
>
>>
>>>
>>>>
>>>> I can fix it by removing the vdd_usb from the usb33 supply[3]:
>>>
>>> This will break all implementations that rely on ID/Vbus pins on MP15.
>>
>> OK. So we will have to use Mark’s suggestion and force it on.
>
> I noticed Mark's reply after I actually answered on friday.
>
> If low power is out of scope, that may be a workaround. As he states,
> it's not ideal.
>
We are running with this to avoid further hardware damage.
> Better approach (likely more reliable) would be to have some way to deal
> with hardware constraints as he suggested, e.g. not to disable a
> regulator (reg18), unless another regulator is off (vdd_usb).
Agree.
>
>
>>
>>>
>>>> The stm32-pwr.c is (to me) rather weird, as it exposes the usb33 as a regulator when in fact it’s a detection pin.
>>>> Is that done on purpose?
>>>>
>>>> I would like introduce a error in the stm32-pwr.c if something is trying to power off reg18 with usb33 present?
>>>
>>> Well, adding some error as you have drafted should protect the hardware.
>>> Doesn't this brings error, when registering into the clock framework ?
>>> Does this prevent registering USB then ?
>>>
>>> There's probably better options. It needs additional fix. I can't think
>>> about right now...
>>> It is just a thought, but when the PHY driver registers the clock, a
>>> better control of all the regulator 1v1, 1v8 and vdd_usb could be to
>>> enforce vdd_usb first gets disabled in this process.
>>
>> This is how u-boot is handling things. The driver hard controls all regulators.
>
> The main difference in u-boot seems that vdd_usb is en(dis)able from
> phy_power_on(off). I haven't inspected the sequence for the clock
> provider in u-boot: the same scheme as in kernel to enable the PLL is
> implemented. Perhaps u-boot simply doesn't disable the clock after all.
>
> I don't know if this could be acceptable, in Linux, to manage the
> vdd_usb also in stm32_usbphyc_regulators_enable() /
> stm32_usbphyc_regulators_disable() ?
I don’t know either :)
>
> static int stm32_usbphyc_regulators_enable(struct stm32_usbphyc *usbphyc)
> {
> + struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys[0];
> int ret;
>
> ...
> ret = regulator_enable(usbphyc->vdda1v8);
> if (ret)
> goto vdda1v1_disable;
>
> + ret = regulator_enable(usbphyc_phy->phy->pwr);
> + if (ret)
> + goto vdda1v8_disable;
> +
> return 0;
>
> +vdda1v8_disable:
> + dev_info(usbphyc->dev, "vdda1v8 disable\n");
> + regulator_disable(usbphyc->vdda1v8);
>
> And the opposite in stm32_usbphyc_regulators_disable().
>
> Doing it, will initialize vdd_usb regulator ref counting, e.g. 1 then 0
> when registering the USBPHYC clock. So it will be managed in the correct
> order (turned off before reg18).
>
> It will work, if and only if, vdd_usb isn't shared on the board, with
> another function, this could enforce from phy driver the correct
> enable/disable sequence.
One could share the vdd_usb on the board. In those cases we need to avoid powering reg18 off.
When entering stm32_usbphyc_regulators_disable() and the phy is still powered on we should block power off.
In my first mail I added a warning if the this happens...
>
> If the vdd_usb regulator is share with some other function, then I see
> no other way, but to look into Mark's suggestion to better control
> hardware constraints.
>
> Hope this helps,
> Please clarify above points,
> Best Regards,
> Fabrice
>
Sorry for the pictures on our own server, what is folks using for sharing pictures on the mailing lists?
/Sean
[…]
More information about the linux-arm-kernel
mailing list