126 lines
4.5 KiB
Diff
126 lines
4.5 KiB
Diff
From 23c08dc4ff28b5ca1aa5ee745a5e9688561e8f6a Mon Sep 17 00:00:00 2001
|
|
From: Marek Vasut <marex@denx.de>
|
|
Date: Tue, 11 Jun 2024 10:36:00 +0200
|
|
Subject: [PATCH 3/8] net: stmmac: dwmac-stm32: Separate out external clock
|
|
rate validation
|
|
|
|
Pull the external clock frequency validation into a separate function,
|
|
to avoid conflating it with external clock DT property decoding and
|
|
clock mux register configuration. This should make the code easier to
|
|
read and understand.
|
|
|
|
This does change the code behavior slightly. The clock mux PMCR register
|
|
setting now depends solely on the DT properties which configure the clock
|
|
mux between external clock and internal RCC generated clock. The mux PMCR
|
|
register settings no longer depend on the supplied clock frequency, that
|
|
supplied clock frequency is now only validated, and if the clock frequency
|
|
is invalid for a mode, it is rejected.
|
|
|
|
Previously, the code would switch the PMCR register clock mux to internal
|
|
RCC generated clock if external clock couldn't provide suitable frequency,
|
|
without checking whether the RCC generated clock frequency is correct. Such
|
|
behavior is risky at best, user should have configured their clock correctly
|
|
in the first place, so this behavior is removed here.
|
|
|
|
Signed-off-by: Marek Vasut <marex@denx.de>
|
|
Signed-off-by: Christophe Roullier <christophe.roullier@foss.st.com>
|
|
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
---
|
|
.../net/ethernet/stmicro/stmmac/dwmac-stm32.c | 51 +++++++++++++++----
|
|
1 file changed, 41 insertions(+), 10 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
|
|
@@ -157,25 +157,54 @@ static int stm32_dwmac_init(struct plat_
|
|
return stm32_dwmac_clk_enable(dwmac, resume);
|
|
}
|
|
|
|
+static int stm32mp1_validate_ethck_rate(struct plat_stmmacenet_data *plat_dat)
|
|
+{
|
|
+ struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
|
|
+ const u32 clk_rate = clk_get_rate(dwmac->clk_eth_ck);
|
|
+
|
|
+ switch (plat_dat->mac_interface) {
|
|
+ case PHY_INTERFACE_MODE_MII:
|
|
+ case PHY_INTERFACE_MODE_GMII:
|
|
+ if (clk_rate == ETH_CK_F_25M)
|
|
+ return 0;
|
|
+ break;
|
|
+ case PHY_INTERFACE_MODE_RMII:
|
|
+ if (clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_50M)
|
|
+ return 0;
|
|
+ break;
|
|
+ case PHY_INTERFACE_MODE_RGMII:
|
|
+ case PHY_INTERFACE_MODE_RGMII_ID:
|
|
+ case PHY_INTERFACE_MODE_RGMII_RXID:
|
|
+ case PHY_INTERFACE_MODE_RGMII_TXID:
|
|
+ if (clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_125M)
|
|
+ return 0;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ dev_err(dwmac->dev, "Mode %s does not match eth-ck frequency %d Hz",
|
|
+ phy_modes(plat_dat->mac_interface), clk_rate);
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
|
|
{
|
|
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
|
|
- u32 reg = dwmac->mode_reg, clk_rate;
|
|
- int val;
|
|
+ u32 reg = dwmac->mode_reg;
|
|
+ int val, ret;
|
|
|
|
- clk_rate = clk_get_rate(dwmac->clk_eth_ck);
|
|
dwmac->enable_eth_ck = false;
|
|
switch (plat_dat->mac_interface) {
|
|
case PHY_INTERFACE_MODE_MII:
|
|
- if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk)
|
|
+ if (dwmac->ext_phyclk)
|
|
dwmac->enable_eth_ck = true;
|
|
val = SYSCFG_PMCR_ETH_SEL_MII;
|
|
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n");
|
|
break;
|
|
case PHY_INTERFACE_MODE_GMII:
|
|
val = SYSCFG_PMCR_ETH_SEL_GMII;
|
|
- if (clk_rate == ETH_CK_F_25M &&
|
|
- (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) {
|
|
+ if (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk) {
|
|
dwmac->enable_eth_ck = true;
|
|
val |= SYSCFG_PMCR_ETH_CLK_SEL;
|
|
}
|
|
@@ -183,8 +212,7 @@ static int stm32mp1_set_mode(struct plat
|
|
break;
|
|
case PHY_INTERFACE_MODE_RMII:
|
|
val = SYSCFG_PMCR_ETH_SEL_RMII;
|
|
- if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_50M) &&
|
|
- (dwmac->eth_ref_clk_sel_reg || dwmac->ext_phyclk)) {
|
|
+ if (dwmac->eth_ref_clk_sel_reg || dwmac->ext_phyclk) {
|
|
dwmac->enable_eth_ck = true;
|
|
val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
|
|
}
|
|
@@ -195,8 +223,7 @@ static int stm32mp1_set_mode(struct plat
|
|
case PHY_INTERFACE_MODE_RGMII_RXID:
|
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
|
val = SYSCFG_PMCR_ETH_SEL_RGMII;
|
|
- if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_125M) &&
|
|
- (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) {
|
|
+ if (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk) {
|
|
dwmac->enable_eth_ck = true;
|
|
val |= SYSCFG_PMCR_ETH_CLK_SEL;
|
|
}
|
|
@@ -209,6 +236,10 @@ static int stm32mp1_set_mode(struct plat
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ ret = stm32mp1_validate_ethck_rate(plat_dat);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
/* Need to update PMCCLRR (clear register) */
|
|
regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
|
|
dwmac->ops->syscfg_eth_mask);
|