Commit 5bcc1afd authored by Christophe Roullier's avatar Christophe Roullier Committed by Paolo Abeni

net: stmmac: dwmac-stm32: stm32: add management of stm32mp25 for stm32

Add Ethernet support for STM32MP25.
STM32MP25 is STM32 SOC with 2 GMACs instances.
GMAC IP version is SNPS 5.3x.
GMAC IP configure with 2 RX and 4 TX queue.
DMA HW capability register supported
RX Checksum Offload Engine supported
TX Checksum insertion supported
Wake-Up On Lan supported
TSO supported
Signed-off-by: default avatarChristophe Roullier <christophe.roullier@foss.st.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Reviewed-by: default avatarMarek Vasut <marex@denx.de>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 3d94d1ac
...@@ -53,7 +53,18 @@ ...@@ -53,7 +53,18 @@
#define SYSCFG_MCU_ETH_SEL_MII 0 #define SYSCFG_MCU_ETH_SEL_MII 0
#define SYSCFG_MCU_ETH_SEL_RMII 1 #define SYSCFG_MCU_ETH_SEL_RMII 1
/* STM32MP1 register definitions /* STM32MP2 register definitions */
#define SYSCFG_MP2_ETH_MASK GENMASK(31, 0)
#define SYSCFG_ETHCR_ETH_PTP_CLK_SEL BIT(2)
#define SYSCFG_ETHCR_ETH_CLK_SEL BIT(1)
#define SYSCFG_ETHCR_ETH_REF_CLK_SEL BIT(0)
#define SYSCFG_ETHCR_ETH_SEL_MII 0
#define SYSCFG_ETHCR_ETH_SEL_RGMII BIT(4)
#define SYSCFG_ETHCR_ETH_SEL_RMII BIT(6)
/* STM32MPx register definitions
* *
* Below table summarizes the clock requirement and clock sources for * Below table summarizes the clock requirement and clock sources for
* supported phy interface modes. * supported phy interface modes.
...@@ -104,7 +115,7 @@ struct stm32_ops { ...@@ -104,7 +115,7 @@ struct stm32_ops {
int (*parse_data)(struct stm32_dwmac *dwmac, int (*parse_data)(struct stm32_dwmac *dwmac,
struct device *dev); struct device *dev);
bool clk_rx_enable_in_suspend; bool clk_rx_enable_in_suspend;
bool is_mp13; bool is_mp13, is_mp2;
u32 syscfg_clr_off; u32 syscfg_clr_off;
}; };
...@@ -277,8 +288,55 @@ static int stm32mp1_configure_pmcr(struct plat_stmmacenet_data *plat_dat) ...@@ -277,8 +288,55 @@ static int stm32mp1_configure_pmcr(struct plat_stmmacenet_data *plat_dat)
dwmac->mode_mask, val); dwmac->mode_mask, val);
} }
static int stm32mp2_configure_syscfg(struct plat_stmmacenet_data *plat_dat)
{
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
u32 reg = dwmac->mode_reg;
int val = 0;
switch (plat_dat->mac_interface) {
case PHY_INTERFACE_MODE_MII:
/* ETH_REF_CLK_SEL bit in SYSCFG register is not applicable in MII mode */
break;
case PHY_INTERFACE_MODE_RMII:
val = SYSCFG_ETHCR_ETH_SEL_RMII;
if (dwmac->enable_eth_ck) {
/* Internal clock ETH_CLK of 50MHz from RCC is used */
val |= SYSCFG_ETHCR_ETH_REF_CLK_SEL;
}
break;
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
val = SYSCFG_ETHCR_ETH_SEL_RGMII;
fallthrough;
case PHY_INTERFACE_MODE_GMII:
if (dwmac->enable_eth_ck) {
/* Internal clock ETH_CLK of 125MHz from RCC is used */
val |= SYSCFG_ETHCR_ETH_CLK_SEL;
}
break;
default:
dev_err(dwmac->dev, "Mode %s not supported",
phy_modes(plat_dat->mac_interface));
/* Do not manage others interfaces */
return -EINVAL;
}
dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface));
/* Select PTP (IEEE1588) clock selection from RCC (ck_ker_ethxptp) */
val |= SYSCFG_ETHCR_ETH_PTP_CLK_SEL;
/* Update ETHCR (set register) */
return regmap_update_bits(dwmac->regmap, reg,
SYSCFG_MP2_ETH_MASK, val);
}
static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
{ {
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
int ret; int ret;
ret = stm32mp1_select_ethck_external(plat_dat); ret = stm32mp1_select_ethck_external(plat_dat);
...@@ -289,7 +347,10 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -289,7 +347,10 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
if (ret) if (ret)
return ret; return ret;
return stm32mp1_configure_pmcr(plat_dat); if (!dwmac->ops->is_mp2)
return stm32mp1_configure_pmcr(plat_dat);
else
return stm32mp2_configure_syscfg(plat_dat);
} }
static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
...@@ -365,6 +426,9 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, ...@@ -365,6 +426,9 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
return err; return err;
} }
if (dwmac->ops->is_mp2)
return 0;
dwmac->mode_mask = SYSCFG_MP1_ETH_MASK; dwmac->mode_mask = SYSCFG_MP1_ETH_MASK;
err = of_property_read_u32_index(np, "st,syscon", 2, &dwmac->mode_mask); err = of_property_read_u32_index(np, "st,syscon", 2, &dwmac->mode_mask);
if (err) { if (err) {
...@@ -586,10 +650,20 @@ static struct stm32_ops stm32mp13_dwmac_data = { ...@@ -586,10 +650,20 @@ static struct stm32_ops stm32mp13_dwmac_data = {
.clk_rx_enable_in_suspend = true .clk_rx_enable_in_suspend = true
}; };
static struct stm32_ops stm32mp25_dwmac_data = {
.set_mode = stm32mp1_set_mode,
.suspend = stm32mp1_suspend,
.resume = stm32mp1_resume,
.parse_data = stm32mp1_parse_data,
.is_mp2 = true,
.clk_rx_enable_in_suspend = true
};
static const struct of_device_id stm32_dwmac_match[] = { static const struct of_device_id stm32_dwmac_match[] = {
{ .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data}, { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data},
{ .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data}, { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data},
{ .compatible = "st,stm32mp13-dwmac", .data = &stm32mp13_dwmac_data}, { .compatible = "st,stm32mp13-dwmac", .data = &stm32mp13_dwmac_data},
{ .compatible = "st,stm32mp25-dwmac", .data = &stm32mp25_dwmac_data},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, stm32_dwmac_match); MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment