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>
337ad269eaSRoger Chen 
34e0fb4013SJoachim Eastwood #include "stmmac_platform.h"
35e0fb4013SJoachim Eastwood 
360fb98db1SHeiko Stübner struct rk_priv_data;
370fb98db1SHeiko Stübner struct rk_gmac_ops {
380fb98db1SHeiko Stübner 	void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
390fb98db1SHeiko Stübner 			     int tx_delay, int rx_delay);
400fb98db1SHeiko Stübner 	void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
410fb98db1SHeiko Stübner 	void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
420fb98db1SHeiko Stübner 	void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
430fb98db1SHeiko Stübner };
440fb98db1SHeiko Stübner 
457ad269eaSRoger Chen struct rk_priv_data {
467ad269eaSRoger Chen 	struct platform_device *pdev;
477ad269eaSRoger Chen 	int phy_iface;
482e12f536SRomain Perier 	struct regulator *regulator;
49229666c1SVincent Palatin 	bool suspended;
5092c2588fSJoachim Eastwood 	const struct rk_gmac_ops *ops;
517ad269eaSRoger Chen 
527ad269eaSRoger Chen 	bool clk_enabled;
537ad269eaSRoger Chen 	bool clock_input;
547ad269eaSRoger Chen 
557ad269eaSRoger Chen 	struct clk *clk_mac;
567ad269eaSRoger Chen 	struct clk *gmac_clkin;
577ad269eaSRoger Chen 	struct clk *mac_clk_rx;
587ad269eaSRoger Chen 	struct clk *mac_clk_tx;
597ad269eaSRoger Chen 	struct clk *clk_mac_ref;
607ad269eaSRoger Chen 	struct clk *clk_mac_refout;
617ad269eaSRoger Chen 	struct clk *aclk_mac;
627ad269eaSRoger Chen 	struct clk *pclk_mac;
637ad269eaSRoger Chen 
647ad269eaSRoger Chen 	int tx_delay;
657ad269eaSRoger Chen 	int rx_delay;
667ad269eaSRoger Chen 
677ad269eaSRoger Chen 	struct regmap *grf;
687ad269eaSRoger Chen };
697ad269eaSRoger Chen 
707ad269eaSRoger Chen #define HIWORD_UPDATE(val, mask, shift) \
717ad269eaSRoger Chen 		((val) << (shift) | (mask) << ((shift) + 16))
727ad269eaSRoger Chen 
737ad269eaSRoger Chen #define GRF_BIT(nr)	(BIT(nr) | BIT(nr+16))
747ad269eaSRoger Chen #define GRF_CLR_BIT(nr)	(BIT(nr+16))
757ad269eaSRoger Chen 
76e7ffd812SXing Zheng #define RK3228_GRF_MAC_CON0	0x0900
77e7ffd812SXing Zheng #define RK3228_GRF_MAC_CON1	0x0904
78e7ffd812SXing Zheng 
79e7ffd812SXing Zheng /* RK3228_GRF_MAC_CON0 */
80e7ffd812SXing Zheng #define RK3228_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
81e7ffd812SXing Zheng #define RK3228_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
82e7ffd812SXing Zheng 
83e7ffd812SXing Zheng /* RK3228_GRF_MAC_CON1 */
84e7ffd812SXing Zheng #define RK3228_GMAC_PHY_INTF_SEL_RGMII	\
85e7ffd812SXing Zheng 		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
86e7ffd812SXing Zheng #define RK3228_GMAC_PHY_INTF_SEL_RMII	\
87e7ffd812SXing Zheng 		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
88e7ffd812SXing Zheng #define RK3228_GMAC_FLOW_CTRL		GRF_BIT(3)
89e7ffd812SXing Zheng #define RK3228_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(3)
90e7ffd812SXing Zheng #define RK3228_GMAC_SPEED_10M		GRF_CLR_BIT(2)
91e7ffd812SXing Zheng #define RK3228_GMAC_SPEED_100M		GRF_BIT(2)
92e7ffd812SXing Zheng #define RK3228_GMAC_RMII_CLK_25M	GRF_BIT(7)
93e7ffd812SXing Zheng #define RK3228_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(7)
94e7ffd812SXing Zheng #define RK3228_GMAC_CLK_125M		(GRF_CLR_BIT(8) | GRF_CLR_BIT(9))
95e7ffd812SXing Zheng #define RK3228_GMAC_CLK_25M		(GRF_BIT(8) | GRF_BIT(9))
96e7ffd812SXing Zheng #define RK3228_GMAC_CLK_2_5M		(GRF_CLR_BIT(8) | GRF_BIT(9))
97e7ffd812SXing Zheng #define RK3228_GMAC_RMII_MODE		GRF_BIT(10)
98e7ffd812SXing Zheng #define RK3228_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(10)
99e7ffd812SXing Zheng #define RK3228_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(0)
100e7ffd812SXing Zheng #define RK3228_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(0)
101e7ffd812SXing Zheng #define RK3228_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(1)
102e7ffd812SXing Zheng #define RK3228_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(1)
103e7ffd812SXing Zheng 
104e7ffd812SXing Zheng static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
105e7ffd812SXing Zheng 				int tx_delay, int rx_delay)
106e7ffd812SXing Zheng {
107e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
108e7ffd812SXing Zheng 
109e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
110e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
111e7ffd812SXing Zheng 		return;
112e7ffd812SXing Zheng 	}
113e7ffd812SXing Zheng 
114e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
115e7ffd812SXing Zheng 		     RK3228_GMAC_PHY_INTF_SEL_RGMII |
116e7ffd812SXing Zheng 		     RK3228_GMAC_RMII_MODE_CLR |
117e7ffd812SXing Zheng 		     RK3228_GMAC_RXCLK_DLY_ENABLE |
118e7ffd812SXing Zheng 		     RK3228_GMAC_TXCLK_DLY_ENABLE);
119e7ffd812SXing Zheng 
120e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON0,
121e7ffd812SXing Zheng 		     RK3228_GMAC_CLK_RX_DL_CFG(rx_delay) |
122e7ffd812SXing Zheng 		     RK3228_GMAC_CLK_TX_DL_CFG(tx_delay));
123e7ffd812SXing Zheng }
124e7ffd812SXing Zheng 
125e7ffd812SXing Zheng static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv)
126e7ffd812SXing Zheng {
127e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
128e7ffd812SXing Zheng 
129e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
130e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
131e7ffd812SXing Zheng 		return;
132e7ffd812SXing Zheng 	}
133e7ffd812SXing Zheng 
134e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
135e7ffd812SXing Zheng 		     RK3228_GMAC_PHY_INTF_SEL_RMII |
136e7ffd812SXing Zheng 		     RK3228_GMAC_RMII_MODE);
137e7ffd812SXing Zheng 
138e7ffd812SXing Zheng 	/* set MAC to RMII mode */
139e7ffd812SXing Zheng 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, GRF_BIT(11));
140e7ffd812SXing Zheng }
141e7ffd812SXing Zheng 
142e7ffd812SXing Zheng static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
143e7ffd812SXing Zheng {
144e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
145e7ffd812SXing Zheng 
146e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
147e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
148e7ffd812SXing Zheng 		return;
149e7ffd812SXing Zheng 	}
150e7ffd812SXing Zheng 
151e7ffd812SXing Zheng 	if (speed == 10)
152e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
153e7ffd812SXing Zheng 			     RK3228_GMAC_CLK_2_5M);
154e7ffd812SXing Zheng 	else if (speed == 100)
155e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
156e7ffd812SXing Zheng 			     RK3228_GMAC_CLK_25M);
157e7ffd812SXing Zheng 	else if (speed == 1000)
158e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
159e7ffd812SXing Zheng 			     RK3228_GMAC_CLK_125M);
160e7ffd812SXing Zheng 	else
161e7ffd812SXing Zheng 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
162e7ffd812SXing Zheng }
163e7ffd812SXing Zheng 
164e7ffd812SXing Zheng static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
165e7ffd812SXing Zheng {
166e7ffd812SXing Zheng 	struct device *dev = &bsp_priv->pdev->dev;
167e7ffd812SXing Zheng 
168e7ffd812SXing Zheng 	if (IS_ERR(bsp_priv->grf)) {
169e7ffd812SXing Zheng 		dev_err(dev, "Missing rockchip,grf property\n");
170e7ffd812SXing Zheng 		return;
171e7ffd812SXing Zheng 	}
172e7ffd812SXing Zheng 
173e7ffd812SXing Zheng 	if (speed == 10)
174e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
175e7ffd812SXing Zheng 			     RK3228_GMAC_RMII_CLK_2_5M |
176e7ffd812SXing Zheng 			     RK3228_GMAC_SPEED_10M);
177e7ffd812SXing Zheng 	else if (speed == 100)
178e7ffd812SXing Zheng 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
179e7ffd812SXing Zheng 			     RK3228_GMAC_RMII_CLK_25M |
180e7ffd812SXing Zheng 			     RK3228_GMAC_SPEED_100M);
181e7ffd812SXing Zheng 	else
182e7ffd812SXing Zheng 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
183e7ffd812SXing Zheng }
184e7ffd812SXing Zheng 
185e7ffd812SXing Zheng static const struct rk_gmac_ops rk3228_ops = {
186e7ffd812SXing Zheng 	.set_to_rgmii = rk3228_set_to_rgmii,
187e7ffd812SXing Zheng 	.set_to_rmii = rk3228_set_to_rmii,
188e7ffd812SXing Zheng 	.set_rgmii_speed = rk3228_set_rgmii_speed,
189e7ffd812SXing Zheng 	.set_rmii_speed = rk3228_set_rmii_speed,
190e7ffd812SXing Zheng };
191e7ffd812SXing Zheng 
1927ad269eaSRoger Chen #define RK3288_GRF_SOC_CON1	0x0248
1937ad269eaSRoger Chen #define RK3288_GRF_SOC_CON3	0x0250
1947ad269eaSRoger Chen 
1957ad269eaSRoger Chen /*RK3288_GRF_SOC_CON1*/
1960fb98db1SHeiko Stübner #define RK3288_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | \
1970fb98db1SHeiko Stübner 					 GRF_CLR_BIT(8))
1980fb98db1SHeiko Stübner #define RK3288_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
1990fb98db1SHeiko Stübner 					 GRF_BIT(8))
2000fb98db1SHeiko Stübner #define RK3288_GMAC_FLOW_CTRL		GRF_BIT(9)
2010fb98db1SHeiko Stübner #define RK3288_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(9)
2020fb98db1SHeiko Stübner #define RK3288_GMAC_SPEED_10M		GRF_CLR_BIT(10)
2030fb98db1SHeiko Stübner #define RK3288_GMAC_SPEED_100M		GRF_BIT(10)
2040fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_CLK_25M	GRF_BIT(11)
2050fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(11)
2060fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_125M		(GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
2070fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_25M		(GRF_BIT(12) | GRF_BIT(13))
2080fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_2_5M		(GRF_CLR_BIT(12) | GRF_BIT(13))
2090fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_MODE		GRF_BIT(14)
2100fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(14)
2117ad269eaSRoger Chen 
2127ad269eaSRoger Chen /*RK3288_GRF_SOC_CON3*/
2130fb98db1SHeiko Stübner #define RK3288_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
2140fb98db1SHeiko Stübner #define RK3288_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
2150fb98db1SHeiko Stübner #define RK3288_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
2160fb98db1SHeiko Stübner #define RK3288_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
2170fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
2180fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
2197ad269eaSRoger Chen 
2200fb98db1SHeiko Stübner static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
2217ad269eaSRoger Chen 				int tx_delay, int rx_delay)
2227ad269eaSRoger Chen {
2237ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2247ad269eaSRoger Chen 
2257ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
226d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2277ad269eaSRoger Chen 		return;
2287ad269eaSRoger Chen 	}
2297ad269eaSRoger Chen 
2307ad269eaSRoger Chen 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2310fb98db1SHeiko Stübner 		     RK3288_GMAC_PHY_INTF_SEL_RGMII |
2320fb98db1SHeiko Stübner 		     RK3288_GMAC_RMII_MODE_CLR);
2337ad269eaSRoger Chen 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
2340fb98db1SHeiko Stübner 		     RK3288_GMAC_RXCLK_DLY_ENABLE |
2350fb98db1SHeiko Stübner 		     RK3288_GMAC_TXCLK_DLY_ENABLE |
2360fb98db1SHeiko Stübner 		     RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
2370fb98db1SHeiko Stübner 		     RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
2387ad269eaSRoger Chen }
2397ad269eaSRoger Chen 
2400fb98db1SHeiko Stübner static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
2417ad269eaSRoger Chen {
2427ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2437ad269eaSRoger Chen 
2447ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
245d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2467ad269eaSRoger Chen 		return;
2477ad269eaSRoger Chen 	}
2487ad269eaSRoger Chen 
2497ad269eaSRoger Chen 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2500fb98db1SHeiko Stübner 		     RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
2517ad269eaSRoger Chen }
2527ad269eaSRoger Chen 
2530fb98db1SHeiko Stübner static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
2547ad269eaSRoger Chen {
2557ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2567ad269eaSRoger Chen 
2577ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
258d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2597ad269eaSRoger Chen 		return;
2607ad269eaSRoger Chen 	}
2617ad269eaSRoger Chen 
2627ad269eaSRoger Chen 	if (speed == 10)
2630fb98db1SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2640fb98db1SHeiko Stübner 			     RK3288_GMAC_CLK_2_5M);
2657ad269eaSRoger Chen 	else if (speed == 100)
2660fb98db1SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2670fb98db1SHeiko Stübner 			     RK3288_GMAC_CLK_25M);
2687ad269eaSRoger Chen 	else if (speed == 1000)
2690fb98db1SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2700fb98db1SHeiko Stübner 			     RK3288_GMAC_CLK_125M);
2717ad269eaSRoger Chen 	else
2727ad269eaSRoger Chen 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
2737ad269eaSRoger Chen }
2747ad269eaSRoger Chen 
2750fb98db1SHeiko Stübner static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
2767ad269eaSRoger Chen {
2777ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
2787ad269eaSRoger Chen 
2797ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
280d42202dcSRomain Perier 		dev_err(dev, "Missing rockchip,grf property\n");
2817ad269eaSRoger Chen 		return;
2827ad269eaSRoger Chen 	}
2837ad269eaSRoger Chen 
2847ad269eaSRoger Chen 	if (speed == 10) {
2857ad269eaSRoger Chen 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2860fb98db1SHeiko Stübner 			     RK3288_GMAC_RMII_CLK_2_5M |
2870fb98db1SHeiko Stübner 			     RK3288_GMAC_SPEED_10M);
2887ad269eaSRoger Chen 	} else if (speed == 100) {
2897ad269eaSRoger Chen 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
2900fb98db1SHeiko Stübner 			     RK3288_GMAC_RMII_CLK_25M |
2910fb98db1SHeiko Stübner 			     RK3288_GMAC_SPEED_100M);
2927ad269eaSRoger Chen 	} else {
2937ad269eaSRoger Chen 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
2947ad269eaSRoger Chen 	}
2957ad269eaSRoger Chen }
2967ad269eaSRoger Chen 
29792c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3288_ops = {
2980fb98db1SHeiko Stübner 	.set_to_rgmii = rk3288_set_to_rgmii,
2990fb98db1SHeiko Stübner 	.set_to_rmii = rk3288_set_to_rmii,
3000fb98db1SHeiko Stübner 	.set_rgmii_speed = rk3288_set_rgmii_speed,
3010fb98db1SHeiko Stübner 	.set_rmii_speed = rk3288_set_rmii_speed,
3020fb98db1SHeiko Stübner };
3030fb98db1SHeiko Stübner 
304df558854SHeiko Stübner #define RK3368_GRF_SOC_CON15	0x043c
305df558854SHeiko Stübner #define RK3368_GRF_SOC_CON16	0x0440
306df558854SHeiko Stübner 
307df558854SHeiko Stübner /* RK3368_GRF_SOC_CON15 */
308df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
309df558854SHeiko Stübner 					 GRF_CLR_BIT(11))
310df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
311df558854SHeiko Stübner 					 GRF_BIT(11))
312df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL		GRF_BIT(8)
313df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
314df558854SHeiko Stübner #define RK3368_GMAC_SPEED_10M		GRF_CLR_BIT(7)
315df558854SHeiko Stübner #define RK3368_GMAC_SPEED_100M		GRF_BIT(7)
316df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_25M	GRF_BIT(3)
317df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
318df558854SHeiko Stübner #define RK3368_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
319df558854SHeiko Stübner #define RK3368_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
320df558854SHeiko Stübner #define RK3368_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
321df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE		GRF_BIT(6)
322df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
323df558854SHeiko Stübner 
324df558854SHeiko Stübner /* RK3368_GRF_SOC_CON16 */
325df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
326df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
327df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
328df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
329df558854SHeiko Stübner #define RK3368_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
330df558854SHeiko Stübner #define RK3368_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
331df558854SHeiko Stübner 
332df558854SHeiko Stübner static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
333df558854SHeiko Stübner 				int tx_delay, int rx_delay)
334df558854SHeiko Stübner {
335df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
336df558854SHeiko Stübner 
337df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
338df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
339df558854SHeiko Stübner 		return;
340df558854SHeiko Stübner 	}
341df558854SHeiko Stübner 
342df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
343df558854SHeiko Stübner 		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
344df558854SHeiko Stübner 		     RK3368_GMAC_RMII_MODE_CLR);
345df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
346df558854SHeiko Stübner 		     RK3368_GMAC_RXCLK_DLY_ENABLE |
347df558854SHeiko Stübner 		     RK3368_GMAC_TXCLK_DLY_ENABLE |
348df558854SHeiko Stübner 		     RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
349df558854SHeiko Stübner 		     RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
350df558854SHeiko Stübner }
351df558854SHeiko Stübner 
352df558854SHeiko Stübner static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
353df558854SHeiko Stübner {
354df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
355df558854SHeiko Stübner 
356df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
357df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
358df558854SHeiko Stübner 		return;
359df558854SHeiko Stübner 	}
360df558854SHeiko Stübner 
361df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
362df558854SHeiko Stübner 		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
363df558854SHeiko Stübner }
364df558854SHeiko Stübner 
365df558854SHeiko Stübner static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
366df558854SHeiko Stübner {
367df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
368df558854SHeiko Stübner 
369df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
370df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
371df558854SHeiko Stübner 		return;
372df558854SHeiko Stübner 	}
373df558854SHeiko Stübner 
374df558854SHeiko Stübner 	if (speed == 10)
375df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
376df558854SHeiko Stübner 			     RK3368_GMAC_CLK_2_5M);
377df558854SHeiko Stübner 	else if (speed == 100)
378df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
379df558854SHeiko Stübner 			     RK3368_GMAC_CLK_25M);
380df558854SHeiko Stübner 	else if (speed == 1000)
381df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
382df558854SHeiko Stübner 			     RK3368_GMAC_CLK_125M);
383df558854SHeiko Stübner 	else
384df558854SHeiko Stübner 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
385df558854SHeiko Stübner }
386df558854SHeiko Stübner 
387df558854SHeiko Stübner static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
388df558854SHeiko Stübner {
389df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
390df558854SHeiko Stübner 
391df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
392df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
393df558854SHeiko Stübner 		return;
394df558854SHeiko Stübner 	}
395df558854SHeiko Stübner 
396df558854SHeiko Stübner 	if (speed == 10) {
397df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
398df558854SHeiko Stübner 			     RK3368_GMAC_RMII_CLK_2_5M |
399df558854SHeiko Stübner 			     RK3368_GMAC_SPEED_10M);
400df558854SHeiko Stübner 	} else if (speed == 100) {
401df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
402df558854SHeiko Stübner 			     RK3368_GMAC_RMII_CLK_25M |
403df558854SHeiko Stübner 			     RK3368_GMAC_SPEED_100M);
404df558854SHeiko Stübner 	} else {
405df558854SHeiko Stübner 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
406df558854SHeiko Stübner 	}
407df558854SHeiko Stübner }
408df558854SHeiko Stübner 
40992c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3368_ops = {
410df558854SHeiko Stübner 	.set_to_rgmii = rk3368_set_to_rgmii,
411df558854SHeiko Stübner 	.set_to_rmii = rk3368_set_to_rmii,
412df558854SHeiko Stübner 	.set_rgmii_speed = rk3368_set_rgmii_speed,
413df558854SHeiko Stübner 	.set_rmii_speed = rk3368_set_rmii_speed,
414df558854SHeiko Stübner };
415df558854SHeiko Stübner 
4167ad269eaSRoger Chen static int gmac_clk_init(struct rk_priv_data *bsp_priv)
4177ad269eaSRoger Chen {
4187ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
4197ad269eaSRoger Chen 
4207ad269eaSRoger Chen 	bsp_priv->clk_enabled = false;
4217ad269eaSRoger Chen 
4227ad269eaSRoger Chen 	bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
4237ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->mac_clk_rx))
424d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
425d42202dcSRomain Perier 			"mac_clk_rx");
4267ad269eaSRoger Chen 
4277ad269eaSRoger Chen 	bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
4287ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->mac_clk_tx))
429d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
430d42202dcSRomain Perier 			"mac_clk_tx");
4317ad269eaSRoger Chen 
4327ad269eaSRoger Chen 	bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
4337ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->aclk_mac))
434d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
435d42202dcSRomain Perier 			"aclk_mac");
4367ad269eaSRoger Chen 
4377ad269eaSRoger Chen 	bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
4387ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->pclk_mac))
439d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
440d42202dcSRomain Perier 			"pclk_mac");
4417ad269eaSRoger Chen 
4427ad269eaSRoger Chen 	bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
4437ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->clk_mac))
444d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
445d42202dcSRomain Perier 			"stmmaceth");
4467ad269eaSRoger Chen 
4477ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
4487ad269eaSRoger Chen 		bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
4497ad269eaSRoger Chen 		if (IS_ERR(bsp_priv->clk_mac_ref))
450d42202dcSRomain Perier 			dev_err(dev, "cannot get clock %s\n",
451d42202dcSRomain Perier 				"clk_mac_ref");
4527ad269eaSRoger Chen 
4537ad269eaSRoger Chen 		if (!bsp_priv->clock_input) {
4547ad269eaSRoger Chen 			bsp_priv->clk_mac_refout =
4557ad269eaSRoger Chen 				devm_clk_get(dev, "clk_mac_refout");
4567ad269eaSRoger Chen 			if (IS_ERR(bsp_priv->clk_mac_refout))
457d42202dcSRomain Perier 				dev_err(dev, "cannot get clock %s\n",
458d42202dcSRomain Perier 					"clk_mac_refout");
4597ad269eaSRoger Chen 		}
4607ad269eaSRoger Chen 	}
4617ad269eaSRoger Chen 
4627ad269eaSRoger Chen 	if (bsp_priv->clock_input) {
463d42202dcSRomain Perier 		dev_info(dev, "clock input from PHY\n");
4647ad269eaSRoger Chen 	} else {
4657ad269eaSRoger Chen 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
466c48fa33cSHeiko Stübner 			clk_set_rate(bsp_priv->clk_mac, 50000000);
4677ad269eaSRoger Chen 	}
4687ad269eaSRoger Chen 
4697ad269eaSRoger Chen 	return 0;
4707ad269eaSRoger Chen }
4717ad269eaSRoger Chen 
4727ad269eaSRoger Chen static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
4737ad269eaSRoger Chen {
474428ad1bcSLABBE Corentin 	int phy_iface = bsp_priv->phy_iface;
4757ad269eaSRoger Chen 
4767ad269eaSRoger Chen 	if (enable) {
4777ad269eaSRoger Chen 		if (!bsp_priv->clk_enabled) {
4787ad269eaSRoger Chen 			if (phy_iface == PHY_INTERFACE_MODE_RMII) {
4797ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->mac_clk_rx))
4807ad269eaSRoger Chen 					clk_prepare_enable(
4817ad269eaSRoger Chen 						bsp_priv->mac_clk_rx);
4827ad269eaSRoger Chen 
4837ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_ref))
4847ad269eaSRoger Chen 					clk_prepare_enable(
4857ad269eaSRoger Chen 						bsp_priv->clk_mac_ref);
4867ad269eaSRoger Chen 
4877ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_refout))
4887ad269eaSRoger Chen 					clk_prepare_enable(
4897ad269eaSRoger Chen 						bsp_priv->clk_mac_refout);
4907ad269eaSRoger Chen 			}
4917ad269eaSRoger Chen 
4927ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->aclk_mac))
4937ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->aclk_mac);
4947ad269eaSRoger Chen 
4957ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->pclk_mac))
4967ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->pclk_mac);
4977ad269eaSRoger Chen 
4987ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->mac_clk_tx))
4997ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->mac_clk_tx);
5007ad269eaSRoger Chen 
5017ad269eaSRoger Chen 			/**
5027ad269eaSRoger Chen 			 * if (!IS_ERR(bsp_priv->clk_mac))
5037ad269eaSRoger Chen 			 *	clk_prepare_enable(bsp_priv->clk_mac);
5047ad269eaSRoger Chen 			 */
5057ad269eaSRoger Chen 			mdelay(5);
5067ad269eaSRoger Chen 			bsp_priv->clk_enabled = true;
5077ad269eaSRoger Chen 		}
5087ad269eaSRoger Chen 	} else {
5097ad269eaSRoger Chen 		if (bsp_priv->clk_enabled) {
5107ad269eaSRoger Chen 			if (phy_iface == PHY_INTERFACE_MODE_RMII) {
5117ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->mac_clk_rx))
5127ad269eaSRoger Chen 					clk_disable_unprepare(
5137ad269eaSRoger Chen 						bsp_priv->mac_clk_rx);
5147ad269eaSRoger Chen 
5157ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_ref))
5167ad269eaSRoger Chen 					clk_disable_unprepare(
5177ad269eaSRoger Chen 						bsp_priv->clk_mac_ref);
5187ad269eaSRoger Chen 
5197ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_refout))
5207ad269eaSRoger Chen 					clk_disable_unprepare(
5217ad269eaSRoger Chen 						bsp_priv->clk_mac_refout);
5227ad269eaSRoger Chen 			}
5237ad269eaSRoger Chen 
5247ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->aclk_mac))
5257ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->aclk_mac);
5267ad269eaSRoger Chen 
5277ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->pclk_mac))
5287ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->pclk_mac);
5297ad269eaSRoger Chen 
5307ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->mac_clk_tx))
5317ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->mac_clk_tx);
5327ad269eaSRoger Chen 			/**
5337ad269eaSRoger Chen 			 * if (!IS_ERR(bsp_priv->clk_mac))
5347ad269eaSRoger Chen 			 *	clk_disable_unprepare(bsp_priv->clk_mac);
5357ad269eaSRoger Chen 			 */
5367ad269eaSRoger Chen 			bsp_priv->clk_enabled = false;
5377ad269eaSRoger Chen 		}
5387ad269eaSRoger Chen 	}
5397ad269eaSRoger Chen 
5407ad269eaSRoger Chen 	return 0;
5417ad269eaSRoger Chen }
5427ad269eaSRoger Chen 
5437ad269eaSRoger Chen static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
5447ad269eaSRoger Chen {
5452e12f536SRomain Perier 	struct regulator *ldo = bsp_priv->regulator;
5467ad269eaSRoger Chen 	int ret;
5477ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
5487ad269eaSRoger Chen 
5492e12f536SRomain Perier 	if (!ldo) {
550d42202dcSRomain Perier 		dev_err(dev, "no regulator found\n");
5517ad269eaSRoger Chen 		return -1;
5527ad269eaSRoger Chen 	}
5537ad269eaSRoger Chen 
5547ad269eaSRoger Chen 	if (enable) {
5557ad269eaSRoger Chen 		ret = regulator_enable(ldo);
5562e12f536SRomain Perier 		if (ret)
557d42202dcSRomain Perier 			dev_err(dev, "fail to enable phy-supply\n");
5587ad269eaSRoger Chen 	} else {
5597ad269eaSRoger Chen 		ret = regulator_disable(ldo);
5602e12f536SRomain Perier 		if (ret)
561d42202dcSRomain Perier 			dev_err(dev, "fail to disable phy-supply\n");
5627ad269eaSRoger Chen 	}
5637ad269eaSRoger Chen 
5647ad269eaSRoger Chen 	return 0;
5657ad269eaSRoger Chen }
5667ad269eaSRoger Chen 
5670fb98db1SHeiko Stübner static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
56892c2588fSJoachim Eastwood 					  const struct rk_gmac_ops *ops)
5697ad269eaSRoger Chen {
5707ad269eaSRoger Chen 	struct rk_priv_data *bsp_priv;
5717ad269eaSRoger Chen 	struct device *dev = &pdev->dev;
5727ad269eaSRoger Chen 	int ret;
5737ad269eaSRoger Chen 	const char *strings = NULL;
5747ad269eaSRoger Chen 	int value;
5757ad269eaSRoger Chen 
5767ad269eaSRoger Chen 	bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL);
5777ad269eaSRoger Chen 	if (!bsp_priv)
5787ad269eaSRoger Chen 		return ERR_PTR(-ENOMEM);
5797ad269eaSRoger Chen 
5807ad269eaSRoger Chen 	bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
5810fb98db1SHeiko Stübner 	bsp_priv->ops = ops;
5827ad269eaSRoger Chen 
5832e12f536SRomain Perier 	bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
5842e12f536SRomain Perier 	if (IS_ERR(bsp_priv->regulator)) {
5852e12f536SRomain Perier 		if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
5862e12f536SRomain Perier 			dev_err(dev, "phy regulator is not available yet, deferred probing\n");
5872e12f536SRomain Perier 			return ERR_PTR(-EPROBE_DEFER);
5882e12f536SRomain Perier 		}
5892e12f536SRomain Perier 		dev_err(dev, "no regulator found\n");
5902e12f536SRomain Perier 		bsp_priv->regulator = NULL;
5917ad269eaSRoger Chen 	}
5927ad269eaSRoger Chen 
5937ad269eaSRoger Chen 	ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
5947ad269eaSRoger Chen 	if (ret) {
595d42202dcSRomain Perier 		dev_err(dev, "Can not read property: clock_in_out.\n");
5967ad269eaSRoger Chen 		bsp_priv->clock_input = true;
5977ad269eaSRoger Chen 	} else {
598d42202dcSRomain Perier 		dev_info(dev, "clock input or output? (%s).\n",
599d42202dcSRomain Perier 			 strings);
6007ad269eaSRoger Chen 		if (!strcmp(strings, "input"))
6017ad269eaSRoger Chen 			bsp_priv->clock_input = true;
6027ad269eaSRoger Chen 		else
6037ad269eaSRoger Chen 			bsp_priv->clock_input = false;
6047ad269eaSRoger Chen 	}
6057ad269eaSRoger Chen 
6067ad269eaSRoger Chen 	ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
6077ad269eaSRoger Chen 	if (ret) {
6087ad269eaSRoger Chen 		bsp_priv->tx_delay = 0x30;
609d42202dcSRomain Perier 		dev_err(dev, "Can not read property: tx_delay.");
610d42202dcSRomain Perier 		dev_err(dev, "set tx_delay to 0x%x\n",
611d42202dcSRomain Perier 			bsp_priv->tx_delay);
6127ad269eaSRoger Chen 	} else {
613d42202dcSRomain Perier 		dev_info(dev, "TX delay(0x%x).\n", value);
6147ad269eaSRoger Chen 		bsp_priv->tx_delay = value;
6157ad269eaSRoger Chen 	}
6167ad269eaSRoger Chen 
6177ad269eaSRoger Chen 	ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
6187ad269eaSRoger Chen 	if (ret) {
6197ad269eaSRoger Chen 		bsp_priv->rx_delay = 0x10;
620d42202dcSRomain Perier 		dev_err(dev, "Can not read property: rx_delay.");
621d42202dcSRomain Perier 		dev_err(dev, "set rx_delay to 0x%x\n",
622d42202dcSRomain Perier 			bsp_priv->rx_delay);
6237ad269eaSRoger Chen 	} else {
624d42202dcSRomain Perier 		dev_info(dev, "RX delay(0x%x).\n", value);
6257ad269eaSRoger Chen 		bsp_priv->rx_delay = value;
6267ad269eaSRoger Chen 	}
6277ad269eaSRoger Chen 
6287ad269eaSRoger Chen 	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
6297ad269eaSRoger Chen 							"rockchip,grf");
6307ad269eaSRoger Chen 	bsp_priv->pdev = pdev;
6317ad269eaSRoger Chen 
6327ad269eaSRoger Chen 	/*rmii or rgmii*/
6337ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
634d42202dcSRomain Perier 		dev_info(dev, "init for RGMII\n");
6350fb98db1SHeiko Stübner 		bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
6360fb98db1SHeiko Stübner 					    bsp_priv->rx_delay);
6377ad269eaSRoger Chen 	} else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
638d42202dcSRomain Perier 		dev_info(dev, "init for RMII\n");
6390fb98db1SHeiko Stübner 		bsp_priv->ops->set_to_rmii(bsp_priv);
6407ad269eaSRoger Chen 	} else {
641d42202dcSRomain Perier 		dev_err(dev, "NO interface defined!\n");
6427ad269eaSRoger Chen 	}
6437ad269eaSRoger Chen 
6447ad269eaSRoger Chen 	gmac_clk_init(bsp_priv);
6457ad269eaSRoger Chen 
6467ad269eaSRoger Chen 	return bsp_priv;
6477ad269eaSRoger Chen }
6487ad269eaSRoger Chen 
649229666c1SVincent Palatin static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
6507ad269eaSRoger Chen {
6517ad269eaSRoger Chen 	int ret;
6527ad269eaSRoger Chen 
6537ad269eaSRoger Chen 	ret = phy_power_on(bsp_priv, true);
6547ad269eaSRoger Chen 	if (ret)
6557ad269eaSRoger Chen 		return ret;
6567ad269eaSRoger Chen 
6577ad269eaSRoger Chen 	ret = gmac_clk_enable(bsp_priv, true);
6587ad269eaSRoger Chen 	if (ret)
6597ad269eaSRoger Chen 		return ret;
6607ad269eaSRoger Chen 
6617ad269eaSRoger Chen 	return 0;
6627ad269eaSRoger Chen }
6637ad269eaSRoger Chen 
664229666c1SVincent Palatin static void rk_gmac_powerdown(struct rk_priv_data *gmac)
6657ad269eaSRoger Chen {
6667ad269eaSRoger Chen 	phy_power_on(gmac, false);
6677ad269eaSRoger Chen 	gmac_clk_enable(gmac, false);
6687ad269eaSRoger Chen }
6697ad269eaSRoger Chen 
670229666c1SVincent Palatin static int rk_gmac_init(struct platform_device *pdev, void *priv)
671229666c1SVincent Palatin {
672229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
673229666c1SVincent Palatin 
674229666c1SVincent Palatin 	return rk_gmac_powerup(bsp_priv);
675229666c1SVincent Palatin }
676229666c1SVincent Palatin 
677229666c1SVincent Palatin static void rk_gmac_exit(struct platform_device *pdev, void *priv)
678229666c1SVincent Palatin {
679229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
680229666c1SVincent Palatin 
681229666c1SVincent Palatin 	rk_gmac_powerdown(bsp_priv);
682229666c1SVincent Palatin }
683229666c1SVincent Palatin 
684229666c1SVincent Palatin static void rk_gmac_suspend(struct platform_device *pdev, void *priv)
685229666c1SVincent Palatin {
686229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
687229666c1SVincent Palatin 
688229666c1SVincent Palatin 	/* Keep the PHY up if we use Wake-on-Lan. */
689229666c1SVincent Palatin 	if (device_may_wakeup(&pdev->dev))
690229666c1SVincent Palatin 		return;
691229666c1SVincent Palatin 
692229666c1SVincent Palatin 	rk_gmac_powerdown(bsp_priv);
693229666c1SVincent Palatin 	bsp_priv->suspended = true;
694229666c1SVincent Palatin }
695229666c1SVincent Palatin 
696229666c1SVincent Palatin static void rk_gmac_resume(struct platform_device *pdev, void *priv)
697229666c1SVincent Palatin {
698229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
699229666c1SVincent Palatin 
700229666c1SVincent Palatin 	/* The PHY was up for Wake-on-Lan. */
701229666c1SVincent Palatin 	if (!bsp_priv->suspended)
702229666c1SVincent Palatin 		return;
703229666c1SVincent Palatin 
704229666c1SVincent Palatin 	rk_gmac_powerup(bsp_priv);
705229666c1SVincent Palatin 	bsp_priv->suspended = false;
706229666c1SVincent Palatin }
707229666c1SVincent Palatin 
7087ad269eaSRoger Chen static void rk_fix_speed(void *priv, unsigned int speed)
7097ad269eaSRoger Chen {
7107ad269eaSRoger Chen 	struct rk_priv_data *bsp_priv = priv;
7117ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
7127ad269eaSRoger Chen 
7137ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
7140fb98db1SHeiko Stübner 		bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
7157ad269eaSRoger Chen 	else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
7160fb98db1SHeiko Stübner 		bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
7177ad269eaSRoger Chen 	else
7187ad269eaSRoger Chen 		dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
7197ad269eaSRoger Chen }
7207ad269eaSRoger Chen 
72127ffefd2SJoachim Eastwood static int rk_gmac_probe(struct platform_device *pdev)
72227ffefd2SJoachim Eastwood {
72327ffefd2SJoachim Eastwood 	struct plat_stmmacenet_data *plat_dat;
72427ffefd2SJoachim Eastwood 	struct stmmac_resources stmmac_res;
725f529f182SJoachim Eastwood 	const struct rk_gmac_ops *data;
72627ffefd2SJoachim Eastwood 	int ret;
72727ffefd2SJoachim Eastwood 
728149adeddSJoachim Eastwood 	data = of_device_get_match_data(&pdev->dev);
729149adeddSJoachim Eastwood 	if (!data) {
730149adeddSJoachim Eastwood 		dev_err(&pdev->dev, "no of match data provided\n");
731149adeddSJoachim Eastwood 		return -EINVAL;
732149adeddSJoachim Eastwood 	}
733149adeddSJoachim Eastwood 
73427ffefd2SJoachim Eastwood 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
73527ffefd2SJoachim Eastwood 	if (ret)
73627ffefd2SJoachim Eastwood 		return ret;
73727ffefd2SJoachim Eastwood 
73827ffefd2SJoachim Eastwood 	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
73927ffefd2SJoachim Eastwood 	if (IS_ERR(plat_dat))
74027ffefd2SJoachim Eastwood 		return PTR_ERR(plat_dat);
74127ffefd2SJoachim Eastwood 
74227ffefd2SJoachim Eastwood 	plat_dat->has_gmac = true;
74327ffefd2SJoachim Eastwood 	plat_dat->init = rk_gmac_init;
74427ffefd2SJoachim Eastwood 	plat_dat->exit = rk_gmac_exit;
74527ffefd2SJoachim Eastwood 	plat_dat->fix_mac_speed = rk_fix_speed;
746229666c1SVincent Palatin 	plat_dat->suspend = rk_gmac_suspend;
747229666c1SVincent Palatin 	plat_dat->resume = rk_gmac_resume;
74827ffefd2SJoachim Eastwood 
749f529f182SJoachim Eastwood 	plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
75027ffefd2SJoachim Eastwood 	if (IS_ERR(plat_dat->bsp_priv))
75127ffefd2SJoachim Eastwood 		return PTR_ERR(plat_dat->bsp_priv);
75227ffefd2SJoachim Eastwood 
75327ffefd2SJoachim Eastwood 	ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
75427ffefd2SJoachim Eastwood 	if (ret)
75527ffefd2SJoachim Eastwood 		return ret;
75627ffefd2SJoachim Eastwood 
75727ffefd2SJoachim Eastwood 	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
75827ffefd2SJoachim Eastwood }
75927ffefd2SJoachim Eastwood 
760e0fb4013SJoachim Eastwood static const struct of_device_id rk_gmac_dwmac_match[] = {
761e7ffd812SXing Zheng 	{ .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
762f529f182SJoachim Eastwood 	{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
763f529f182SJoachim Eastwood 	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
764e0fb4013SJoachim Eastwood 	{ }
765e0fb4013SJoachim Eastwood };
766e0fb4013SJoachim Eastwood MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
767e0fb4013SJoachim Eastwood 
768e0fb4013SJoachim Eastwood static struct platform_driver rk_gmac_dwmac_driver = {
76927ffefd2SJoachim Eastwood 	.probe  = rk_gmac_probe,
770e0fb4013SJoachim Eastwood 	.remove = stmmac_pltfr_remove,
771e0fb4013SJoachim Eastwood 	.driver = {
772e0fb4013SJoachim Eastwood 		.name           = "rk_gmac-dwmac",
773e0fb4013SJoachim Eastwood 		.pm		= &stmmac_pltfr_pm_ops,
774e0fb4013SJoachim Eastwood 		.of_match_table = rk_gmac_dwmac_match,
775e0fb4013SJoachim Eastwood 	},
776e0fb4013SJoachim Eastwood };
777e0fb4013SJoachim Eastwood module_platform_driver(rk_gmac_dwmac_driver);
778e0fb4013SJoachim Eastwood 
779e0fb4013SJoachim Eastwood MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
780e0fb4013SJoachim Eastwood MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
781e0fb4013SJoachim Eastwood MODULE_LICENSE("GPL");
782