[PATCH RESEND] phy: sun4i-usb: fix phy write on H3 and newer
Evgeny Boger
boger at wirenboard.com
Sun Dec 12 05:14:48 PST 2021
Hi Maxime!
I'm sorry to bother you, but is there anything else I can do to make
this patch merged?
It's been sitting there for 5 months already.
16.11.2021 12:35, Evgeny Boger пишет:
> On older SoCs (prior to H3) PHY register are accessed by manipulating
> the common register for all PHYs. PHY index is specified by pulsing
> usbc bit.
>
> Newer SoCs leave the access procedure mostly unchanged, the
> difference being that the latch registers are separate for each PHY.
>
> Additionally, accessing USB PHY registers is only possible if phy0 is
> routed to musb IP instead of HCI.
>
> Introduce phy_reg_access_v2 cfg flag for H3 (H2+, H5),
> R40 (V40, A40i, T3), V3s (V3, S3) and A64 SoCs.
>
> On A83t, H6, H616, T507 and probably on more recent hardware,
> these PHY registers are not used in vendor BSP.
> So don't set v2 flag for these even newer SoCs as a precaution.
>
> Signed-off-by: Evgeny Boger <boger at wirenboard.com>
> ---
> drivers/phy/allwinner/phy-sun4i-usb.c | 44 ++++++++++++++++++++++++---
> 1 file changed, 39 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
> index 788dd5cdbb7d..cf10e385f199 100644
> --- a/drivers/phy/allwinner/phy-sun4i-usb.c
> +++ b/drivers/phy/allwinner/phy-sun4i-usb.c
> @@ -119,6 +119,7 @@ struct sun4i_usb_phy_cfg {
> bool dedicated_clocks;
> bool enable_pmu_unk1;
> bool phy0_dual_route;
> + bool phy_reg_access_v2;
> int missing_phys;
> };
>
> @@ -192,13 +193,38 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
> int len)
> {
> struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
> - u32 temp, usbc_bit = BIT(phy->index * 2);
> + u32 otgctl_val, temp, usbc_bit;
> void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
> + void __iomem *phyctl_latch;
> unsigned long flags;
> int i;
>
> spin_lock_irqsave(&phy_data->reg_lock, flags);
>
> + /* On older SoCs (prior to H3) PHY register are accessed by manipulating the
> + * common register for all PHYs. PHY index is specified by pulsing usbc bit.
> + * Newer SoCs leave the access procedure mostly unchanged, the difference
> + * being that the latch registers are separate for each PHY.
> + */
> + if (phy_data->cfg->phy_reg_access_v2) {
> + if (phy->index == 0)
> + phyctl_latch = phy_data->base + phy_data->cfg->phyctl_offset;
> + else
> + phyctl_latch = phy->pmu + phy_data->cfg->phyctl_offset;
> + usbc_bit = 1;
> +
> + /* Accessing USB PHY registers is only possible if phy0 is routed to musb.
> + * As it's not clear whether is this related to actual PHY
> + * routing or rather the hardware is just reusing the same bit,
> + * don't check phy0_dual_route here.
> + */
> + otgctl_val = readl(phy_data->base + REG_PHY_OTGCTL);
> + writel(otgctl_val | OTGCTL_ROUTE_MUSB, phy_data->base + REG_PHY_OTGCTL);
> + } else {
> + phyctl_latch = phyctl;
> + usbc_bit = BIT(phy->index * 2);
> + }
> +
> if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
> /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
> writel(0, phyctl);
> @@ -224,17 +250,21 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
> writeb(temp, phyctl);
>
> /* pulse usbc_bit */
> - temp = readb(phyctl);
> + temp = readb(phyctl_latch);
> temp |= usbc_bit;
> - writeb(temp, phyctl);
> + writeb(temp, phyctl_latch);
>
> - temp = readb(phyctl);
> + temp = readb(phyctl_latch);
> temp &= ~usbc_bit;
> - writeb(temp, phyctl);
> + writeb(temp, phyctl_latch);
>
> data >>= 1;
> }
>
> + /* Restore PHY routing and the rest of OTGCTL */
> + if (phy_data->cfg->phy_reg_access_v2)
> + writel(otgctl_val, phy_data->base + REG_PHY_OTGCTL);
> +
> spin_unlock_irqrestore(&phy_data->reg_lock, flags);
> }
>
> @@ -927,6 +957,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
> .dedicated_clocks = true,
> .enable_pmu_unk1 = true,
> .phy0_dual_route = true,
> + .phy_reg_access_v2 = true,
> };
>
> static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
> @@ -937,6 +968,7 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
> .dedicated_clocks = true,
> .enable_pmu_unk1 = true,
> .phy0_dual_route = true,
> + .phy_reg_access_v2 = true,
> };
>
> static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
> @@ -947,6 +979,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
> .dedicated_clocks = true,
> .enable_pmu_unk1 = true,
> .phy0_dual_route = true,
> + .phy_reg_access_v2 = true,
> };
>
> static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
> @@ -957,6 +990,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
> .dedicated_clocks = true,
> .enable_pmu_unk1 = true,
> .phy0_dual_route = true,
> + .phy_reg_access_v2 = true,
> };
>
> static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
--
С уважением,
Евгений Богер / Evgeny Boger
CTO, Wiren Board Team
https://wirenboard.com/ru
+7 495 150 66 19 (# 33)
More information about the linux-arm-kernel
mailing list