[PATCH 3/8] net: dw_eth_qos: add support for Qualcomm SM8150 SoC

Sumit Garg sumit.garg at linaro.org
Tue Mar 5 07:49:02 CET 2024


On Thu, 29 Feb 2024 at 19:53, Volodymyr Babchuk
<Volodymyr_Babchuk at epam.com> wrote:
>
> Add support for Qualcomm SM8150 SoC to the EQOS driver. SM8150 has two
> main differences from already supported QCS404: it has another RGMII
> configuration registers set and it does require RGMII loopback to
> be disabled.
>
> To support different variants of QCOM SoC we had to add two new fields
> to the eqos_priv struct: eqos_qcom_rgmii_regs and
> qcom_enable_loopback.
>
> Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk at epam.com>
> ---
>
>  drivers/net/dwc_eth_qos.c      |  4 +++
>  drivers/net/dwc_eth_qos.h      |  2 ++
>  drivers/net/dwc_eth_qos_qcom.c | 47 +++++++++++++++++++++++++++-------
>  3 files changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 9b3bce1dc8..882b854697 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1700,6 +1700,10 @@ static const struct udevice_id eqos_ids[] = {
>                 .compatible = "qcom,qcs404-ethqos",
>                 .data = (ulong)&eqos_qcom_config
>         },
> +       {
> +               .compatible = "qcom,sm8150-ethqos",
> +               .data = (ulong)&eqos_qcom_config
> +       },
>  #endif
>  #if IS_ENABLED(CONFIG_DWC_ETH_QOS_STARFIVE)
>         {
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index e3222e1e17..216e1afe53 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -255,6 +255,7 @@ struct eqos_priv {
>         struct eqos_dma_regs *dma_regs;
>         struct eqos_tegra186_regs *tegra186_regs;
>         void *eqos_qcom_rgmii_regs;
> +       struct dwmac_rgmii_regs *eqos_qcom_por;
>         struct reset_ctl reset_ctl;
>         struct gpio_desc phy_reset_gpio;
>         struct clk clk_master_bus;
> @@ -277,6 +278,7 @@ struct eqos_priv {
>         bool started;
>         bool reg_access_ok;
>         bool clk_ck_enabled;
> +       bool qcom_enable_loopback;
>         unsigned int tx_fifo_sz, rx_fifo_sz;
>         u32 reset_delays[3];
>  };
> diff --git a/drivers/net/dwc_eth_qos_qcom.c b/drivers/net/dwc_eth_qos_qcom.c
> index 8178138fc6..e9592ff686 100644
> --- a/drivers/net/dwc_eth_qos_qcom.c
> +++ b/drivers/net/dwc_eth_qos_qcom.c
> @@ -95,6 +95,15 @@ static struct dwmac_rgmii_regs emac_v2_3_0_por = {
>         .io_macro_config2 = 0x00002060
>  };
>
> +static struct dwmac_rgmii_regs emac_v2_1_0_por = {
> +       .io_macro_config = 0x40C01343,
> +       .sdcc_hc_dll_config = 0x2004642C,
> +       .sdcc_hc_ddr_config = 0x00000000,
> +       .sdcc_hc_dll_config2 = 0x00200000,
> +       .sdcc_usr_ctl = 0x00010800,
> +       .io_macro_config2 = 0x00002060
> +};
> +
>  static void ethqos_set_func_clk_en(struct dwmac_rgmii_regs *regs)
>  {
>         setbits_le32(&regs->io_macro_config, RGMII_CONFIG_FUNC_CLK_EN);
> @@ -172,6 +181,8 @@ static int ethqos_rgmii_macro_init(struct udevice *dev,
>                                    struct dwmac_rgmii_regs *regs,
>                                    unsigned long speed)
>  {
> +       struct eqos_priv *eqos = dev_get_priv(dev);
> +
>         /* Disable loopback mode */
>         clrbits_le32(&regs->io_macro_config2,
>                      RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
> @@ -202,7 +213,9 @@ static int ethqos_rgmii_macro_init(struct udevice *dev,
>                                 SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57);
>                 setbits_le32(&regs->sdcc_hc_ddr_config, SDCC_DDR_CONFIG_PRG_DLY_EN);
>
> -               setbits_le32(&regs->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
> +               if (eqos->qcom_enable_loopback)
> +                       setbits_le32(&regs->io_macro_config,
> +                                    RGMII_CONFIG_LOOPBACK_EN);

We should explicitly clear the loopback bit for the else part too. I
suppose it can be written cleanly as below here and other places too:

        loopback = eqos->qcom_enable_loopback ? RGMII_CONFIG_LOOPBACK_EN : 0;

        clrsetbits_le32(&regs->io_macro_config,
                                RGMII_CONFIG_LOOPBACK_EN,
                                loopback);

-Sumit

>                 break;
>
>         case SPEED_100:
> @@ -233,7 +246,9 @@ static int ethqos_rgmii_macro_init(struct udevice *dev,
>                 setbits_le32(&regs->sdcc_hc_ddr_config,
>                              SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
>
> -               setbits_le32(&regs->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
> +               if (eqos->qcom_enable_loopback)
> +                       setbits_le32(&regs->io_macro_config,
> +                                    RGMII_CONFIG_LOOPBACK_EN);
>                 break;
>
>         case SPEED_10:
> @@ -265,7 +280,9 @@ static int ethqos_rgmii_macro_init(struct udevice *dev,
>                 setbits_le32(&regs->sdcc_hc_ddr_config,
>                              SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
>
> -               setbits_le32(&regs->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
> +               if (eqos->qcom_enable_loopback)
> +                       setbits_le32(&regs->io_macro_config,
> +                                    RGMII_CONFIG_LOOPBACK_EN);
>                 break;
>
>         default:
> @@ -281,14 +298,15 @@ static int ethqos_configure(struct udevice *dev,
>                             unsigned long speed)
>  {
>         unsigned int retry = 1000;
> +       struct eqos_priv *eqos = dev_get_priv(dev);
>
>         /* Reset to POR values and enable clk */
> -       writel(emac_v2_3_0_por.io_macro_config, &regs->io_macro_config);
> -       writel(emac_v2_3_0_por.sdcc_hc_dll_config, &regs->sdcc_hc_dll_config);
> -       writel(emac_v2_3_0_por.sdcc_hc_ddr_config, &regs->sdcc_hc_ddr_config);
> -       writel(emac_v2_3_0_por.sdcc_hc_dll_config2, &regs->sdcc_hc_dll_config2);
> -       writel(emac_v2_3_0_por.sdcc_usr_ctl, &regs->sdcc_usr_ctl);
> -       writel(emac_v2_3_0_por.io_macro_config2, &regs->io_macro_config2);
> +       writel(eqos->eqos_qcom_por->io_macro_config, &regs->io_macro_config);
> +       writel(eqos->eqos_qcom_por->sdcc_hc_dll_config, &regs->sdcc_hc_dll_config);
> +       writel(eqos->eqos_qcom_por->sdcc_hc_ddr_config, &regs->sdcc_hc_ddr_config);
> +       writel(eqos->eqos_qcom_por->sdcc_hc_dll_config2, &regs->sdcc_hc_dll_config2);
> +       writel(eqos->eqos_qcom_por->sdcc_usr_ctl, &regs->sdcc_usr_ctl);
> +       writel(eqos->eqos_qcom_por->io_macro_config2, &regs->io_macro_config2);
>
>         ethqos_set_func_clk_en(regs);
>
> @@ -565,6 +583,17 @@ static int eqos_probe_resources_qcom(struct udevice *dev)
>                 return -EINVAL;
>         }
>
> +       if (device_is_compatible(dev, "qcom,qcs404-ethqos")) {
> +               eqos->eqos_qcom_por = &emac_v2_3_0_por;
> +               eqos->qcom_enable_loopback = true;
> +       } else if (device_is_compatible(dev, "qcom,sm8150-ethqos")) {
> +               eqos->eqos_qcom_por = &emac_v2_1_0_por;
> +               eqos->qcom_enable_loopback = false;
> +       } else {
> +               pr_err("Unknown QCOM ethernet device\n");
> +               return -EINVAL;
> +       }
> +
>         debug("%s: OK\n", __func__);
>         return 0;
>  }
> --
> 2.43.0


More information about the U-Boot mailing list