
Add rk_gmac_ops and other special handling that is needed for GMAC to work on RK3576.
Signed-off-by: Heiko Stuebner heiko@sntech.de --- drivers/net/dwc_eth_qos.c | 4 + drivers/net/dwc_eth_qos_rockchip.c | 141 ++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 2279481d935..1a05d285576 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1615,6 +1615,10 @@ static const struct udevice_id eqos_ids[] = { .compatible = "rockchip,rk3568-gmac", .data = (ulong)&eqos_rockchip_config }, + { + .compatible = "rockchip,rk3576-gmac", + .data = (ulong)&eqos_rockchip_config + }, { .compatible = "rockchip,rk3588-gmac", .data = (ulong)&eqos_rockchip_config diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c index 9fc8c686b88..7115fe49bd5 100644 --- a/drivers/net/dwc_eth_qos_rockchip.c +++ b/drivers/net/dwc_eth_qos_rockchip.c @@ -131,6 +131,132 @@ static int rk3568_set_gmac_speed(struct udevice *dev) return 0; }
+#define RK3576_SDGMAC_GRF_GMAC0_CON 0x020 +#define RK3576_SDGMAC_GRF_GMAC1_CON 0x024 + +#define RK3576_GMAC_CLK_RMII_MODE GRF_BIT(3) +#define RK3576_GMAC_CLK_RGMII_MODE GRF_CLR_BIT(3) + +#define RK3576_GMAC_CLK_RMII_DIV2 GRF_BIT(5) +#define RK3576_GMAC_CLK_RMII_DIV20 GRF_CLR_BIT(5) +#define RK3576_GMAC_CLK_RGMII_DIV1 (GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) +#define RK3576_GMAC_CLK_RGMII_DIV5 (GRF_BIT(5) | GRF_BIT(6)) +#define RK3576_GMAC_CLK_RGMII_DIV50 (GRF_CLR_BIT(5) | GRF_BIT(6)) + +/* FIXME-check: in TRM swapped compared to rk3588 */ +#define RK3576_GMAC_CLK_SELECT_IO GRF_BIT(7) +#define RK3576_GMAC_CLK_SELECT_CRU GRF_CLR_BIT(7) + +#define RK3576_GMAC_CLK_GATE GRF_BIT(0) +#define RK3576_GMAC_CLK_NOGATE GRF_CLR_BIT(0) + +#define RK3576_IOC_GRF_MISC_CON2 0x6408 +#define RK3576_IOC_GRF_MISC_CON3 0x640c +#define RK3576_IOC_GRF_MISC_CON4 0x6410 +#define RK3576_IOC_GRF_MISC_CON5 0x6414 + +#define RK3576_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) +#define RK3576_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) +#define RK3576_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7f, 8) +#define RK3576_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) +#define RK3576_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) +#define RK3576_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7f, 0) + +static int rk3576_set_to_rgmii(struct udevice *dev, + int tx_delay, int rx_delay) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 delay_con_m0, delay_con_m1, con, val; + + con = (data->id == 1) ? RK3576_SDGMAC_GRF_GMAC1_CON : + RK3576_SDGMAC_GRF_GMAC0_CON; + regmap_write(data->grf, con, RK3576_GMAC_CLK_RGMII_MODE); + + delay_con_m0 = data->id ? RK3576_IOC_GRF_MISC_CON4 : + RK3576_IOC_GRF_MISC_CON2; + delay_con_m1 = data->id ? RK3576_IOC_GRF_MISC_CON5 : + RK3576_IOC_GRF_MISC_CON3; + + val = RK3576_GMAC_RXCLK_DLY_ENABLE | RK3576_GMAC_TXCLK_DLY_ENABLE; + val |= RK3576_GMAC_CLK_RX_DL_CFG(rx_delay); + val |= RK3576_GMAC_CLK_TX_DL_CFG(tx_delay); + + regmap_write(data->php_grf, delay_con_m0, val); + regmap_write(data->php_grf, delay_con_m1, val); + + return 0; +} + +static int rk3576_set_to_rmii(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 con; + + con = (data->id == 1) ? RK3576_SDGMAC_GRF_GMAC1_CON : + RK3576_SDGMAC_GRF_GMAC0_CON; + regmap_write(data->grf, con, RK3576_GMAC_CLK_RMII_MODE); + + return 0; +} + +static int rk3576_set_gmac_speed(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 con, val; + + con = (data->id == 1) ? RK3576_SDGMAC_GRF_GMAC1_CON : + RK3576_SDGMAC_GRF_GMAC0_CON; + + switch (eqos->phy->speed) { + case SPEED_10: + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RMII_DIV20; + else + val = RK3576_GMAC_CLK_RGMII_DIV50; + break; + case SPEED_100: + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RMII_DIV2; + else + val = RK3576_GMAC_CLK_RGMII_DIV5; + break; + case SPEED_1000: + if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RGMII_DIV1; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + regmap_write(data->grf, con, val); + + return 0; +} + +static void rk3576_set_clock_selection(struct udevice *dev, bool enable) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 con, val; + + con = (data->id == 1) ? RK3576_SDGMAC_GRF_GMAC1_CON : + RK3576_SDGMAC_GRF_GMAC0_CON; + + val = data->clock_input ? RK3576_GMAC_CLK_SELECT_IO : + RK3576_GMAC_CLK_SELECT_CRU; + + val |= enable ? RK3576_GMAC_CLK_NOGATE : + RK3576_GMAC_CLK_GATE; + + regmap_write(data->grf, con, val); +} + /* sys_grf */ #define RK3588_GRF_GMAC_CON7 0x031c #define RK3588_GRF_GMAC_CON8 0x0320 @@ -274,6 +400,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = { 0x0, /* sentinel */ }, }, + { + .compatible = "rockchip,rk3576-gmac", + .set_to_rgmii = rk3576_set_to_rgmii, + .set_to_rmii = rk3576_set_to_rmii, + .set_gmac_speed = rk3576_set_gmac_speed, + .set_clock_selection = rk3576_set_clock_selection, + .regs = { + 0x2a220000, /* gmac0 */ + 0x2a230000, /* gmac1 */ + 0x0, /* sentinel */ + }, + }, { .compatible = "rockchip,rk3588-gmac", .set_to_rgmii = rk3588_set_to_rgmii, @@ -351,7 +489,8 @@ static int eqos_probe_resources_rk(struct udevice *dev) goto err_free; }
- if (device_is_compatible(dev, "rockchip,rk3588-gmac")) { + if (device_is_compatible(dev, "rockchip,rk3588-gmac") || + device_is_compatible(dev, "rockchip,rk3576-gmac")) { data->php_grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,php-grf"); if (IS_ERR(data->php_grf)) {