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> 180125bcf0SSjoerd Simons #include <asm/arch/grf_rk3288.h> 19793f2fd2SPhilipp Tomsich #include <asm/arch/grf_rk3368.h> 201f08aa1cSPhilipp Tomsich #include <asm/arch/grf_rk3399.h> 21*0a33ce65SDavid Wu #include <asm/arch/grf_rv1108.h> 220125bcf0SSjoerd Simons #include <dm/pinctrl.h> 230125bcf0SSjoerd Simons #include <dt-bindings/clock/rk3288-cru.h> 240125bcf0SSjoerd Simons #include "designware.h" 250125bcf0SSjoerd Simons 260125bcf0SSjoerd Simons DECLARE_GLOBAL_DATA_PTR; 270125bcf0SSjoerd Simons 280125bcf0SSjoerd Simons /* 290125bcf0SSjoerd Simons * Platform data for the gmac 300125bcf0SSjoerd Simons * 310125bcf0SSjoerd Simons * dw_eth_pdata: Required platform data for designware driver (must be first) 320125bcf0SSjoerd Simons */ 330125bcf0SSjoerd Simons struct gmac_rockchip_platdata { 340125bcf0SSjoerd Simons struct dw_eth_pdata dw_eth_pdata; 35*0a33ce65SDavid Wu bool clock_input; 360125bcf0SSjoerd Simons int tx_delay; 370125bcf0SSjoerd Simons int rx_delay; 380125bcf0SSjoerd Simons }; 390125bcf0SSjoerd Simons 401f08aa1cSPhilipp Tomsich struct rk_gmac_ops { 411f08aa1cSPhilipp Tomsich int (*fix_mac_speed)(struct dw_eth_dev *priv); 42*0a33ce65SDavid Wu void (*set_to_rmii)(struct gmac_rockchip_platdata *pdata); 431f08aa1cSPhilipp Tomsich void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata); 441f08aa1cSPhilipp Tomsich }; 451f08aa1cSPhilipp Tomsich 461eb9d064SDavid Wu void gmac_set_rgmii(struct udevice *dev, u32 tx_delay, u32 rx_delay) 471eb9d064SDavid Wu { 481eb9d064SDavid Wu struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); 491eb9d064SDavid Wu struct rk_gmac_ops *ops = 501eb9d064SDavid Wu (struct rk_gmac_ops *)dev_get_driver_data(dev); 511eb9d064SDavid Wu 521eb9d064SDavid Wu pdata->tx_delay = tx_delay; 531eb9d064SDavid Wu pdata->rx_delay = rx_delay; 541eb9d064SDavid Wu 551eb9d064SDavid Wu ops->set_to_rgmii(pdata); 561eb9d064SDavid Wu } 571f08aa1cSPhilipp Tomsich 580125bcf0SSjoerd Simons static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev) 590125bcf0SSjoerd Simons { 600125bcf0SSjoerd Simons struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); 61*0a33ce65SDavid Wu const char *string; 62*0a33ce65SDavid Wu 63*0a33ce65SDavid Wu string = dev_read_string(dev, "clock_in_out"); 64*0a33ce65SDavid Wu if (!strcmp(string, "input")) 65*0a33ce65SDavid Wu pdata->clock_input = true; 66*0a33ce65SDavid Wu else 67*0a33ce65SDavid Wu pdata->clock_input = false; 680125bcf0SSjoerd Simons 691f08aa1cSPhilipp Tomsich /* Check the new naming-style first... */ 707ad326a9SPhilipp Tomsich pdata->tx_delay = dev_read_u32_default(dev, "tx_delay", -ENOENT); 717ad326a9SPhilipp Tomsich pdata->rx_delay = dev_read_u32_default(dev, "rx_delay", -ENOENT); 721f08aa1cSPhilipp Tomsich 731f08aa1cSPhilipp Tomsich /* ... and fall back to the old naming style or default, if necessary */ 741f08aa1cSPhilipp Tomsich if (pdata->tx_delay == -ENOENT) 757ad326a9SPhilipp Tomsich pdata->tx_delay = dev_read_u32_default(dev, "tx-delay", 0x30); 761f08aa1cSPhilipp Tomsich if (pdata->rx_delay == -ENOENT) 777ad326a9SPhilipp Tomsich pdata->rx_delay = dev_read_u32_default(dev, "rx-delay", 0x10); 780125bcf0SSjoerd Simons 790125bcf0SSjoerd Simons return designware_eth_ofdata_to_platdata(dev); 800125bcf0SSjoerd Simons } 810125bcf0SSjoerd Simons 821f08aa1cSPhilipp Tomsich static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) 830125bcf0SSjoerd Simons { 840125bcf0SSjoerd Simons struct rk3288_grf *grf; 850125bcf0SSjoerd Simons int clk; 860125bcf0SSjoerd Simons 870125bcf0SSjoerd Simons switch (priv->phydev->speed) { 880125bcf0SSjoerd Simons case 10: 891f08aa1cSPhilipp Tomsich clk = RK3288_GMAC_CLK_SEL_2_5M; 900125bcf0SSjoerd Simons break; 910125bcf0SSjoerd Simons case 100: 921f08aa1cSPhilipp Tomsich clk = RK3288_GMAC_CLK_SEL_25M; 930125bcf0SSjoerd Simons break; 940125bcf0SSjoerd Simons case 1000: 951f08aa1cSPhilipp Tomsich clk = RK3288_GMAC_CLK_SEL_125M; 960125bcf0SSjoerd Simons break; 970125bcf0SSjoerd Simons default: 980125bcf0SSjoerd Simons debug("Unknown phy speed: %d\n", priv->phydev->speed); 990125bcf0SSjoerd Simons return -EINVAL; 1000125bcf0SSjoerd Simons } 1010125bcf0SSjoerd Simons 1020125bcf0SSjoerd Simons grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1031f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con1, RK3288_GMAC_CLK_SEL_MASK, clk); 1040125bcf0SSjoerd Simons 1050125bcf0SSjoerd Simons return 0; 1060125bcf0SSjoerd Simons } 1070125bcf0SSjoerd Simons 108793f2fd2SPhilipp Tomsich static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv) 109793f2fd2SPhilipp Tomsich { 110793f2fd2SPhilipp Tomsich struct rk3368_grf *grf; 111793f2fd2SPhilipp Tomsich int clk; 112793f2fd2SPhilipp Tomsich enum { 113793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_2_5M = 2 << 4, 114793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_25M = 3 << 4, 115793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_125M = 0 << 4, 116793f2fd2SPhilipp Tomsich RK3368_GMAC_CLK_SEL_MASK = GENMASK(5, 4), 117793f2fd2SPhilipp Tomsich }; 118793f2fd2SPhilipp Tomsich 119793f2fd2SPhilipp Tomsich switch (priv->phydev->speed) { 120793f2fd2SPhilipp Tomsich case 10: 121793f2fd2SPhilipp Tomsich clk = RK3368_GMAC_CLK_SEL_2_5M; 122793f2fd2SPhilipp Tomsich break; 123793f2fd2SPhilipp Tomsich case 100: 124793f2fd2SPhilipp Tomsich clk = RK3368_GMAC_CLK_SEL_25M; 125793f2fd2SPhilipp Tomsich break; 126793f2fd2SPhilipp Tomsich case 1000: 127793f2fd2SPhilipp Tomsich clk = RK3368_GMAC_CLK_SEL_125M; 128793f2fd2SPhilipp Tomsich break; 129793f2fd2SPhilipp Tomsich default: 130793f2fd2SPhilipp Tomsich debug("Unknown phy speed: %d\n", priv->phydev->speed); 131793f2fd2SPhilipp Tomsich return -EINVAL; 132793f2fd2SPhilipp Tomsich } 133793f2fd2SPhilipp Tomsich 134793f2fd2SPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 135793f2fd2SPhilipp Tomsich rk_clrsetreg(&grf->soc_con15, RK3368_GMAC_CLK_SEL_MASK, clk); 136793f2fd2SPhilipp Tomsich 137793f2fd2SPhilipp Tomsich return 0; 138793f2fd2SPhilipp Tomsich } 139793f2fd2SPhilipp Tomsich 1401f08aa1cSPhilipp Tomsich static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv) 1411f08aa1cSPhilipp Tomsich { 1421f08aa1cSPhilipp Tomsich struct rk3399_grf_regs *grf; 1431f08aa1cSPhilipp Tomsich int clk; 1441f08aa1cSPhilipp Tomsich 1451f08aa1cSPhilipp Tomsich switch (priv->phydev->speed) { 1461f08aa1cSPhilipp Tomsich case 10: 1471f08aa1cSPhilipp Tomsich clk = RK3399_GMAC_CLK_SEL_2_5M; 1481f08aa1cSPhilipp Tomsich break; 1491f08aa1cSPhilipp Tomsich case 100: 1501f08aa1cSPhilipp Tomsich clk = RK3399_GMAC_CLK_SEL_25M; 1511f08aa1cSPhilipp Tomsich break; 1521f08aa1cSPhilipp Tomsich case 1000: 1531f08aa1cSPhilipp Tomsich clk = RK3399_GMAC_CLK_SEL_125M; 1541f08aa1cSPhilipp Tomsich break; 1551f08aa1cSPhilipp Tomsich default: 1561f08aa1cSPhilipp Tomsich debug("Unknown phy speed: %d\n", priv->phydev->speed); 1571f08aa1cSPhilipp Tomsich return -EINVAL; 1581f08aa1cSPhilipp Tomsich } 1591f08aa1cSPhilipp Tomsich 1601f08aa1cSPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1611f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con5, RK3399_GMAC_CLK_SEL_MASK, clk); 1621f08aa1cSPhilipp Tomsich 1631f08aa1cSPhilipp Tomsich return 0; 1641f08aa1cSPhilipp Tomsich } 1651f08aa1cSPhilipp Tomsich 166*0a33ce65SDavid Wu static int rv1108_set_rmii_speed(struct dw_eth_dev *priv) 167*0a33ce65SDavid Wu { 168*0a33ce65SDavid Wu struct rv1108_grf *grf; 169*0a33ce65SDavid Wu int clk, speed; 170*0a33ce65SDavid Wu enum { 171*0a33ce65SDavid Wu RV1108_GMAC_SPEED_MASK = BIT(2), 172*0a33ce65SDavid Wu RV1108_GMAC_SPEED_10M = 0 << 2, 173*0a33ce65SDavid Wu RV1108_GMAC_SPEED_100M = 1 << 2, 174*0a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_MASK = BIT(7), 175*0a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_2_5M = 0 << 7, 176*0a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_25M = 1 << 7, 177*0a33ce65SDavid Wu }; 178*0a33ce65SDavid Wu 179*0a33ce65SDavid Wu switch (priv->phydev->speed) { 180*0a33ce65SDavid Wu case 10: 181*0a33ce65SDavid Wu clk = RV1108_GMAC_CLK_SEL_2_5M; 182*0a33ce65SDavid Wu speed = RV1108_GMAC_SPEED_10M; 183*0a33ce65SDavid Wu break; 184*0a33ce65SDavid Wu case 100: 185*0a33ce65SDavid Wu clk = RV1108_GMAC_CLK_SEL_25M; 186*0a33ce65SDavid Wu speed = RV1108_GMAC_SPEED_100M; 187*0a33ce65SDavid Wu break; 188*0a33ce65SDavid Wu default: 189*0a33ce65SDavid Wu debug("Unknown phy speed: %d\n", priv->phydev->speed); 190*0a33ce65SDavid Wu return -EINVAL; 191*0a33ce65SDavid Wu } 192*0a33ce65SDavid Wu 193*0a33ce65SDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 194*0a33ce65SDavid Wu rk_clrsetreg(&grf->gmac_con0, 195*0a33ce65SDavid Wu RV1108_GMAC_CLK_SEL_MASK | RV1108_GMAC_SPEED_MASK, 196*0a33ce65SDavid Wu clk | speed); 197*0a33ce65SDavid Wu 198*0a33ce65SDavid Wu return 0; 199*0a33ce65SDavid Wu } 200*0a33ce65SDavid Wu 2011f08aa1cSPhilipp Tomsich static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 2021f08aa1cSPhilipp Tomsich { 2031f08aa1cSPhilipp Tomsich struct rk3288_grf *grf; 2041f08aa1cSPhilipp Tomsich 2051f08aa1cSPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2061f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con1, 2071f08aa1cSPhilipp Tomsich RK3288_RMII_MODE_MASK | RK3288_GMAC_PHY_INTF_SEL_MASK, 2081f08aa1cSPhilipp Tomsich RK3288_GMAC_PHY_INTF_SEL_RGMII); 2091f08aa1cSPhilipp Tomsich 2101f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con3, 2111f08aa1cSPhilipp Tomsich RK3288_RXCLK_DLY_ENA_GMAC_MASK | 2121f08aa1cSPhilipp Tomsich RK3288_TXCLK_DLY_ENA_GMAC_MASK | 2131f08aa1cSPhilipp Tomsich RK3288_CLK_RX_DL_CFG_GMAC_MASK | 2141f08aa1cSPhilipp Tomsich RK3288_CLK_TX_DL_CFG_GMAC_MASK, 2151f08aa1cSPhilipp Tomsich RK3288_RXCLK_DLY_ENA_GMAC_ENABLE | 2161f08aa1cSPhilipp Tomsich RK3288_TXCLK_DLY_ENA_GMAC_ENABLE | 2171f08aa1cSPhilipp Tomsich pdata->rx_delay << RK3288_CLK_RX_DL_CFG_GMAC_SHIFT | 2181f08aa1cSPhilipp Tomsich pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT); 2191f08aa1cSPhilipp Tomsich } 2201f08aa1cSPhilipp Tomsich 221793f2fd2SPhilipp Tomsich static void rk3368_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 222793f2fd2SPhilipp Tomsich { 223793f2fd2SPhilipp Tomsich struct rk3368_grf *grf; 224793f2fd2SPhilipp Tomsich enum { 225793f2fd2SPhilipp Tomsich RK3368_GMAC_PHY_INTF_SEL_RGMII = 1 << 9, 226793f2fd2SPhilipp Tomsich RK3368_GMAC_PHY_INTF_SEL_MASK = GENMASK(11, 9), 227793f2fd2SPhilipp Tomsich RK3368_RMII_MODE_MASK = BIT(6), 228793f2fd2SPhilipp Tomsich RK3368_RMII_MODE = BIT(6), 229793f2fd2SPhilipp Tomsich }; 230793f2fd2SPhilipp Tomsich enum { 231793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_MASK = BIT(15), 232793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_DISABLE = 0, 233793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(15), 234793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_MASK = BIT(7), 235793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_DISABLE = 0, 236793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(7), 237793f2fd2SPhilipp Tomsich RK3368_CLK_RX_DL_CFG_GMAC_SHIFT = 8, 238793f2fd2SPhilipp Tomsich RK3368_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(14, 8), 239793f2fd2SPhilipp Tomsich RK3368_CLK_TX_DL_CFG_GMAC_SHIFT = 0, 240793f2fd2SPhilipp Tomsich RK3368_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), 241793f2fd2SPhilipp Tomsich }; 242793f2fd2SPhilipp Tomsich 243793f2fd2SPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 244793f2fd2SPhilipp Tomsich rk_clrsetreg(&grf->soc_con15, 245793f2fd2SPhilipp Tomsich RK3368_RMII_MODE_MASK | RK3368_GMAC_PHY_INTF_SEL_MASK, 246793f2fd2SPhilipp Tomsich RK3368_GMAC_PHY_INTF_SEL_RGMII); 247793f2fd2SPhilipp Tomsich 248793f2fd2SPhilipp Tomsich rk_clrsetreg(&grf->soc_con16, 249793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_MASK | 250793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_MASK | 251793f2fd2SPhilipp Tomsich RK3368_CLK_RX_DL_CFG_GMAC_MASK | 252793f2fd2SPhilipp Tomsich RK3368_CLK_TX_DL_CFG_GMAC_MASK, 253793f2fd2SPhilipp Tomsich RK3368_RXCLK_DLY_ENA_GMAC_ENABLE | 254793f2fd2SPhilipp Tomsich RK3368_TXCLK_DLY_ENA_GMAC_ENABLE | 255793f2fd2SPhilipp Tomsich pdata->rx_delay << RK3368_CLK_RX_DL_CFG_GMAC_SHIFT | 256793f2fd2SPhilipp Tomsich pdata->tx_delay << RK3368_CLK_TX_DL_CFG_GMAC_SHIFT); 257793f2fd2SPhilipp Tomsich } 258793f2fd2SPhilipp Tomsich 2591f08aa1cSPhilipp Tomsich static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) 2601f08aa1cSPhilipp Tomsich { 2611f08aa1cSPhilipp Tomsich struct rk3399_grf_regs *grf; 2621f08aa1cSPhilipp Tomsich 2631f08aa1cSPhilipp Tomsich grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2641f08aa1cSPhilipp Tomsich 2651f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con5, 2661f08aa1cSPhilipp Tomsich RK3399_GMAC_PHY_INTF_SEL_MASK, 2671f08aa1cSPhilipp Tomsich RK3399_GMAC_PHY_INTF_SEL_RGMII); 2681f08aa1cSPhilipp Tomsich 2691f08aa1cSPhilipp Tomsich rk_clrsetreg(&grf->soc_con6, 2701f08aa1cSPhilipp Tomsich RK3399_RXCLK_DLY_ENA_GMAC_MASK | 2711f08aa1cSPhilipp Tomsich RK3399_TXCLK_DLY_ENA_GMAC_MASK | 2721f08aa1cSPhilipp Tomsich RK3399_CLK_RX_DL_CFG_GMAC_MASK | 2731f08aa1cSPhilipp Tomsich RK3399_CLK_TX_DL_CFG_GMAC_MASK, 2741f08aa1cSPhilipp Tomsich RK3399_RXCLK_DLY_ENA_GMAC_ENABLE | 2751f08aa1cSPhilipp Tomsich RK3399_TXCLK_DLY_ENA_GMAC_ENABLE | 2761f08aa1cSPhilipp Tomsich pdata->rx_delay << RK3399_CLK_RX_DL_CFG_GMAC_SHIFT | 2771f08aa1cSPhilipp Tomsich pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT); 2781f08aa1cSPhilipp Tomsich } 2791f08aa1cSPhilipp Tomsich 280*0a33ce65SDavid Wu static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata) 281*0a33ce65SDavid Wu { 282*0a33ce65SDavid Wu struct rv1108_grf *grf; 283*0a33ce65SDavid Wu 284*0a33ce65SDavid Wu enum { 285*0a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), 286*0a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_RMII = 4 << 4, 287*0a33ce65SDavid Wu }; 288*0a33ce65SDavid Wu 289*0a33ce65SDavid Wu grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 290*0a33ce65SDavid Wu rk_clrsetreg(&grf->gmac_con0, 291*0a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_MASK, 292*0a33ce65SDavid Wu RV1108_GMAC_PHY_INTF_SEL_RMII); 293*0a33ce65SDavid Wu } 294*0a33ce65SDavid Wu 2950125bcf0SSjoerd Simons static int gmac_rockchip_probe(struct udevice *dev) 2960125bcf0SSjoerd Simons { 2970125bcf0SSjoerd Simons struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); 2981f08aa1cSPhilipp Tomsich struct rk_gmac_ops *ops = 2991f08aa1cSPhilipp Tomsich (struct rk_gmac_ops *)dev_get_driver_data(dev); 300*0a33ce65SDavid Wu struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev); 301*0a33ce65SDavid Wu struct eth_pdata *eth_pdata = &dw_pdata->eth_pdata; 3020125bcf0SSjoerd Simons struct clk clk; 303*0a33ce65SDavid Wu ulong rate; 3040125bcf0SSjoerd Simons int ret; 3050125bcf0SSjoerd Simons 3060125bcf0SSjoerd Simons ret = clk_get_by_index(dev, 0, &clk); 3070125bcf0SSjoerd Simons if (ret) 3080125bcf0SSjoerd Simons return ret; 3090125bcf0SSjoerd Simons 310*0a33ce65SDavid Wu switch (eth_pdata->phy_interface) { 311*0a33ce65SDavid Wu case PHY_INTERFACE_MODE_RGMII: 312*0a33ce65SDavid Wu /* 313*0a33ce65SDavid Wu * If the gmac clock is from internal pll, need to set and 314*0a33ce65SDavid Wu * check the return value for gmac clock at RGMII mode. If 315*0a33ce65SDavid Wu * the gmac clock is from external source, the clock rate 316*0a33ce65SDavid Wu * is not set, because of it is bypassed. 317*0a33ce65SDavid Wu */ 318*0a33ce65SDavid Wu if (!pdata->clock_input) { 319*0a33ce65SDavid Wu rate = clk_set_rate(&clk, 125000000); 320*0a33ce65SDavid Wu if (rate != 125000000) 321*0a33ce65SDavid Wu return -EINVAL; 322*0a33ce65SDavid Wu } 3230125bcf0SSjoerd Simons 3240125bcf0SSjoerd Simons /* Set to RGMII mode */ 325*0a33ce65SDavid Wu if (ops->set_to_rgmii) 3261f08aa1cSPhilipp Tomsich ops->set_to_rgmii(pdata); 327*0a33ce65SDavid Wu else 328*0a33ce65SDavid Wu return -EPERM; 329*0a33ce65SDavid Wu 330*0a33ce65SDavid Wu break; 331*0a33ce65SDavid Wu case PHY_INTERFACE_MODE_RMII: 332*0a33ce65SDavid Wu /* The commet is the same as RGMII mode */ 333*0a33ce65SDavid Wu if (!pdata->clock_input) { 334*0a33ce65SDavid Wu rate = clk_set_rate(&clk, 50000000); 335*0a33ce65SDavid Wu if (rate != 50000000) 336*0a33ce65SDavid Wu return -EINVAL; 337*0a33ce65SDavid Wu } 338*0a33ce65SDavid Wu 339*0a33ce65SDavid Wu /* Set to RMII mode */ 340*0a33ce65SDavid Wu if (ops->set_to_rmii) 341*0a33ce65SDavid Wu ops->set_to_rmii(pdata); 342*0a33ce65SDavid Wu else 343*0a33ce65SDavid Wu return -EPERM; 344*0a33ce65SDavid Wu 345*0a33ce65SDavid Wu break; 346*0a33ce65SDavid Wu default: 347*0a33ce65SDavid Wu debug("NO interface defined!\n"); 348*0a33ce65SDavid Wu return -ENXIO; 349*0a33ce65SDavid Wu } 3500125bcf0SSjoerd Simons 3510125bcf0SSjoerd Simons return designware_eth_probe(dev); 3520125bcf0SSjoerd Simons } 3530125bcf0SSjoerd Simons 3540125bcf0SSjoerd Simons static int gmac_rockchip_eth_start(struct udevice *dev) 3550125bcf0SSjoerd Simons { 3560125bcf0SSjoerd Simons struct eth_pdata *pdata = dev_get_platdata(dev); 3570125bcf0SSjoerd Simons struct dw_eth_dev *priv = dev_get_priv(dev); 3581f08aa1cSPhilipp Tomsich struct rk_gmac_ops *ops = 3591f08aa1cSPhilipp Tomsich (struct rk_gmac_ops *)dev_get_driver_data(dev); 3600125bcf0SSjoerd Simons int ret; 3610125bcf0SSjoerd Simons 3620125bcf0SSjoerd Simons ret = designware_eth_init(priv, pdata->enetaddr); 3630125bcf0SSjoerd Simons if (ret) 3640125bcf0SSjoerd Simons return ret; 3651f08aa1cSPhilipp Tomsich ret = ops->fix_mac_speed(priv); 3660125bcf0SSjoerd Simons if (ret) 3670125bcf0SSjoerd Simons return ret; 3680125bcf0SSjoerd Simons ret = designware_eth_enable(priv); 3690125bcf0SSjoerd Simons if (ret) 3700125bcf0SSjoerd Simons return ret; 3710125bcf0SSjoerd Simons 3720125bcf0SSjoerd Simons return 0; 3730125bcf0SSjoerd Simons } 3740125bcf0SSjoerd Simons 3750125bcf0SSjoerd Simons const struct eth_ops gmac_rockchip_eth_ops = { 3760125bcf0SSjoerd Simons .start = gmac_rockchip_eth_start, 3770125bcf0SSjoerd Simons .send = designware_eth_send, 3780125bcf0SSjoerd Simons .recv = designware_eth_recv, 3790125bcf0SSjoerd Simons .free_pkt = designware_eth_free_pkt, 3800125bcf0SSjoerd Simons .stop = designware_eth_stop, 3810125bcf0SSjoerd Simons .write_hwaddr = designware_eth_write_hwaddr, 3820125bcf0SSjoerd Simons }; 3830125bcf0SSjoerd Simons 3841f08aa1cSPhilipp Tomsich const struct rk_gmac_ops rk3288_gmac_ops = { 3851f08aa1cSPhilipp Tomsich .fix_mac_speed = rk3288_gmac_fix_mac_speed, 3861f08aa1cSPhilipp Tomsich .set_to_rgmii = rk3288_gmac_set_to_rgmii, 3871f08aa1cSPhilipp Tomsich }; 3881f08aa1cSPhilipp Tomsich 389793f2fd2SPhilipp Tomsich const struct rk_gmac_ops rk3368_gmac_ops = { 390793f2fd2SPhilipp Tomsich .fix_mac_speed = rk3368_gmac_fix_mac_speed, 391793f2fd2SPhilipp Tomsich .set_to_rgmii = rk3368_gmac_set_to_rgmii, 392793f2fd2SPhilipp Tomsich }; 393793f2fd2SPhilipp Tomsich 3941f08aa1cSPhilipp Tomsich const struct rk_gmac_ops rk3399_gmac_ops = { 3951f08aa1cSPhilipp Tomsich .fix_mac_speed = rk3399_gmac_fix_mac_speed, 3961f08aa1cSPhilipp Tomsich .set_to_rgmii = rk3399_gmac_set_to_rgmii, 3971f08aa1cSPhilipp Tomsich }; 3981f08aa1cSPhilipp Tomsich 399*0a33ce65SDavid Wu const struct rk_gmac_ops rv1108_gmac_ops = { 400*0a33ce65SDavid Wu .fix_mac_speed = rv1108_set_rmii_speed, 401*0a33ce65SDavid Wu .set_to_rmii = rv1108_gmac_set_to_rmii, 402*0a33ce65SDavid Wu }; 403*0a33ce65SDavid Wu 4040125bcf0SSjoerd Simons static const struct udevice_id rockchip_gmac_ids[] = { 4051f08aa1cSPhilipp Tomsich { .compatible = "rockchip,rk3288-gmac", 4061f08aa1cSPhilipp Tomsich .data = (ulong)&rk3288_gmac_ops }, 407793f2fd2SPhilipp Tomsich { .compatible = "rockchip,rk3368-gmac", 408793f2fd2SPhilipp Tomsich .data = (ulong)&rk3368_gmac_ops }, 4091f08aa1cSPhilipp Tomsich { .compatible = "rockchip,rk3399-gmac", 4101f08aa1cSPhilipp Tomsich .data = (ulong)&rk3399_gmac_ops }, 411*0a33ce65SDavid Wu { .compatible = "rockchip,rv1108-gmac", 412*0a33ce65SDavid Wu .data = (ulong)&rv1108_gmac_ops }, 4130125bcf0SSjoerd Simons { } 4140125bcf0SSjoerd Simons }; 4150125bcf0SSjoerd Simons 4160125bcf0SSjoerd Simons U_BOOT_DRIVER(eth_gmac_rockchip) = { 4170125bcf0SSjoerd Simons .name = "gmac_rockchip", 4180125bcf0SSjoerd Simons .id = UCLASS_ETH, 4190125bcf0SSjoerd Simons .of_match = rockchip_gmac_ids, 4200125bcf0SSjoerd Simons .ofdata_to_platdata = gmac_rockchip_ofdata_to_platdata, 4210125bcf0SSjoerd Simons .probe = gmac_rockchip_probe, 4220125bcf0SSjoerd Simons .ops = &gmac_rockchip_eth_ops, 4230125bcf0SSjoerd Simons .priv_auto_alloc_size = sizeof(struct dw_eth_dev), 4240125bcf0SSjoerd Simons .platdata_auto_alloc_size = sizeof(struct gmac_rockchip_platdata), 4250125bcf0SSjoerd Simons .flags = DM_FLAG_ALLOC_PRIV_DMA, 4260125bcf0SSjoerd Simons }; 427