Re: [PATCH v2 2/2] ethernet: stmmac: dwmac-rk: Add GMAC support for RK3576
From: Detlev Casanova <detlev.casanova@collabora.com>
Date: 2024-08-09 14:37:47
Also in:
linux-devicetree, linux-rockchip, lkml
On Friday, 9 August 2024 09:16:44 EDT Heiko Stübner wrote:
Hi Detlev, Am Donnerstag, 8. August 2024, 19:00:18 CEST schrieb Detlev Casanova:quoted
From: David Wu <redacted> Add constants and callback functions for the dwmac on RK3576 soc. Signed-off-by: David Wu <redacted> [rebase, extracted bindings] Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com> --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+)diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.cb/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 7ae04d8d291c8..e1fa8fc9f4012 100644--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c@@ -1116,6 +1116,161 @@ static const struct rk_gmac_ops rk3568_ops = { }, };
[...]
quoted
+/* SDGMAC_GRF */ +#define RK3576_GRF_GMAC_CON0 0X0020 +#define RK3576_GRF_GMAC_CON1 0X0024 + +#define RK3576_GMAC_RMII_MODE GRF_BIT(3) +#define RK3576_GMAC_RGMII_MODE GRF_CLR_BIT(3) + +#define RK3576_GMAC_CLK_SELET_IO GRF_BIT(7) +#define RK3576_GMAC_CLK_SELET_CRU GRF_CLR_BIT(7)nit: typos _CLK_SELECT_ ... missing the C in select
Ack
quoted
+ +#define RK3576_GMAC_CLK_RMII_DIV2 GRF_BIT(5) +#define RK3576_GMAC_CLK_RMII_DIV20 GRF_CLR_BIT(5)I think those are backwards The TRM says bit[5]=0: 25MHz (DIV2) and bit[5]=1: 2.5MHz (DIV20) I guess nobody also on Rockchip's side tested a RMII phy on those controllrs
Can't be sure about that. An error in the TRM is not impossible either, as for rk3588, it is also bit[5]=0: DIV20 and bit[5]=1: DIV2. I can switch them to match the TRM though, we may never now.
quoted
+ +#define RK3576_GMAC_CLK_RGMII_DIV1 \ + (GRF_CLR_BIT(6) | GRF_CLR_BIT(5)) +#define RK3576_GMAC_CLK_RGMII_DIV5 \ + (GRF_BIT(6) | GRF_BIT(5)) +#define RK3576_GMAC_CLK_RGMII_DIV50 \ + (GRF_BIT(6) | GRF_CLR_BIT(5)) +in contrast, these are correct and match the TRMquoted
+#define RK3576_GMAC_CLK_RMII_GATE GRF_BIT(4) +#define RK3576_GMAC_CLK_RMII_NOGATE GRF_CLR_BIT(4) + +static void rk3576_set_to_rgmii(struct rk_priv_data *bsp_priv, + int tx_delay, int rx_delay) +{ + struct device *dev = &bsp_priv->pdev->dev; + unsigned int offset_con; + + if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) { + dev_err(dev, "Missing rockchip,grf or rockchip,php_grf
property\n");
quoted
+ return; + } + + offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(bsp_priv->grf, offset_con, RK3576_GMAC_RGMII_MODE); + + offset_con = bsp_priv->id == 1 ? RK3576_VCCIO0_1_3_IOC_CON4 : +
RK3576_VCCIO0_1_3_IOC_CON2;
quoted
+ + /* m0 && m1 delay enabled */ + regmap_write(bsp_priv->php_grf, offset_con, + DELAY_ENABLE(RK3576, tx_delay, rx_delay)); + regmap_write(bsp_priv->php_grf, offset_con + 0x4, + DELAY_ENABLE(RK3576, tx_delay, rx_delay)); + + /* m0 && m1 delay value */ + regmap_write(bsp_priv->php_grf, offset_con, + RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) | + RK3576_GMAC_CLK_RX_DL_CFG(rx_delay)); + regmap_write(bsp_priv->php_grf, offset_con + 0x4, + RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) | + RK3576_GMAC_CLK_RX_DL_CFG(rx_delay)); +} + +static void rk3576_set_to_rmii(struct rk_priv_data *bsp_priv) +{ + struct device *dev = &bsp_priv->pdev->dev; + unsigned int offset_con; + + if (IS_ERR(bsp_priv->php_grf)) { + dev_err(dev, "%s: Missing rockchip,php_grf property\n",
__func__);
quoted
+ return; + } + + offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(bsp_priv->grf, offset_con, RK3576_GMAC_RMII_MODE); +} + +static void rk3576_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) +{ + struct device *dev = &bsp_priv->pdev->dev; + unsigned int val = 0, offset_con; + + switch (speed) { + case 10: + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RMII_DIV20; + else + val = RK3576_GMAC_CLK_RGMII_DIV50;val = bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII ? RK3576_GMAC_CLK_RMII_DIV20 : RK3576_GMAC_CLK_RGMII_DIV50; perhaps?
This way matches how it is written in rk3588_set_gmac_speed(). I find that having similar code for similar functions helps reading and understanding it better (although I agree that your suggestion looks better). I'd rather keep it like it is for now if that's ok.
quoted
+ break; + case 100: + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RMII_DIV2; + else + val = RK3576_GMAC_CLK_RGMII_DIV5;same as above?quoted
+ break; + case 1000: + if (bsp_priv->phy_iface != PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RGMII_DIV1; + else + goto err;if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) goto err; val = RK3576_GMAC_CLK_RGMII_DIV1;quoted
+ break; + default: + goto err; + } + + offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(bsp_priv->grf, offset_con, val); + + return; +err: + dev_err(dev, "unknown speed value for GMAC speed=%d", speed); +} + +static void rk3576_set_clock_selection(struct rk_priv_data *bsp_priv, bool input, + bool enable) +{ + unsigned int val = input ? RK3576_GMAC_CLK_SELET_IO : + RK3576_GMAC_CLK_SELET_CRU; + unsigned int offset_con; + + val |= enable ? RK3576_GMAC_CLK_RMII_NOGATE : + RK3576_GMAC_CLK_RMII_GATE; + + offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0;nit: alignment of both looks like it could be nicer
That's strange, the alignments looks good in vim and git diff. It also looks nice on the archive: https://lore.kernel.org/linux-rockchip/ 20240808170113.82775-3-detlev.casanova@collabora.com/ Regards, Detlev