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