Add rk_gmac_ops and other special handling that is needed for GMAC to
work on RK3576.

Signed-off-by: Heiko Stuebner <[email protected]>
---
 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)) {
-- 
2.45.2

Reply via email to