xref: /rk3399_rockchip-uboot/drivers/net/gmac_rockchip.c (revision 0a33ce653deee71d7ccbc64e2e3168db33a3c7c0)
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