[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