xref: /openbmc/linux/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c (revision ba289af8020a6e81eac424e1d4ef3fcc8ff1b23d)
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 
304*ba289af8SRoger Chen #define RK3366_GRF_SOC_CON6	0x0418
305*ba289af8SRoger Chen #define RK3366_GRF_SOC_CON7	0x041c
306*ba289af8SRoger Chen 
307*ba289af8SRoger Chen /* RK3366_GRF_SOC_CON6 */
308*ba289af8SRoger Chen #define RK3366_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
309*ba289af8SRoger Chen 					 GRF_CLR_BIT(11))
310*ba289af8SRoger Chen #define RK3366_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
311*ba289af8SRoger Chen 					 GRF_BIT(11))
312*ba289af8SRoger Chen #define RK3366_GMAC_FLOW_CTRL		GRF_BIT(8)
313*ba289af8SRoger Chen #define RK3366_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
314*ba289af8SRoger Chen #define RK3366_GMAC_SPEED_10M		GRF_CLR_BIT(7)
315*ba289af8SRoger Chen #define RK3366_GMAC_SPEED_100M		GRF_BIT(7)
316*ba289af8SRoger Chen #define RK3366_GMAC_RMII_CLK_25M	GRF_BIT(3)
317*ba289af8SRoger Chen #define RK3366_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
318*ba289af8SRoger Chen #define RK3366_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
319*ba289af8SRoger Chen #define RK3366_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
320*ba289af8SRoger Chen #define RK3366_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
321*ba289af8SRoger Chen #define RK3366_GMAC_RMII_MODE		GRF_BIT(6)
322*ba289af8SRoger Chen #define RK3366_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
323*ba289af8SRoger Chen 
324*ba289af8SRoger Chen /* RK3366_GRF_SOC_CON7 */
325*ba289af8SRoger Chen #define RK3366_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
326*ba289af8SRoger Chen #define RK3366_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
327*ba289af8SRoger Chen #define RK3366_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
328*ba289af8SRoger Chen #define RK3366_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
329*ba289af8SRoger Chen #define RK3366_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
330*ba289af8SRoger Chen #define RK3366_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
331*ba289af8SRoger Chen 
332*ba289af8SRoger Chen static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
333*ba289af8SRoger Chen 				int tx_delay, int rx_delay)
334*ba289af8SRoger Chen {
335*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
336*ba289af8SRoger Chen 
337*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
338*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
339*ba289af8SRoger Chen 		return;
340*ba289af8SRoger Chen 	}
341*ba289af8SRoger Chen 
342*ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
343*ba289af8SRoger Chen 		     RK3366_GMAC_PHY_INTF_SEL_RGMII |
344*ba289af8SRoger Chen 		     RK3366_GMAC_RMII_MODE_CLR);
345*ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON7,
346*ba289af8SRoger Chen 		     RK3366_GMAC_RXCLK_DLY_ENABLE |
347*ba289af8SRoger Chen 		     RK3366_GMAC_TXCLK_DLY_ENABLE |
348*ba289af8SRoger Chen 		     RK3366_GMAC_CLK_RX_DL_CFG(rx_delay) |
349*ba289af8SRoger Chen 		     RK3366_GMAC_CLK_TX_DL_CFG(tx_delay));
350*ba289af8SRoger Chen }
351*ba289af8SRoger Chen 
352*ba289af8SRoger Chen static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv)
353*ba289af8SRoger Chen {
354*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
355*ba289af8SRoger Chen 
356*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
357*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
358*ba289af8SRoger Chen 		return;
359*ba289af8SRoger Chen 	}
360*ba289af8SRoger Chen 
361*ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
362*ba289af8SRoger Chen 		     RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE);
363*ba289af8SRoger Chen }
364*ba289af8SRoger Chen 
365*ba289af8SRoger Chen static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
366*ba289af8SRoger Chen {
367*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
368*ba289af8SRoger Chen 
369*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
370*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
371*ba289af8SRoger Chen 		return;
372*ba289af8SRoger Chen 	}
373*ba289af8SRoger Chen 
374*ba289af8SRoger Chen 	if (speed == 10)
375*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
376*ba289af8SRoger Chen 			     RK3366_GMAC_CLK_2_5M);
377*ba289af8SRoger Chen 	else if (speed == 100)
378*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
379*ba289af8SRoger Chen 			     RK3366_GMAC_CLK_25M);
380*ba289af8SRoger Chen 	else if (speed == 1000)
381*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
382*ba289af8SRoger Chen 			     RK3366_GMAC_CLK_125M);
383*ba289af8SRoger Chen 	else
384*ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
385*ba289af8SRoger Chen }
386*ba289af8SRoger Chen 
387*ba289af8SRoger Chen static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
388*ba289af8SRoger Chen {
389*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
390*ba289af8SRoger Chen 
391*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
392*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
393*ba289af8SRoger Chen 		return;
394*ba289af8SRoger Chen 	}
395*ba289af8SRoger Chen 
396*ba289af8SRoger Chen 	if (speed == 10) {
397*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
398*ba289af8SRoger Chen 			     RK3366_GMAC_RMII_CLK_2_5M |
399*ba289af8SRoger Chen 			     RK3366_GMAC_SPEED_10M);
400*ba289af8SRoger Chen 	} else if (speed == 100) {
401*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
402*ba289af8SRoger Chen 			     RK3366_GMAC_RMII_CLK_25M |
403*ba289af8SRoger Chen 			     RK3366_GMAC_SPEED_100M);
404*ba289af8SRoger Chen 	} else {
405*ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
406*ba289af8SRoger Chen 	}
407*ba289af8SRoger Chen }
408*ba289af8SRoger Chen 
409*ba289af8SRoger Chen static const struct rk_gmac_ops rk3366_ops = {
410*ba289af8SRoger Chen 	.set_to_rgmii = rk3366_set_to_rgmii,
411*ba289af8SRoger Chen 	.set_to_rmii = rk3366_set_to_rmii,
412*ba289af8SRoger Chen 	.set_rgmii_speed = rk3366_set_rgmii_speed,
413*ba289af8SRoger Chen 	.set_rmii_speed = rk3366_set_rmii_speed,
414*ba289af8SRoger Chen };
415*ba289af8SRoger Chen 
416df558854SHeiko Stübner #define RK3368_GRF_SOC_CON15	0x043c
417df558854SHeiko Stübner #define RK3368_GRF_SOC_CON16	0x0440
418df558854SHeiko Stübner 
419df558854SHeiko Stübner /* RK3368_GRF_SOC_CON15 */
420df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
421df558854SHeiko Stübner 					 GRF_CLR_BIT(11))
422df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
423df558854SHeiko Stübner 					 GRF_BIT(11))
424df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL		GRF_BIT(8)
425df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
426df558854SHeiko Stübner #define RK3368_GMAC_SPEED_10M		GRF_CLR_BIT(7)
427df558854SHeiko Stübner #define RK3368_GMAC_SPEED_100M		GRF_BIT(7)
428df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_25M	GRF_BIT(3)
429df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
430df558854SHeiko Stübner #define RK3368_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
431df558854SHeiko Stübner #define RK3368_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
432df558854SHeiko Stübner #define RK3368_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
433df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE		GRF_BIT(6)
434df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
435df558854SHeiko Stübner 
436df558854SHeiko Stübner /* RK3368_GRF_SOC_CON16 */
437df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
438df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
439df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
440df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
441df558854SHeiko Stübner #define RK3368_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
442df558854SHeiko Stübner #define RK3368_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
443df558854SHeiko Stübner 
444df558854SHeiko Stübner static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
445df558854SHeiko Stübner 				int tx_delay, int rx_delay)
446df558854SHeiko Stübner {
447df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
448df558854SHeiko Stübner 
449df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
450df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
451df558854SHeiko Stübner 		return;
452df558854SHeiko Stübner 	}
453df558854SHeiko Stübner 
454df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
455df558854SHeiko Stübner 		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
456df558854SHeiko Stübner 		     RK3368_GMAC_RMII_MODE_CLR);
457df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
458df558854SHeiko Stübner 		     RK3368_GMAC_RXCLK_DLY_ENABLE |
459df558854SHeiko Stübner 		     RK3368_GMAC_TXCLK_DLY_ENABLE |
460df558854SHeiko Stübner 		     RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
461df558854SHeiko Stübner 		     RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
462df558854SHeiko Stübner }
463df558854SHeiko Stübner 
464df558854SHeiko Stübner static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
465df558854SHeiko Stübner {
466df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
467df558854SHeiko Stübner 
468df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
469df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
470df558854SHeiko Stübner 		return;
471df558854SHeiko Stübner 	}
472df558854SHeiko Stübner 
473df558854SHeiko Stübner 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
474df558854SHeiko Stübner 		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
475df558854SHeiko Stübner }
476df558854SHeiko Stübner 
477df558854SHeiko Stübner static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
478df558854SHeiko Stübner {
479df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
480df558854SHeiko Stübner 
481df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
482df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
483df558854SHeiko Stübner 		return;
484df558854SHeiko Stübner 	}
485df558854SHeiko Stübner 
486df558854SHeiko Stübner 	if (speed == 10)
487df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
488df558854SHeiko Stübner 			     RK3368_GMAC_CLK_2_5M);
489df558854SHeiko Stübner 	else if (speed == 100)
490df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
491df558854SHeiko Stübner 			     RK3368_GMAC_CLK_25M);
492df558854SHeiko Stübner 	else if (speed == 1000)
493df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
494df558854SHeiko Stübner 			     RK3368_GMAC_CLK_125M);
495df558854SHeiko Stübner 	else
496df558854SHeiko Stübner 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
497df558854SHeiko Stübner }
498df558854SHeiko Stübner 
499df558854SHeiko Stübner static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
500df558854SHeiko Stübner {
501df558854SHeiko Stübner 	struct device *dev = &bsp_priv->pdev->dev;
502df558854SHeiko Stübner 
503df558854SHeiko Stübner 	if (IS_ERR(bsp_priv->grf)) {
504df558854SHeiko Stübner 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
505df558854SHeiko Stübner 		return;
506df558854SHeiko Stübner 	}
507df558854SHeiko Stübner 
508df558854SHeiko Stübner 	if (speed == 10) {
509df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
510df558854SHeiko Stübner 			     RK3368_GMAC_RMII_CLK_2_5M |
511df558854SHeiko Stübner 			     RK3368_GMAC_SPEED_10M);
512df558854SHeiko Stübner 	} else if (speed == 100) {
513df558854SHeiko Stübner 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
514df558854SHeiko Stübner 			     RK3368_GMAC_RMII_CLK_25M |
515df558854SHeiko Stübner 			     RK3368_GMAC_SPEED_100M);
516df558854SHeiko Stübner 	} else {
517df558854SHeiko Stübner 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
518df558854SHeiko Stübner 	}
519df558854SHeiko Stübner }
520df558854SHeiko Stübner 
52192c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3368_ops = {
522df558854SHeiko Stübner 	.set_to_rgmii = rk3368_set_to_rgmii,
523df558854SHeiko Stübner 	.set_to_rmii = rk3368_set_to_rmii,
524df558854SHeiko Stübner 	.set_rgmii_speed = rk3368_set_rgmii_speed,
525df558854SHeiko Stübner 	.set_rmii_speed = rk3368_set_rmii_speed,
526df558854SHeiko Stübner };
527df558854SHeiko Stübner 
528*ba289af8SRoger Chen #define RK3399_GRF_SOC_CON5	0xc214
529*ba289af8SRoger Chen #define RK3399_GRF_SOC_CON6	0xc218
530*ba289af8SRoger Chen 
531*ba289af8SRoger Chen /* RK3399_GRF_SOC_CON5 */
532*ba289af8SRoger Chen #define RK3399_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
533*ba289af8SRoger Chen 					 GRF_CLR_BIT(11))
534*ba289af8SRoger Chen #define RK3399_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
535*ba289af8SRoger Chen 					 GRF_BIT(11))
536*ba289af8SRoger Chen #define RK3399_GMAC_FLOW_CTRL		GRF_BIT(8)
537*ba289af8SRoger Chen #define RK3399_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
538*ba289af8SRoger Chen #define RK3399_GMAC_SPEED_10M		GRF_CLR_BIT(7)
539*ba289af8SRoger Chen #define RK3399_GMAC_SPEED_100M		GRF_BIT(7)
540*ba289af8SRoger Chen #define RK3399_GMAC_RMII_CLK_25M	GRF_BIT(3)
541*ba289af8SRoger Chen #define RK3399_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
542*ba289af8SRoger Chen #define RK3399_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
543*ba289af8SRoger Chen #define RK3399_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
544*ba289af8SRoger Chen #define RK3399_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
545*ba289af8SRoger Chen #define RK3399_GMAC_RMII_MODE		GRF_BIT(6)
546*ba289af8SRoger Chen #define RK3399_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
547*ba289af8SRoger Chen 
548*ba289af8SRoger Chen /* RK3399_GRF_SOC_CON6 */
549*ba289af8SRoger Chen #define RK3399_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
550*ba289af8SRoger Chen #define RK3399_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
551*ba289af8SRoger Chen #define RK3399_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
552*ba289af8SRoger Chen #define RK3399_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
553*ba289af8SRoger Chen #define RK3399_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
554*ba289af8SRoger Chen #define RK3399_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
555*ba289af8SRoger Chen 
556*ba289af8SRoger Chen static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
557*ba289af8SRoger Chen 				int tx_delay, int rx_delay)
558*ba289af8SRoger Chen {
559*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
560*ba289af8SRoger Chen 
561*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
562*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
563*ba289af8SRoger Chen 		return;
564*ba289af8SRoger Chen 	}
565*ba289af8SRoger Chen 
566*ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
567*ba289af8SRoger Chen 		     RK3399_GMAC_PHY_INTF_SEL_RGMII |
568*ba289af8SRoger Chen 		     RK3399_GMAC_RMII_MODE_CLR);
569*ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON6,
570*ba289af8SRoger Chen 		     RK3399_GMAC_RXCLK_DLY_ENABLE |
571*ba289af8SRoger Chen 		     RK3399_GMAC_TXCLK_DLY_ENABLE |
572*ba289af8SRoger Chen 		     RK3399_GMAC_CLK_RX_DL_CFG(rx_delay) |
573*ba289af8SRoger Chen 		     RK3399_GMAC_CLK_TX_DL_CFG(tx_delay));
574*ba289af8SRoger Chen }
575*ba289af8SRoger Chen 
576*ba289af8SRoger Chen static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv)
577*ba289af8SRoger Chen {
578*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
579*ba289af8SRoger Chen 
580*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
581*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
582*ba289af8SRoger Chen 		return;
583*ba289af8SRoger Chen 	}
584*ba289af8SRoger Chen 
585*ba289af8SRoger Chen 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
586*ba289af8SRoger Chen 		     RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE);
587*ba289af8SRoger Chen }
588*ba289af8SRoger Chen 
589*ba289af8SRoger Chen static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
590*ba289af8SRoger Chen {
591*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
592*ba289af8SRoger Chen 
593*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
594*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
595*ba289af8SRoger Chen 		return;
596*ba289af8SRoger Chen 	}
597*ba289af8SRoger Chen 
598*ba289af8SRoger Chen 	if (speed == 10)
599*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
600*ba289af8SRoger Chen 			     RK3399_GMAC_CLK_2_5M);
601*ba289af8SRoger Chen 	else if (speed == 100)
602*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
603*ba289af8SRoger Chen 			     RK3399_GMAC_CLK_25M);
604*ba289af8SRoger Chen 	else if (speed == 1000)
605*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
606*ba289af8SRoger Chen 			     RK3399_GMAC_CLK_125M);
607*ba289af8SRoger Chen 	else
608*ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
609*ba289af8SRoger Chen }
610*ba289af8SRoger Chen 
611*ba289af8SRoger Chen static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
612*ba289af8SRoger Chen {
613*ba289af8SRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
614*ba289af8SRoger Chen 
615*ba289af8SRoger Chen 	if (IS_ERR(bsp_priv->grf)) {
616*ba289af8SRoger Chen 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
617*ba289af8SRoger Chen 		return;
618*ba289af8SRoger Chen 	}
619*ba289af8SRoger Chen 
620*ba289af8SRoger Chen 	if (speed == 10) {
621*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
622*ba289af8SRoger Chen 			     RK3399_GMAC_RMII_CLK_2_5M |
623*ba289af8SRoger Chen 			     RK3399_GMAC_SPEED_10M);
624*ba289af8SRoger Chen 	} else if (speed == 100) {
625*ba289af8SRoger Chen 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
626*ba289af8SRoger Chen 			     RK3399_GMAC_RMII_CLK_25M |
627*ba289af8SRoger Chen 			     RK3399_GMAC_SPEED_100M);
628*ba289af8SRoger Chen 	} else {
629*ba289af8SRoger Chen 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
630*ba289af8SRoger Chen 	}
631*ba289af8SRoger Chen }
632*ba289af8SRoger Chen 
633*ba289af8SRoger Chen static const struct rk_gmac_ops rk3399_ops = {
634*ba289af8SRoger Chen 	.set_to_rgmii = rk3399_set_to_rgmii,
635*ba289af8SRoger Chen 	.set_to_rmii = rk3399_set_to_rmii,
636*ba289af8SRoger Chen 	.set_rgmii_speed = rk3399_set_rgmii_speed,
637*ba289af8SRoger Chen 	.set_rmii_speed = rk3399_set_rmii_speed,
638*ba289af8SRoger Chen };
639*ba289af8SRoger Chen 
6407ad269eaSRoger Chen static int gmac_clk_init(struct rk_priv_data *bsp_priv)
6417ad269eaSRoger Chen {
6427ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
6437ad269eaSRoger Chen 
6447ad269eaSRoger Chen 	bsp_priv->clk_enabled = false;
6457ad269eaSRoger Chen 
6467ad269eaSRoger Chen 	bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
6477ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->mac_clk_rx))
648d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
649d42202dcSRomain Perier 			"mac_clk_rx");
6507ad269eaSRoger Chen 
6517ad269eaSRoger Chen 	bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
6527ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->mac_clk_tx))
653d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
654d42202dcSRomain Perier 			"mac_clk_tx");
6557ad269eaSRoger Chen 
6567ad269eaSRoger Chen 	bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
6577ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->aclk_mac))
658d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
659d42202dcSRomain Perier 			"aclk_mac");
6607ad269eaSRoger Chen 
6617ad269eaSRoger Chen 	bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
6627ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->pclk_mac))
663d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
664d42202dcSRomain Perier 			"pclk_mac");
6657ad269eaSRoger Chen 
6667ad269eaSRoger Chen 	bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
6677ad269eaSRoger Chen 	if (IS_ERR(bsp_priv->clk_mac))
668d42202dcSRomain Perier 		dev_err(dev, "cannot get clock %s\n",
669d42202dcSRomain Perier 			"stmmaceth");
6707ad269eaSRoger Chen 
6717ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
6727ad269eaSRoger Chen 		bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
6737ad269eaSRoger Chen 		if (IS_ERR(bsp_priv->clk_mac_ref))
674d42202dcSRomain Perier 			dev_err(dev, "cannot get clock %s\n",
675d42202dcSRomain Perier 				"clk_mac_ref");
6767ad269eaSRoger Chen 
6777ad269eaSRoger Chen 		if (!bsp_priv->clock_input) {
6787ad269eaSRoger Chen 			bsp_priv->clk_mac_refout =
6797ad269eaSRoger Chen 				devm_clk_get(dev, "clk_mac_refout");
6807ad269eaSRoger Chen 			if (IS_ERR(bsp_priv->clk_mac_refout))
681d42202dcSRomain Perier 				dev_err(dev, "cannot get clock %s\n",
682d42202dcSRomain Perier 					"clk_mac_refout");
6837ad269eaSRoger Chen 		}
6847ad269eaSRoger Chen 	}
6857ad269eaSRoger Chen 
6867ad269eaSRoger Chen 	if (bsp_priv->clock_input) {
687d42202dcSRomain Perier 		dev_info(dev, "clock input from PHY\n");
6887ad269eaSRoger Chen 	} else {
6897ad269eaSRoger Chen 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
690c48fa33cSHeiko Stübner 			clk_set_rate(bsp_priv->clk_mac, 50000000);
6917ad269eaSRoger Chen 	}
6927ad269eaSRoger Chen 
6937ad269eaSRoger Chen 	return 0;
6947ad269eaSRoger Chen }
6957ad269eaSRoger Chen 
6967ad269eaSRoger Chen static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
6977ad269eaSRoger Chen {
698428ad1bcSLABBE Corentin 	int phy_iface = bsp_priv->phy_iface;
6997ad269eaSRoger Chen 
7007ad269eaSRoger Chen 	if (enable) {
7017ad269eaSRoger Chen 		if (!bsp_priv->clk_enabled) {
7027ad269eaSRoger Chen 			if (phy_iface == PHY_INTERFACE_MODE_RMII) {
7037ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->mac_clk_rx))
7047ad269eaSRoger Chen 					clk_prepare_enable(
7057ad269eaSRoger Chen 						bsp_priv->mac_clk_rx);
7067ad269eaSRoger Chen 
7077ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_ref))
7087ad269eaSRoger Chen 					clk_prepare_enable(
7097ad269eaSRoger Chen 						bsp_priv->clk_mac_ref);
7107ad269eaSRoger Chen 
7117ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_refout))
7127ad269eaSRoger Chen 					clk_prepare_enable(
7137ad269eaSRoger Chen 						bsp_priv->clk_mac_refout);
7147ad269eaSRoger Chen 			}
7157ad269eaSRoger Chen 
7167ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->aclk_mac))
7177ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->aclk_mac);
7187ad269eaSRoger Chen 
7197ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->pclk_mac))
7207ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->pclk_mac);
7217ad269eaSRoger Chen 
7227ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->mac_clk_tx))
7237ad269eaSRoger Chen 				clk_prepare_enable(bsp_priv->mac_clk_tx);
7247ad269eaSRoger Chen 
7257ad269eaSRoger Chen 			/**
7267ad269eaSRoger Chen 			 * if (!IS_ERR(bsp_priv->clk_mac))
7277ad269eaSRoger Chen 			 *	clk_prepare_enable(bsp_priv->clk_mac);
7287ad269eaSRoger Chen 			 */
7297ad269eaSRoger Chen 			mdelay(5);
7307ad269eaSRoger Chen 			bsp_priv->clk_enabled = true;
7317ad269eaSRoger Chen 		}
7327ad269eaSRoger Chen 	} else {
7337ad269eaSRoger Chen 		if (bsp_priv->clk_enabled) {
7347ad269eaSRoger Chen 			if (phy_iface == PHY_INTERFACE_MODE_RMII) {
7357ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->mac_clk_rx))
7367ad269eaSRoger Chen 					clk_disable_unprepare(
7377ad269eaSRoger Chen 						bsp_priv->mac_clk_rx);
7387ad269eaSRoger Chen 
7397ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_ref))
7407ad269eaSRoger Chen 					clk_disable_unprepare(
7417ad269eaSRoger Chen 						bsp_priv->clk_mac_ref);
7427ad269eaSRoger Chen 
7437ad269eaSRoger Chen 				if (!IS_ERR(bsp_priv->clk_mac_refout))
7447ad269eaSRoger Chen 					clk_disable_unprepare(
7457ad269eaSRoger Chen 						bsp_priv->clk_mac_refout);
7467ad269eaSRoger Chen 			}
7477ad269eaSRoger Chen 
7487ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->aclk_mac))
7497ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->aclk_mac);
7507ad269eaSRoger Chen 
7517ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->pclk_mac))
7527ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->pclk_mac);
7537ad269eaSRoger Chen 
7547ad269eaSRoger Chen 			if (!IS_ERR(bsp_priv->mac_clk_tx))
7557ad269eaSRoger Chen 				clk_disable_unprepare(bsp_priv->mac_clk_tx);
7567ad269eaSRoger Chen 			/**
7577ad269eaSRoger Chen 			 * if (!IS_ERR(bsp_priv->clk_mac))
7587ad269eaSRoger Chen 			 *	clk_disable_unprepare(bsp_priv->clk_mac);
7597ad269eaSRoger Chen 			 */
7607ad269eaSRoger Chen 			bsp_priv->clk_enabled = false;
7617ad269eaSRoger Chen 		}
7627ad269eaSRoger Chen 	}
7637ad269eaSRoger Chen 
7647ad269eaSRoger Chen 	return 0;
7657ad269eaSRoger Chen }
7667ad269eaSRoger Chen 
7677ad269eaSRoger Chen static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
7687ad269eaSRoger Chen {
7692e12f536SRomain Perier 	struct regulator *ldo = bsp_priv->regulator;
7707ad269eaSRoger Chen 	int ret;
7717ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
7727ad269eaSRoger Chen 
7732e12f536SRomain Perier 	if (!ldo) {
774d42202dcSRomain Perier 		dev_err(dev, "no regulator found\n");
7757ad269eaSRoger Chen 		return -1;
7767ad269eaSRoger Chen 	}
7777ad269eaSRoger Chen 
7787ad269eaSRoger Chen 	if (enable) {
7797ad269eaSRoger Chen 		ret = regulator_enable(ldo);
7802e12f536SRomain Perier 		if (ret)
781d42202dcSRomain Perier 			dev_err(dev, "fail to enable phy-supply\n");
7827ad269eaSRoger Chen 	} else {
7837ad269eaSRoger Chen 		ret = regulator_disable(ldo);
7842e12f536SRomain Perier 		if (ret)
785d42202dcSRomain Perier 			dev_err(dev, "fail to disable phy-supply\n");
7867ad269eaSRoger Chen 	}
7877ad269eaSRoger Chen 
7887ad269eaSRoger Chen 	return 0;
7897ad269eaSRoger Chen }
7907ad269eaSRoger Chen 
7910fb98db1SHeiko Stübner static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
79292c2588fSJoachim Eastwood 					  const struct rk_gmac_ops *ops)
7937ad269eaSRoger Chen {
7947ad269eaSRoger Chen 	struct rk_priv_data *bsp_priv;
7957ad269eaSRoger Chen 	struct device *dev = &pdev->dev;
7967ad269eaSRoger Chen 	int ret;
7977ad269eaSRoger Chen 	const char *strings = NULL;
7987ad269eaSRoger Chen 	int value;
7997ad269eaSRoger Chen 
8007ad269eaSRoger Chen 	bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL);
8017ad269eaSRoger Chen 	if (!bsp_priv)
8027ad269eaSRoger Chen 		return ERR_PTR(-ENOMEM);
8037ad269eaSRoger Chen 
8047ad269eaSRoger Chen 	bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
8050fb98db1SHeiko Stübner 	bsp_priv->ops = ops;
8067ad269eaSRoger Chen 
8072e12f536SRomain Perier 	bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
8082e12f536SRomain Perier 	if (IS_ERR(bsp_priv->regulator)) {
8092e12f536SRomain Perier 		if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
8102e12f536SRomain Perier 			dev_err(dev, "phy regulator is not available yet, deferred probing\n");
8112e12f536SRomain Perier 			return ERR_PTR(-EPROBE_DEFER);
8122e12f536SRomain Perier 		}
8132e12f536SRomain Perier 		dev_err(dev, "no regulator found\n");
8142e12f536SRomain Perier 		bsp_priv->regulator = NULL;
8157ad269eaSRoger Chen 	}
8167ad269eaSRoger Chen 
8177ad269eaSRoger Chen 	ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
8187ad269eaSRoger Chen 	if (ret) {
819d42202dcSRomain Perier 		dev_err(dev, "Can not read property: clock_in_out.\n");
8207ad269eaSRoger Chen 		bsp_priv->clock_input = true;
8217ad269eaSRoger Chen 	} else {
822d42202dcSRomain Perier 		dev_info(dev, "clock input or output? (%s).\n",
823d42202dcSRomain Perier 			 strings);
8247ad269eaSRoger Chen 		if (!strcmp(strings, "input"))
8257ad269eaSRoger Chen 			bsp_priv->clock_input = true;
8267ad269eaSRoger Chen 		else
8277ad269eaSRoger Chen 			bsp_priv->clock_input = false;
8287ad269eaSRoger Chen 	}
8297ad269eaSRoger Chen 
8307ad269eaSRoger Chen 	ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
8317ad269eaSRoger Chen 	if (ret) {
8327ad269eaSRoger Chen 		bsp_priv->tx_delay = 0x30;
833d42202dcSRomain Perier 		dev_err(dev, "Can not read property: tx_delay.");
834d42202dcSRomain Perier 		dev_err(dev, "set tx_delay to 0x%x\n",
835d42202dcSRomain Perier 			bsp_priv->tx_delay);
8367ad269eaSRoger Chen 	} else {
837d42202dcSRomain Perier 		dev_info(dev, "TX delay(0x%x).\n", value);
8387ad269eaSRoger Chen 		bsp_priv->tx_delay = value;
8397ad269eaSRoger Chen 	}
8407ad269eaSRoger Chen 
8417ad269eaSRoger Chen 	ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
8427ad269eaSRoger Chen 	if (ret) {
8437ad269eaSRoger Chen 		bsp_priv->rx_delay = 0x10;
844d42202dcSRomain Perier 		dev_err(dev, "Can not read property: rx_delay.");
845d42202dcSRomain Perier 		dev_err(dev, "set rx_delay to 0x%x\n",
846d42202dcSRomain Perier 			bsp_priv->rx_delay);
8477ad269eaSRoger Chen 	} else {
848d42202dcSRomain Perier 		dev_info(dev, "RX delay(0x%x).\n", value);
8497ad269eaSRoger Chen 		bsp_priv->rx_delay = value;
8507ad269eaSRoger Chen 	}
8517ad269eaSRoger Chen 
8527ad269eaSRoger Chen 	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
8537ad269eaSRoger Chen 							"rockchip,grf");
8547ad269eaSRoger Chen 	bsp_priv->pdev = pdev;
8557ad269eaSRoger Chen 
8567ad269eaSRoger Chen 	/*rmii or rgmii*/
8577ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
858d42202dcSRomain Perier 		dev_info(dev, "init for RGMII\n");
8590fb98db1SHeiko Stübner 		bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
8600fb98db1SHeiko Stübner 					    bsp_priv->rx_delay);
8617ad269eaSRoger Chen 	} else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
862d42202dcSRomain Perier 		dev_info(dev, "init for RMII\n");
8630fb98db1SHeiko Stübner 		bsp_priv->ops->set_to_rmii(bsp_priv);
8647ad269eaSRoger Chen 	} else {
865d42202dcSRomain Perier 		dev_err(dev, "NO interface defined!\n");
8667ad269eaSRoger Chen 	}
8677ad269eaSRoger Chen 
8687ad269eaSRoger Chen 	gmac_clk_init(bsp_priv);
8697ad269eaSRoger Chen 
8707ad269eaSRoger Chen 	return bsp_priv;
8717ad269eaSRoger Chen }
8727ad269eaSRoger Chen 
873229666c1SVincent Palatin static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
8747ad269eaSRoger Chen {
8757ad269eaSRoger Chen 	int ret;
8767ad269eaSRoger Chen 
8777ad269eaSRoger Chen 	ret = phy_power_on(bsp_priv, true);
8787ad269eaSRoger Chen 	if (ret)
8797ad269eaSRoger Chen 		return ret;
8807ad269eaSRoger Chen 
8817ad269eaSRoger Chen 	ret = gmac_clk_enable(bsp_priv, true);
8827ad269eaSRoger Chen 	if (ret)
8837ad269eaSRoger Chen 		return ret;
8847ad269eaSRoger Chen 
8857ad269eaSRoger Chen 	return 0;
8867ad269eaSRoger Chen }
8877ad269eaSRoger Chen 
888229666c1SVincent Palatin static void rk_gmac_powerdown(struct rk_priv_data *gmac)
8897ad269eaSRoger Chen {
8907ad269eaSRoger Chen 	phy_power_on(gmac, false);
8917ad269eaSRoger Chen 	gmac_clk_enable(gmac, false);
8927ad269eaSRoger Chen }
8937ad269eaSRoger Chen 
894229666c1SVincent Palatin static int rk_gmac_init(struct platform_device *pdev, void *priv)
895229666c1SVincent Palatin {
896229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
897229666c1SVincent Palatin 
898229666c1SVincent Palatin 	return rk_gmac_powerup(bsp_priv);
899229666c1SVincent Palatin }
900229666c1SVincent Palatin 
901229666c1SVincent Palatin static void rk_gmac_exit(struct platform_device *pdev, void *priv)
902229666c1SVincent Palatin {
903229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
904229666c1SVincent Palatin 
905229666c1SVincent Palatin 	rk_gmac_powerdown(bsp_priv);
906229666c1SVincent Palatin }
907229666c1SVincent Palatin 
908229666c1SVincent Palatin static void rk_gmac_suspend(struct platform_device *pdev, void *priv)
909229666c1SVincent Palatin {
910229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
911229666c1SVincent Palatin 
912229666c1SVincent Palatin 	/* Keep the PHY up if we use Wake-on-Lan. */
913229666c1SVincent Palatin 	if (device_may_wakeup(&pdev->dev))
914229666c1SVincent Palatin 		return;
915229666c1SVincent Palatin 
916229666c1SVincent Palatin 	rk_gmac_powerdown(bsp_priv);
917229666c1SVincent Palatin 	bsp_priv->suspended = true;
918229666c1SVincent Palatin }
919229666c1SVincent Palatin 
920229666c1SVincent Palatin static void rk_gmac_resume(struct platform_device *pdev, void *priv)
921229666c1SVincent Palatin {
922229666c1SVincent Palatin 	struct rk_priv_data *bsp_priv = priv;
923229666c1SVincent Palatin 
924229666c1SVincent Palatin 	/* The PHY was up for Wake-on-Lan. */
925229666c1SVincent Palatin 	if (!bsp_priv->suspended)
926229666c1SVincent Palatin 		return;
927229666c1SVincent Palatin 
928229666c1SVincent Palatin 	rk_gmac_powerup(bsp_priv);
929229666c1SVincent Palatin 	bsp_priv->suspended = false;
930229666c1SVincent Palatin }
931229666c1SVincent Palatin 
9327ad269eaSRoger Chen static void rk_fix_speed(void *priv, unsigned int speed)
9337ad269eaSRoger Chen {
9347ad269eaSRoger Chen 	struct rk_priv_data *bsp_priv = priv;
9357ad269eaSRoger Chen 	struct device *dev = &bsp_priv->pdev->dev;
9367ad269eaSRoger Chen 
9377ad269eaSRoger Chen 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
9380fb98db1SHeiko Stübner 		bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
9397ad269eaSRoger Chen 	else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
9400fb98db1SHeiko Stübner 		bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
9417ad269eaSRoger Chen 	else
9427ad269eaSRoger Chen 		dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
9437ad269eaSRoger Chen }
9447ad269eaSRoger Chen 
94527ffefd2SJoachim Eastwood static int rk_gmac_probe(struct platform_device *pdev)
94627ffefd2SJoachim Eastwood {
94727ffefd2SJoachim Eastwood 	struct plat_stmmacenet_data *plat_dat;
94827ffefd2SJoachim Eastwood 	struct stmmac_resources stmmac_res;
949f529f182SJoachim Eastwood 	const struct rk_gmac_ops *data;
95027ffefd2SJoachim Eastwood 	int ret;
95127ffefd2SJoachim Eastwood 
952149adeddSJoachim Eastwood 	data = of_device_get_match_data(&pdev->dev);
953149adeddSJoachim Eastwood 	if (!data) {
954149adeddSJoachim Eastwood 		dev_err(&pdev->dev, "no of match data provided\n");
955149adeddSJoachim Eastwood 		return -EINVAL;
956149adeddSJoachim Eastwood 	}
957149adeddSJoachim Eastwood 
95827ffefd2SJoachim Eastwood 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
95927ffefd2SJoachim Eastwood 	if (ret)
96027ffefd2SJoachim Eastwood 		return ret;
96127ffefd2SJoachim Eastwood 
96227ffefd2SJoachim Eastwood 	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
96327ffefd2SJoachim Eastwood 	if (IS_ERR(plat_dat))
96427ffefd2SJoachim Eastwood 		return PTR_ERR(plat_dat);
96527ffefd2SJoachim Eastwood 
96627ffefd2SJoachim Eastwood 	plat_dat->has_gmac = true;
96727ffefd2SJoachim Eastwood 	plat_dat->init = rk_gmac_init;
96827ffefd2SJoachim Eastwood 	plat_dat->exit = rk_gmac_exit;
96927ffefd2SJoachim Eastwood 	plat_dat->fix_mac_speed = rk_fix_speed;
970229666c1SVincent Palatin 	plat_dat->suspend = rk_gmac_suspend;
971229666c1SVincent Palatin 	plat_dat->resume = rk_gmac_resume;
97227ffefd2SJoachim Eastwood 
973f529f182SJoachim Eastwood 	plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
97427ffefd2SJoachim Eastwood 	if (IS_ERR(plat_dat->bsp_priv))
97527ffefd2SJoachim Eastwood 		return PTR_ERR(plat_dat->bsp_priv);
97627ffefd2SJoachim Eastwood 
97727ffefd2SJoachim Eastwood 	ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
97827ffefd2SJoachim Eastwood 	if (ret)
97927ffefd2SJoachim Eastwood 		return ret;
98027ffefd2SJoachim Eastwood 
98127ffefd2SJoachim Eastwood 	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
98227ffefd2SJoachim Eastwood }
98327ffefd2SJoachim Eastwood 
984e0fb4013SJoachim Eastwood static const struct of_device_id rk_gmac_dwmac_match[] = {
985e7ffd812SXing Zheng 	{ .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
986f529f182SJoachim Eastwood 	{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
987*ba289af8SRoger Chen 	{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
988f529f182SJoachim Eastwood 	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
989*ba289af8SRoger Chen 	{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
990e0fb4013SJoachim Eastwood 	{ }
991e0fb4013SJoachim Eastwood };
992e0fb4013SJoachim Eastwood MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
993e0fb4013SJoachim Eastwood 
994e0fb4013SJoachim Eastwood static struct platform_driver rk_gmac_dwmac_driver = {
99527ffefd2SJoachim Eastwood 	.probe  = rk_gmac_probe,
996e0fb4013SJoachim Eastwood 	.remove = stmmac_pltfr_remove,
997e0fb4013SJoachim Eastwood 	.driver = {
998e0fb4013SJoachim Eastwood 		.name           = "rk_gmac-dwmac",
999e0fb4013SJoachim Eastwood 		.pm		= &stmmac_pltfr_pm_ops,
1000e0fb4013SJoachim Eastwood 		.of_match_table = rk_gmac_dwmac_match,
1001e0fb4013SJoachim Eastwood 	},
1002e0fb4013SJoachim Eastwood };
1003e0fb4013SJoachim Eastwood module_platform_driver(rk_gmac_dwmac_driver);
1004e0fb4013SJoachim Eastwood 
1005e0fb4013SJoachim Eastwood MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
1006e0fb4013SJoachim Eastwood MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
1007e0fb4013SJoachim Eastwood MODULE_LICENSE("GPL");
1008