10125bcf0SSjoerd Simons /* 20125bcf0SSjoerd Simons * (C) Copyright 2015 Sjoerd Simons <sjoerd.simons@collabora.co.uk> 30125bcf0SSjoerd Simons * 40125bcf0SSjoerd Simons * SPDX-License-Identifier: GPL-2.0+ 50125bcf0SSjoerd Simons * 60125bcf0SSjoerd Simons * Rockchip GMAC ethernet IP driver for U-Boot 70125bcf0SSjoerd Simons */ 80125bcf0SSjoerd Simons 90125bcf0SSjoerd Simons #include <common.h> 100125bcf0SSjoerd Simons #include <dm.h> 110125bcf0SSjoerd Simons #include <clk.h> 120125bcf0SSjoerd Simons #include <phy.h> 130125bcf0SSjoerd Simons #include <syscon.h> 140125bcf0SSjoerd Simons #include <asm/io.h> 150125bcf0SSjoerd Simons #include <asm/arch/periph.h> 160125bcf0SSjoerd Simons #include <asm/arch/clock.h> 171f08aa1cSPhilipp Tomsich #include <asm/arch/hardware.h> 18af166ffaSDavid Wu #include <asm/arch/grf_rk322x.h> 190125bcf0SSjoerd Simons #include <asm/arch/grf_rk3288.h> 20c36b26c0SDavid Wu #include <asm/arch/grf_rk3328.h> 21793f2fd2SPhilipp Tomsich #include <asm/arch/grf_rk3368.h> 221f08aa1cSPhilipp Tomsich #include <asm/arch/grf_rk3399.h> 230a33ce65SDavid Wu #include <asm/arch/grf_rv1108.h> 240125bcf0SSjoerd Simons #include <dm/pinctrl.h> 250125bcf0SSjoerd Simons #include <dt-bindings/clock/rk3288-cru.h> 260125bcf0SSjoerd Simons #include "designware.h" 270125bcf0SSjoerd Simons 280125bcf0SSjoerd Simons DECLARE_GLOBAL_DATA_PTR; 290125bcf0SSjoerd Simons 300125bcf0SSjoerd Simons /* 310125bcf0SSjoerd Simons * Platform data for the gmac 320125bcf0SSjoerd Simons * 330125bcf0SSjoerd Simons * dw_eth_pdata: Required platform data for designware driver (must be first) 340125bcf0SSjoerd Simons */ 350125bcf0SSjoerd Simons struct gmac_rockchip_platdata { 360125bcf0SSjoerd Simons struct dw_eth_pdata dw_eth_pdata; 370a33ce65SDavid Wu bool clock_input; 380125bcf0SSjoerd Simons int tx_delay; 390125bcf0SSjoerd Simons int rx_delay; 400125bcf0SSjoerd Simons }; 410125bcf0SSjoerd Simons 421f08aa1cSPhilipp Tomsich struct rk_gmac_ops { 431f08aa1cSPhilipp Tomsich int (*fix_mac_speed)(struct dw_eth_dev *priv); 440a33ce65SDavid Wu void (*set_to_rmii)(struct gmac_rockchip_platdata *pdata); 451f08aa1cSPhilipp Tomsich void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata); 461f08aa1cSPhilipp Tomsich }; 471f08aa1cSPhilipp Tomsich 481eb9d064SDavid Wu void gmac_set_rgmii(struct udevice *dev, u32 tx_delay, u32 rx_delay) 491eb9d064SDavid Wu { 501eb9d064SDavid Wu struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); 511eb9d064SDavid Wu struct rk_gmac_ops *ops = 521eb9d064SDavid Wu (struct rk_gmac_ops *)dev_get_driver_data(dev); 531eb9d064SDavid Wu 541eb9d064SDavid Wu pdata->tx_delay = tx_delay; 551eb9d064SDavid Wu pdata->rx_delay = rx_delay; 561eb9d064SDavid Wu 571eb9d064SDavid Wu ops->set_to_rgmii(pdata); 581eb9d064SDavid Wu } 591f08aa1cSPhilipp Tomsich 600125bcf0SSjoerd Simons static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev) 610125bcf0SSjoerd Simons { 620125bcf0SSjoerd Simons struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); 630a33ce65SDavid Wu const char *string; 640a33ce65SDavid Wu 650a33ce65SDavid Wu string = dev_read_string(dev, "clock_in_out"); 660a33ce65SDavid Wu if (!strcmp(string, "input")) 670a33ce65SDavid Wu pdata->clock_input = true; 680a33ce65SDavid Wu else 690a33ce65SDavid Wu pdata->clock_input = false; 700125bcf0SSjoerd Simons 711f08aa1cSPhilipp Tomsich /* Check the new naming-style first... */ 727ad326a9SPhilipp Tomsich pdata->tx_delay = dev_read_u32_default(dev, "tx_delay", -ENOENT); 737ad326a9SPhilipp Tomsich pdata->rx_delay = dev_read_u32_default(dev, "rx_delay", -ENOENT); 741f08aa1cSPhilipp Tomsich 751f08aa1cSPhilipp Tomsich /* ... and fall back to the old naming style or default, if necessary */ 761f08aa1cSPhilipp Tomsich if (pdata->tx_delay == -ENOENT) 777ad326a9SPhilipp Tomsich pdata->tx_delay = dev_read_u32_default(dev, "tx-delay", 0x30); 781f08aa1cSPhilipp Tomsich if (pdata->rx_delay == -ENOENT) 797ad326a9SPhilipp Tomsich pdata->rx_delay = dev_read_u32_default(dev, "rx-delay", 0x10); 800125bcf0SSjoerd Simons 810125bcf0SSjoerd Simons return designware_eth_ofdata_to_platdata(dev); 820125bcf0SSjoerd Simons } 830125bcf0SSjoerd Simons 84af166ffaSDavid Wu static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv) 85af166ffaSDavid Wu { 86af166ffaSDavid Wu struct rk322x_grf *grf; 87af166ffaSDavid Wu int clk; 88af166ffaSDavid Wu enum { 89af166ffaSDavid Wu RK3228_GMAC_CLK_SEL_SHIFT = 8, 90af166ffaSDavid Wu RK3228_GMAC_CLK_SEL_MASK = GENMASK(9, 8), 91af166ffaSDavid Wu RK3228_GMAC_CLK_SEL_125M = 0 << 8, 92af166ffaSDavid Wu RK3228_GMAC_CLK_SEL_25M = 3 << 8, 93af166ffaSDavid Wu RK3228_GMAC_CLK_SEL_2_5M = 2 << 8, 94af166ffaSDavid Wu }; 95af166ffaSDavid Wu 96af166ffaSDavid Wu switch (priv->phydev->speed) { 97af166ffaSDavid Wu case 10: 98af166ffaSDavid Wu clk = RK3228_GMAC_CLK_SEL_2_5M; 99af166ffaSDavid Wu break; 100af166ffaSDavid Wu case 100: 101af166ffaSDavid Wu clk = RK3228_GMAC_CLK_SEL_25M; 102af166ffaSDavid Wu break; 103af166ffaSDavid Wu case 1000: 104af166ffaSDavid Wu clk = RK3228_GMAC_CLK_SEL_125M; 105af166ffaSDavid Wu break; 106af166ffaSDavid Wu default: 107af166ffaSDavid Wu debug("Unknown phy speed: %d\n", priv->phydev->speed); 108af166ffaSDavid Wu return -EINVAL; 109af166ffaSDavid Wu } 110af166ffaSDavid Wu 111af166ffaSDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 112af166ffaSDavid Wu rk_clrsetreg(&grf->mac_con[1], RK3228_GMAC_CLK_SEL_MASK, clk); 113af166ffaSDavid Wu 114af166ffaSDavid Wu return 0; 115af166ffaSDavid Wu } 116af166ffaSDavid Wu 1171f08aa1cSPhilipp Tomsich static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) 1180125bcf0SSjoerd Simons { 1190125bcf0SSjoerd Simons struct rk3288_grf *grf; 1200125bcf0SSjoerd Simons int clk; 1210125bcf0SSjoerd Simons 1220125bcf0SSjoerd Simons switch (priv->phydev->speed) { 1230125bcf0SSjoerd Simons case 10: 1241f08aa1cSPhilipp Tomsich clk = RK3288_GMAC_CLK_SEL_2_5M; 1250125bcf0SSjoerd Simons break; 1260125bcf0SSjoerd Simons case 100: 1271f08aa1cSPhilipp Tomsich clk = RK3288_GMAC_CLK_SEL_25M; 1280125bcf0SSjoerd Simons break; 1290125bcf0SSjoerd Simons case 1000: 1301f08aa1cSPhilipp Tomsich clk = RK3288_GMAC_CLK_SEL_125M; 1310125bcf0SSjoerd Simons break; 1320125bcf0SSjoerd Simons default: 1330125bcf0SSjoerd Simons debug("Unknown phy speed: %d\n", priv->phydev->speed); 1340125bcf0SSjoerd Simons return -EINVAL; 1350125bcf0SSjoerd Simons } 1360125bcf0SSjoerd Simons 1370125bcf0SSjoerd Simons grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1381f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con1, RK3288_GMAC_CLK_SEL_MASK, clk); 1390125bcf0SSjoerd Simons 1400125bcf0SSjoerd Simons return 0; 1410125bcf0SSjoerd Simons } 1420125bcf0SSjoerd Simons 143c36b26c0SDavid Wu static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv) 144c36b26c0SDavid Wu { 145c36b26c0SDavid Wu struct rk3328_grf_regs *grf; 146c36b26c0SDavid Wu int clk; 147c36b26c0SDavid Wu enum { 148c36b26c0SDavid Wu RK3328_GMAC_CLK_SEL_SHIFT = 11, 149c36b26c0SDavid Wu RK3328_GMAC_CLK_SEL_MASK = GENMASK(12, 11), 150c36b26c0SDavid Wu RK3328_GMAC_CLK_SEL_125M = 0 << 11, 151c36b26c0SDavid Wu RK3328_GMAC_CLK_SEL_25M = 3 << 11, 152c36b26c0SDavid Wu RK3328_GMAC_CLK_SEL_2_5M = 2 << 11, 153c36b26c0SDavid Wu }; 154c36b26c0SDavid Wu 155c36b26c0SDavid Wu switch (priv->phydev->speed) { 156c36b26c0SDavid Wu case 10: 157c36b26c0SDavid Wu clk = RK3328_GMAC_CLK_SEL_2_5M; 158c36b26c0SDavid Wu break; 159c36b26c0SDavid Wu case 100: 160c36b26c0SDavid Wu clk = RK3328_GMAC_CLK_SEL_25M; 161c36b26c0SDavid Wu break; 162c36b26c0SDavid Wu case 1000: 163c36b26c0SDavid Wu clk = RK3328_GMAC_CLK_SEL_125M; 164c36b26c0SDavid Wu break; 165c36b26c0SDavid Wu default: 166c36b26c0SDavid Wu debug("Unknown phy speed: %d\n", priv->phydev->speed); 167c36b26c0SDavid Wu return -EINVAL; 168c36b26c0SDavid Wu } 169c36b26c0SDavid Wu 170c36b26c0SDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 171c36b26c0SDavid Wu rk_clrsetreg(&grf->mac_con[1], RK3328_GMAC_CLK_SEL_MASK, clk); 172c36b26c0SDavid Wu 173c36b26c0SDavid Wu return 0; 174c36b26c0SDavid Wu } 175c36b26c0SDavid Wu 176793f2fd2SPhilipp Tomsich static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv) 177793f2fd2SPhilipp Tomsich { 178793f2fd2SPhilipp Tomsich struct rk3368_grf *grf; 179793f2fd2SPhilipp Tomsich int clk; 180793f2fd2SPhilipp Tomsich enum { 181793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_2_5M = 2 << 4, 182793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_25M = 3 << 4, 183793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_125M = 0 << 4, 184793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_MASK = GENMASK(5, 4), 185793f2fd2SPhilipp Tomsich }; 186793f2fd2SPhilipp Tomsich 187793f2fd2SPhilipp Tomsich switch (priv->phydev->speed) { 188793f2fd2SPhilipp Tomsich case 10: 189793f2fd2SPhilipp Tomsich clk = RK3368_GMAC_CLK_SEL_2_5M; 190793f2fd2SPhilipp Tomsich break; 191793f2fd2SPhilipp Tomsich case 100: 192793f2fd2SPhilipp Tomsich clk = RK3368_GMAC_CLK_SEL_25M; 193793f2fd2SPhilipp Tomsich break; 194793f2fd2SPhilipp Tomsich case 1000: 195793f2fd2SPhilipp Tomsich clk = RK3368_GMAC_CLK_SEL_125M; 196793f2fd2SPhilipp Tomsich break; 197793f2fd2SPhilipp Tomsich default: 198793f2fd2SPhilipp Tomsich debug("Unknown phy speed: %d\n", priv->phydev->speed); 199793f2fd2SPhilipp Tomsich return -EINVAL; 200793f2fd2SPhilipp Tomsich } 201793f2fd2SPhilipp Tomsich 202793f2fd2SPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 203793f2fd2SPhilipp Tomsich rk_clrsetreg(&grf->soc_con15, RK3368_GMAC_CLK_SEL_MASK, clk); 204793f2fd2SPhilipp Tomsich 205793f2fd2SPhilipp Tomsich return 0; 206793f2fd2SPhilipp Tomsich } 207793f2fd2SPhilipp Tomsich 2081f08aa1cSPhilipp Tomsich static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv) 2091f08aa1cSPhilipp Tomsich { 2101f08aa1cSPhilipp Tomsich struct rk3399_grf_regs *grf; 2111f08aa1cSPhilipp Tomsich int clk; 2121f08aa1cSPhilipp Tomsich 2131f08aa1cSPhilipp Tomsich switch (priv->phydev->speed) { 2141f08aa1cSPhilipp Tomsich case 10: 2151f08aa1cSPhilipp Tomsich clk = RK3399_GMAC_CLK_SEL_2_5M; 2161f08aa1cSPhilipp Tomsich break; 2171f08aa1cSPhilipp Tomsich case 100: 2181f08aa1cSPhilipp Tomsich clk = RK3399_GMAC_CLK_SEL_25M; 2191f08aa1cSPhilipp Tomsich break; 2201f08aa1cSPhilipp Tomsich case 1000: 2211f08aa1cSPhilipp Tomsich clk = RK3399_GMAC_CLK_SEL_125M; 2221f08aa1cSPhilipp Tomsich break; 2231f08aa1cSPhilipp Tomsich default: 2241f08aa1cSPhilipp Tomsich debug("Unknown phy speed: %d\n", priv->phydev->speed); 2251f08aa1cSPhilipp Tomsich return -EINVAL; 2261f08aa1cSPhilipp Tomsich } 2271f08aa1cSPhilipp Tomsich 2281f08aa1cSPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2291f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con5, RK3399_GMAC_CLK_SEL_MASK, clk); 2301f08aa1cSPhilipp Tomsich 2311f08aa1cSPhilipp Tomsich return 0; 2321f08aa1cSPhilipp Tomsich } 2331f08aa1cSPhilipp Tomsich 2340a33ce65SDavid Wu static int rv1108_set_rmii_speed(struct dw_eth_dev *priv) 2350a33ce65SDavid Wu { 2360a33ce65SDavid Wu struct rv1108_grf *grf; 2370a33ce65SDavid Wu int clk, speed; 2380a33ce65SDavid Wu enum { 2390a33ce65SDavid Wu RV1108_GMAC_SPEED_MASK = BIT(2), 2400a33ce65SDavid Wu RV1108_GMAC_SPEED_10M = 0 << 2, 2410a33ce65SDavid Wu RV1108_GMAC_SPEED_100M = 1 << 2, 2420a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_MASK = BIT(7), 2430a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_2_5M = 0 << 7, 2440a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_25M = 1 << 7, 2450a33ce65SDavid Wu }; 2460a33ce65SDavid Wu 2470a33ce65SDavid Wu switch (priv->phydev->speed) { 2480a33ce65SDavid Wu case 10: 2490a33ce65SDavid Wu clk = RV1108_GMAC_CLK_SEL_2_5M; 2500a33ce65SDavid Wu speed = RV1108_GMAC_SPEED_10M; 2510a33ce65SDavid Wu break; 2520a33ce65SDavid Wu case 100: 2530a33ce65SDavid Wu clk = RV1108_GMAC_CLK_SEL_25M; 2540a33ce65SDavid Wu speed = RV1108_GMAC_SPEED_100M; 2550a33ce65SDavid Wu break; 2560a33ce65SDavid Wu default: 2570a33ce65SDavid Wu debug("Unknown phy speed: %d\n", priv->phydev->speed); 2580a33ce65SDavid Wu return -EINVAL; 2590a33ce65SDavid Wu } 2600a33ce65SDavid Wu 2610a33ce65SDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2620a33ce65SDavid Wu rk_clrsetreg(&grf->gmac_con0, 2630a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_MASK | RV1108_GMAC_SPEED_MASK, 2640a33ce65SDavid Wu clk | speed); 2650a33ce65SDavid Wu 2660a33ce65SDavid Wu return 0; 2670a33ce65SDavid Wu } 2680a33ce65SDavid Wu 269af166ffaSDavid Wu static void rk3228_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 270af166ffaSDavid Wu { 271af166ffaSDavid Wu struct rk322x_grf *grf; 272af166ffaSDavid Wu enum { 273af166ffaSDavid Wu RK3228_RMII_MODE_SHIFT = 10, 274af166ffaSDavid Wu RK3228_RMII_MODE_MASK = BIT(10), 275af166ffaSDavid Wu 276af166ffaSDavid Wu RK3228_GMAC_PHY_INTF_SEL_SHIFT = 4, 277af166ffaSDavid Wu RK3228_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), 278af166ffaSDavid Wu RK3228_GMAC_PHY_INTF_SEL_RGMII = BIT(4), 279af166ffaSDavid Wu 280af166ffaSDavid Wu RK3228_RXCLK_DLY_ENA_GMAC_MASK = BIT(1), 281af166ffaSDavid Wu RK3228_RXCLK_DLY_ENA_GMAC_DISABLE = 0, 282af166ffaSDavid Wu RK3228_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(1), 283af166ffaSDavid Wu 284af166ffaSDavid Wu RK3228_TXCLK_DLY_ENA_GMAC_MASK = BIT(0), 285af166ffaSDavid Wu RK3228_TXCLK_DLY_ENA_GMAC_DISABLE = 0, 286af166ffaSDavid Wu RK3228_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(0), 287af166ffaSDavid Wu }; 288af166ffaSDavid Wu enum { 289af166ffaSDavid Wu RK3228_CLK_RX_DL_CFG_GMAC_SHIFT = 0x7, 290af166ffaSDavid Wu RK3228_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(13, 7), 291af166ffaSDavid Wu 292af166ffaSDavid Wu RK3228_CLK_TX_DL_CFG_GMAC_SHIFT = 0x0, 293af166ffaSDavid Wu RK3228_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), 294af166ffaSDavid Wu }; 295af166ffaSDavid Wu 296af166ffaSDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 297af166ffaSDavid Wu rk_clrsetreg(&grf->mac_con[1], 298af166ffaSDavid Wu RK3228_RMII_MODE_MASK | 299af166ffaSDavid Wu RK3228_GMAC_PHY_INTF_SEL_MASK | 300af166ffaSDavid Wu RK3228_RXCLK_DLY_ENA_GMAC_MASK | 301af166ffaSDavid Wu RK3228_TXCLK_DLY_ENA_GMAC_MASK, 302af166ffaSDavid Wu RK3228_GMAC_PHY_INTF_SEL_RGMII | 303af166ffaSDavid Wu RK3228_RXCLK_DLY_ENA_GMAC_ENABLE | 304af166ffaSDavid Wu RK3228_TXCLK_DLY_ENA_GMAC_ENABLE); 305af166ffaSDavid Wu 306af166ffaSDavid Wu rk_clrsetreg(&grf->mac_con[0], 307af166ffaSDavid Wu RK3228_CLK_RX_DL_CFG_GMAC_MASK | 308af166ffaSDavid Wu RK3228_CLK_TX_DL_CFG_GMAC_MASK, 309af166ffaSDavid Wu pdata->rx_delay << RK3228_CLK_RX_DL_CFG_GMAC_SHIFT | 310af166ffaSDavid Wu pdata->tx_delay << RK3228_CLK_TX_DL_CFG_GMAC_SHIFT); 311af166ffaSDavid Wu } 312af166ffaSDavid Wu 3131f08aa1cSPhilipp Tomsich static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 3141f08aa1cSPhilipp Tomsich { 3151f08aa1cSPhilipp Tomsich struct rk3288_grf *grf; 3161f08aa1cSPhilipp Tomsich 3171f08aa1cSPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 3181f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con1, 3191f08aa1cSPhilipp Tomsich RK3288_RMII_MODE_MASK | RK3288_GMAC_PHY_INTF_SEL_MASK, 3201f08aa1cSPhilipp Tomsich RK3288_GMAC_PHY_INTF_SEL_RGMII); 3211f08aa1cSPhilipp Tomsich 3221f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con3, 3231f08aa1cSPhilipp Tomsich RK3288_RXCLK_DLY_ENA_GMAC_MASK | 3241f08aa1cSPhilipp Tomsich RK3288_TXCLK_DLY_ENA_GMAC_MASK | 3251f08aa1cSPhilipp Tomsich RK3288_CLK_RX_DL_CFG_GMAC_MASK | 3261f08aa1cSPhilipp Tomsich RK3288_CLK_TX_DL_CFG_GMAC_MASK, 3271f08aa1cSPhilipp Tomsich RK3288_RXCLK_DLY_ENA_GMAC_ENABLE | 3281f08aa1cSPhilipp Tomsich RK3288_TXCLK_DLY_ENA_GMAC_ENABLE | 3291f08aa1cSPhilipp Tomsich pdata->rx_delay << RK3288_CLK_RX_DL_CFG_GMAC_SHIFT | 3301f08aa1cSPhilipp Tomsich pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT); 3311f08aa1cSPhilipp Tomsich } 3321f08aa1cSPhilipp Tomsich 333c36b26c0SDavid Wu static void rk3328_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 334c36b26c0SDavid Wu { 335c36b26c0SDavid Wu struct rk3328_grf_regs *grf; 336c36b26c0SDavid Wu enum { 337c36b26c0SDavid Wu RK3328_RMII_MODE_SHIFT = 9, 338c36b26c0SDavid Wu RK3328_RMII_MODE_MASK = BIT(9), 339c36b26c0SDavid Wu 340c36b26c0SDavid Wu RK3328_GMAC_PHY_INTF_SEL_SHIFT = 4, 341c36b26c0SDavid Wu RK3328_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), 342c36b26c0SDavid Wu RK3328_GMAC_PHY_INTF_SEL_RGMII = BIT(4), 343c36b26c0SDavid Wu 344c36b26c0SDavid Wu RK3328_RXCLK_DLY_ENA_GMAC_MASK = BIT(1), 345c36b26c0SDavid Wu RK3328_RXCLK_DLY_ENA_GMAC_DISABLE = 0, 346c36b26c0SDavid Wu RK3328_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(1), 347c36b26c0SDavid Wu 348c36b26c0SDavid Wu RK3328_TXCLK_DLY_ENA_GMAC_MASK = BIT(0), 349c36b26c0SDavid Wu RK3328_TXCLK_DLY_ENA_GMAC_DISABLE = 0, 350c36b26c0SDavid Wu RK3328_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(0), 351c36b26c0SDavid Wu }; 352c36b26c0SDavid Wu enum { 353c36b26c0SDavid Wu RK3328_CLK_RX_DL_CFG_GMAC_SHIFT = 0x7, 354c36b26c0SDavid Wu RK3328_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(13, 7), 355c36b26c0SDavid Wu 356c36b26c0SDavid Wu RK3328_CLK_TX_DL_CFG_GMAC_SHIFT = 0x0, 357c36b26c0SDavid Wu RK3328_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), 358c36b26c0SDavid Wu }; 359c36b26c0SDavid Wu 360c36b26c0SDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 361c36b26c0SDavid Wu rk_clrsetreg(&grf->mac_con[1], 362c36b26c0SDavid Wu RK3328_RMII_MODE_MASK | 363c36b26c0SDavid Wu RK3328_GMAC_PHY_INTF_SEL_MASK | 364c36b26c0SDavid Wu RK3328_RXCLK_DLY_ENA_GMAC_MASK | 365c36b26c0SDavid Wu RK3328_TXCLK_DLY_ENA_GMAC_MASK, 366c36b26c0SDavid Wu RK3328_GMAC_PHY_INTF_SEL_RGMII | 367c36b26c0SDavid Wu RK3328_RXCLK_DLY_ENA_GMAC_MASK | 368c36b26c0SDavid Wu RK3328_TXCLK_DLY_ENA_GMAC_ENABLE); 369c36b26c0SDavid Wu 370c36b26c0SDavid Wu rk_clrsetreg(&grf->mac_con[0], 371c36b26c0SDavid Wu RK3328_CLK_RX_DL_CFG_GMAC_MASK | 372c36b26c0SDavid Wu RK3328_CLK_TX_DL_CFG_GMAC_MASK, 373c36b26c0SDavid Wu pdata->rx_delay << RK3328_CLK_RX_DL_CFG_GMAC_SHIFT | 374c36b26c0SDavid Wu pdata->tx_delay << RK3328_CLK_TX_DL_CFG_GMAC_SHIFT); 375c36b26c0SDavid Wu } 376c36b26c0SDavid Wu 377793f2fd2SPhilipp Tomsich static void rk3368_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 378793f2fd2SPhilipp Tomsich { 379793f2fd2SPhilipp Tomsich struct rk3368_grf *grf; 380793f2fd2SPhilipp Tomsich enum { 381793f2fd2SPhilipp Tomsich RK3368_GMAC_PHY_INTF_SEL_RGMII = 1 << 9, 382793f2fd2SPhilipp Tomsich RK3368_GMAC_PHY_INTF_SEL_MASK = GENMASK(11, 9), 383793f2fd2SPhilipp Tomsich RK3368_RMII_MODE_MASK = BIT(6), 384793f2fd2SPhilipp Tomsich RK3368_RMII_MODE = BIT(6), 385793f2fd2SPhilipp Tomsich }; 386793f2fd2SPhilipp Tomsich enum { 387793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_MASK = BIT(15), 388793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_DISABLE = 0, 389793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(15), 390793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_MASK = BIT(7), 391793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_DISABLE = 0, 392793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(7), 393793f2fd2SPhilipp Tomsich RK3368_CLK_RX_DL_CFG_GMAC_SHIFT = 8, 394793f2fd2SPhilipp Tomsich RK3368_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(14, 8), 395793f2fd2SPhilipp Tomsich RK3368_CLK_TX_DL_CFG_GMAC_SHIFT = 0, 396793f2fd2SPhilipp Tomsich RK3368_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), 397793f2fd2SPhilipp Tomsich }; 398793f2fd2SPhilipp Tomsich 399793f2fd2SPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 400793f2fd2SPhilipp Tomsich rk_clrsetreg(&grf->soc_con15, 401793f2fd2SPhilipp Tomsich RK3368_RMII_MODE_MASK | RK3368_GMAC_PHY_INTF_SEL_MASK, 402793f2fd2SPhilipp Tomsich RK3368_GMAC_PHY_INTF_SEL_RGMII); 403793f2fd2SPhilipp Tomsich 404793f2fd2SPhilipp Tomsich rk_clrsetreg(&grf->soc_con16, 405793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_MASK | 406793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_MASK | 407793f2fd2SPhilipp Tomsich RK3368_CLK_RX_DL_CFG_GMAC_MASK | 408793f2fd2SPhilipp Tomsich RK3368_CLK_TX_DL_CFG_GMAC_MASK, 409793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_ENABLE | 410793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_ENABLE | 411793f2fd2SPhilipp Tomsich pdata->rx_delay << RK3368_CLK_RX_DL_CFG_GMAC_SHIFT | 412793f2fd2SPhilipp Tomsich pdata->tx_delay << RK3368_CLK_TX_DL_CFG_GMAC_SHIFT); 413793f2fd2SPhilipp Tomsich } 414793f2fd2SPhilipp Tomsich 4151f08aa1cSPhilipp Tomsich static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 4161f08aa1cSPhilipp Tomsich { 4171f08aa1cSPhilipp Tomsich struct rk3399_grf_regs *grf; 4181f08aa1cSPhilipp Tomsich 4191f08aa1cSPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 4201f08aa1cSPhilipp Tomsich 4211f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con5, 4221f08aa1cSPhilipp Tomsich RK3399_GMAC_PHY_INTF_SEL_MASK, 4231f08aa1cSPhilipp Tomsich RK3399_GMAC_PHY_INTF_SEL_RGMII); 4241f08aa1cSPhilipp Tomsich 4251f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con6, 4261f08aa1cSPhilipp Tomsich RK3399_RXCLK_DLY_ENA_GMAC_MASK | 4271f08aa1cSPhilipp Tomsich RK3399_TXCLK_DLY_ENA_GMAC_MASK | 4281f08aa1cSPhilipp Tomsich RK3399_CLK_RX_DL_CFG_GMAC_MASK | 4291f08aa1cSPhilipp Tomsich RK3399_CLK_TX_DL_CFG_GMAC_MASK, 4301f08aa1cSPhilipp Tomsich RK3399_RXCLK_DLY_ENA_GMAC_ENABLE | 4311f08aa1cSPhilipp Tomsich RK3399_TXCLK_DLY_ENA_GMAC_ENABLE | 4321f08aa1cSPhilipp Tomsich pdata->rx_delay << RK3399_CLK_RX_DL_CFG_GMAC_SHIFT | 4331f08aa1cSPhilipp Tomsich pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT); 4341f08aa1cSPhilipp Tomsich } 4351f08aa1cSPhilipp Tomsich 4360a33ce65SDavid Wu static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata) 4370a33ce65SDavid Wu { 4380a33ce65SDavid Wu struct rv1108_grf *grf; 4390a33ce65SDavid Wu 4400a33ce65SDavid Wu enum { 4410a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), 4420a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_RMII = 4 << 4, 4430a33ce65SDavid Wu }; 4440a33ce65SDavid Wu 4450a33ce65SDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 4460a33ce65SDavid Wu rk_clrsetreg(&grf->gmac_con0, 4470a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_MASK, 4480a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_RMII); 4490a33ce65SDavid Wu } 4500a33ce65SDavid Wu 4510125bcf0SSjoerd Simons static int gmac_rockchip_probe(struct udevice *dev) 4520125bcf0SSjoerd Simons { 4530125bcf0SSjoerd Simons struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); 4541f08aa1cSPhilipp Tomsich struct rk_gmac_ops *ops = 4551f08aa1cSPhilipp Tomsich (struct rk_gmac_ops *)dev_get_driver_data(dev); 4560a33ce65SDavid Wu struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev); 4570a33ce65SDavid Wu struct eth_pdata *eth_pdata = &dw_pdata->eth_pdata; 4580125bcf0SSjoerd Simons struct clk clk; 4590a33ce65SDavid Wu ulong rate; 4600125bcf0SSjoerd Simons int ret; 4610125bcf0SSjoerd Simons 462*cadc8d74SKever Yang /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 463*cadc8d74SKever Yang ret = clk_set_defaults(dev); 464*cadc8d74SKever Yang if (ret) 465*cadc8d74SKever Yang debug("%s clk_set_defaults failed %d\n", __func__, ret); 466*cadc8d74SKever Yang 4670125bcf0SSjoerd Simons ret = clk_get_by_index(dev, 0, &clk); 4680125bcf0SSjoerd Simons if (ret) 4690125bcf0SSjoerd Simons return ret; 4700125bcf0SSjoerd Simons 4710a33ce65SDavid Wu switch (eth_pdata->phy_interface) { 4720a33ce65SDavid Wu case PHY_INTERFACE_MODE_RGMII: 4730a33ce65SDavid Wu /* 4740a33ce65SDavid Wu * If the gmac clock is from internal pll, need to set and 4750a33ce65SDavid Wu * check the return value for gmac clock at RGMII mode. If 4760a33ce65SDavid Wu * the gmac clock is from external source, the clock rate 4770a33ce65SDavid Wu * is not set, because of it is bypassed. 4780a33ce65SDavid Wu */ 4790a33ce65SDavid Wu if (!pdata->clock_input) { 4800a33ce65SDavid Wu rate = clk_set_rate(&clk, 125000000); 4810a33ce65SDavid Wu if (rate != 125000000) 4820a33ce65SDavid Wu return -EINVAL; 4830a33ce65SDavid Wu } 4840125bcf0SSjoerd Simons 4850125bcf0SSjoerd Simons /* Set to RGMII mode */ 4860a33ce65SDavid Wu if (ops->set_to_rgmii) 4871f08aa1cSPhilipp Tomsich ops->set_to_rgmii(pdata); 4880a33ce65SDavid Wu else 4890a33ce65SDavid Wu return -EPERM; 4900a33ce65SDavid Wu 4910a33ce65SDavid Wu break; 4920a33ce65SDavid Wu case PHY_INTERFACE_MODE_RMII: 4930a33ce65SDavid Wu /* The commet is the same as RGMII mode */ 4940a33ce65SDavid Wu if (!pdata->clock_input) { 4950a33ce65SDavid Wu rate = clk_set_rate(&clk, 50000000); 4960a33ce65SDavid Wu if (rate != 50000000) 4970a33ce65SDavid Wu return -EINVAL; 4980a33ce65SDavid Wu } 4990a33ce65SDavid Wu 5000a33ce65SDavid Wu /* Set to RMII mode */ 5010a33ce65SDavid Wu if (ops->set_to_rmii) 5020a33ce65SDavid Wu ops->set_to_rmii(pdata); 5030a33ce65SDavid Wu else 5040a33ce65SDavid Wu return -EPERM; 5050a33ce65SDavid Wu 5060a33ce65SDavid Wu break; 5070a33ce65SDavid Wu default: 5080a33ce65SDavid Wu debug("NO interface defined!\n"); 5090a33ce65SDavid Wu return -ENXIO; 5100a33ce65SDavid Wu } 5110125bcf0SSjoerd Simons 5120125bcf0SSjoerd Simons return designware_eth_probe(dev); 5130125bcf0SSjoerd Simons } 5140125bcf0SSjoerd Simons 5150125bcf0SSjoerd Simons static int gmac_rockchip_eth_start(struct udevice *dev) 5160125bcf0SSjoerd Simons { 5170125bcf0SSjoerd Simons struct eth_pdata *pdata = dev_get_platdata(dev); 5180125bcf0SSjoerd Simons struct dw_eth_dev *priv = dev_get_priv(dev); 5191f08aa1cSPhilipp Tomsich struct rk_gmac_ops *ops = 5201f08aa1cSPhilipp Tomsich (struct rk_gmac_ops *)dev_get_driver_data(dev); 5210125bcf0SSjoerd Simons int ret; 5220125bcf0SSjoerd Simons 5230125bcf0SSjoerd Simons ret = designware_eth_init(priv, pdata->enetaddr); 5240125bcf0SSjoerd Simons if (ret) 5250125bcf0SSjoerd Simons return ret; 5261f08aa1cSPhilipp Tomsich ret = ops->fix_mac_speed(priv); 5270125bcf0SSjoerd Simons if (ret) 5280125bcf0SSjoerd Simons return ret; 5290125bcf0SSjoerd Simons ret = designware_eth_enable(priv); 5300125bcf0SSjoerd Simons if (ret) 5310125bcf0SSjoerd Simons return ret; 5320125bcf0SSjoerd Simons 5330125bcf0SSjoerd Simons return 0; 5340125bcf0SSjoerd Simons } 5350125bcf0SSjoerd Simons 5360125bcf0SSjoerd Simons const struct eth_ops gmac_rockchip_eth_ops = { 5370125bcf0SSjoerd Simons .start = gmac_rockchip_eth_start, 5380125bcf0SSjoerd Simons .send = designware_eth_send, 5390125bcf0SSjoerd Simons .recv = designware_eth_recv, 5400125bcf0SSjoerd Simons .free_pkt = designware_eth_free_pkt, 5410125bcf0SSjoerd Simons .stop = designware_eth_stop, 5420125bcf0SSjoerd Simons .write_hwaddr = designware_eth_write_hwaddr, 5430125bcf0SSjoerd Simons }; 5440125bcf0SSjoerd Simons 545af166ffaSDavid Wu const struct rk_gmac_ops rk3228_gmac_ops = { 546af166ffaSDavid Wu .fix_mac_speed = rk3228_gmac_fix_mac_speed, 547af166ffaSDavid Wu .set_to_rgmii = rk3228_gmac_set_to_rgmii, 548af166ffaSDavid Wu }; 549af166ffaSDavid Wu 5501f08aa1cSPhilipp Tomsich const struct rk_gmac_ops rk3288_gmac_ops = { 5511f08aa1cSPhilipp Tomsich .fix_mac_speed = rk3288_gmac_fix_mac_speed, 5521f08aa1cSPhilipp Tomsich .set_to_rgmii = rk3288_gmac_set_to_rgmii, 5531f08aa1cSPhilipp Tomsich }; 5541f08aa1cSPhilipp Tomsich 555c36b26c0SDavid Wu const struct rk_gmac_ops rk3328_gmac_ops = { 556c36b26c0SDavid Wu .fix_mac_speed = rk3328_gmac_fix_mac_speed, 557c36b26c0SDavid Wu .set_to_rgmii = rk3328_gmac_set_to_rgmii, 558c36b26c0SDavid Wu }; 559c36b26c0SDavid Wu 560793f2fd2SPhilipp Tomsich const struct rk_gmac_ops rk3368_gmac_ops = { 561793f2fd2SPhilipp Tomsich .fix_mac_speed = rk3368_gmac_fix_mac_speed, 562793f2fd2SPhilipp Tomsich .set_to_rgmii = rk3368_gmac_set_to_rgmii, 563793f2fd2SPhilipp Tomsich }; 564793f2fd2SPhilipp Tomsich 5651f08aa1cSPhilipp Tomsich const struct rk_gmac_ops rk3399_gmac_ops = { 5661f08aa1cSPhilipp Tomsich .fix_mac_speed = rk3399_gmac_fix_mac_speed, 5671f08aa1cSPhilipp Tomsich .set_to_rgmii = rk3399_gmac_set_to_rgmii, 5681f08aa1cSPhilipp Tomsich }; 5691f08aa1cSPhilipp Tomsich 5700a33ce65SDavid Wu const struct rk_gmac_ops rv1108_gmac_ops = { 5710a33ce65SDavid Wu .fix_mac_speed = rv1108_set_rmii_speed, 5720a33ce65SDavid Wu .set_to_rmii = rv1108_gmac_set_to_rmii, 5730a33ce65SDavid Wu }; 5740a33ce65SDavid Wu 5750125bcf0SSjoerd Simons static const struct udevice_id rockchip_gmac_ids[] = { 576af166ffaSDavid Wu { .compatible = "rockchip,rk3228-gmac", 577af166ffaSDavid Wu .data = (ulong)&rk3228_gmac_ops }, 5781f08aa1cSPhilipp Tomsich { .compatible = "rockchip,rk3288-gmac", 5791f08aa1cSPhilipp Tomsich .data = (ulong)&rk3288_gmac_ops }, 580c36b26c0SDavid Wu { .compatible = "rockchip,rk3328-gmac", 581c36b26c0SDavid Wu .data = (ulong)&rk3328_gmac_ops }, 582793f2fd2SPhilipp Tomsich { .compatible = "rockchip,rk3368-gmac", 583793f2fd2SPhilipp Tomsich .data = (ulong)&rk3368_gmac_ops }, 5841f08aa1cSPhilipp Tomsich { .compatible = "rockchip,rk3399-gmac", 5851f08aa1cSPhilipp Tomsich .data = (ulong)&rk3399_gmac_ops }, 5860a33ce65SDavid Wu { .compatible = "rockchip,rv1108-gmac", 5870a33ce65SDavid Wu .data = (ulong)&rv1108_gmac_ops }, 5880125bcf0SSjoerd Simons { } 5890125bcf0SSjoerd Simons }; 5900125bcf0SSjoerd Simons 5910125bcf0SSjoerd Simons U_BOOT_DRIVER(eth_gmac_rockchip) = { 5920125bcf0SSjoerd Simons .name = "gmac_rockchip", 5930125bcf0SSjoerd Simons .id = UCLASS_ETH, 5940125bcf0SSjoerd Simons .of_match = rockchip_gmac_ids, 5950125bcf0SSjoerd Simons .ofdata_to_platdata = gmac_rockchip_ofdata_to_platdata, 5960125bcf0SSjoerd Simons .probe = gmac_rockchip_probe, 5970125bcf0SSjoerd Simons .ops = &gmac_rockchip_eth_ops, 5980125bcf0SSjoerd Simons .priv_auto_alloc_size = sizeof(struct dw_eth_dev), 5990125bcf0SSjoerd Simons .platdata_auto_alloc_size = sizeof(struct gmac_rockchip_platdata), 6000125bcf0SSjoerd Simons .flags = DM_FLAG_ALLOC_PRIV_DMA, 6010125bcf0SSjoerd Simons }; 602