net: gmac_rockchip: Add support for the RK3399 GMAC
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>
Fri, 24 Mar 2017 18:24:26 +0000 (19:24 +0100)
committerSimon Glass <sjg@chromium.org>
Wed, 5 Apr 2017 02:01:57 +0000 (20:01 -0600)
The GMAC in the RK3399 is very similar to the RK3288 variant (i.e. it
is a Designware GMAC core and requires similar configuration as the
RK3288 to switch it to RGMII and set up the TX/RX delays for Gigabit).
The key difference is that the register offsets (within the GRF block)
and bit-offsets (within those registers) used to hold the configuration
differ between the various RK32/33 CPUs.

This change refactors the gmac_rockchip.c driver to use a function
table (selected via driver_data) to factor out these differences. Each
function's implementation then matches the underlying processor.

Some collateral changes are needed in the definitions describing the
bits and offsets in the GRF are needed to prefix each set of symbolic
constants with the SoC name to avoid name clashes... and in doing so,
the shifts for masks and constants have been moved into the header
files for readability (and to make it easier to stay below 80 chars).

X-AffectedPlatforms: RK3399-Q7
Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Tested-by: Klaus Goger <klaus.goger@theobroma-systems.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Acked-by: Simon Glass <sjg@chromium.org>
Fixed commit message typo s/factor our/factor out/:
Signed-off-by: Simon Glass <sjg@chromium.org>
arch/arm/include/asm/arch-rockchip/grf_rk3288.h
arch/arm/include/asm/arch-rockchip/grf_rk3399.h
drivers/net/gmac_rockchip.c

index aaffd19dea7071edf8d1026e2ece42069e3a3c6e..1a7c8199c3810ee9a8b5d86b689303afdbd36664 100644 (file)
@@ -720,20 +720,20 @@ enum {
 
 /* GRF_SOC_CON1 */
 enum {
-       RMII_MODE_SHIFT = 0xe,
-       RMII_MODE_MASK = 1,
-       RMII_MODE = 1,
+       RK3288_RMII_MODE_SHIFT = 14,
+       RK3288_RMII_MODE_MASK  = (1 << RK3288_RMII_MODE_SHIFT),
+       RK3288_RMII_MODE       = (1 << RK3288_RMII_MODE_SHIFT),
 
-       GMAC_CLK_SEL_SHIFT      = 0xc,
-       GMAC_CLK_SEL_MASK       = 3,
-       GMAC_CLK_SEL_125M       = 0,
-       GMAC_CLK_SEL_25M        = 0x3,
-       GMAC_CLK_SEL_2_5M       = 0x2,
+       RK3288_GMAC_CLK_SEL_SHIFT = 12,
+       RK3288_GMAC_CLK_SEL_MASK  = (3 << RK3288_GMAC_CLK_SEL_SHIFT),
+       RK3288_GMAC_CLK_SEL_125M  = (0 << RK3288_GMAC_CLK_SEL_SHIFT),
+       RK3288_GMAC_CLK_SEL_25M   = (3 << RK3288_GMAC_CLK_SEL_SHIFT),
+       RK3288_GMAC_CLK_SEL_2_5M  = (2 << RK3288_GMAC_CLK_SEL_SHIFT),
 
-       RMII_CLK_SEL_SHIFT      = 0xb,
-       RMII_CLK_SEL_MASK       = 1,
-       RMII_CLK_SEL_2_5M       = 0,
-       RMII_CLK_SEL_25M,
+       RK3288_RMII_CLK_SEL_SHIFT = 11,
+       RK3288_RMII_CLK_SEL_MASK  = (1 << RK3288_RMII_CLK_SEL_SHIFT),
+       RK3288_RMII_CLK_SEL_2_5M  = (0 << RK3288_RMII_CLK_SEL_SHIFT),
+       RK3288_RMII_CLK_SEL_25M   = (1 << RK3288_RMII_CLK_SEL_SHIFT),
 
        GMAC_SPEED_SHIFT        = 0xa,
        GMAC_SPEED_MASK         = 1,
@@ -743,10 +743,10 @@ enum {
        GMAC_FLOWCTRL_SHIFT     = 0x9,
        GMAC_FLOWCTRL_MASK      = 1,
 
-       GMAC_PHY_INTF_SEL_SHIFT = 0x6,
-       GMAC_PHY_INTF_SEL_MASK  = 0x7,
-       GMAC_PHY_INTF_SEL_RGMII = 0x1,
-       GMAC_PHY_INTF_SEL_RMII  = 0x4,
+       RK3288_GMAC_PHY_INTF_SEL_SHIFT = 6,
+       RK3288_GMAC_PHY_INTF_SEL_MASK  = (7 << RK3288_GMAC_PHY_INTF_SEL_SHIFT),
+       RK3288_GMAC_PHY_INTF_SEL_RGMII = (1 << RK3288_GMAC_PHY_INTF_SEL_SHIFT),
+       RK3288_GMAC_PHY_INTF_SEL_RMII  = (4 << RK3288_GMAC_PHY_INTF_SEL_SHIFT),
 
        HOST_REMAP_SHIFT        = 0x5,
        HOST_REMAP_MASK         = 1
@@ -801,21 +801,27 @@ enum {
 
 /* GRF_SOC_CON3 */
 enum {
-       RXCLK_DLY_ENA_GMAC_SHIFT        = 0xf,
-       RXCLK_DLY_ENA_GMAC_MASK         = 1,
-       RXCLK_DLY_ENA_GMAC_DISABLE      = 0,
-       RXCLK_DLY_ENA_GMAC_ENABLE,
-
-       TXCLK_DLY_ENA_GMAC_SHIFT        = 0xe,
-       TXCLK_DLY_ENA_GMAC_MASK         = 1,
-       TXCLK_DLY_ENA_GMAC_DISABLE      = 0,
-       TXCLK_DLY_ENA_GMAC_ENABLE,
-
-       CLK_RX_DL_CFG_GMAC_SHIFT        = 0x7,
-       CLK_RX_DL_CFG_GMAC_MASK         = 0x7f,
-
-       CLK_TX_DL_CFG_GMAC_SHIFT        = 0x0,
-       CLK_TX_DL_CFG_GMAC_MASK         = 0x7f,
+       RK3288_RXCLK_DLY_ENA_GMAC_SHIFT = 0xf,
+       RK3288_RXCLK_DLY_ENA_GMAC_MASK =
+               (1 << RK3288_RXCLK_DLY_ENA_GMAC_SHIFT),
+       RK3288_RXCLK_DLY_ENA_GMAC_DISABLE = 0,
+       RK3288_RXCLK_DLY_ENA_GMAC_ENABLE =
+               (1 << RK3288_RXCLK_DLY_ENA_GMAC_SHIFT),
+
+       RK3288_TXCLK_DLY_ENA_GMAC_SHIFT = 0xe,
+       RK3288_TXCLK_DLY_ENA_GMAC_MASK =
+               (1 << RK3288_TXCLK_DLY_ENA_GMAC_SHIFT),
+       RK3288_TXCLK_DLY_ENA_GMAC_DISABLE = 0,
+       RK3288_TXCLK_DLY_ENA_GMAC_ENABLE =
+               (1 << RK3288_RXCLK_DLY_ENA_GMAC_SHIFT),
+
+       RK3288_CLK_RX_DL_CFG_GMAC_SHIFT = 0x7,
+       RK3288_CLK_RX_DL_CFG_GMAC_MASK =
+               (0x7f << RK3288_CLK_RX_DL_CFG_GMAC_SHIFT),
+
+       RK3288_CLK_TX_DL_CFG_GMAC_SHIFT = 0x0,
+       RK3288_CLK_TX_DL_CFG_GMAC_MASK =
+               (0x7f << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT),
 };
 
 #endif
index e709fdaad20a2a74acc55d4a3408b5b3b2e2a4b4..b340b05e36e995871d164f8ce1c50bf4895d34fe 100644 (file)
@@ -144,7 +144,9 @@ struct rk3399_grf_regs {
        };
        u32 gpio4d_iomux;
        u32 reserved21[4];
-       u32 gpio2_p[3][4];
+       u32 gpio2_p[4];
+       u32 gpio3_p[4];
+       u32 gpio4_p[4];
        u32 reserved22[4];
        u32 gpio2_sr[3][4];
        u32 reserved23[4];
@@ -215,7 +217,9 @@ struct rk3399_pmugrf_regs {
        };
        u32 gpio1d_iomux;
        u32 reserved1[8];
-       u32 gpio0_p[2][4];
+       u32 gpio0_p[2];
+       u32 reserved2[2];
+       u32 gpio1_p[4];
        u32 reserved3[8];
        u32 gpio0a_e;
        u32 reserved4;
@@ -473,4 +477,43 @@ enum {
 
 };
 
+/* GRF_SOC_CON5 */
+enum {
+       RK3399_GMAC_PHY_INTF_SEL_SHIFT = 9,
+       RK3399_GMAC_PHY_INTF_SEL_MASK  = (7 << RK3399_GMAC_PHY_INTF_SEL_SHIFT),
+       RK3399_GMAC_PHY_INTF_SEL_RGMII = (1 << RK3399_GMAC_PHY_INTF_SEL_SHIFT),
+       RK3399_GMAC_PHY_INTF_SEL_RMII  = (4 << RK3399_GMAC_PHY_INTF_SEL_SHIFT),
+
+       RK3399_GMAC_CLK_SEL_SHIFT = 4,
+       RK3399_GMAC_CLK_SEL_MASK  = (3 << RK3399_GMAC_CLK_SEL_SHIFT),
+       RK3399_GMAC_CLK_SEL_125M  = (0 << RK3399_GMAC_CLK_SEL_SHIFT),
+       RK3399_GMAC_CLK_SEL_25M   = (3 << RK3399_GMAC_CLK_SEL_SHIFT),
+       RK3399_GMAC_CLK_SEL_2_5M  = (2 << RK3399_GMAC_CLK_SEL_SHIFT),
+};
+
+/* GRF_SOC_CON6 */
+enum {
+       RK3399_RXCLK_DLY_ENA_GMAC_SHIFT = 15,
+       RK3399_RXCLK_DLY_ENA_GMAC_MASK =
+               (1 << RK3399_RXCLK_DLY_ENA_GMAC_SHIFT),
+       RK3399_RXCLK_DLY_ENA_GMAC_DISABLE = 0,
+       RK3399_RXCLK_DLY_ENA_GMAC_ENABLE =
+               (1 << RK3399_RXCLK_DLY_ENA_GMAC_SHIFT),
+
+       RK3399_TXCLK_DLY_ENA_GMAC_SHIFT = 7,
+       RK3399_TXCLK_DLY_ENA_GMAC_MASK =
+               (1 << RK3399_TXCLK_DLY_ENA_GMAC_SHIFT),
+       RK3399_TXCLK_DLY_ENA_GMAC_DISABLE = 0,
+       RK3399_TXCLK_DLY_ENA_GMAC_ENABLE =
+               (1 << RK3399_TXCLK_DLY_ENA_GMAC_SHIFT),
+
+       RK3399_CLK_RX_DL_CFG_GMAC_SHIFT = 8,
+       RK3399_CLK_RX_DL_CFG_GMAC_MASK =
+               (0x7f << RK3399_CLK_RX_DL_CFG_GMAC_SHIFT),
+
+       RK3399_CLK_TX_DL_CFG_GMAC_SHIFT = 0,
+       RK3399_CLK_TX_DL_CFG_GMAC_MASK =
+               (0x7f << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT),
+};
+
 #endif /* __SOC_ROCKCHIP_RK3399_GRF_H__ */
index e9b202ab9ae81c26d48f8f943568fc84bf781ab6..5e2ca763027aa5b145265bd1c17c6d7d74873d9a 100644 (file)
@@ -14,7 +14,9 @@
 #include <asm/io.h>
 #include <asm/arch/periph.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
 #include <asm/arch/grf_rk3288.h>
+#include <asm/arch/grf_rk3399.h>
 #include <dm/pinctrl.h>
 #include <dt-bindings/clock/rk3288-cru.h>
 #include "designware.h"
@@ -32,32 +34,45 @@ struct gmac_rockchip_platdata {
        int rx_delay;
 };
 
+struct rk_gmac_ops {
+       int (*fix_mac_speed)(struct dw_eth_dev *priv);
+       void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata);
+};
+
+
 static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev)
 {
        struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+       const void *blob = gd->fdt_blob;
+       int node = dev_of_offset(dev);
+
+       /* Check the new naming-style first... */
+       pdata->tx_delay = fdtdec_get_int(blob, node, "tx_delay", -ENOENT);
+       pdata->rx_delay = fdtdec_get_int(blob, node, "rx_delay", -ENOENT);
 
-       pdata->tx_delay = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-                                        "tx-delay", 0x30);
-       pdata->rx_delay = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-                                        "rx-delay", 0x10);
+       /* ... and fall back to the old naming style or default, if necessary */
+       if (pdata->tx_delay == -ENOENT)
+               pdata->tx_delay = fdtdec_get_int(blob, node, "tx-delay", 0x30);
+       if (pdata->rx_delay == -ENOENT)
+               pdata->rx_delay = fdtdec_get_int(blob, node, "rx-delay", 0x10);
 
        return designware_eth_ofdata_to_platdata(dev);
 }
 
-static int gmac_rockchip_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 {
        struct rk3288_grf *grf;
        int clk;
 
        switch (priv->phydev->speed) {
        case 10:
-               clk = GMAC_CLK_SEL_2_5M;
+               clk = RK3288_GMAC_CLK_SEL_2_5M;
                break;
        case 100:
-               clk = GMAC_CLK_SEL_25M;
+               clk = RK3288_GMAC_CLK_SEL_25M;
                break;
        case 1000:
-               clk = GMAC_CLK_SEL_125M;
+               clk = RK3288_GMAC_CLK_SEL_125M;
                break;
        default:
                debug("Unknown phy speed: %d\n", priv->phydev->speed);
@@ -65,17 +80,83 @@ static int gmac_rockchip_fix_mac_speed(struct dw_eth_dev *priv)
        }
 
        grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
-       rk_clrsetreg(&grf->soc_con1,
-                    GMAC_CLK_SEL_MASK << GMAC_CLK_SEL_SHIFT,
-                    clk << GMAC_CLK_SEL_SHIFT);
+       rk_clrsetreg(&grf->soc_con1, RK3288_GMAC_CLK_SEL_MASK, clk);
+
+       return 0;
+}
+
+static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+{
+       struct rk3399_grf_regs *grf;
+       int clk;
+
+       switch (priv->phydev->speed) {
+       case 10:
+               clk = RK3399_GMAC_CLK_SEL_2_5M;
+               break;
+       case 100:
+               clk = RK3399_GMAC_CLK_SEL_25M;
+               break;
+       case 1000:
+               clk = RK3399_GMAC_CLK_SEL_125M;
+               break;
+       default:
+               debug("Unknown phy speed: %d\n", priv->phydev->speed);
+               return -EINVAL;
+       }
+
+       grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+       rk_clrsetreg(&grf->soc_con5, RK3399_GMAC_CLK_SEL_MASK, clk);
 
        return 0;
 }
 
+static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
+{
+       struct rk3288_grf *grf;
+
+       grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+       rk_clrsetreg(&grf->soc_con1,
+                    RK3288_RMII_MODE_MASK | RK3288_GMAC_PHY_INTF_SEL_MASK,
+                    RK3288_GMAC_PHY_INTF_SEL_RGMII);
+
+       rk_clrsetreg(&grf->soc_con3,
+                    RK3288_RXCLK_DLY_ENA_GMAC_MASK |
+                    RK3288_TXCLK_DLY_ENA_GMAC_MASK |
+                    RK3288_CLK_RX_DL_CFG_GMAC_MASK |
+                    RK3288_CLK_TX_DL_CFG_GMAC_MASK,
+                    RK3288_RXCLK_DLY_ENA_GMAC_ENABLE |
+                    RK3288_TXCLK_DLY_ENA_GMAC_ENABLE |
+                    pdata->rx_delay << RK3288_CLK_RX_DL_CFG_GMAC_SHIFT |
+                    pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT);
+}
+
+static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
+{
+       struct rk3399_grf_regs *grf;
+
+       grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+
+       rk_clrsetreg(&grf->soc_con5,
+                    RK3399_GMAC_PHY_INTF_SEL_MASK,
+                    RK3399_GMAC_PHY_INTF_SEL_RGMII);
+
+       rk_clrsetreg(&grf->soc_con6,
+                    RK3399_RXCLK_DLY_ENA_GMAC_MASK |
+                    RK3399_TXCLK_DLY_ENA_GMAC_MASK |
+                    RK3399_CLK_RX_DL_CFG_GMAC_MASK |
+                    RK3399_CLK_TX_DL_CFG_GMAC_MASK,
+                    RK3399_RXCLK_DLY_ENA_GMAC_ENABLE |
+                    RK3399_TXCLK_DLY_ENA_GMAC_ENABLE |
+                    pdata->rx_delay << RK3399_CLK_RX_DL_CFG_GMAC_SHIFT |
+                    pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT);
+}
+
 static int gmac_rockchip_probe(struct udevice *dev)
 {
        struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
-       struct rk3288_grf *grf;
+       struct rk_gmac_ops *ops =
+               (struct rk_gmac_ops *)dev_get_driver_data(dev);
        struct clk clk;
        int ret;
 
@@ -89,21 +170,7 @@ static int gmac_rockchip_probe(struct udevice *dev)
                return ret;
 
        /* Set to RGMII mode */
-       grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
-       rk_clrsetreg(&grf->soc_con1,
-                    RMII_MODE_MASK << RMII_MODE_SHIFT |
-                    GMAC_PHY_INTF_SEL_MASK << GMAC_PHY_INTF_SEL_SHIFT,
-                    GMAC_PHY_INTF_SEL_RGMII << GMAC_PHY_INTF_SEL_SHIFT);
-
-       rk_clrsetreg(&grf->soc_con3,
-                    RXCLK_DLY_ENA_GMAC_MASK <<  RXCLK_DLY_ENA_GMAC_SHIFT |
-                    TXCLK_DLY_ENA_GMAC_MASK <<  TXCLK_DLY_ENA_GMAC_SHIFT |
-                    CLK_RX_DL_CFG_GMAC_MASK <<  CLK_RX_DL_CFG_GMAC_SHIFT |
-                    CLK_TX_DL_CFG_GMAC_MASK <<  CLK_TX_DL_CFG_GMAC_SHIFT,
-                    RXCLK_DLY_ENA_GMAC_ENABLE << RXCLK_DLY_ENA_GMAC_SHIFT |
-                    TXCLK_DLY_ENA_GMAC_ENABLE << TXCLK_DLY_ENA_GMAC_SHIFT |
-                    pdata->rx_delay << CLK_RX_DL_CFG_GMAC_SHIFT |
-                    pdata->tx_delay << CLK_TX_DL_CFG_GMAC_SHIFT);
+       ops->set_to_rgmii(pdata);
 
        return designware_eth_probe(dev);
 }
@@ -112,12 +179,14 @@ static int gmac_rockchip_eth_start(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct dw_eth_dev *priv = dev_get_priv(dev);
+       struct rk_gmac_ops *ops =
+               (struct rk_gmac_ops *)dev_get_driver_data(dev);
        int ret;
 
        ret = designware_eth_init(priv, pdata->enetaddr);
        if (ret)
                return ret;
-       ret = gmac_rockchip_fix_mac_speed(priv);
+       ret = ops->fix_mac_speed(priv);
        if (ret)
                return ret;
        ret = designware_eth_enable(priv);
@@ -136,8 +205,21 @@ const struct eth_ops gmac_rockchip_eth_ops = {
        .write_hwaddr           = designware_eth_write_hwaddr,
 };
 
+const struct rk_gmac_ops rk3288_gmac_ops = {
+       .fix_mac_speed = rk3288_gmac_fix_mac_speed,
+       .set_to_rgmii = rk3288_gmac_set_to_rgmii,
+};
+
+const struct rk_gmac_ops rk3399_gmac_ops = {
+       .fix_mac_speed = rk3399_gmac_fix_mac_speed,
+       .set_to_rgmii = rk3399_gmac_set_to_rgmii,
+};
+
 static const struct udevice_id rockchip_gmac_ids[] = {
-       { .compatible = "rockchip,rk3288-gmac" },
+       { .compatible = "rockchip,rk3288-gmac",
+         .data = (ulong)&rk3288_gmac_ops },
+       { .compatible = "rockchip,rk3399-gmac",
+         .data = (ulong)&rk3399_gmac_ops },
        { }
 };