[PATCH v1] net: designware: eqos: stm32: add stm32mp13 support
Oleksij Rempel
o.rempel at pengutronix.de
Tue Dec 3 06:01:25 PST 2024
Add support for STM32MP13x variants. Tested on STM32MP133.
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
drivers/net/designware_stm32.c | 94 +++++++++++++++++++++++++++++-----
1 file changed, 80 insertions(+), 14 deletions(-)
diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c
index 54dabcc8d32a..b21cb5cb13ac 100644
--- a/drivers/net/designware_stm32.c
+++ b/drivers/net/designware_stm32.c
@@ -8,10 +8,11 @@
#include <common.h>
#include <init.h>
-#include <net.h>
#include <linux/clk.h>
-#include <mfd/syscon.h>
#include <linux/regmap.h>
+#include <mfd/syscon.h>
+#include <net.h>
+#include <of_device.h>
#include "designware_eqos.h"
@@ -44,13 +45,21 @@
#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16)
#define SYSCFG_PMCCLRR_OFFSET 0x40
+struct stm32_ops {
+ const struct eqos_ops *eqos_ops;
+ bool is_mp13;
+ u32 syscfg_clr_off;
+};
+
struct eqos_stm32 {
struct clk_bulk_data *clks;
int num_clks;
struct regmap *regmap;
u32 mode_reg;
+ u32 mode_mask;
int eth_clk_sel_reg;
int eth_ref_clk_sel_reg;
+ const struct stm32_ops *ops;
};
static inline struct eqos_stm32 *to_stm32(struct eqos *eqos)
@@ -72,12 +81,20 @@ static unsigned long eqos_get_csr_clk_rate_stm32(struct eqos *eqos)
static int eqos_set_mode_stm32(struct eqos_stm32 *priv, phy_interface_t interface)
{
- u32 val, reg = priv->mode_reg;
+ u32 reg = priv->mode_reg;
+ u32 val = 0;
int ret;
switch (interface) {
case PHY_INTERFACE_MODE_MII:
- val = SYSCFG_PMCR_ETH_SEL_MII;
+ /*
+ * STM32MP15xx supports both MII and GMII, STM32MP13xx MII only.
+ * SYSCFG_PMCSETR ETH_SELMII is present only on STM32MP15xx and
+ * acts as a selector between 0:GMII and 1:MII. As STM32MP13xx
+ * supports only MII, ETH_SELMII is not present.
+ */
+ if (!priv->ops->is_mp13) /* Select MII mode on STM32MP15xx */
+ val |= SYSCFG_PMCR_ETH_SEL_MII;
break;
case PHY_INTERFACE_MODE_GMII:
val = SYSCFG_PMCR_ETH_SEL_GMII;
@@ -101,16 +118,16 @@ static int eqos_set_mode_stm32(struct eqos_stm32 *priv, phy_interface_t interfac
return -EINVAL;
}
+ /* Shift value at correct ethernet MAC offset in SYSCFG_PMCSETR */
+ val <<= ffs(priv->mode_mask) - ffs(SYSCFG_MP1_ETH_MASK);
+
/* Need to update PMCCLRR (clear register) */
- ret = regmap_write(priv->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
- SYSCFG_MP1_ETH_MASK);
+ ret = regmap_write(priv->regmap, priv->ops->syscfg_clr_off,
+ priv->mode_mask);
if (ret)
- return -EIO;
-
- /* Update PMCSETR (set register) */
- regmap_update_bits(priv->regmap, reg, GENMASK(23, 16), val);
+ return ret;
- return 0;
+ return regmap_update_bits(priv->regmap, reg, priv->mode_mask, val);
}
static int eqos_init_stm32(struct device *dev, struct eqos *eqos)
@@ -142,6 +159,18 @@ static int eqos_init_stm32(struct device *dev, struct eqos *eqos)
return -EINVAL;
}
+ priv->mode_mask = SYSCFG_MP1_ETH_MASK;
+ ret = of_property_read_u32_index(np, "st,syscon", 2, &priv->mode_mask);
+ if (ret) {
+ if (priv->ops->is_mp13) {
+ dev_err(dev, "Sysconfig register mask must be set (%pe)\n",
+ ERR_PTR(ret));
+ } else {
+ dev_dbg(dev, "Warning sysconfig register mask not set (%pe)\n",
+ ERR_PTR(ret));
+ }
+ }
+
ret = eqos_set_mode_stm32(priv, eqos->interface);
if (ret)
dev_warn(dev, "Configuring syscfg failed: %s\n", strerror(-ret));
@@ -167,7 +196,18 @@ static int eqos_init_stm32(struct device *dev, struct eqos *eqos)
return clk_bulk_enable(priv->num_clks, priv->clks);
}
-static struct eqos_ops stm32_ops = {
+static struct eqos_ops stm32mp13_ops = {
+ .init = eqos_init_stm32,
+ .get_ethaddr = eqos_get_ethaddr,
+ .set_ethaddr = eqos_set_ethaddr,
+ .adjust_link = eqos_adjust_link,
+ .get_csr_clk_rate = eqos_get_csr_clk_rate_stm32,
+
+ .clk_csr = EQOS_MDIO_ADDR_CR_250_300,
+ .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+};
+
+static struct eqos_ops stm32mp15_ops = {
.init = eqos_init_stm32,
.get_ethaddr = eqos_get_ethaddr,
.set_ethaddr = eqos_set_ethaddr,
@@ -178,9 +218,34 @@ static struct eqos_ops stm32_ops = {
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
};
+static struct stm32_ops stm32mp13_dwmac_data = {
+ .eqos_ops = &stm32mp13_ops,
+ .syscfg_clr_off = 0x08,
+ .is_mp13 = true,
+};
+
+static struct stm32_ops stm32mp15_dwmac_data = {
+ .eqos_ops = &stm32mp15_ops,
+ .syscfg_clr_off = 0x44,
+ .is_mp13 = false,
+};
+
static int eqos_probe_stm32(struct device *dev)
{
- return eqos_probe(dev, &stm32_ops, xzalloc(sizeof(struct eqos_stm32)));
+ const struct stm32_ops *data;
+ struct eqos_stm32 *priv;
+
+ priv = xzalloc(sizeof(*priv));
+ if (!priv)
+ return -ENOMEM;
+
+ data = of_device_get_match_data(dev);
+ if (!data)
+ return -EINVAL;
+
+ priv->ops = data;
+
+ return eqos_probe(dev, data->eqos_ops, priv);
}
static void eqos_remove_stm32(struct device *dev)
@@ -194,7 +259,8 @@ static void eqos_remove_stm32(struct device *dev)
}
static const struct of_device_id eqos_stm32_ids[] = {
- { .compatible = "st,stm32mp1-dwmac" },
+ { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp15_dwmac_data},
+ { .compatible = "st,stm32mp13-dwmac", .data = &stm32mp13_dwmac_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, eqos_stm32_ids);
--
2.39.5
More information about the barebox
mailing list