xref: /linux/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c (revision 07a5e76924a1a4549bc176f49ec9e37ca7315b43)
17ad269eaSRoger Chen /**
27ad269eaSRoger Chen  * dwmac-rk.c - Rockchip RK3288 DWMAC specific glue layer
37ad269eaSRoger Chen  *
47ad269eaSRoger Chen  * Copyright (C) 2014 Chen-Zhi (Roger Chen)
57ad269eaSRoger Chen  *
67ad269eaSRoger Chen  * Chen-Zhi (Roger Chen)  <roger.chen@rock-chips.com>
77ad269eaSRoger Chen  *
87ad269eaSRoger Chen  * This program is free software; you can redistribute it and/or modify
97ad269eaSRoger Chen  * it under the terms of the GNU General Public License as published by
107ad269eaSRoger Chen  * the Free Software Foundation; either version 2 of the License, or
117ad269eaSRoger Chen  * (at your option) any later version.
127ad269eaSRoger Chen  *
137ad269eaSRoger Chen  * This program is distributed in the hope that it will be useful,
147ad269eaSRoger Chen  * but WITHOUT ANY WARRANTY; without even the implied warranty of
157ad269eaSRoger Chen  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
167ad269eaSRoger Chen  * GNU General Public License for more details.
177ad269eaSRoger Chen  */
187ad269eaSRoger Chen 
197ad269eaSRoger Chen #include <linux/stmmac.h>
207ad269eaSRoger Chen #include <linux/bitops.h>
217ad269eaSRoger Chen #include <linux/clk.h>
227ad269eaSRoger Chen #include <linux/phy.h>
237ad269eaSRoger Chen #include <linux/of_net.h>
247ad269eaSRoger Chen #include <linux/gpio.h>
25e0fb4013SJoachim Eastwood #include <linux/module.h>
267ad269eaSRoger Chen #include <linux/of_gpio.h>
277ad269eaSRoger Chen #include <linux/of_device.h>
28e0fb4013SJoachim Eastwood #include <linux/platform_device.h>
297ad269eaSRoger Chen #include <linux/regulator/consumer.h>
307ad269eaSRoger Chen #include <linux/delay.h>
317ad269eaSRoger Chen #include <linux/mfd/syscon.h>
327ad269eaSRoger Chen #include <linux/regmap.h>
332c896fb0SDavid Wu #include <linux/pm_runtime.h>
347ad269eaSRoger Chen 
35e0fb4013SJoachim Eastwood #include "stmmac_platform.h"
36e0fb4013SJoachim Eastwood 
370fb98db1SHeiko Stübner struct rk_priv_data;
380fb98db1SHeiko Stübner struct rk_gmac_ops {
390fb98db1SHeiko Stübner 	void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
400fb98db1SHeiko Stübner 			     int tx_delay, int rx_delay);
410fb98db1SHeiko Stübner 	void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
420fb98db1SHeiko Stübner 	void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
430fb98db1SHeiko Stübner 	void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
440fb98db1SHeiko Stübner };
450fb98db1SHeiko Stübner 
467ad269eaSRoger Chen struct rk_priv_data {
477ad269eaSRoger Chen 	struct platform_device *pdev;
487ad269eaSRoger Chen 	int phy_iface;
492e12f536SRomain Perier 	struct regulator *regulator;
50229666c1SVincent Palatin 	bool suspended;
5192c2588fSJoachim Eastwood 	const struct rk_gmac_ops *ops;
527ad269eaSRoger Chen 
537ad269eaSRoger Chen 	bool clk_enabled;
547ad269eaSRoger Chen 	bool clock_input;
557ad269eaSRoger Chen 
567ad269eaSRoger Chen 	struct clk *clk_mac;
577ad269eaSRoger Chen 	struct clk *gmac_clkin;
587ad269eaSRoger Chen 	struct clk *mac_clk_rx;
597ad269eaSRoger Chen 	struct clk *mac_clk_tx;
607ad269eaSRoger Chen 	struct clk *clk_mac_ref;
617ad269eaSRoger Chen 	struct clk *clk_mac_refout;
627ad269eaSRoger Chen 	struct clk *aclk_mac;
637ad269eaSRoger Chen 	struct clk *pclk_mac;
647ad269eaSRoger Chen 
657ad269eaSRoger Chen 	int tx_delay;
667ad269eaSRoger Chen 	int rx_delay;
677ad269eaSRoger Chen 
687ad269eaSRoger Chen 	struct regmap *grf;
697ad269eaSRoger Chen };
707ad269eaSRoger Chen 
717ad269eaSRoger Chen #define HIWORD_UPDATE(val, mask, shift) \
727ad269eaSRoger Chen 		((val) << (shift) | (mask) << ((shift) + 16))
737ad269eaSRoger Chen 
747ad269eaSRoger Chen #define GRF_BIT(nr)	(BIT(nr) | BIT(nr+16))
757ad269eaSRoger Chen #define GRF_CLR_BIT(nr)	(BIT(nr+16))
767ad269eaSRoger Chen 
77e7ffd812SXing Zheng #define RK3228_GRF_MAC_CON0	0x0900
78e7ffd812SXing Zheng #define RK3228_GRF_MAC_CON1	0x0904
79e7ffd812SXing Zheng 
80e7ffd812SXing Zheng /* RK3228_GRF_MAC_CON0 */
81e7ffd812SXing Zheng #define RK3228_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
82e7ffd812SXing Zheng #define RK3228_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
83e7ffd812SXing Zheng 
84e7ffd812SXing Zheng /* RK3228_GRF_MAC_CON1 */
85e7ffd812SXing Zheng #define RK3228_GMAC_PHY_INTF_SEL_RGMII	\
86e7ffd812SXing Zheng 		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
87e7ffd812SXing Zheng #define RK3228_GMAC_PHY_INTF_SEL_RMII	\
88e7ffd812SXing Zheng 		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
89e7ffd812SXing Zheng #define RK3228_GMAC_FLOW_CTRL		GRF_BIT(3)
90e7ffd812SXing Zheng #define RK3228_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(3)
91e7ffd812SXing Zheng #define RK3228_GMAC_SPEED_10M		GRF_CLR_BIT(2)
92e7ffd812SXing Zheng #define RK3228_GMAC_SPEED_100M		GRF_BIT(2)
93e7ffd812SXing Zheng #define RK3228_GMAC_RMII_CLK_25M	GRF_BIT(7)
94e7ffd812SXing Zheng #define RK3228_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(7)
95e7ffd812SXing Zheng #define RK3228_GMAC_CLK_125M		(GRF_CLR_BIT(8) | GRF_CLR_BIT(9))
96e7ffd812SXing Zheng #define RK3228_GMAC_CLK_25M		(GRF_BIT(8) | GRF_BIT(9))
97e7ffd812SXing Zheng #define RK3228_GMAC_CLK_2_5M		(GRF_CLR_BIT(8) | GRF_BIT(9))
98e7ffd812SXing Zheng #define RK3228_GMAC_RMII_MODE		GRF_BIT(10)
99e7ffd812SXing Zheng #define RK3228_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(10)
100e7ffd812SXing Zheng #define RK3228_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(0)
101e7ffd812SXing Zheng #define RK3228_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(0)
102e7ffd812SXing Zheng #define RK3228_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(1)
103e7ffd812SXing Zheng #define RK3228_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(1)
104e7ffd812SXing Zheng 
105e7ffd812SXing Zheng static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
106e7ffd812SXing Zheng 				int tx_delay, int rx_delay)
107e7ffd812SXing Zheng {
108e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
109e7ffd812SXing Zheng 
110e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
111e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
112e7ffd812SXing Zheng 		return;
113e7ffd812SXing Zheng 	}
114e7ffd812SXing Zheng 
115e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
116e7ffd812SXing Zheng 		     RK3228_GMAC_PHY_INTF_SEL_RGMII |
117e7ffd812SXing Zheng 		     RK3228_GMAC_RMII_MODE_CLR |
118e7ffd812SXing Zheng 		     RK3228_GMAC_RXCLK_DLY_ENABLE |
119e7ffd812SXing Zheng 		     RK3228_GMAC_TXCLK_DLY_ENABLE);
120e7ffd812SXing Zheng 
121e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON0,
122e7ffd812SXing Zheng 		     RK3228_GMAC_CLK_RX_DL_CFG(rx_delay) |
123e7ffd812SXing Zheng 		     RK3228_GMAC_CLK_TX_DL_CFG(tx_delay));
124e7ffd812SXing Zheng }
125e7ffd812SXing Zheng 
126e7ffd812SXing Zheng static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv)
127e7ffd812SXing Zheng {
128e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
129e7ffd812SXing Zheng 
130e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
131e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
132e7ffd812SXing Zheng 		return;
133e7ffd812SXing Zheng 	}
134e7ffd812SXing Zheng 
135e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
136e7ffd812SXing Zheng 		     RK3228_GMAC_PHY_INTF_SEL_RMII |
137e7ffd812SXing Zheng 		     RK3228_GMAC_RMII_MODE);
138e7ffd812SXing Zheng 
139e7ffd812SXing Zheng 	/* set MAC to RMII mode */
140e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, GRF_BIT(11));
141e7ffd812SXing Zheng }
142e7ffd812SXing Zheng 
143e7ffd812SXing Zheng static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
144e7ffd812SXing Zheng {
145e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
146e7ffd812SXing Zheng 
147e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
148e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
149e7ffd812SXing Zheng 		return;
150e7ffd812SXing Zheng 	}
151e7ffd812SXing Zheng 
152e7ffd812SXing Zheng 	if (speed == 10)
153e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
154e7ffd812SXing Zheng 			     RK3228_GMAC_CLK_2_5M);
155e7ffd812SXing Zheng 	else if (speed == 100)
156e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
157e7ffd812SXing Zheng 			     RK3228_GMAC_CLK_25M);
158e7ffd812SXing Zheng 	else if (speed == 1000)
159e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
160e7ffd812SXing Zheng 			     RK3228_GMAC_CLK_125M);
161e7ffd812SXing Zheng 	else
162e7ffd812SXing Zheng 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
163e7ffd812SXing Zheng }
164e7ffd812SXing Zheng 
165e7ffd812SXing Zheng static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
166e7ffd812SXing Zheng {
167e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
168e7ffd812SXing Zheng 
169e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
170e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
171e7ffd812SXing Zheng 		return;
172e7ffd812SXing Zheng 	}
173e7ffd812SXing Zheng 
174e7ffd812SXing Zheng 	if (speed == 10)
175e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
176e7ffd812SXing Zheng 			     RK3228_GMAC_RMII_CLK_2_5M |
177e7ffd812SXing Zheng 			     RK3228_GMAC_SPEED_10M);
178e7ffd812SXing Zheng 	else if (speed == 100)
179e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
180e7ffd812SXing Zheng 			     RK3228_GMAC_RMII_CLK_25M |
181e7ffd812SXing Zheng 			     RK3228_GMAC_SPEED_100M);
182e7ffd812SXing Zheng 	else
183e7ffd812SXing Zheng 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
184e7ffd812SXing Zheng }
185e7ffd812SXing Zheng 
186e7ffd812SXing Zheng static const struct rk_gmac_ops rk3228_ops = {
187e7ffd812SXing Zheng 	.set_to_rgmii = rk3228_set_to_rgmii,
188e7ffd812SXing Zheng 	.set_to_rmii = rk3228_set_to_rmii,
189e7ffd812SXing Zheng 	.set_rgmii_speed = rk3228_set_rgmii_speed,
190e7ffd812SXing Zheng 	.set_rmii_speed = rk3228_set_rmii_speed,
191e7ffd812SXing Zheng };
192e7ffd812SXing Zheng 
1937ad269eaSRoger Chen #define RK3288_GRF_SOC_CON1	0x0248
1947ad269eaSRoger Chen #define RK3288_GRF_SOC_CON3	0x0250
1957ad269eaSRoger Chen 
1967ad269eaSRoger Chen /*RK3288_GRF_SOC_CON1*/
1970fb98db1SHeiko Stübner #define RK3288_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | \
1980fb98db1SHeiko Stübner 					 GRF_CLR_BIT(8))
1990fb98db1SHeiko Stübner #define RK3288_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
2000fb98db1SHeiko Stübner 					 GRF_BIT(8))
2010fb98db1SHeiko Stübner #define RK3288_GMAC_FLOW_CTRL		GRF_BIT(9)
2020fb98db1SHeiko Stübner #define RK3288_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(9)
2030fb98db1SHeiko Stübner #define RK3288_GMAC_SPEED_10M		GRF_CLR_BIT(10)
2040fb98db1SHeiko Stübner #define RK3288_GMAC_SPEED_100M		GRF_BIT(10)
2050fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_CLK_25M	GRF_BIT(11)
2060fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(11)
2070fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_125M		(GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
2080fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_25M		(GRF_BIT(12) | GRF_BIT(13))
2090fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_2_5M		(GRF_CLR_BIT(12) | GRF_BIT(13))
2100fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_MODE		GRF_BIT(14)
2110fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(14)
2127ad269eaSRoger Chen 
2137ad269eaSRoger Chen /*RK3288_GRF_SOC_CON3*/
2140fb98db1SHeiko Stübner #define RK3288_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
2150fb98db1SHeiko Stübner #define RK3288_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
2160fb98db1SHeiko Stübner #define RK3288_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
2170fb98db1SHeiko Stübner #define RK3288_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
2180fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
2190fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
2207ad269eaSRoger Chen 
2210fb98db1SHeiko Stübner static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
2227ad269eaSRoger Chen 				int tx_delay, int rx_delay)
2237ad269eaSRoger Chen {
2247ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2257ad269eaSRoger Chen 
2267ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
227d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2287ad269eaSRoger Chen 		return;
2297ad269eaSRoger Chen 	}
2307ad269eaSRoger Chen 
2317ad269eaSRoger Chen 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2320fb98db1SHeiko Stübner 		     RK3288_GMAC_PHY_INTF_SEL_RGMII |
2330fb98db1SHeiko Stübner 		     RK3288_GMAC_RMII_MODE_CLR);
2347ad269eaSRoger Chen 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
2350fb98db1SHeiko Stübner 		     RK3288_GMAC_RXCLK_DLY_ENABLE |
2360fb98db1SHeiko Stübner 		     RK3288_GMAC_TXCLK_DLY_ENABLE |
2370fb98db1SHeiko Stübner 		     RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
2380fb98db1SHeiko Stübner 		     RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
2397ad269eaSRoger Chen }
2407ad269eaSRoger Chen 
2410fb98db1SHeiko Stübner static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
2427ad269eaSRoger Chen {
2437ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2447ad269eaSRoger Chen 
2457ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
246d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2477ad269eaSRoger Chen 		return;
2487ad269eaSRoger Chen 	}
2497ad269eaSRoger Chen 
2507ad269eaSRoger Chen 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2510fb98db1SHeiko Stübner 		     RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
2527ad269eaSRoger Chen }
2537ad269eaSRoger Chen 
2540fb98db1SHeiko Stübner static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
2557ad269eaSRoger Chen {
2567ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2577ad269eaSRoger Chen 
2587ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
259d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2607ad269eaSRoger Chen 		return;
2617ad269eaSRoger Chen 	}
2627ad269eaSRoger Chen 
2637ad269eaSRoger Chen 	if (speed == 10)
2640fb98db1SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2650fb98db1SHeiko Stübner 			     RK3288_GMAC_CLK_2_5M);
2667ad269eaSRoger Chen 	else if (speed == 100)
2670fb98db1SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2680fb98db1SHeiko Stübner 			     RK3288_GMAC_CLK_25M);
2697ad269eaSRoger Chen 	else if (speed == 1000)
2700fb98db1SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2710fb98db1SHeiko Stübner 			     RK3288_GMAC_CLK_125M);
2727ad269eaSRoger Chen 	else
2737ad269eaSRoger Chen 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
2747ad269eaSRoger Chen }
2757ad269eaSRoger Chen 
2760fb98db1SHeiko Stübner static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
2777ad269eaSRoger Chen {
2787ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2797ad269eaSRoger Chen 
2807ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
281d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2827ad269eaSRoger Chen 		return;
2837ad269eaSRoger Chen 	}
2847ad269eaSRoger Chen 
2857ad269eaSRoger Chen 	if (speed == 10) {
2867ad269eaSRoger Chen 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2870fb98db1SHeiko Stübner 			     RK3288_GMAC_RMII_CLK_2_5M |
2880fb98db1SHeiko Stübner 			     RK3288_GMAC_SPEED_10M);
2897ad269eaSRoger Chen 	} else if (speed == 100) {
2907ad269eaSRoger Chen 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2910fb98db1SHeiko Stübner 			     RK3288_GMAC_RMII_CLK_25M |
2920fb98db1SHeiko Stübner 			     RK3288_GMAC_SPEED_100M);
2937ad269eaSRoger Chen 	} else {
2947ad269eaSRoger Chen 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
2957ad269eaSRoger Chen 	}
2967ad269eaSRoger Chen }
2977ad269eaSRoger Chen 
29892c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3288_ops = {
2990fb98db1SHeiko Stübner 	.set_to_rgmii = rk3288_set_to_rgmii,
3000fb98db1SHeiko Stübner 	.set_to_rmii = rk3288_set_to_rmii,
3010fb98db1SHeiko Stübner 	.set_rgmii_speed = rk3288_set_rgmii_speed,
3020fb98db1SHeiko Stübner 	.set_rmii_speed = rk3288_set_rmii_speed,
3030fb98db1SHeiko Stübner };
3040fb98db1SHeiko Stübner 
305ba289af8SRoger Chen #define RK3366_GRF_SOC_CON6	0x0418
306ba289af8SRoger Chen #define RK3366_GRF_SOC_CON7	0x041c
307ba289af8SRoger Chen 
308ba289af8SRoger Chen /* RK3366_GRF_SOC_CON6 */
309ba289af8SRoger Chen #define RK3366_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
310ba289af8SRoger Chen 					 GRF_CLR_BIT(11))
311ba289af8SRoger Chen #define RK3366_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
312ba289af8SRoger Chen 					 GRF_BIT(11))
313ba289af8SRoger Chen #define RK3366_GMAC_FLOW_CTRL		GRF_BIT(8)
314ba289af8SRoger Chen #define RK3366_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
315ba289af8SRoger Chen #define RK3366_GMAC_SPEED_10M		GRF_CLR_BIT(7)
316ba289af8SRoger Chen #define RK3366_GMAC_SPEED_100M		GRF_BIT(7)
317ba289af8SRoger Chen #define RK3366_GMAC_RMII_CLK_25M	GRF_BIT(3)
318ba289af8SRoger Chen #define RK3366_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
319ba289af8SRoger Chen #define RK3366_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
320ba289af8SRoger Chen #define RK3366_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
321ba289af8SRoger Chen #define RK3366_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
322ba289af8SRoger Chen #define RK3366_GMAC_RMII_MODE		GRF_BIT(6)
323ba289af8SRoger Chen #define RK3366_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
324ba289af8SRoger Chen 
325ba289af8SRoger Chen /* RK3366_GRF_SOC_CON7 */
326ba289af8SRoger Chen #define RK3366_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
327ba289af8SRoger Chen #define RK3366_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
328ba289af8SRoger Chen #define RK3366_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
329ba289af8SRoger Chen #define RK3366_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
330ba289af8SRoger Chen #define RK3366_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
331ba289af8SRoger Chen #define RK3366_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
332ba289af8SRoger Chen 
333ba289af8SRoger Chen static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
334ba289af8SRoger Chen 				int tx_delay, int rx_delay)
335ba289af8SRoger Chen {
336ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
337ba289af8SRoger Chen 
338ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
339ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
340ba289af8SRoger Chen 		return;
341ba289af8SRoger Chen 	}
342ba289af8SRoger Chen 
343ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
344ba289af8SRoger Chen 		     RK3366_GMAC_PHY_INTF_SEL_RGMII |
345ba289af8SRoger Chen 		     RK3366_GMAC_RMII_MODE_CLR);
346ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON7,
347ba289af8SRoger Chen 		     RK3366_GMAC_RXCLK_DLY_ENABLE |
348ba289af8SRoger Chen 		     RK3366_GMAC_TXCLK_DLY_ENABLE |
349ba289af8SRoger Chen 		     RK3366_GMAC_CLK_RX_DL_CFG(rx_delay) |
350ba289af8SRoger Chen 		     RK3366_GMAC_CLK_TX_DL_CFG(tx_delay));
351ba289af8SRoger Chen }
352ba289af8SRoger Chen 
353ba289af8SRoger Chen static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv)
354ba289af8SRoger Chen {
355ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
356ba289af8SRoger Chen 
357ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
358ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
359ba289af8SRoger Chen 		return;
360ba289af8SRoger Chen 	}
361ba289af8SRoger Chen 
362ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
363ba289af8SRoger Chen 		     RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE);
364ba289af8SRoger Chen }
365ba289af8SRoger Chen 
366ba289af8SRoger Chen static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
367ba289af8SRoger Chen {
368ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
369ba289af8SRoger Chen 
370ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
371ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
372ba289af8SRoger Chen 		return;
373ba289af8SRoger Chen 	}
374ba289af8SRoger Chen 
375ba289af8SRoger Chen 	if (speed == 10)
376ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
377ba289af8SRoger Chen 			     RK3366_GMAC_CLK_2_5M);
378ba289af8SRoger Chen 	else if (speed == 100)
379ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
380ba289af8SRoger Chen 			     RK3366_GMAC_CLK_25M);
381ba289af8SRoger Chen 	else if (speed == 1000)
382ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
383ba289af8SRoger Chen 			     RK3366_GMAC_CLK_125M);
384ba289af8SRoger Chen 	else
385ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
386ba289af8SRoger Chen }
387ba289af8SRoger Chen 
388ba289af8SRoger Chen static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
389ba289af8SRoger Chen {
390ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
391ba289af8SRoger Chen 
392ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
393ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
394ba289af8SRoger Chen 		return;
395ba289af8SRoger Chen 	}
396ba289af8SRoger Chen 
397ba289af8SRoger Chen 	if (speed == 10) {
398ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
399ba289af8SRoger Chen 			     RK3366_GMAC_RMII_CLK_2_5M |
400ba289af8SRoger Chen 			     RK3366_GMAC_SPEED_10M);
401ba289af8SRoger Chen 	} else if (speed == 100) {
402ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
403ba289af8SRoger Chen 			     RK3366_GMAC_RMII_CLK_25M |
404ba289af8SRoger Chen 			     RK3366_GMAC_SPEED_100M);
405ba289af8SRoger Chen 	} else {
406ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
407ba289af8SRoger Chen 	}
408ba289af8SRoger Chen }
409ba289af8SRoger Chen 
410ba289af8SRoger Chen static const struct rk_gmac_ops rk3366_ops = {
411ba289af8SRoger Chen 	.set_to_rgmii = rk3366_set_to_rgmii,
412ba289af8SRoger Chen 	.set_to_rmii = rk3366_set_to_rmii,
413ba289af8SRoger Chen 	.set_rgmii_speed = rk3366_set_rgmii_speed,
414ba289af8SRoger Chen 	.set_rmii_speed = rk3366_set_rmii_speed,
415ba289af8SRoger Chen };
416ba289af8SRoger Chen 
417df558854SHeiko Stübner #define RK3368_GRF_SOC_CON15	0x043c
418df558854SHeiko Stübner #define RK3368_GRF_SOC_CON16	0x0440
419df558854SHeiko Stübner 
420df558854SHeiko Stübner /* RK3368_GRF_SOC_CON15 */
421df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
422df558854SHeiko Stübner 					 GRF_CLR_BIT(11))
423df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
424df558854SHeiko Stübner 					 GRF_BIT(11))
425df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL		GRF_BIT(8)
426df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
427df558854SHeiko Stübner #define RK3368_GMAC_SPEED_10M		GRF_CLR_BIT(7)
428df558854SHeiko Stübner #define RK3368_GMAC_SPEED_100M		GRF_BIT(7)
429df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_25M	GRF_BIT(3)
430df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
431df558854SHeiko Stübner #define RK3368_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
432df558854SHeiko Stübner #define RK3368_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
433df558854SHeiko Stübner #define RK3368_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
434df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE		GRF_BIT(6)
435df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
436df558854SHeiko Stübner 
437df558854SHeiko Stübner /* RK3368_GRF_SOC_CON16 */
438df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
439df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
440df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
441df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
442df558854SHeiko Stübner #define RK3368_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
443df558854SHeiko Stübner #define RK3368_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
444df558854SHeiko Stübner 
445df558854SHeiko Stübner static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
446df558854SHeiko Stübner 				int tx_delay, int rx_delay)
447df558854SHeiko Stübner {
448df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
449df558854SHeiko Stübner 
450df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
451df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
452df558854SHeiko Stübner 		return;
453df558854SHeiko Stübner 	}
454df558854SHeiko Stübner 
455df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
456df558854SHeiko Stübner 		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
457df558854SHeiko Stübner 		     RK3368_GMAC_RMII_MODE_CLR);
458df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
459df558854SHeiko Stübner 		     RK3368_GMAC_RXCLK_DLY_ENABLE |
460df558854SHeiko Stübner 		     RK3368_GMAC_TXCLK_DLY_ENABLE |
461df558854SHeiko Stübner 		     RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
462df558854SHeiko Stübner 		     RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
463df558854SHeiko Stübner }
464df558854SHeiko Stübner 
465df558854SHeiko Stübner static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
466df558854SHeiko Stübner {
467df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
468df558854SHeiko Stübner 
469df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
470df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
471df558854SHeiko Stübner 		return;
472df558854SHeiko Stübner 	}
473df558854SHeiko Stübner 
474df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
475df558854SHeiko Stübner 		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
476df558854SHeiko Stübner }
477df558854SHeiko Stübner 
478df558854SHeiko Stübner static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
479df558854SHeiko Stübner {
480df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
481df558854SHeiko Stübner 
482df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
483df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
484df558854SHeiko Stübner 		return;
485df558854SHeiko Stübner 	}
486df558854SHeiko Stübner 
487df558854SHeiko Stübner 	if (speed == 10)
488df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
489df558854SHeiko Stübner 			     RK3368_GMAC_CLK_2_5M);
490df558854SHeiko Stübner 	else if (speed == 100)
491df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
492df558854SHeiko Stübner 			     RK3368_GMAC_CLK_25M);
493df558854SHeiko Stübner 	else if (speed == 1000)
494df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
495df558854SHeiko Stübner 			     RK3368_GMAC_CLK_125M);
496df558854SHeiko Stübner 	else
497df558854SHeiko Stübner 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
498df558854SHeiko Stübner }
499df558854SHeiko Stübner 
500df558854SHeiko Stübner static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
501df558854SHeiko Stübner {
502df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
503df558854SHeiko Stübner 
504df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
505df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
506df558854SHeiko Stübner 		return;
507df558854SHeiko Stübner 	}
508df558854SHeiko Stübner 
509df558854SHeiko Stübner 	if (speed == 10) {
510df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
511df558854SHeiko Stübner 			     RK3368_GMAC_RMII_CLK_2_5M |
512df558854SHeiko Stübner 			     RK3368_GMAC_SPEED_10M);
513df558854SHeiko Stübner 	} else if (speed == 100) {
514df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
515df558854SHeiko Stübner 			     RK3368_GMAC_RMII_CLK_25M |
516df558854SHeiko Stübner 			     RK3368_GMAC_SPEED_100M);
517df558854SHeiko Stübner 	} else {
518df558854SHeiko Stübner 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
519df558854SHeiko Stübner 	}
520df558854SHeiko Stübner }
521df558854SHeiko Stübner 
52292c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3368_ops = {
523df558854SHeiko Stübner 	.set_to_rgmii = rk3368_set_to_rgmii,
524df558854SHeiko Stübner 	.set_to_rmii = rk3368_set_to_rmii,
525df558854SHeiko Stübner 	.set_rgmii_speed = rk3368_set_rgmii_speed,
526df558854SHeiko Stübner 	.set_rmii_speed = rk3368_set_rmii_speed,
527df558854SHeiko Stübner };
528df558854SHeiko Stübner 
529ba289af8SRoger Chen #define RK3399_GRF_SOC_CON5	0xc214
530ba289af8SRoger Chen #define RK3399_GRF_SOC_CON6	0xc218
531ba289af8SRoger Chen 
532ba289af8SRoger Chen /* RK3399_GRF_SOC_CON5 */
533ba289af8SRoger Chen #define RK3399_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
534ba289af8SRoger Chen 					 GRF_CLR_BIT(11))
535ba289af8SRoger Chen #define RK3399_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
536ba289af8SRoger Chen 					 GRF_BIT(11))
537ba289af8SRoger Chen #define RK3399_GMAC_FLOW_CTRL		GRF_BIT(8)
538ba289af8SRoger Chen #define RK3399_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
539ba289af8SRoger Chen #define RK3399_GMAC_SPEED_10M		GRF_CLR_BIT(7)
540ba289af8SRoger Chen #define RK3399_GMAC_SPEED_100M		GRF_BIT(7)
541ba289af8SRoger Chen #define RK3399_GMAC_RMII_CLK_25M	GRF_BIT(3)
542ba289af8SRoger Chen #define RK3399_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
543ba289af8SRoger Chen #define RK3399_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
544ba289af8SRoger Chen #define RK3399_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
545ba289af8SRoger Chen #define RK3399_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
546ba289af8SRoger Chen #define RK3399_GMAC_RMII_MODE		GRF_BIT(6)
547ba289af8SRoger Chen #define RK3399_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
548ba289af8SRoger Chen 
549ba289af8SRoger Chen /* RK3399_GRF_SOC_CON6 */
550ba289af8SRoger Chen #define RK3399_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
551ba289af8SRoger Chen #define RK3399_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
552ba289af8SRoger Chen #define RK3399_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
553ba289af8SRoger Chen #define RK3399_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
554ba289af8SRoger Chen #define RK3399_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
555ba289af8SRoger Chen #define RK3399_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
556ba289af8SRoger Chen 
557ba289af8SRoger Chen static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
558ba289af8SRoger Chen 				int tx_delay, int rx_delay)
559ba289af8SRoger Chen {
560ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
561ba289af8SRoger Chen 
562ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
563ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
564ba289af8SRoger Chen 		return;
565ba289af8SRoger Chen 	}
566ba289af8SRoger Chen 
567ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
568ba289af8SRoger Chen 		     RK3399_GMAC_PHY_INTF_SEL_RGMII |
569ba289af8SRoger Chen 		     RK3399_GMAC_RMII_MODE_CLR);
570ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON6,
571ba289af8SRoger Chen 		     RK3399_GMAC_RXCLK_DLY_ENABLE |
572ba289af8SRoger Chen 		     RK3399_GMAC_TXCLK_DLY_ENABLE |
573ba289af8SRoger Chen 		     RK3399_GMAC_CLK_RX_DL_CFG(rx_delay) |
574ba289af8SRoger Chen 		     RK3399_GMAC_CLK_TX_DL_CFG(tx_delay));
575ba289af8SRoger Chen }
576ba289af8SRoger Chen 
577ba289af8SRoger Chen static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv)
578ba289af8SRoger Chen {
579ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
580ba289af8SRoger Chen 
581ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
582ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
583ba289af8SRoger Chen 		return;
584ba289af8SRoger Chen 	}
585ba289af8SRoger Chen 
586ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
587ba289af8SRoger Chen 		     RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE);
588ba289af8SRoger Chen }
589ba289af8SRoger Chen 
590ba289af8SRoger Chen static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
591ba289af8SRoger Chen {
592ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
593ba289af8SRoger Chen 
594ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
595ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
596ba289af8SRoger Chen 		return;
597ba289af8SRoger Chen 	}
598ba289af8SRoger Chen 
599ba289af8SRoger Chen 	if (speed == 10)
600ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
601ba289af8SRoger Chen 			     RK3399_GMAC_CLK_2_5M);
602ba289af8SRoger Chen 	else if (speed == 100)
603ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
604ba289af8SRoger Chen 			     RK3399_GMAC_CLK_25M);
605ba289af8SRoger Chen 	else if (speed == 1000)
606ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
607ba289af8SRoger Chen 			     RK3399_GMAC_CLK_125M);
608ba289af8SRoger Chen 	else
609ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
610ba289af8SRoger Chen }
611ba289af8SRoger Chen 
612ba289af8SRoger Chen static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
613ba289af8SRoger Chen {
614ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
615ba289af8SRoger Chen 
616ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
617ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
618ba289af8SRoger Chen 		return;
619ba289af8SRoger Chen 	}
620ba289af8SRoger Chen 
621ba289af8SRoger Chen 	if (speed == 10) {
622ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
623ba289af8SRoger Chen 			     RK3399_GMAC_RMII_CLK_2_5M |
624ba289af8SRoger Chen 			     RK3399_GMAC_SPEED_10M);
625ba289af8SRoger Chen 	} else if (speed == 100) {
626ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
627ba289af8SRoger Chen 			     RK3399_GMAC_RMII_CLK_25M |
628ba289af8SRoger Chen 			     RK3399_GMAC_SPEED_100M);
629ba289af8SRoger Chen 	} else {
630ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
631ba289af8SRoger Chen 	}
632ba289af8SRoger Chen }
633ba289af8SRoger Chen 
634ba289af8SRoger Chen static const struct rk_gmac_ops rk3399_ops = {
635ba289af8SRoger Chen 	.set_to_rgmii = rk3399_set_to_rgmii,
636ba289af8SRoger Chen 	.set_to_rmii = rk3399_set_to_rmii,
637ba289af8SRoger Chen 	.set_rgmii_speed = rk3399_set_rgmii_speed,
638ba289af8SRoger Chen 	.set_rmii_speed = rk3399_set_rmii_speed,
639ba289af8SRoger Chen };
640ba289af8SRoger Chen 
6417ad269eaSRoger Chen static int gmac_clk_init(struct rk_priv_data *bsp_priv)
6427ad269eaSRoger Chen {
6437ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
6447ad269eaSRoger Chen 
6457ad269eaSRoger Chen 	bsp_priv->clk_enabled = false;
6467ad269eaSRoger Chen 
6477ad269eaSRoger Chen 	bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
6487ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->mac_clk_rx))
649d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
650d42202dcSRomain Perier 			"mac_clk_rx");
6517ad269eaSRoger Chen 
6527ad269eaSRoger Chen 	bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
6537ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->mac_clk_tx))
654d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
655d42202dcSRomain Perier 			"mac_clk_tx");
6567ad269eaSRoger Chen 
6577ad269eaSRoger Chen 	bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
6587ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->aclk_mac))
659d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
660d42202dcSRomain Perier 			"aclk_mac");
6617ad269eaSRoger Chen 
6627ad269eaSRoger Chen 	bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
6637ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->pclk_mac))
664d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
665d42202dcSRomain Perier 			"pclk_mac");
6667ad269eaSRoger Chen 
6677ad269eaSRoger Chen 	bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
6687ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->clk_mac))
669d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
670d42202dcSRomain Perier 			"stmmaceth");
6717ad269eaSRoger Chen 
6727ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
6737ad269eaSRoger Chen 		bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
6747ad269eaSRoger Chen 		if (IS_ERR(bsp_priv->clk_mac_ref))
675d42202dcSRomain Perier 			dev_err(dev, "cannot get clock %s\n",
676d42202dcSRomain Perier 				"clk_mac_ref");
6777ad269eaSRoger Chen 
6787ad269eaSRoger Chen 		if (!bsp_priv->clock_input) {
6797ad269eaSRoger Chen 			bsp_priv->clk_mac_refout =
6807ad269eaSRoger Chen 				devm_clk_get(dev, "clk_mac_refout");
6817ad269eaSRoger Chen 			if (IS_ERR(bsp_priv->clk_mac_refout))
682d42202dcSRomain Perier 				dev_err(dev, "cannot get clock %s\n",
683d42202dcSRomain Perier 					"clk_mac_refout");
6847ad269eaSRoger Chen 		}
6857ad269eaSRoger Chen 	}
6867ad269eaSRoger Chen 
6877ad269eaSRoger Chen 	if (bsp_priv->clock_input) {
688d42202dcSRomain Perier 		dev_info(dev, "clock input from PHY\n");
6897ad269eaSRoger Chen 	} else {
6907ad269eaSRoger Chen 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
691c48fa33cSHeiko Stübner 			clk_set_rate(bsp_priv->clk_mac, 50000000);
6927ad269eaSRoger Chen 	}
6937ad269eaSRoger Chen 
6947ad269eaSRoger Chen 	return 0;
6957ad269eaSRoger Chen }
6967ad269eaSRoger Chen 
6977ad269eaSRoger Chen static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
6987ad269eaSRoger Chen {
699428ad1bcSLABBE Corentin 	int phy_iface = bsp_priv->phy_iface;
7007ad269eaSRoger Chen 
7017ad269eaSRoger Chen 	if (enable) {
7027ad269eaSRoger Chen 		if (!bsp_priv->clk_enabled) {
7037ad269eaSRoger Chen 			if (phy_iface == PHY_INTERFACE_MODE_RMII) {
7047ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->mac_clk_rx))
7057ad269eaSRoger Chen 					clk_prepare_enable(
7067ad269eaSRoger Chen 						bsp_priv->mac_clk_rx);
7077ad269eaSRoger Chen 
7087ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_ref))
7097ad269eaSRoger Chen 					clk_prepare_enable(
7107ad269eaSRoger Chen 						bsp_priv->clk_mac_ref);
7117ad269eaSRoger Chen 
7127ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_refout))
7137ad269eaSRoger Chen 					clk_prepare_enable(
7147ad269eaSRoger Chen 						bsp_priv->clk_mac_refout);
7157ad269eaSRoger Chen 			}
7167ad269eaSRoger Chen 
7177ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->aclk_mac))
7187ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->aclk_mac);
7197ad269eaSRoger Chen 
7207ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->pclk_mac))
7217ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->pclk_mac);
7227ad269eaSRoger Chen 
7237ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->mac_clk_tx))
7247ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->mac_clk_tx);
7257ad269eaSRoger Chen 
7267ad269eaSRoger Chen 			/**
7277ad269eaSRoger Chen 			 * if (!IS_ERR(bsp_priv->clk_mac))
7287ad269eaSRoger Chen 			 *	clk_prepare_enable(bsp_priv->clk_mac);
7297ad269eaSRoger Chen 			 */
7307ad269eaSRoger Chen 			mdelay(5);
7317ad269eaSRoger Chen 			bsp_priv->clk_enabled = true;
7327ad269eaSRoger Chen 		}
7337ad269eaSRoger Chen 	} else {
7347ad269eaSRoger Chen 		if (bsp_priv->clk_enabled) {
7357ad269eaSRoger Chen 			if (phy_iface == PHY_INTERFACE_MODE_RMII) {
7367ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->mac_clk_rx))
7377ad269eaSRoger Chen 					clk_disable_unprepare(
7387ad269eaSRoger Chen 						bsp_priv->mac_clk_rx);
7397ad269eaSRoger Chen 
7407ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_ref))
7417ad269eaSRoger Chen 					clk_disable_unprepare(
7427ad269eaSRoger Chen 						bsp_priv->clk_mac_ref);
7437ad269eaSRoger Chen 
7447ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_refout))
7457ad269eaSRoger Chen 					clk_disable_unprepare(
7467ad269eaSRoger Chen 						bsp_priv->clk_mac_refout);
7477ad269eaSRoger Chen 			}
7487ad269eaSRoger Chen 
7497ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->aclk_mac))
7507ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->aclk_mac);
7517ad269eaSRoger Chen 
7527ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->pclk_mac))
7537ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->pclk_mac);
7547ad269eaSRoger Chen 
7557ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->mac_clk_tx))
7567ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->mac_clk_tx);
7577ad269eaSRoger Chen 			/**
7587ad269eaSRoger Chen 			 * if (!IS_ERR(bsp_priv->clk_mac))
7597ad269eaSRoger Chen 			 *	clk_disable_unprepare(bsp_priv->clk_mac);
7607ad269eaSRoger Chen 			 */
7617ad269eaSRoger Chen 			bsp_priv->clk_enabled = false;
7627ad269eaSRoger Chen 		}
7637ad269eaSRoger Chen 	}
7647ad269eaSRoger Chen 
7657ad269eaSRoger Chen 	return 0;
7667ad269eaSRoger Chen }
7677ad269eaSRoger Chen 
7687ad269eaSRoger Chen static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
7697ad269eaSRoger Chen {
7702e12f536SRomain Perier 	struct regulator *ldo = bsp_priv->regulator;
7717ad269eaSRoger Chen 	int ret;
7727ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
7737ad269eaSRoger Chen 
7742e12f536SRomain Perier 	if (!ldo) {
775d42202dcSRomain Perier 		dev_err(dev, "no regulator found\n");
7767ad269eaSRoger Chen 		return -1;
7777ad269eaSRoger Chen 	}
7787ad269eaSRoger Chen 
7797ad269eaSRoger Chen 	if (enable) {
7807ad269eaSRoger Chen 		ret = regulator_enable(ldo);
7812e12f536SRomain Perier 		if (ret)
782d42202dcSRomain Perier 			dev_err(dev, "fail to enable phy-supply\n");
7837ad269eaSRoger Chen 	} else {
7847ad269eaSRoger Chen 		ret = regulator_disable(ldo);
7852e12f536SRomain Perier 		if (ret)
786d42202dcSRomain Perier 			dev_err(dev, "fail to disable phy-supply\n");
7877ad269eaSRoger Chen 	}
7887ad269eaSRoger Chen 
7897ad269eaSRoger Chen 	return 0;
7907ad269eaSRoger Chen }
7917ad269eaSRoger Chen 
7920fb98db1SHeiko Stübner static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
79392c2588fSJoachim Eastwood 					  const struct rk_gmac_ops *ops)
7947ad269eaSRoger Chen {
7957ad269eaSRoger Chen 	struct rk_priv_data *bsp_priv;
7967ad269eaSRoger Chen 	struct device *dev = &pdev->dev;
7977ad269eaSRoger Chen 	int ret;
7987ad269eaSRoger Chen 	const char *strings = NULL;
7997ad269eaSRoger Chen 	int value;
8007ad269eaSRoger Chen 
8017ad269eaSRoger Chen 	bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL);
8027ad269eaSRoger Chen 	if (!bsp_priv)
8037ad269eaSRoger Chen 		return ERR_PTR(-ENOMEM);
8047ad269eaSRoger Chen 
8057ad269eaSRoger Chen 	bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
8060fb98db1SHeiko Stübner 	bsp_priv->ops = ops;
8077ad269eaSRoger Chen 
8082e12f536SRomain Perier 	bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
8092e12f536SRomain Perier 	if (IS_ERR(bsp_priv->regulator)) {
8102e12f536SRomain Perier 		if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
8112e12f536SRomain Perier 			dev_err(dev, "phy regulator is not available yet, deferred probing\n");
8122e12f536SRomain Perier 			return ERR_PTR(-EPROBE_DEFER);
8132e12f536SRomain Perier 		}
8142e12f536SRomain Perier 		dev_err(dev, "no regulator found\n");
8152e12f536SRomain Perier 		bsp_priv->regulator = NULL;
8167ad269eaSRoger Chen 	}
8177ad269eaSRoger Chen 
8187ad269eaSRoger Chen 	ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
8197ad269eaSRoger Chen 	if (ret) {
820d42202dcSRomain Perier 		dev_err(dev, "Can not read property: clock_in_out.\n");
8217ad269eaSRoger Chen 		bsp_priv->clock_input = true;
8227ad269eaSRoger Chen 	} else {
823d42202dcSRomain Perier 		dev_info(dev, "clock input or output? (%s).\n",
824d42202dcSRomain Perier 			 strings);
8257ad269eaSRoger Chen 		if (!strcmp(strings, "input"))
8267ad269eaSRoger Chen 			bsp_priv->clock_input = true;
8277ad269eaSRoger Chen 		else
8287ad269eaSRoger Chen 			bsp_priv->clock_input = false;
8297ad269eaSRoger Chen 	}
8307ad269eaSRoger Chen 
8317ad269eaSRoger Chen 	ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
8327ad269eaSRoger Chen 	if (ret) {
8337ad269eaSRoger Chen 		bsp_priv->tx_delay = 0x30;
834d42202dcSRomain Perier 		dev_err(dev, "Can not read property: tx_delay.");
835d42202dcSRomain Perier 		dev_err(dev, "set tx_delay to 0x%x\n",
836d42202dcSRomain Perier 			bsp_priv->tx_delay);
8377ad269eaSRoger Chen 	} else {
838d42202dcSRomain Perier 		dev_info(dev, "TX delay(0x%x).\n", value);
8397ad269eaSRoger Chen 		bsp_priv->tx_delay = value;
8407ad269eaSRoger Chen 	}
8417ad269eaSRoger Chen 
8427ad269eaSRoger Chen 	ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
8437ad269eaSRoger Chen 	if (ret) {
8447ad269eaSRoger Chen 		bsp_priv->rx_delay = 0x10;
845d42202dcSRomain Perier 		dev_err(dev, "Can not read property: rx_delay.");
846d42202dcSRomain Perier 		dev_err(dev, "set rx_delay to 0x%x\n",
847d42202dcSRomain Perier 			bsp_priv->rx_delay);
8487ad269eaSRoger Chen 	} else {
849d42202dcSRomain Perier 		dev_info(dev, "RX delay(0x%x).\n", value);
8507ad269eaSRoger Chen 		bsp_priv->rx_delay = value;
8517ad269eaSRoger Chen 	}
8527ad269eaSRoger Chen 
8537ad269eaSRoger Chen 	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
8547ad269eaSRoger Chen 							"rockchip,grf");
8557ad269eaSRoger Chen 	bsp_priv->pdev = pdev;
8567ad269eaSRoger Chen 
85745383f52SRoger Chen 	gmac_clk_init(bsp_priv);
85845383f52SRoger Chen 
85945383f52SRoger Chen 	return bsp_priv;
86045383f52SRoger Chen }
86145383f52SRoger Chen 
86245383f52SRoger Chen static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
86345383f52SRoger Chen {
86445383f52SRoger Chen 	int ret;
86545383f52SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
86645383f52SRoger Chen 
8677ad269eaSRoger Chen 	/*rmii or rgmii*/
8687ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
869d42202dcSRomain Perier 		dev_info(dev, "init for RGMII\n");
8700fb98db1SHeiko Stübner 		bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
8710fb98db1SHeiko Stübner 					    bsp_priv->rx_delay);
8727ad269eaSRoger Chen 	} else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
873d42202dcSRomain Perier 		dev_info(dev, "init for RMII\n");
8740fb98db1SHeiko Stübner 		bsp_priv->ops->set_to_rmii(bsp_priv);
8757ad269eaSRoger Chen 	} else {
876d42202dcSRomain Perier 		dev_err(dev, "NO interface defined!\n");
8777ad269eaSRoger Chen 	}
8787ad269eaSRoger Chen 
8797ad269eaSRoger Chen 	ret = phy_power_on(bsp_priv, true);
8807ad269eaSRoger Chen 	if (ret)
8817ad269eaSRoger Chen 		return ret;
8827ad269eaSRoger Chen 
8837ad269eaSRoger Chen 	ret = gmac_clk_enable(bsp_priv, true);
8847ad269eaSRoger Chen 	if (ret)
8857ad269eaSRoger Chen 		return ret;
8867ad269eaSRoger Chen 
8872c896fb0SDavid Wu 	pm_runtime_enable(dev);
8882c896fb0SDavid Wu 	pm_runtime_get_sync(dev);
8892c896fb0SDavid Wu 
8907ad269eaSRoger Chen 	return 0;
8917ad269eaSRoger Chen }
8927ad269eaSRoger Chen 
893229666c1SVincent Palatin static void rk_gmac_powerdown(struct rk_priv_data *gmac)
8947ad269eaSRoger Chen {
8952c896fb0SDavid Wu 	struct device *dev = &gmac->pdev->dev;
8962c896fb0SDavid Wu 
8972c896fb0SDavid Wu 	pm_runtime_put_sync(dev);
8982c896fb0SDavid Wu 	pm_runtime_disable(dev);
8992c896fb0SDavid Wu 
9007ad269eaSRoger Chen 	phy_power_on(gmac, false);
9017ad269eaSRoger Chen 	gmac_clk_enable(gmac, false);
9027ad269eaSRoger Chen }
9037ad269eaSRoger Chen 
9047ad269eaSRoger Chen static void rk_fix_speed(void *priv, unsigned int speed)
9057ad269eaSRoger Chen {
9067ad269eaSRoger Chen 	struct rk_priv_data *bsp_priv = priv;
9077ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
9087ad269eaSRoger Chen 
9097ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
9100fb98db1SHeiko Stübner 		bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
9117ad269eaSRoger Chen 	else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
9120fb98db1SHeiko Stübner 		bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
9137ad269eaSRoger Chen 	else
9147ad269eaSRoger Chen 		dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
9157ad269eaSRoger Chen }
9167ad269eaSRoger Chen 
91727ffefd2SJoachim Eastwood static int rk_gmac_probe(struct platform_device *pdev)
91827ffefd2SJoachim Eastwood {
91927ffefd2SJoachim Eastwood 	struct plat_stmmacenet_data *plat_dat;
92027ffefd2SJoachim Eastwood 	struct stmmac_resources stmmac_res;
921f529f182SJoachim Eastwood 	const struct rk_gmac_ops *data;
92227ffefd2SJoachim Eastwood 	int ret;
92327ffefd2SJoachim Eastwood 
924149adeddSJoachim Eastwood 	data = of_device_get_match_data(&pdev->dev);
925149adeddSJoachim Eastwood 	if (!data) {
926149adeddSJoachim Eastwood 		dev_err(&pdev->dev, "no of match data provided\n");
927149adeddSJoachim Eastwood 		return -EINVAL;
928149adeddSJoachim Eastwood 	}
929149adeddSJoachim Eastwood 
93027ffefd2SJoachim Eastwood 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
93127ffefd2SJoachim Eastwood 	if (ret)
93227ffefd2SJoachim Eastwood 		return ret;
93327ffefd2SJoachim Eastwood 
93427ffefd2SJoachim Eastwood 	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
93527ffefd2SJoachim Eastwood 	if (IS_ERR(plat_dat))
93627ffefd2SJoachim Eastwood 		return PTR_ERR(plat_dat);
93727ffefd2SJoachim Eastwood 
93827ffefd2SJoachim Eastwood 	plat_dat->has_gmac = true;
93927ffefd2SJoachim Eastwood 	plat_dat->fix_mac_speed = rk_fix_speed;
94027ffefd2SJoachim Eastwood 
941f529f182SJoachim Eastwood 	plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
94227ffefd2SJoachim Eastwood 	if (IS_ERR(plat_dat->bsp_priv))
94327ffefd2SJoachim Eastwood 		return PTR_ERR(plat_dat->bsp_priv);
94427ffefd2SJoachim Eastwood 
945*07a5e769SJoachim Eastwood 	ret = rk_gmac_powerup(plat_dat->bsp_priv);
94627ffefd2SJoachim Eastwood 	if (ret)
94727ffefd2SJoachim Eastwood 		return ret;
94827ffefd2SJoachim Eastwood 
94927ffefd2SJoachim Eastwood 	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
95027ffefd2SJoachim Eastwood }
95127ffefd2SJoachim Eastwood 
9520de8c4c9SJoachim Eastwood static int rk_gmac_remove(struct platform_device *pdev)
9530de8c4c9SJoachim Eastwood {
9540de8c4c9SJoachim Eastwood 	struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev);
9550de8c4c9SJoachim Eastwood 	int ret = stmmac_dvr_remove(&pdev->dev);
9560de8c4c9SJoachim Eastwood 
9570de8c4c9SJoachim Eastwood 	rk_gmac_powerdown(bsp_priv);
9580de8c4c9SJoachim Eastwood 
9590de8c4c9SJoachim Eastwood 	return ret;
9600de8c4c9SJoachim Eastwood }
9610de8c4c9SJoachim Eastwood 
9625619468aSJoachim Eastwood #ifdef CONFIG_PM_SLEEP
9635619468aSJoachim Eastwood static int rk_gmac_suspend(struct device *dev)
9645619468aSJoachim Eastwood {
9655619468aSJoachim Eastwood 	struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
9665619468aSJoachim Eastwood 	int ret = stmmac_suspend(dev);
9675619468aSJoachim Eastwood 
9685619468aSJoachim Eastwood 	/* Keep the PHY up if we use Wake-on-Lan. */
9695619468aSJoachim Eastwood 	if (!device_may_wakeup(dev)) {
9705619468aSJoachim Eastwood 		rk_gmac_powerdown(bsp_priv);
9715619468aSJoachim Eastwood 		bsp_priv->suspended = true;
9725619468aSJoachim Eastwood 	}
9735619468aSJoachim Eastwood 
9745619468aSJoachim Eastwood 	return ret;
9755619468aSJoachim Eastwood }
9765619468aSJoachim Eastwood 
9775619468aSJoachim Eastwood static int rk_gmac_resume(struct device *dev)
9785619468aSJoachim Eastwood {
9795619468aSJoachim Eastwood 	struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
9805619468aSJoachim Eastwood 
9815619468aSJoachim Eastwood 	/* The PHY was up for Wake-on-Lan. */
9825619468aSJoachim Eastwood 	if (bsp_priv->suspended) {
9835619468aSJoachim Eastwood 		rk_gmac_powerup(bsp_priv);
9845619468aSJoachim Eastwood 		bsp_priv->suspended = false;
9855619468aSJoachim Eastwood 	}
9865619468aSJoachim Eastwood 
9875619468aSJoachim Eastwood 	return stmmac_resume(dev);
9885619468aSJoachim Eastwood }
9895619468aSJoachim Eastwood #endif /* CONFIG_PM_SLEEP */
9905619468aSJoachim Eastwood 
9915619468aSJoachim Eastwood static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume);
9925619468aSJoachim Eastwood 
993e0fb4013SJoachim Eastwood static const struct of_device_id rk_gmac_dwmac_match[] = {
994e7ffd812SXing Zheng 	{ .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
995f529f182SJoachim Eastwood 	{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
996ba289af8SRoger Chen 	{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
997f529f182SJoachim Eastwood 	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
998ba289af8SRoger Chen 	{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
999e0fb4013SJoachim Eastwood 	{ }
1000e0fb4013SJoachim Eastwood };
1001e0fb4013SJoachim Eastwood MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
1002e0fb4013SJoachim Eastwood 
1003e0fb4013SJoachim Eastwood static struct platform_driver rk_gmac_dwmac_driver = {
100427ffefd2SJoachim Eastwood 	.probe  = rk_gmac_probe,
10050de8c4c9SJoachim Eastwood 	.remove = rk_gmac_remove,
1006e0fb4013SJoachim Eastwood 	.driver = {
1007e0fb4013SJoachim Eastwood 		.name           = "rk_gmac-dwmac",
10085619468aSJoachim Eastwood 		.pm		= &rk_gmac_pm_ops,
1009e0fb4013SJoachim Eastwood 		.of_match_table = rk_gmac_dwmac_match,
1010e0fb4013SJoachim Eastwood 	},
1011e0fb4013SJoachim Eastwood };
1012e0fb4013SJoachim Eastwood module_platform_driver(rk_gmac_dwmac_driver);
1013e0fb4013SJoachim Eastwood 
1014e0fb4013SJoachim Eastwood MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
1015e0fb4013SJoachim Eastwood MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
1016e0fb4013SJoachim Eastwood MODULE_LICENSE("GPL");
1017