lede/target/linux/rockchip/patches-6.12/306-ethernet-stmmac-dwmac-rk3528-add-GMAC-support.patch
2024-12-20 16:00:04 +08:00

228 lines
7.1 KiB
Diff

From 61c0ac431798861b0696ccc549138b2eec8a4766 Mon Sep 17 00:00:00 2001
From: David Wu <david.wu@rock-chips.com>
Date: Sat, 24 Sep 2022 18:29:52 +0800
Subject: [PATCH] ethernet: stmmac: dwmac-rk: Add GMAC support for RK3528
Add constants and callback functions for the dwmac on RK3528 Soc.
As can be seen, the base structure is the same. In addition, there
is an internal phy inside with Gmac0.
Signed-off-by: David Wu <david.wu@rock-chips.com>
Change-Id: I8a69a1239ed3ae91bfe44c96287210da758f9cf9
---
.../net/ethernet/stmicro/stmmac/dwmac-rk.c | 179 +++++++++++++++++-
1 file changed, 173 insertions(+), 6 deletions(-)
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1140,6 +1140,201 @@ static const struct rk_gmac_ops rk3399_o
.set_rmii_speed = rk3399_set_rmii_speed,
};
+#define RK3528_VO_GRF_GMAC_CON 0X60018
+#define RK3528_VPU_GRF_GMAC_CON5 0X40018
+#define RK3528_VPU_GRF_GMAC_CON6 0X4001c
+
+#define RK3528_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
+#define RK3528_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
+#define RK3528_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
+#define RK3528_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
+
+#define RK3528_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3528_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 0)
+
+#define RK3528_GMAC0_PHY_INTF_SEL_RMII GRF_BIT(1)
+#define RK3528_GMAC1_PHY_INTF_SEL_RGMII GRF_CLR_BIT(8)
+#define RK3528_GMAC1_PHY_INTF_SEL_RMII GRF_BIT(8)
+
+#define RK3528_GMAC1_CLK_SELET_CRU GRF_CLR_BIT(12)
+#define RK3528_GMAC1_CLK_SELET_IO GRF_BIT(12)
+
+#define RK3528_GMAC0_CLK_RMII_DIV2 GRF_BIT(3)
+#define RK3528_GMAC0_CLK_RMII_DIV20 GRF_CLR_BIT(3)
+#define RK3528_GMAC1_CLK_RMII_DIV2 GRF_BIT(10)
+#define RK3528_GMAC1_CLK_RMII_DIV20 GRF_CLR_BIT(10)
+
+#define RK3528_GMAC1_CLK_RGMII_DIV1 \
+ (GRF_CLR_BIT(11) | GRF_CLR_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV5 \
+ (GRF_BIT(11) | GRF_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV50 \
+ (GRF_BIT(11) | GRF_CLR_BIT(10))
+
+#define RK3528_GMAC0_CLK_RMII_GATE GRF_BIT(2)
+#define RK3528_GMAC0_CLK_RMII_NOGATE GRF_CLR_BIT(2)
+#define RK3528_GMAC1_CLK_RMII_GATE GRF_BIT(9)
+#define RK3528_GMAC1_CLK_RMII_NOGATE GRF_CLR_BIT(9)
+
+#define RK3528_VO_GRF_MACPHY_CON0 0X6001c
+#define RK3528_VO_GRF_MACPHY_CON1 0X60020
+
+static void rk3528_set_to_rgmii(struct rk_priv_data *bsp_priv,
+ int tx_delay, int rx_delay)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+
+ if (IS_ERR(bsp_priv->grf)) {
+ dev_err(dev, "Missing rockchip,grf property\n");
+ return;
+ }
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC1_PHY_INTF_SEL_RGMII);
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) |
+ RK3528_GMAC_CLK_TX_DL_CFG(tx_delay));
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON6,
+ RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) |
+ RK3528_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+ unsigned int id = bsp_priv->id;
+
+ if (IS_ERR(bsp_priv->grf)) {
+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+ return;
+ }
+
+ if (id == 1)
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC1_PHY_INTF_SEL_RMII);
+ else
+ regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON,
+ RK3528_GMAC0_PHY_INTF_SEL_RMII);
+}
+
+static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+ unsigned int val = 0;
+
+ switch (speed) {
+ case 10:
+ val = RK3528_GMAC1_CLK_RGMII_DIV50;
+ break;
+ case 100:
+ val = RK3528_GMAC1_CLK_RGMII_DIV5;
+ break;
+ case 1000:
+ val = RK3528_GMAC1_CLK_RGMII_DIV1;
+ break;
+ default:
+ goto err;
+ }
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, val);
+ return;
+err:
+ dev_err(dev, "unknown RGMII speed value for GMAC speed=%d", speed);
+}
+
+static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+ unsigned int val, offset, id = bsp_priv->id;
+
+ switch (speed) {
+ case 10:
+ val = (id == 1) ? RK3528_GMAC1_CLK_RMII_DIV20 :
+ RK3528_GMAC0_CLK_RMII_DIV20;
+ break;
+ case 100:
+ val = (id == 1) ? RK3528_GMAC1_CLK_RMII_DIV2 :
+ RK3528_GMAC0_CLK_RMII_DIV2;
+ break;
+ default:
+ goto err;
+ }
+
+ offset = (id == 1) ? RK3528_VPU_GRF_GMAC_CON5 : RK3528_VO_GRF_GMAC_CON;
+ regmap_write(bsp_priv->grf, offset, val);
+
+ return;
+err:
+ dev_err(dev, "unknown RMII speed value for GMAC speed=%d", speed);
+}
+
+static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
+ bool input, bool enable)
+{
+ unsigned int value, id = bsp_priv->id;
+
+ if (id == 1) {
+ value = input ? RK3528_GMAC1_CLK_SELET_IO :
+ RK3528_GMAC1_CLK_SELET_CRU;
+ value |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE :
+ RK3528_GMAC1_CLK_RMII_GATE;
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, value);
+ } else {
+ value = enable ? RK3528_GMAC0_CLK_RMII_NOGATE :
+ RK3528_GMAC0_CLK_RMII_GATE;
+ regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON, value);
+ }
+}
+
+/* Integrated FEPHY */
+#define RK_FEPHY_SHUTDOWN GRF_BIT(1)
+#define RK_FEPHY_POWERUP GRF_CLR_BIT(1)
+#define RK_FEPHY_INTERNAL_RMII_SEL GRF_BIT(6)
+#define RK_FEPHY_24M_CLK_SEL (GRF_BIT(8) | GRF_BIT(9))
+#define RK_FEPHY_PHY_ID GRF_BIT(11)
+
+#define RK_FEPHY_BGS HIWORD_UPDATE(0x0, 0xf, 0)
+
+static void rk3528_integrated_sphy_power(struct rk_priv_data *priv)
+{
+ struct device *dev = &priv->pdev->dev;
+
+ if (IS_ERR(priv->grf) || !priv->phy_reset) {
+ dev_err(dev, "%s: Missing rockchip,grf or phy_reset property\n",
+ __func__);
+ return;
+ }
+
+ unsigned int bgs = RK_FEPHY_BGS;
+
+ reset_control_assert(priv->phy_reset);
+ udelay(20);
+ regmap_write(priv->grf, RK3528_VO_GRF_MACPHY_CON0,
+ RK_FEPHY_POWERUP |
+ RK_FEPHY_INTERNAL_RMII_SEL |
+ RK_FEPHY_24M_CLK_SEL |
+ RK_FEPHY_PHY_ID);
+
+ /*if (priv->otp_data > 0)
+ bgs = HIWORD_UPDATE(priv->otp_data, 0xf, 0);*/
+
+ regmap_write(priv->grf, RK3528_VO_GRF_MACPHY_CON1, bgs);
+ usleep_range(10 * 1000, 12 * 1000);
+ reset_control_deassert(priv->phy_reset);
+ usleep_range(50 * 1000, 60 * 1000);
+}
+
+static const struct rk_gmac_ops rk3528_ops = {
+ .set_to_rgmii = rk3528_set_to_rgmii,
+ .set_to_rmii = rk3528_set_to_rmii,
+ .set_rgmii_speed = rk3528_set_rgmii_speed,
+ .set_rmii_speed = rk3528_set_rmii_speed,
+ .set_clock_selection = rk3528_set_clock_selection,
+ .integrated_phy_powerup = rk3528_integrated_sphy_power,
+};
+
#define RK3568_GRF_GMAC0_CON0 0x0380
#define RK3568_GRF_GMAC0_CON1 0x0384
#define RK3568_GRF_GMAC1_CON0 0x0388
@@ -2255,6 +2450,7 @@ static const struct of_device_id rk_gmac
{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
+ { .compatible = "rockchip,rk3528-gmac", .data = &rk3528_ops },
{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
{ .compatible = "rockchip,rk3576-gmac", .data = &rk3576_ops },
{ .compatible = "rockchip,rk3588-gmac", .data = &rk3588_ops },