From 1d4790c73189bb5faa12245f030a2c01d0c25ff6 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 22 Oct 2020 16:05:25 +0800 Subject: [PATCH] net: ethernet: stmicro: stmmac: dwmac-rk: Add RK3568 support Add constants and callback functions for the dwmac on RK3568 soc. As can be seen, the base structure is the same, only registers and the bits in them moved slightly. Because there are two gmac controllers at rk3568, use bus id to set the corresponding registers respectively. Signed-off-by: David Wu Change-Id: I26e8dbc172c7c14df230f531251e2cd23d78a787 --- .../bindings/net/rockchip-dwmac.txt | 1 + .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 101 ++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt index 44a163db9aa4..97a887f8821c 100644 --- a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt +++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt @@ -13,6 +13,7 @@ Required properties: "rockchip,rk3366-gmac": found on RK3366 SoCs "rockchip,rk3368-gmac": found on RK3368 SoCs "rockchip,rk3399-gmac": found on RK3399 SoCs + "rockchip,rk3568-gmac": found on RK3568 SoCs "rockchip,rv1108-gmac": found on RV1108 SoCs "rockchip,rv1126-gmac": found on RV1126 SoCs - reg: addresses and length of the register sets for the device. diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index b09fd0e89f0c..21b55049f236 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -39,6 +39,7 @@ struct rk_gmac_ops { struct rk_priv_data { struct platform_device *pdev; phy_interface_t phy_iface; + int bus_id; struct regulator *regulator; bool suspended; const struct rk_gmac_ops *ops; @@ -1130,6 +1131,104 @@ static const struct rk_gmac_ops rk3399_ops = { .set_rmii_speed = rk3399_set_rmii_speed, }; +#define RK3568_GRF_GMAC0_CON0 0X0380 +#define RK3568_GRF_GMAC0_CON1 0X0384 +#define RK3568_GRF_GMAC1_CON0 0X0388 +#define RK3568_GRF_GMAC1_CON1 0X038c + +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */ +#define RK3568_GMAC_PHY_INTF_SEL_RGMII \ + (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) +#define RK3568_GMAC_PHY_INTF_SEL_RMII \ + (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6)) +#define RK3568_GMAC_FLOW_CTRL GRF_BIT(3) +#define RK3568_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3) +#define RK3568_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1) +#define RK3568_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1) +#define RK3568_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0) +#define RK3568_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0) + +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */ +#define RK3568_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) +#define RK3568_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) + +static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv, + int tx_delay, int rx_delay) +{ + struct device *dev = &bsp_priv->pdev->dev; + u32 offset_con0, offset_con1; + + if (IS_ERR(bsp_priv->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return; + } + + offset_con0 = (bsp_priv->bus_id == 1) + ? RK3568_GRF_GMAC1_CON0 : RK3568_GRF_GMAC0_CON0; + offset_con1 = (bsp_priv->bus_id == 1) + ? RK3568_GRF_GMAC1_CON1 : RK3568_GRF_GMAC0_CON1; + + regmap_write(bsp_priv->grf, offset_con1, + RK3568_GMAC_PHY_INTF_SEL_RGMII | + RK3568_GMAC_RXCLK_DLY_ENABLE | + RK3568_GMAC_TXCLK_DLY_ENABLE); + + regmap_write(bsp_priv->grf, offset_con0, + RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) | + RK3568_GMAC_CLK_TX_DL_CFG(tx_delay)); +} + +static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv) +{ + struct device *dev = &bsp_priv->pdev->dev; + u32 offset_con1; + + if (IS_ERR(bsp_priv->grf)) { + dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); + return; + } + + offset_con1 = (bsp_priv->bus_id == 1) + ? RK3568_GRF_GMAC1_CON1 : RK3568_GRF_GMAC0_CON1; + + regmap_write(bsp_priv->grf, offset_con1, + RK3568_GMAC_PHY_INTF_SEL_RMII); +} + +static void rk3568_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) +{ + struct device *dev = &bsp_priv->pdev->dev; + unsigned long rate; + int ret; + + switch (speed) { + case 10: + rate = 2500000; + break; + case 100: + rate = 25000000; + break; + case 1000: + rate = 125000000; + break; + default: + dev_err(dev, "unknown speed value for GMAC speed=%d", speed); + return; + } + + ret = clk_set_rate(bsp_priv->clk_mac_speed, rate); + if (ret) + dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", + __func__, rate, ret); +} + +static const struct rk_gmac_ops rk3568_ops = { + .set_to_rgmii = rk3568_set_to_rgmii, + .set_to_rmii = rk3568_set_to_rmii, + .set_rgmii_speed = rk3568_set_gmac_speed, + .set_rmii_speed = rk3568_set_gmac_speed, +}; + #define RV1108_GRF_GMAC_CON0 0X0900 /* RV1108_GRF_GMAC_CON0 */ @@ -1535,6 +1634,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, of_get_phy_mode(dev->of_node, &bsp_priv->phy_iface); bsp_priv->ops = ops; + bsp_priv->bus_id = plat->bus_id; bsp_priv->regulator = devm_regulator_get_optional(dev, "phy"); if (IS_ERR(bsp_priv->regulator)) { @@ -1863,6 +1963,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = { { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops }, { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops }, + { .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops }, { .compatible = "rockchip,rv1108-gmac", .data = &rv1108_ops }, { .compatible = "rockchip,rv1126-gmac", .data = &rv1126_ops }, { }