Hi, On Sun, Oct 01, 2023 at 07:17:20PM +0000, Jonas Karlman wrote: > Add rk_gmac_ops and other special handling that is needed for GMAC to > work on RK3588. > > rk_gmac_ops was ported from linux commits: > 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac support for rk3588") > 88619e77b33d ("net: stmmac: rk3588: Allow multiple gmac controller") > > Signed-off-by: Jonas Karlman <jo...@kwiboo.se> > Reviewed-by: Kever Yang <kever.y...@rock-chips.com> > --- > Cc: David Wu <david...@rock-chips.com> > Cc: Sebastian Reichel <sebastian.reic...@collabora.com> > Cc: Benjamin Gaignard <benjamin.gaign...@collabora.com> > ---
Looks like I've send my R-b to v1 while you were preparing v2. Since nothing changed this is still: Reviewed-by: Sebastian Reichel <sebastian.reic...@collabora.com> Greetings, -- Sebastian > v2: > - Collect r-b tag > > drivers/net/dwc_eth_qos.c | 4 + > drivers/net/dwc_eth_qos_rockchip.c | 182 ++++++++++++++++++++++++++++- > 2 files changed, 182 insertions(+), 4 deletions(-) > > diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c > index 9fb98a2c3c74..dc04416865dd 100644 > --- a/drivers/net/dwc_eth_qos.c > +++ b/drivers/net/dwc_eth_qos.c > @@ -1712,6 +1712,10 @@ static const struct udevice_id eqos_ids[] = { > .compatible = "rockchip,rk3568-gmac", > .data = (ulong)&eqos_rockchip_config > }, > + { > + .compatible = "rockchip,rk3588-gmac", > + .data = (ulong)&eqos_rockchip_config > + }, > #endif > #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM) > { > diff --git a/drivers/net/dwc_eth_qos_rockchip.c > b/drivers/net/dwc_eth_qos_rockchip.c > index 05edc098f50d..20fd3a25c3dd 100644 > --- a/drivers/net/dwc_eth_qos_rockchip.c > +++ b/drivers/net/dwc_eth_qos_rockchip.c > @@ -28,6 +28,7 @@ struct rk_gmac_ops { > int tx_delay, int rx_delay); > int (*set_to_rmii)(struct udevice *dev); > int (*set_gmac_speed)(struct udevice *dev); > + void (*set_clock_selection)(struct udevice *dev, bool enable); > u32 regs[3]; > }; > > @@ -35,7 +36,9 @@ struct rockchip_platform_data { > struct reset_ctl_bulk resets; > const struct rk_gmac_ops *ops; > int id; > + bool clock_input; > struct regmap *grf; > + struct regmap *php_grf; > }; > > #define HIWORD_UPDATE(val, mask, shift) \ > @@ -129,6 +132,137 @@ static int rk3568_set_gmac_speed(struct udevice *dev) > return 0; > } > > +/* sys_grf */ > +#define RK3588_GRF_GMAC_CON7 0x031c > +#define RK3588_GRF_GMAC_CON8 0x0320 > +#define RK3588_GRF_GMAC_CON9 0x0324 > + > +#define RK3588_GMAC_RXCLK_DLY_ENABLE(id) GRF_BIT(2 * (id) + 3) > +#define RK3588_GMAC_RXCLK_DLY_DISABLE(id) GRF_CLR_BIT(2 * (id) + 3) > +#define RK3588_GMAC_TXCLK_DLY_ENABLE(id) GRF_BIT(2 * (id) + 2) > +#define RK3588_GMAC_TXCLK_DLY_DISABLE(id) GRF_CLR_BIT(2 * (id) + 2) > + > +#define RK3588_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, > 0xFF, 8) > +#define RK3588_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, > 0xFF, 0) > + > +/* php_grf */ > +#define RK3588_GRF_GMAC_CON0 0x0008 > +#define RK3588_GRF_CLK_CON1 0x0070 > + > +#define RK3588_GMAC_PHY_INTF_SEL_RGMII(id) \ > + (GRF_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_CLR_BIT(5 + > (id) * 6)) > +#define RK3588_GMAC_PHY_INTF_SEL_RMII(id) \ > + (GRF_CLR_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_BIT(5 + > (id) * 6)) > + > +#define RK3588_GMAC_CLK_RMII_MODE(id) GRF_BIT(5 * (id)) > +#define RK3588_GMAC_CLK_RGMII_MODE(id) GRF_CLR_BIT(5 * (id)) > + > +#define RK3588_GMAC_CLK_SELET_CRU(id) GRF_BIT(5 * (id) + 4) > +#define RK3588_GMAC_CLK_SELET_IO(id) GRF_CLR_BIT(5 * (id) + 4) > + > +#define RK3588_GMAC_CLK_RMII_DIV2(id) GRF_BIT(5 * (id) + 2) > +#define RK3588_GMAC_CLK_RMII_DIV20(id) GRF_CLR_BIT(5 * (id) + > 2) > + > +#define RK3588_GMAC_CLK_RGMII_DIV1(id) \ > + (GRF_CLR_BIT(5 * (id) + 2) | GRF_CLR_BIT(5 * (id) + 3)) > +#define RK3588_GMAC_CLK_RGMII_DIV5(id) \ > + (GRF_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3)) > +#define RK3588_GMAC_CLK_RGMII_DIV50(id) \ > + (GRF_CLR_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3)) > + > +#define RK3588_GMAC_CLK_RMII_GATE(id) GRF_BIT(5 * (id) + 1) > +#define RK3588_GMAC_CLK_RMII_NOGATE(id) GRF_CLR_BIT(5 * (id) + > 1) > + > +static int rk3588_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 offset_con, id = data->id; > + > + offset_con = data->id == 1 ? RK3588_GRF_GMAC_CON9 : > + RK3588_GRF_GMAC_CON8; > + > + regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0, > + RK3588_GMAC_PHY_INTF_SEL_RGMII(id)); > + > + regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, > + RK3588_GMAC_CLK_RGMII_MODE(id)); > + > + regmap_write(data->grf, RK3588_GRF_GMAC_CON7, > + RK3588_GMAC_RXCLK_DLY_ENABLE(id) | > + RK3588_GMAC_TXCLK_DLY_ENABLE(id)); > + > + regmap_write(data->grf, offset_con, > + RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) | > + RK3588_GMAC_CLK_TX_DL_CFG(tx_delay)); > + > + return 0; > +} > + > +static int rk3588_set_to_rmii(struct udevice *dev) > +{ > + struct eth_pdata *pdata = dev_get_plat(dev); > + struct rockchip_platform_data *data = pdata->priv_pdata; > + > + regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0, > + RK3588_GMAC_PHY_INTF_SEL_RMII(data->id)); > + > + regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, > + RK3588_GMAC_CLK_RMII_MODE(data->id)); > + > + return 0; > +} > + > +static int rk3588_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 val = 0, id = data->id; > + > + switch (eqos->phy->speed) { > + case SPEED_10: > + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) > + val = RK3588_GMAC_CLK_RMII_DIV20(id); > + else > + val = RK3588_GMAC_CLK_RGMII_DIV50(id); > + break; > + case SPEED_100: > + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) > + val = RK3588_GMAC_CLK_RMII_DIV2(id); > + else > + val = RK3588_GMAC_CLK_RGMII_DIV5(id); > + break; > + case SPEED_1000: > + if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII) > + val = RK3588_GMAC_CLK_RGMII_DIV1(id); > + else > + return -EINVAL; > + break; > + default: > + return -EINVAL; > + } > + > + regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val); > + > + return 0; > +} > + > +static void rk3588_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 val = data->clock_input ? RK3588_GMAC_CLK_SELET_IO(data->id) : > + RK3588_GMAC_CLK_SELET_CRU(data->id); > + > + val |= enable ? RK3588_GMAC_CLK_RMII_NOGATE(data->id) : > + RK3588_GMAC_CLK_RMII_GATE(data->id); > + > + regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val); > +} > + > static const struct rk_gmac_ops rk_gmac_ops[] = { > { > .compatible = "rockchip,rk3568-gmac", > @@ -141,6 +275,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = { > 0x0, /* sentinel */ > }, > }, > + { > + .compatible = "rockchip,rk3588-gmac", > + .set_to_rgmii = rk3588_set_to_rgmii, > + .set_to_rmii = rk3588_set_to_rmii, > + .set_gmac_speed = rk3588_set_gmac_speed, > + .set_clock_selection = rk3588_set_clock_selection, > + .regs = { > + 0xfe1b0000, /* gmac0 */ > + 0xfe1c0000, /* gmac1 */ > + 0x0, /* sentinel */ > + }, > + }, > { } > }; > > @@ -162,6 +308,7 @@ static int eqos_probe_resources_rk(struct udevice *dev) > struct eqos_priv *eqos = dev_get_priv(dev); > struct eth_pdata *pdata = dev_get_plat(dev); > struct rockchip_platform_data *data; > + const char *clock_in_out; > int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE; > int ret; > > @@ -199,6 +346,16 @@ static int eqos_probe_resources_rk(struct udevice *dev) > goto err_free; > } > > + if (device_is_compatible(dev, "rockchip,rk3588-gmac")) { > + data->php_grf = > + syscon_regmap_lookup_by_phandle(dev, > "rockchip,php-grf"); > + if (IS_ERR(data->php_grf)) { > + dev_err(dev, "Missing rockchip,php-grf property\n"); > + ret = -EINVAL; > + goto err_free; > + } > + } > + > ret = reset_get_bulk(dev, &data->resets); > if (ret < 0) > goto err_free; > @@ -211,12 +368,20 @@ static int eqos_probe_resources_rk(struct udevice *dev) > goto err_release_resets; > } > > - ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx); > - if (ret) { > - dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret); > - goto err_free_clk_master_bus; > + if (device_is_compatible(dev, "rockchip,rk3568-gmac")) { > + ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx); > + if (ret) { > + dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: > %d", ret); > + goto err_free_clk_master_bus; > + } > } > > + clock_in_out = dev_read_string(dev, "clock_in_out"); > + if (clock_in_out && !strcmp(clock_in_out, "input")) > + data->clock_input = true; > + else > + data->clock_input = false; > + > /* snps,reset props are deprecated, do bare minimum to support them */ > if (dev_read_bool(dev, "snps,reset-active-low")) > reset_flags |= GPIOD_ACTIVE_LOW; > @@ -273,6 +438,12 @@ static int eqos_start_resets_rk(struct udevice *dev) > > static int eqos_stop_clks_rk(struct udevice *dev) > { > + struct eth_pdata *pdata = dev_get_plat(dev); > + struct rockchip_platform_data *data = pdata->priv_pdata; > + > + if (data->ops->set_clock_selection) > + data->ops->set_clock_selection(dev, false); > + > return 0; > } > > @@ -293,6 +464,9 @@ static int eqos_start_clks_rk(struct udevice *dev) > udelay(eqos->reset_delays[2]); > } > > + if (data->ops->set_clock_selection) > + data->ops->set_clock_selection(dev, true); > + > tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30); > rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10); > > -- > 2.42.0 >
signature.asc
Description: PGP signature