Commit | Line | Data |
---|---|---|
7ad269ea RC |
1 | /** |
2 | * dwmac-rk.c - Rockchip RK3288 DWMAC specific glue layer | |
3 | * | |
4 | * Copyright (C) 2014 Chen-Zhi (Roger Chen) | |
5 | * | |
6 | * Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | */ | |
18 | ||
19 | #include <linux/stmmac.h> | |
20 | #include <linux/bitops.h> | |
21 | #include <linux/clk.h> | |
22 | #include <linux/phy.h> | |
23 | #include <linux/of_net.h> | |
24 | #include <linux/gpio.h> | |
e0fb4013 | 25 | #include <linux/module.h> |
7ad269ea RC |
26 | #include <linux/of_gpio.h> |
27 | #include <linux/of_device.h> | |
e0fb4013 | 28 | #include <linux/platform_device.h> |
7ad269ea RC |
29 | #include <linux/regulator/consumer.h> |
30 | #include <linux/delay.h> | |
31 | #include <linux/mfd/syscon.h> | |
32 | #include <linux/regmap.h> | |
2c896fb0 | 33 | #include <linux/pm_runtime.h> |
7ad269ea | 34 | |
e0fb4013 JE |
35 | #include "stmmac_platform.h" |
36 | ||
0fb98db1 HS |
37 | struct rk_priv_data; |
38 | struct rk_gmac_ops { | |
39 | void (*set_to_rgmii)(struct rk_priv_data *bsp_priv, | |
40 | int tx_delay, int rx_delay); | |
41 | void (*set_to_rmii)(struct rk_priv_data *bsp_priv); | |
42 | void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); | |
43 | void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); | |
44 | }; | |
45 | ||
7ad269ea RC |
46 | struct rk_priv_data { |
47 | struct platform_device *pdev; | |
48 | int phy_iface; | |
2e12f536 | 49 | struct regulator *regulator; |
229666c1 | 50 | bool suspended; |
92c2588f | 51 | const struct rk_gmac_ops *ops; |
7ad269ea RC |
52 | |
53 | bool clk_enabled; | |
54 | bool clock_input; | |
55 | ||
56 | struct clk *clk_mac; | |
7ad269ea RC |
57 | struct clk *gmac_clkin; |
58 | struct clk *mac_clk_rx; | |
59 | struct clk *mac_clk_tx; | |
60 | struct clk *clk_mac_ref; | |
61 | struct clk *clk_mac_refout; | |
62 | struct clk *aclk_mac; | |
63 | struct clk *pclk_mac; | |
64 | ||
65 | int tx_delay; | |
66 | int rx_delay; | |
67 | ||
68 | struct regmap *grf; | |
69 | }; | |
70 | ||
71 | #define HIWORD_UPDATE(val, mask, shift) \ | |
72 | ((val) << (shift) | (mask) << ((shift) + 16)) | |
73 | ||
74 | #define GRF_BIT(nr) (BIT(nr) | BIT(nr+16)) | |
75 | #define GRF_CLR_BIT(nr) (BIT(nr+16)) | |
76 | ||
e7ffd812 XZ |
77 | #define RK3228_GRF_MAC_CON0 0x0900 |
78 | #define RK3228_GRF_MAC_CON1 0x0904 | |
79 | ||
80 | /* RK3228_GRF_MAC_CON0 */ | |
81 | #define RK3228_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) | |
82 | #define RK3228_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) | |
83 | ||
84 | /* RK3228_GRF_MAC_CON1 */ | |
85 | #define RK3228_GMAC_PHY_INTF_SEL_RGMII \ | |
86 | (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) | |
87 | #define RK3228_GMAC_PHY_INTF_SEL_RMII \ | |
88 | (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6)) | |
89 | #define RK3228_GMAC_FLOW_CTRL GRF_BIT(3) | |
90 | #define RK3228_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3) | |
91 | #define RK3228_GMAC_SPEED_10M GRF_CLR_BIT(2) | |
92 | #define RK3228_GMAC_SPEED_100M GRF_BIT(2) | |
93 | #define RK3228_GMAC_RMII_CLK_25M GRF_BIT(7) | |
94 | #define RK3228_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7) | |
95 | #define RK3228_GMAC_CLK_125M (GRF_CLR_BIT(8) | GRF_CLR_BIT(9)) | |
96 | #define RK3228_GMAC_CLK_25M (GRF_BIT(8) | GRF_BIT(9)) | |
97 | #define RK3228_GMAC_CLK_2_5M (GRF_CLR_BIT(8) | GRF_BIT(9)) | |
98 | #define RK3228_GMAC_RMII_MODE GRF_BIT(10) | |
99 | #define RK3228_GMAC_RMII_MODE_CLR GRF_CLR_BIT(10) | |
100 | #define RK3228_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0) | |
101 | #define RK3228_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0) | |
102 | #define RK3228_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1) | |
103 | #define RK3228_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1) | |
104 | ||
105 | static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv, | |
106 | int tx_delay, int rx_delay) | |
107 | { | |
108 | struct device *dev = &bsp_priv->pdev->dev; | |
109 | ||
110 | if (IS_ERR(bsp_priv->grf)) { | |
111 | dev_err(dev, "Missing rockchip,grf property\n"); | |
112 | return; | |
113 | } | |
114 | ||
115 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
116 | RK3228_GMAC_PHY_INTF_SEL_RGMII | | |
117 | RK3228_GMAC_RMII_MODE_CLR | | |
118 | RK3228_GMAC_RXCLK_DLY_ENABLE | | |
119 | RK3228_GMAC_TXCLK_DLY_ENABLE); | |
120 | ||
121 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON0, | |
122 | RK3228_GMAC_CLK_RX_DL_CFG(rx_delay) | | |
123 | RK3228_GMAC_CLK_TX_DL_CFG(tx_delay)); | |
124 | } | |
125 | ||
126 | static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv) | |
127 | { | |
128 | struct device *dev = &bsp_priv->pdev->dev; | |
129 | ||
130 | if (IS_ERR(bsp_priv->grf)) { | |
131 | dev_err(dev, "Missing rockchip,grf property\n"); | |
132 | return; | |
133 | } | |
134 | ||
135 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
136 | RK3228_GMAC_PHY_INTF_SEL_RMII | | |
137 | RK3228_GMAC_RMII_MODE); | |
138 | ||
139 | /* set MAC to RMII mode */ | |
140 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, GRF_BIT(11)); | |
141 | } | |
142 | ||
143 | static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
144 | { | |
145 | struct device *dev = &bsp_priv->pdev->dev; | |
146 | ||
147 | if (IS_ERR(bsp_priv->grf)) { | |
148 | dev_err(dev, "Missing rockchip,grf property\n"); | |
149 | return; | |
150 | } | |
151 | ||
152 | if (speed == 10) | |
153 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
154 | RK3228_GMAC_CLK_2_5M); | |
155 | else if (speed == 100) | |
156 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
157 | RK3228_GMAC_CLK_25M); | |
158 | else if (speed == 1000) | |
159 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
160 | RK3228_GMAC_CLK_125M); | |
161 | else | |
162 | dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); | |
163 | } | |
164 | ||
165 | static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
166 | { | |
167 | struct device *dev = &bsp_priv->pdev->dev; | |
168 | ||
169 | if (IS_ERR(bsp_priv->grf)) { | |
170 | dev_err(dev, "Missing rockchip,grf property\n"); | |
171 | return; | |
172 | } | |
173 | ||
174 | if (speed == 10) | |
175 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
176 | RK3228_GMAC_RMII_CLK_2_5M | | |
177 | RK3228_GMAC_SPEED_10M); | |
178 | else if (speed == 100) | |
179 | regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, | |
180 | RK3228_GMAC_RMII_CLK_25M | | |
181 | RK3228_GMAC_SPEED_100M); | |
182 | else | |
183 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | |
184 | } | |
185 | ||
186 | static const struct rk_gmac_ops rk3228_ops = { | |
187 | .set_to_rgmii = rk3228_set_to_rgmii, | |
188 | .set_to_rmii = rk3228_set_to_rmii, | |
189 | .set_rgmii_speed = rk3228_set_rgmii_speed, | |
190 | .set_rmii_speed = rk3228_set_rmii_speed, | |
191 | }; | |
192 | ||
7ad269ea RC |
193 | #define RK3288_GRF_SOC_CON1 0x0248 |
194 | #define RK3288_GRF_SOC_CON3 0x0250 | |
7ad269ea RC |
195 | |
196 | /*RK3288_GRF_SOC_CON1*/ | |
0fb98db1 HS |
197 | #define RK3288_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | \ |
198 | GRF_CLR_BIT(8)) | |
199 | #define RK3288_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \ | |
200 | GRF_BIT(8)) | |
201 | #define RK3288_GMAC_FLOW_CTRL GRF_BIT(9) | |
202 | #define RK3288_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9) | |
203 | #define RK3288_GMAC_SPEED_10M GRF_CLR_BIT(10) | |
204 | #define RK3288_GMAC_SPEED_100M GRF_BIT(10) | |
205 | #define RK3288_GMAC_RMII_CLK_25M GRF_BIT(11) | |
206 | #define RK3288_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11) | |
207 | #define RK3288_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13)) | |
208 | #define RK3288_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13)) | |
209 | #define RK3288_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13)) | |
210 | #define RK3288_GMAC_RMII_MODE GRF_BIT(14) | |
211 | #define RK3288_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14) | |
7ad269ea RC |
212 | |
213 | /*RK3288_GRF_SOC_CON3*/ | |
0fb98db1 HS |
214 | #define RK3288_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) |
215 | #define RK3288_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) | |
216 | #define RK3288_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) | |
217 | #define RK3288_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) | |
218 | #define RK3288_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) | |
219 | #define RK3288_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) | |
220 | ||
221 | static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv, | |
222 | int tx_delay, int rx_delay) | |
7ad269ea RC |
223 | { |
224 | struct device *dev = &bsp_priv->pdev->dev; | |
225 | ||
226 | if (IS_ERR(bsp_priv->grf)) { | |
d42202dc | 227 | dev_err(dev, "Missing rockchip,grf property\n"); |
7ad269ea RC |
228 | return; |
229 | } | |
230 | ||
231 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | |
0fb98db1 HS |
232 | RK3288_GMAC_PHY_INTF_SEL_RGMII | |
233 | RK3288_GMAC_RMII_MODE_CLR); | |
7ad269ea | 234 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3, |
0fb98db1 HS |
235 | RK3288_GMAC_RXCLK_DLY_ENABLE | |
236 | RK3288_GMAC_TXCLK_DLY_ENABLE | | |
237 | RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) | | |
238 | RK3288_GMAC_CLK_TX_DL_CFG(tx_delay)); | |
7ad269ea RC |
239 | } |
240 | ||
0fb98db1 | 241 | static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv) |
7ad269ea RC |
242 | { |
243 | struct device *dev = &bsp_priv->pdev->dev; | |
244 | ||
245 | if (IS_ERR(bsp_priv->grf)) { | |
d42202dc | 246 | dev_err(dev, "Missing rockchip,grf property\n"); |
7ad269ea RC |
247 | return; |
248 | } | |
249 | ||
250 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | |
0fb98db1 | 251 | RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE); |
7ad269ea RC |
252 | } |
253 | ||
0fb98db1 | 254 | static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) |
7ad269ea RC |
255 | { |
256 | struct device *dev = &bsp_priv->pdev->dev; | |
257 | ||
258 | if (IS_ERR(bsp_priv->grf)) { | |
d42202dc | 259 | dev_err(dev, "Missing rockchip,grf property\n"); |
7ad269ea RC |
260 | return; |
261 | } | |
262 | ||
263 | if (speed == 10) | |
0fb98db1 HS |
264 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, |
265 | RK3288_GMAC_CLK_2_5M); | |
7ad269ea | 266 | else if (speed == 100) |
0fb98db1 HS |
267 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, |
268 | RK3288_GMAC_CLK_25M); | |
7ad269ea | 269 | else if (speed == 1000) |
0fb98db1 HS |
270 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, |
271 | RK3288_GMAC_CLK_125M); | |
7ad269ea RC |
272 | else |
273 | dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); | |
274 | } | |
275 | ||
0fb98db1 | 276 | static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) |
7ad269ea RC |
277 | { |
278 | struct device *dev = &bsp_priv->pdev->dev; | |
279 | ||
280 | if (IS_ERR(bsp_priv->grf)) { | |
d42202dc | 281 | dev_err(dev, "Missing rockchip,grf property\n"); |
7ad269ea RC |
282 | return; |
283 | } | |
284 | ||
285 | if (speed == 10) { | |
286 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | |
0fb98db1 HS |
287 | RK3288_GMAC_RMII_CLK_2_5M | |
288 | RK3288_GMAC_SPEED_10M); | |
7ad269ea RC |
289 | } else if (speed == 100) { |
290 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | |
0fb98db1 HS |
291 | RK3288_GMAC_RMII_CLK_25M | |
292 | RK3288_GMAC_SPEED_100M); | |
7ad269ea RC |
293 | } else { |
294 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | |
295 | } | |
296 | } | |
297 | ||
92c2588f | 298 | static const struct rk_gmac_ops rk3288_ops = { |
0fb98db1 HS |
299 | .set_to_rgmii = rk3288_set_to_rgmii, |
300 | .set_to_rmii = rk3288_set_to_rmii, | |
301 | .set_rgmii_speed = rk3288_set_rgmii_speed, | |
302 | .set_rmii_speed = rk3288_set_rmii_speed, | |
303 | }; | |
304 | ||
ba289af8 RC |
305 | #define RK3366_GRF_SOC_CON6 0x0418 |
306 | #define RK3366_GRF_SOC_CON7 0x041c | |
307 | ||
308 | /* RK3366_GRF_SOC_CON6 */ | |
309 | #define RK3366_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ | |
310 | GRF_CLR_BIT(11)) | |
311 | #define RK3366_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ | |
312 | GRF_BIT(11)) | |
313 | #define RK3366_GMAC_FLOW_CTRL GRF_BIT(8) | |
314 | #define RK3366_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) | |
315 | #define RK3366_GMAC_SPEED_10M GRF_CLR_BIT(7) | |
316 | #define RK3366_GMAC_SPEED_100M GRF_BIT(7) | |
317 | #define RK3366_GMAC_RMII_CLK_25M GRF_BIT(3) | |
318 | #define RK3366_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) | |
319 | #define RK3366_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) | |
320 | #define RK3366_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) | |
321 | #define RK3366_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) | |
322 | #define RK3366_GMAC_RMII_MODE GRF_BIT(6) | |
323 | #define RK3366_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) | |
324 | ||
325 | /* RK3366_GRF_SOC_CON7 */ | |
326 | #define RK3366_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) | |
327 | #define RK3366_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) | |
328 | #define RK3366_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) | |
329 | #define RK3366_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) | |
330 | #define RK3366_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) | |
331 | #define RK3366_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) | |
332 | ||
333 | static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv, | |
334 | int tx_delay, int rx_delay) | |
335 | { | |
336 | struct device *dev = &bsp_priv->pdev->dev; | |
337 | ||
338 | if (IS_ERR(bsp_priv->grf)) { | |
339 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
340 | return; | |
341 | } | |
342 | ||
343 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
344 | RK3366_GMAC_PHY_INTF_SEL_RGMII | | |
345 | RK3366_GMAC_RMII_MODE_CLR); | |
346 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON7, | |
347 | RK3366_GMAC_RXCLK_DLY_ENABLE | | |
348 | RK3366_GMAC_TXCLK_DLY_ENABLE | | |
349 | RK3366_GMAC_CLK_RX_DL_CFG(rx_delay) | | |
350 | RK3366_GMAC_CLK_TX_DL_CFG(tx_delay)); | |
351 | } | |
352 | ||
353 | static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv) | |
354 | { | |
355 | struct device *dev = &bsp_priv->pdev->dev; | |
356 | ||
357 | if (IS_ERR(bsp_priv->grf)) { | |
358 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
359 | return; | |
360 | } | |
361 | ||
362 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
363 | RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE); | |
364 | } | |
365 | ||
366 | static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
367 | { | |
368 | struct device *dev = &bsp_priv->pdev->dev; | |
369 | ||
370 | if (IS_ERR(bsp_priv->grf)) { | |
371 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
372 | return; | |
373 | } | |
374 | ||
375 | if (speed == 10) | |
376 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
377 | RK3366_GMAC_CLK_2_5M); | |
378 | else if (speed == 100) | |
379 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
380 | RK3366_GMAC_CLK_25M); | |
381 | else if (speed == 1000) | |
382 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
383 | RK3366_GMAC_CLK_125M); | |
384 | else | |
385 | dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); | |
386 | } | |
387 | ||
388 | static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
389 | { | |
390 | struct device *dev = &bsp_priv->pdev->dev; | |
391 | ||
392 | if (IS_ERR(bsp_priv->grf)) { | |
393 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
394 | return; | |
395 | } | |
396 | ||
397 | if (speed == 10) { | |
398 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
399 | RK3366_GMAC_RMII_CLK_2_5M | | |
400 | RK3366_GMAC_SPEED_10M); | |
401 | } else if (speed == 100) { | |
402 | regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, | |
403 | RK3366_GMAC_RMII_CLK_25M | | |
404 | RK3366_GMAC_SPEED_100M); | |
405 | } else { | |
406 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | |
407 | } | |
408 | } | |
409 | ||
410 | static const struct rk_gmac_ops rk3366_ops = { | |
411 | .set_to_rgmii = rk3366_set_to_rgmii, | |
412 | .set_to_rmii = rk3366_set_to_rmii, | |
413 | .set_rgmii_speed = rk3366_set_rgmii_speed, | |
414 | .set_rmii_speed = rk3366_set_rmii_speed, | |
415 | }; | |
416 | ||
df558854 HS |
417 | #define RK3368_GRF_SOC_CON15 0x043c |
418 | #define RK3368_GRF_SOC_CON16 0x0440 | |
419 | ||
420 | /* RK3368_GRF_SOC_CON15 */ | |
421 | #define RK3368_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ | |
422 | GRF_CLR_BIT(11)) | |
423 | #define RK3368_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ | |
424 | GRF_BIT(11)) | |
425 | #define RK3368_GMAC_FLOW_CTRL GRF_BIT(8) | |
426 | #define RK3368_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) | |
427 | #define RK3368_GMAC_SPEED_10M GRF_CLR_BIT(7) | |
428 | #define RK3368_GMAC_SPEED_100M GRF_BIT(7) | |
429 | #define RK3368_GMAC_RMII_CLK_25M GRF_BIT(3) | |
430 | #define RK3368_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) | |
431 | #define RK3368_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) | |
432 | #define RK3368_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) | |
433 | #define RK3368_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) | |
434 | #define RK3368_GMAC_RMII_MODE GRF_BIT(6) | |
435 | #define RK3368_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) | |
436 | ||
437 | /* RK3368_GRF_SOC_CON16 */ | |
438 | #define RK3368_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) | |
439 | #define RK3368_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) | |
440 | #define RK3368_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) | |
441 | #define RK3368_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) | |
442 | #define RK3368_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) | |
443 | #define RK3368_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) | |
444 | ||
445 | static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv, | |
446 | int tx_delay, int rx_delay) | |
447 | { | |
448 | struct device *dev = &bsp_priv->pdev->dev; | |
449 | ||
450 | if (IS_ERR(bsp_priv->grf)) { | |
451 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
452 | return; | |
453 | } | |
454 | ||
455 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
456 | RK3368_GMAC_PHY_INTF_SEL_RGMII | | |
457 | RK3368_GMAC_RMII_MODE_CLR); | |
458 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16, | |
459 | RK3368_GMAC_RXCLK_DLY_ENABLE | | |
460 | RK3368_GMAC_TXCLK_DLY_ENABLE | | |
461 | RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) | | |
462 | RK3368_GMAC_CLK_TX_DL_CFG(tx_delay)); | |
463 | } | |
464 | ||
465 | static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv) | |
466 | { | |
467 | struct device *dev = &bsp_priv->pdev->dev; | |
468 | ||
469 | if (IS_ERR(bsp_priv->grf)) { | |
470 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
471 | return; | |
472 | } | |
473 | ||
474 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
475 | RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE); | |
476 | } | |
477 | ||
478 | static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
479 | { | |
480 | struct device *dev = &bsp_priv->pdev->dev; | |
481 | ||
482 | if (IS_ERR(bsp_priv->grf)) { | |
483 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
484 | return; | |
485 | } | |
486 | ||
487 | if (speed == 10) | |
488 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
489 | RK3368_GMAC_CLK_2_5M); | |
490 | else if (speed == 100) | |
491 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
492 | RK3368_GMAC_CLK_25M); | |
493 | else if (speed == 1000) | |
494 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
495 | RK3368_GMAC_CLK_125M); | |
496 | else | |
497 | dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); | |
498 | } | |
499 | ||
500 | static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
501 | { | |
502 | struct device *dev = &bsp_priv->pdev->dev; | |
503 | ||
504 | if (IS_ERR(bsp_priv->grf)) { | |
505 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
506 | return; | |
507 | } | |
508 | ||
509 | if (speed == 10) { | |
510 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
511 | RK3368_GMAC_RMII_CLK_2_5M | | |
512 | RK3368_GMAC_SPEED_10M); | |
513 | } else if (speed == 100) { | |
514 | regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, | |
515 | RK3368_GMAC_RMII_CLK_25M | | |
516 | RK3368_GMAC_SPEED_100M); | |
517 | } else { | |
518 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | |
519 | } | |
520 | } | |
521 | ||
92c2588f | 522 | static const struct rk_gmac_ops rk3368_ops = { |
df558854 HS |
523 | .set_to_rgmii = rk3368_set_to_rgmii, |
524 | .set_to_rmii = rk3368_set_to_rmii, | |
525 | .set_rgmii_speed = rk3368_set_rgmii_speed, | |
526 | .set_rmii_speed = rk3368_set_rmii_speed, | |
527 | }; | |
528 | ||
ba289af8 RC |
529 | #define RK3399_GRF_SOC_CON5 0xc214 |
530 | #define RK3399_GRF_SOC_CON6 0xc218 | |
531 | ||
532 | /* RK3399_GRF_SOC_CON5 */ | |
533 | #define RK3399_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ | |
534 | GRF_CLR_BIT(11)) | |
535 | #define RK3399_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ | |
536 | GRF_BIT(11)) | |
537 | #define RK3399_GMAC_FLOW_CTRL GRF_BIT(8) | |
538 | #define RK3399_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) | |
539 | #define RK3399_GMAC_SPEED_10M GRF_CLR_BIT(7) | |
540 | #define RK3399_GMAC_SPEED_100M GRF_BIT(7) | |
541 | #define RK3399_GMAC_RMII_CLK_25M GRF_BIT(3) | |
542 | #define RK3399_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) | |
543 | #define RK3399_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) | |
544 | #define RK3399_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) | |
545 | #define RK3399_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) | |
546 | #define RK3399_GMAC_RMII_MODE GRF_BIT(6) | |
547 | #define RK3399_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) | |
548 | ||
549 | /* RK3399_GRF_SOC_CON6 */ | |
550 | #define RK3399_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) | |
551 | #define RK3399_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) | |
552 | #define RK3399_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) | |
553 | #define RK3399_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) | |
554 | #define RK3399_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) | |
555 | #define RK3399_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) | |
556 | ||
557 | static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv, | |
558 | int tx_delay, int rx_delay) | |
559 | { | |
560 | struct device *dev = &bsp_priv->pdev->dev; | |
561 | ||
562 | if (IS_ERR(bsp_priv->grf)) { | |
563 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
564 | return; | |
565 | } | |
566 | ||
567 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
568 | RK3399_GMAC_PHY_INTF_SEL_RGMII | | |
569 | RK3399_GMAC_RMII_MODE_CLR); | |
570 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON6, | |
571 | RK3399_GMAC_RXCLK_DLY_ENABLE | | |
572 | RK3399_GMAC_TXCLK_DLY_ENABLE | | |
573 | RK3399_GMAC_CLK_RX_DL_CFG(rx_delay) | | |
574 | RK3399_GMAC_CLK_TX_DL_CFG(tx_delay)); | |
575 | } | |
576 | ||
577 | static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv) | |
578 | { | |
579 | struct device *dev = &bsp_priv->pdev->dev; | |
580 | ||
581 | if (IS_ERR(bsp_priv->grf)) { | |
582 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
583 | return; | |
584 | } | |
585 | ||
586 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
587 | RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE); | |
588 | } | |
589 | ||
590 | static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
591 | { | |
592 | struct device *dev = &bsp_priv->pdev->dev; | |
593 | ||
594 | if (IS_ERR(bsp_priv->grf)) { | |
595 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
596 | return; | |
597 | } | |
598 | ||
599 | if (speed == 10) | |
600 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
601 | RK3399_GMAC_CLK_2_5M); | |
602 | else if (speed == 100) | |
603 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
604 | RK3399_GMAC_CLK_25M); | |
605 | else if (speed == 1000) | |
606 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
607 | RK3399_GMAC_CLK_125M); | |
608 | else | |
609 | dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); | |
610 | } | |
611 | ||
612 | static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) | |
613 | { | |
614 | struct device *dev = &bsp_priv->pdev->dev; | |
615 | ||
616 | if (IS_ERR(bsp_priv->grf)) { | |
617 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | |
618 | return; | |
619 | } | |
620 | ||
621 | if (speed == 10) { | |
622 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
623 | RK3399_GMAC_RMII_CLK_2_5M | | |
624 | RK3399_GMAC_SPEED_10M); | |
625 | } else if (speed == 100) { | |
626 | regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, | |
627 | RK3399_GMAC_RMII_CLK_25M | | |
628 | RK3399_GMAC_SPEED_100M); | |
629 | } else { | |
630 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | |
631 | } | |
632 | } | |
633 | ||
634 | static const struct rk_gmac_ops rk3399_ops = { | |
635 | .set_to_rgmii = rk3399_set_to_rgmii, | |
636 | .set_to_rmii = rk3399_set_to_rmii, | |
637 | .set_rgmii_speed = rk3399_set_rgmii_speed, | |
638 | .set_rmii_speed = rk3399_set_rmii_speed, | |
639 | }; | |
640 | ||
7ad269ea RC |
641 | static int gmac_clk_init(struct rk_priv_data *bsp_priv) |
642 | { | |
643 | struct device *dev = &bsp_priv->pdev->dev; | |
644 | ||
645 | bsp_priv->clk_enabled = false; | |
646 | ||
647 | bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx"); | |
648 | if (IS_ERR(bsp_priv->mac_clk_rx)) | |
d42202dc RP |
649 | dev_err(dev, "cannot get clock %s\n", |
650 | "mac_clk_rx"); | |
7ad269ea RC |
651 | |
652 | bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx"); | |
653 | if (IS_ERR(bsp_priv->mac_clk_tx)) | |
d42202dc RP |
654 | dev_err(dev, "cannot get clock %s\n", |
655 | "mac_clk_tx"); | |
7ad269ea RC |
656 | |
657 | bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac"); | |
658 | if (IS_ERR(bsp_priv->aclk_mac)) | |
d42202dc RP |
659 | dev_err(dev, "cannot get clock %s\n", |
660 | "aclk_mac"); | |
7ad269ea RC |
661 | |
662 | bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac"); | |
663 | if (IS_ERR(bsp_priv->pclk_mac)) | |
d42202dc RP |
664 | dev_err(dev, "cannot get clock %s\n", |
665 | "pclk_mac"); | |
7ad269ea RC |
666 | |
667 | bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth"); | |
668 | if (IS_ERR(bsp_priv->clk_mac)) | |
d42202dc RP |
669 | dev_err(dev, "cannot get clock %s\n", |
670 | "stmmaceth"); | |
7ad269ea RC |
671 | |
672 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { | |
673 | bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref"); | |
674 | if (IS_ERR(bsp_priv->clk_mac_ref)) | |
d42202dc RP |
675 | dev_err(dev, "cannot get clock %s\n", |
676 | "clk_mac_ref"); | |
7ad269ea RC |
677 | |
678 | if (!bsp_priv->clock_input) { | |
679 | bsp_priv->clk_mac_refout = | |
680 | devm_clk_get(dev, "clk_mac_refout"); | |
681 | if (IS_ERR(bsp_priv->clk_mac_refout)) | |
d42202dc RP |
682 | dev_err(dev, "cannot get clock %s\n", |
683 | "clk_mac_refout"); | |
7ad269ea RC |
684 | } |
685 | } | |
686 | ||
687 | if (bsp_priv->clock_input) { | |
d42202dc | 688 | dev_info(dev, "clock input from PHY\n"); |
7ad269ea RC |
689 | } else { |
690 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) | |
c48fa33c | 691 | clk_set_rate(bsp_priv->clk_mac, 50000000); |
7ad269ea RC |
692 | } |
693 | ||
694 | return 0; | |
695 | } | |
696 | ||
697 | static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) | |
698 | { | |
428ad1bc | 699 | int phy_iface = bsp_priv->phy_iface; |
7ad269ea RC |
700 | |
701 | if (enable) { | |
702 | if (!bsp_priv->clk_enabled) { | |
703 | if (phy_iface == PHY_INTERFACE_MODE_RMII) { | |
704 | if (!IS_ERR(bsp_priv->mac_clk_rx)) | |
705 | clk_prepare_enable( | |
706 | bsp_priv->mac_clk_rx); | |
707 | ||
708 | if (!IS_ERR(bsp_priv->clk_mac_ref)) | |
709 | clk_prepare_enable( | |
710 | bsp_priv->clk_mac_ref); | |
711 | ||
712 | if (!IS_ERR(bsp_priv->clk_mac_refout)) | |
713 | clk_prepare_enable( | |
714 | bsp_priv->clk_mac_refout); | |
715 | } | |
716 | ||
717 | if (!IS_ERR(bsp_priv->aclk_mac)) | |
718 | clk_prepare_enable(bsp_priv->aclk_mac); | |
719 | ||
720 | if (!IS_ERR(bsp_priv->pclk_mac)) | |
721 | clk_prepare_enable(bsp_priv->pclk_mac); | |
722 | ||
723 | if (!IS_ERR(bsp_priv->mac_clk_tx)) | |
724 | clk_prepare_enable(bsp_priv->mac_clk_tx); | |
725 | ||
726 | /** | |
727 | * if (!IS_ERR(bsp_priv->clk_mac)) | |
728 | * clk_prepare_enable(bsp_priv->clk_mac); | |
729 | */ | |
730 | mdelay(5); | |
731 | bsp_priv->clk_enabled = true; | |
732 | } | |
733 | } else { | |
734 | if (bsp_priv->clk_enabled) { | |
735 | if (phy_iface == PHY_INTERFACE_MODE_RMII) { | |
736 | if (!IS_ERR(bsp_priv->mac_clk_rx)) | |
737 | clk_disable_unprepare( | |
738 | bsp_priv->mac_clk_rx); | |
739 | ||
740 | if (!IS_ERR(bsp_priv->clk_mac_ref)) | |
741 | clk_disable_unprepare( | |
742 | bsp_priv->clk_mac_ref); | |
743 | ||
744 | if (!IS_ERR(bsp_priv->clk_mac_refout)) | |
745 | clk_disable_unprepare( | |
746 | bsp_priv->clk_mac_refout); | |
747 | } | |
748 | ||
749 | if (!IS_ERR(bsp_priv->aclk_mac)) | |
750 | clk_disable_unprepare(bsp_priv->aclk_mac); | |
751 | ||
752 | if (!IS_ERR(bsp_priv->pclk_mac)) | |
753 | clk_disable_unprepare(bsp_priv->pclk_mac); | |
754 | ||
755 | if (!IS_ERR(bsp_priv->mac_clk_tx)) | |
756 | clk_disable_unprepare(bsp_priv->mac_clk_tx); | |
757 | /** | |
758 | * if (!IS_ERR(bsp_priv->clk_mac)) | |
759 | * clk_disable_unprepare(bsp_priv->clk_mac); | |
760 | */ | |
761 | bsp_priv->clk_enabled = false; | |
762 | } | |
763 | } | |
764 | ||
765 | return 0; | |
766 | } | |
767 | ||
768 | static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable) | |
769 | { | |
2e12f536 | 770 | struct regulator *ldo = bsp_priv->regulator; |
7ad269ea RC |
771 | int ret; |
772 | struct device *dev = &bsp_priv->pdev->dev; | |
773 | ||
2e12f536 | 774 | if (!ldo) { |
d42202dc | 775 | dev_err(dev, "no regulator found\n"); |
7ad269ea RC |
776 | return -1; |
777 | } | |
778 | ||
2e12f536 RP |
779 | if (enable) { |
780 | ret = regulator_enable(ldo); | |
781 | if (ret) | |
d42202dc | 782 | dev_err(dev, "fail to enable phy-supply\n"); |
7ad269ea | 783 | } else { |
2e12f536 RP |
784 | ret = regulator_disable(ldo); |
785 | if (ret) | |
d42202dc | 786 | dev_err(dev, "fail to disable phy-supply\n"); |
7ad269ea RC |
787 | } |
788 | ||
789 | return 0; | |
790 | } | |
791 | ||
0fb98db1 | 792 | static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, |
92c2588f | 793 | const struct rk_gmac_ops *ops) |
7ad269ea RC |
794 | { |
795 | struct rk_priv_data *bsp_priv; | |
796 | struct device *dev = &pdev->dev; | |
797 | int ret; | |
798 | const char *strings = NULL; | |
799 | int value; | |
800 | ||
801 | bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL); | |
802 | if (!bsp_priv) | |
803 | return ERR_PTR(-ENOMEM); | |
804 | ||
805 | bsp_priv->phy_iface = of_get_phy_mode(dev->of_node); | |
0fb98db1 | 806 | bsp_priv->ops = ops; |
7ad269ea | 807 | |
2e12f536 RP |
808 | bsp_priv->regulator = devm_regulator_get_optional(dev, "phy"); |
809 | if (IS_ERR(bsp_priv->regulator)) { | |
810 | if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) { | |
811 | dev_err(dev, "phy regulator is not available yet, deferred probing\n"); | |
812 | return ERR_PTR(-EPROBE_DEFER); | |
813 | } | |
814 | dev_err(dev, "no regulator found\n"); | |
815 | bsp_priv->regulator = NULL; | |
7ad269ea RC |
816 | } |
817 | ||
818 | ret = of_property_read_string(dev->of_node, "clock_in_out", &strings); | |
819 | if (ret) { | |
d42202dc | 820 | dev_err(dev, "Can not read property: clock_in_out.\n"); |
7ad269ea RC |
821 | bsp_priv->clock_input = true; |
822 | } else { | |
d42202dc RP |
823 | dev_info(dev, "clock input or output? (%s).\n", |
824 | strings); | |
7ad269ea RC |
825 | if (!strcmp(strings, "input")) |
826 | bsp_priv->clock_input = true; | |
827 | else | |
828 | bsp_priv->clock_input = false; | |
829 | } | |
830 | ||
831 | ret = of_property_read_u32(dev->of_node, "tx_delay", &value); | |
832 | if (ret) { | |
833 | bsp_priv->tx_delay = 0x30; | |
d42202dc RP |
834 | dev_err(dev, "Can not read property: tx_delay."); |
835 | dev_err(dev, "set tx_delay to 0x%x\n", | |
836 | bsp_priv->tx_delay); | |
7ad269ea | 837 | } else { |
d42202dc | 838 | dev_info(dev, "TX delay(0x%x).\n", value); |
7ad269ea RC |
839 | bsp_priv->tx_delay = value; |
840 | } | |
841 | ||
842 | ret = of_property_read_u32(dev->of_node, "rx_delay", &value); | |
843 | if (ret) { | |
844 | bsp_priv->rx_delay = 0x10; | |
d42202dc RP |
845 | dev_err(dev, "Can not read property: rx_delay."); |
846 | dev_err(dev, "set rx_delay to 0x%x\n", | |
847 | bsp_priv->rx_delay); | |
7ad269ea | 848 | } else { |
d42202dc | 849 | dev_info(dev, "RX delay(0x%x).\n", value); |
7ad269ea RC |
850 | bsp_priv->rx_delay = value; |
851 | } | |
852 | ||
853 | bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, | |
854 | "rockchip,grf"); | |
855 | bsp_priv->pdev = pdev; | |
856 | ||
45383f52 RC |
857 | gmac_clk_init(bsp_priv); |
858 | ||
859 | return bsp_priv; | |
860 | } | |
861 | ||
862 | static int rk_gmac_powerup(struct rk_priv_data *bsp_priv) | |
863 | { | |
864 | int ret; | |
865 | struct device *dev = &bsp_priv->pdev->dev; | |
866 | ||
7ad269ea RC |
867 | /*rmii or rgmii*/ |
868 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) { | |
d42202dc | 869 | dev_info(dev, "init for RGMII\n"); |
0fb98db1 HS |
870 | bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, |
871 | bsp_priv->rx_delay); | |
7ad269ea | 872 | } else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { |
d42202dc | 873 | dev_info(dev, "init for RMII\n"); |
0fb98db1 | 874 | bsp_priv->ops->set_to_rmii(bsp_priv); |
7ad269ea | 875 | } else { |
d42202dc | 876 | dev_err(dev, "NO interface defined!\n"); |
7ad269ea RC |
877 | } |
878 | ||
7ad269ea RC |
879 | ret = phy_power_on(bsp_priv, true); |
880 | if (ret) | |
881 | return ret; | |
882 | ||
883 | ret = gmac_clk_enable(bsp_priv, true); | |
884 | if (ret) | |
885 | return ret; | |
886 | ||
2c896fb0 DW |
887 | pm_runtime_enable(dev); |
888 | pm_runtime_get_sync(dev); | |
889 | ||
7ad269ea RC |
890 | return 0; |
891 | } | |
892 | ||
229666c1 | 893 | static void rk_gmac_powerdown(struct rk_priv_data *gmac) |
7ad269ea | 894 | { |
2c896fb0 DW |
895 | struct device *dev = &gmac->pdev->dev; |
896 | ||
897 | pm_runtime_put_sync(dev); | |
898 | pm_runtime_disable(dev); | |
899 | ||
7ad269ea RC |
900 | phy_power_on(gmac, false); |
901 | gmac_clk_enable(gmac, false); | |
902 | } | |
903 | ||
229666c1 VP |
904 | static int rk_gmac_init(struct platform_device *pdev, void *priv) |
905 | { | |
906 | struct rk_priv_data *bsp_priv = priv; | |
907 | ||
908 | return rk_gmac_powerup(bsp_priv); | |
909 | } | |
910 | ||
911 | static void rk_gmac_exit(struct platform_device *pdev, void *priv) | |
912 | { | |
913 | struct rk_priv_data *bsp_priv = priv; | |
914 | ||
915 | rk_gmac_powerdown(bsp_priv); | |
916 | } | |
917 | ||
918 | static void rk_gmac_suspend(struct platform_device *pdev, void *priv) | |
919 | { | |
920 | struct rk_priv_data *bsp_priv = priv; | |
921 | ||
922 | /* Keep the PHY up if we use Wake-on-Lan. */ | |
923 | if (device_may_wakeup(&pdev->dev)) | |
924 | return; | |
925 | ||
926 | rk_gmac_powerdown(bsp_priv); | |
927 | bsp_priv->suspended = true; | |
928 | } | |
929 | ||
930 | static void rk_gmac_resume(struct platform_device *pdev, void *priv) | |
931 | { | |
932 | struct rk_priv_data *bsp_priv = priv; | |
933 | ||
934 | /* The PHY was up for Wake-on-Lan. */ | |
935 | if (!bsp_priv->suspended) | |
936 | return; | |
937 | ||
938 | rk_gmac_powerup(bsp_priv); | |
939 | bsp_priv->suspended = false; | |
940 | } | |
941 | ||
7ad269ea RC |
942 | static void rk_fix_speed(void *priv, unsigned int speed) |
943 | { | |
944 | struct rk_priv_data *bsp_priv = priv; | |
945 | struct device *dev = &bsp_priv->pdev->dev; | |
946 | ||
947 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) | |
0fb98db1 | 948 | bsp_priv->ops->set_rgmii_speed(bsp_priv, speed); |
7ad269ea | 949 | else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) |
0fb98db1 | 950 | bsp_priv->ops->set_rmii_speed(bsp_priv, speed); |
7ad269ea RC |
951 | else |
952 | dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); | |
953 | } | |
954 | ||
27ffefd2 JE |
955 | static int rk_gmac_probe(struct platform_device *pdev) |
956 | { | |
957 | struct plat_stmmacenet_data *plat_dat; | |
958 | struct stmmac_resources stmmac_res; | |
f529f182 | 959 | const struct rk_gmac_ops *data; |
27ffefd2 JE |
960 | int ret; |
961 | ||
149adedd JE |
962 | data = of_device_get_match_data(&pdev->dev); |
963 | if (!data) { | |
964 | dev_err(&pdev->dev, "no of match data provided\n"); | |
965 | return -EINVAL; | |
966 | } | |
967 | ||
27ffefd2 JE |
968 | ret = stmmac_get_platform_resources(pdev, &stmmac_res); |
969 | if (ret) | |
970 | return ret; | |
971 | ||
972 | plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); | |
973 | if (IS_ERR(plat_dat)) | |
974 | return PTR_ERR(plat_dat); | |
975 | ||
976 | plat_dat->has_gmac = true; | |
977 | plat_dat->init = rk_gmac_init; | |
978 | plat_dat->exit = rk_gmac_exit; | |
979 | plat_dat->fix_mac_speed = rk_fix_speed; | |
229666c1 VP |
980 | plat_dat->suspend = rk_gmac_suspend; |
981 | plat_dat->resume = rk_gmac_resume; | |
27ffefd2 | 982 | |
f529f182 | 983 | plat_dat->bsp_priv = rk_gmac_setup(pdev, data); |
27ffefd2 JE |
984 | if (IS_ERR(plat_dat->bsp_priv)) |
985 | return PTR_ERR(plat_dat->bsp_priv); | |
986 | ||
987 | ret = rk_gmac_init(pdev, plat_dat->bsp_priv); | |
988 | if (ret) | |
989 | return ret; | |
990 | ||
991 | return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | |
992 | } | |
993 | ||
e0fb4013 | 994 | static const struct of_device_id rk_gmac_dwmac_match[] = { |
e7ffd812 | 995 | { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, |
f529f182 | 996 | { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, |
ba289af8 | 997 | { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops }, |
f529f182 | 998 | { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, |
ba289af8 | 999 | { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops }, |
e0fb4013 JE |
1000 | { } |
1001 | }; | |
1002 | MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match); | |
1003 | ||
1004 | static struct platform_driver rk_gmac_dwmac_driver = { | |
27ffefd2 | 1005 | .probe = rk_gmac_probe, |
e0fb4013 JE |
1006 | .remove = stmmac_pltfr_remove, |
1007 | .driver = { | |
1008 | .name = "rk_gmac-dwmac", | |
1009 | .pm = &stmmac_pltfr_pm_ops, | |
1010 | .of_match_table = rk_gmac_dwmac_match, | |
1011 | }, | |
1012 | }; | |
1013 | module_platform_driver(rk_gmac_dwmac_driver); | |
1014 | ||
1015 | MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>"); | |
1016 | MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer"); | |
1017 | MODULE_LICENSE("GPL"); |