diff mbox series

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

Message ID 20240306005230.2638972-4-volodymyr_babchuk@epam.com
State Changes Requested
Delegated to: Caleb Connolly
Headers show
Series Add support for Qualcomm SA8155-ADP board | expand

Commit Message

Volodymyr Babchuk March 6, 2024, 12:52 a.m. UTC
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@epam.com>

---

Changes in v2:
 - Clear loopback bit explicitly

 drivers/net/dwc_eth_qos.c      |  4 +++
 drivers/net/dwc_eth_qos.h      |  2 ++
 drivers/net/dwc_eth_qos_qcom.c | 46 +++++++++++++++++++++++++++-------
 3 files changed, 43 insertions(+), 9 deletions(-)

Comments

Sumit Garg March 6, 2024, 6:01 a.m. UTC | #1
On Wed, 6 Mar 2024 at 06:23, Volodymyr Babchuk
<Volodymyr_Babchuk@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@epam.com>
>
> ---
>
> Changes in v2:
>  - Clear loopback bit explicitly
>
>  drivers/net/dwc_eth_qos.c      |  4 +++
>  drivers/net/dwc_eth_qos.h      |  2 ++
>  drivers/net/dwc_eth_qos_qcom.c | 46 +++++++++++++++++++++++++++-------
>  3 files changed, 43 insertions(+), 9 deletions(-)
>

Reviewed-by: Sumit Garg <sumit.garg@linaro.org>

-Sumit

> 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..ee8420c71d 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,10 @@ 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);
> +       uint32_t loopback =
> +               eqos->qcom_enable_loopback ? RGMII_CONFIG_LOOPBACK_EN : 0;
> +
>         /* Disable loopback mode */
>         clrbits_le32(&regs->io_macro_config2,
>                      RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
> @@ -202,7 +215,8 @@ 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);
> +               clrsetbits_le32(&regs->io_macro_config,
> +                               RGMII_CONFIG_LOOPBACK_EN, loopback);
>                 break;
>
>         case SPEED_100:
> @@ -233,7 +247,8 @@ 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);
> +               clrsetbits_le32(&regs->io_macro_config,
> +                               RGMII_CONFIG_LOOPBACK_EN, loopback);
>                 break;
>
>         case SPEED_10:
> @@ -265,7 +280,8 @@ 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);
> +               clrsetbits_le32(&regs->io_macro_config,
> +                               RGMII_CONFIG_LOOPBACK_EN, loopback);
>                 break;
>
>         default:
> @@ -281,14 +297,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 +582,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
diff mbox series

Patch

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..ee8420c71d 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,10 @@  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);
+	uint32_t loopback =
+		eqos->qcom_enable_loopback ? RGMII_CONFIG_LOOPBACK_EN : 0;
+
 	/* Disable loopback mode */
 	clrbits_le32(&regs->io_macro_config2,
 		     RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
@@ -202,7 +215,8 @@  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);
+		clrsetbits_le32(&regs->io_macro_config,
+				RGMII_CONFIG_LOOPBACK_EN, loopback);
 		break;
 
 	case SPEED_100:
@@ -233,7 +247,8 @@  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);
+		clrsetbits_le32(&regs->io_macro_config,
+				RGMII_CONFIG_LOOPBACK_EN, loopback);
 		break;
 
 	case SPEED_10:
@@ -265,7 +280,8 @@  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);
+		clrsetbits_le32(&regs->io_macro_config,
+				RGMII_CONFIG_LOOPBACK_EN, loopback);
 		break;
 
 	default:
@@ -281,14 +297,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 +582,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;
 }