]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
0125bcf0 SS |
2 | /* |
3 | * (C) Copyright 2015 Sjoerd Simons <[email protected]> | |
4 | * | |
0125bcf0 SS |
5 | * Rockchip GMAC ethernet IP driver for U-Boot |
6 | */ | |
7 | ||
8 | #include <common.h> | |
9 | #include <dm.h> | |
10 | #include <clk.h> | |
f7ae49fc | 11 | #include <log.h> |
90526e9f | 12 | #include <net.h> |
0125bcf0 SS |
13 | #include <phy.h> |
14 | #include <syscon.h> | |
15 | #include <asm/io.h> | |
15f09a1a KY |
16 | #include <asm/arch-rockchip/periph.h> |
17 | #include <asm/arch-rockchip/clock.h> | |
18 | #include <asm/arch-rockchip/hardware.h> | |
b0791184 | 19 | #include <asm/arch-rockchip/grf_px30.h> |
15f09a1a KY |
20 | #include <asm/arch-rockchip/grf_rk322x.h> |
21 | #include <asm/arch-rockchip/grf_rk3288.h> | |
0ed8f1e5 | 22 | #include <asm/arch-rk3308/grf_rk3308.h> |
15f09a1a KY |
23 | #include <asm/arch-rockchip/grf_rk3328.h> |
24 | #include <asm/arch-rockchip/grf_rk3368.h> | |
25 | #include <asm/arch-rockchip/grf_rk3399.h> | |
26 | #include <asm/arch-rockchip/grf_rv1108.h> | |
0125bcf0 SS |
27 | #include <dm/pinctrl.h> |
28 | #include <dt-bindings/clock/rk3288-cru.h> | |
cd93d625 | 29 | #include <linux/bitops.h> |
0125bcf0 SS |
30 | #include "designware.h" |
31 | ||
3d1bd5b5 JH |
32 | DECLARE_GLOBAL_DATA_PTR; |
33 | #define DELAY_ENABLE(soc, tx, rx) \ | |
34 | (((tx) ? soc##_TXCLK_DLY_ENA_GMAC_ENABLE : soc##_TXCLK_DLY_ENA_GMAC_DISABLE) | \ | |
35 | ((rx) ? soc##_RXCLK_DLY_ENA_GMAC_ENABLE : soc##_RXCLK_DLY_ENA_GMAC_DISABLE)) | |
36 | ||
0125bcf0 SS |
37 | /* |
38 | * Platform data for the gmac | |
39 | * | |
40 | * dw_eth_pdata: Required platform data for designware driver (must be first) | |
41 | */ | |
8a8d24bd | 42 | struct gmac_rockchip_plat { |
0125bcf0 | 43 | struct dw_eth_pdata dw_eth_pdata; |
caf74617 | 44 | bool clock_input; |
0125bcf0 SS |
45 | int tx_delay; |
46 | int rx_delay; | |
47 | }; | |
48 | ||
1f08aa1c PT |
49 | struct rk_gmac_ops { |
50 | int (*fix_mac_speed)(struct dw_eth_dev *priv); | |
8a8d24bd SG |
51 | void (*set_to_rmii)(struct gmac_rockchip_plat *pdata); |
52 | void (*set_to_rgmii)(struct gmac_rockchip_plat *pdata); | |
1f08aa1c PT |
53 | }; |
54 | ||
55 | ||
d1998a9f | 56 | static int gmac_rockchip_of_to_plat(struct udevice *dev) |
0125bcf0 | 57 | { |
8a8d24bd | 58 | struct gmac_rockchip_plat *pdata = dev_get_plat(dev); |
caf74617 DW |
59 | const char *string; |
60 | ||
61 | string = dev_read_string(dev, "clock_in_out"); | |
62 | if (!strcmp(string, "input")) | |
63 | pdata->clock_input = true; | |
64 | else | |
65 | pdata->clock_input = false; | |
1f08aa1c PT |
66 | |
67 | /* Check the new naming-style first... */ | |
7ad326a9 PT |
68 | pdata->tx_delay = dev_read_u32_default(dev, "tx_delay", -ENOENT); |
69 | pdata->rx_delay = dev_read_u32_default(dev, "rx_delay", -ENOENT); | |
0125bcf0 | 70 | |
1f08aa1c PT |
71 | /* ... and fall back to the old naming style or default, if necessary */ |
72 | if (pdata->tx_delay == -ENOENT) | |
7ad326a9 | 73 | pdata->tx_delay = dev_read_u32_default(dev, "tx-delay", 0x30); |
1f08aa1c | 74 | if (pdata->rx_delay == -ENOENT) |
7ad326a9 | 75 | pdata->rx_delay = dev_read_u32_default(dev, "rx-delay", 0x10); |
0125bcf0 | 76 | |
d1998a9f | 77 | return designware_eth_of_to_plat(dev); |
0125bcf0 SS |
78 | } |
79 | ||
b0791184 HS |
80 | static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
81 | { | |
82 | struct px30_grf *grf; | |
83 | struct clk clk_speed; | |
84 | int speed, ret; | |
85 | enum { | |
86 | PX30_GMAC_SPEED_SHIFT = 0x2, | |
87 | PX30_GMAC_SPEED_MASK = BIT(2), | |
88 | PX30_GMAC_SPEED_10M = 0, | |
89 | PX30_GMAC_SPEED_100M = BIT(2), | |
90 | }; | |
91 | ||
92 | ret = clk_get_by_name(priv->phydev->dev, "clk_mac_speed", | |
93 | &clk_speed); | |
94 | if (ret) | |
95 | return ret; | |
96 | ||
97 | switch (priv->phydev->speed) { | |
98 | case 10: | |
99 | speed = PX30_GMAC_SPEED_10M; | |
100 | ret = clk_set_rate(&clk_speed, 2500000); | |
101 | if (ret) | |
102 | return ret; | |
103 | break; | |
104 | case 100: | |
105 | speed = PX30_GMAC_SPEED_100M; | |
106 | ret = clk_set_rate(&clk_speed, 25000000); | |
107 | if (ret) | |
108 | return ret; | |
109 | break; | |
110 | default: | |
111 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
112 | return -EINVAL; | |
113 | } | |
114 | ||
115 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
116 | rk_clrsetreg(&grf->mac_con1, PX30_GMAC_SPEED_MASK, speed); | |
117 | ||
118 | return 0; | |
119 | } | |
120 | ||
d12d7c09 DW |
121 | static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
122 | { | |
123 | struct rk322x_grf *grf; | |
124 | int clk; | |
125 | enum { | |
126 | RK3228_GMAC_CLK_SEL_SHIFT = 8, | |
127 | RK3228_GMAC_CLK_SEL_MASK = GENMASK(9, 8), | |
128 | RK3228_GMAC_CLK_SEL_125M = 0 << 8, | |
129 | RK3228_GMAC_CLK_SEL_25M = 3 << 8, | |
130 | RK3228_GMAC_CLK_SEL_2_5M = 2 << 8, | |
131 | }; | |
132 | ||
133 | switch (priv->phydev->speed) { | |
134 | case 10: | |
135 | clk = RK3228_GMAC_CLK_SEL_2_5M; | |
136 | break; | |
137 | case 100: | |
138 | clk = RK3228_GMAC_CLK_SEL_25M; | |
139 | break; | |
140 | case 1000: | |
141 | clk = RK3228_GMAC_CLK_SEL_125M; | |
142 | break; | |
143 | default: | |
144 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
145 | return -EINVAL; | |
146 | } | |
147 | ||
148 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
149 | rk_clrsetreg(&grf->mac_con[1], RK3228_GMAC_CLK_SEL_MASK, clk); | |
150 | ||
151 | return 0; | |
152 | } | |
153 | ||
1f08aa1c | 154 | static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
0125bcf0 SS |
155 | { |
156 | struct rk3288_grf *grf; | |
157 | int clk; | |
158 | ||
159 | switch (priv->phydev->speed) { | |
160 | case 10: | |
1f08aa1c | 161 | clk = RK3288_GMAC_CLK_SEL_2_5M; |
0125bcf0 SS |
162 | break; |
163 | case 100: | |
1f08aa1c | 164 | clk = RK3288_GMAC_CLK_SEL_25M; |
0125bcf0 SS |
165 | break; |
166 | case 1000: | |
1f08aa1c | 167 | clk = RK3288_GMAC_CLK_SEL_125M; |
0125bcf0 SS |
168 | break; |
169 | default: | |
170 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
171 | return -EINVAL; | |
172 | } | |
173 | ||
174 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
1f08aa1c PT |
175 | rk_clrsetreg(&grf->soc_con1, RK3288_GMAC_CLK_SEL_MASK, clk); |
176 | ||
177 | return 0; | |
178 | } | |
179 | ||
0ed8f1e5 DW |
180 | static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
181 | { | |
182 | struct rk3308_grf *grf; | |
183 | struct clk clk_speed; | |
184 | int speed, ret; | |
185 | enum { | |
186 | RK3308_GMAC_SPEED_SHIFT = 0x0, | |
187 | RK3308_GMAC_SPEED_MASK = BIT(0), | |
188 | RK3308_GMAC_SPEED_10M = 0, | |
189 | RK3308_GMAC_SPEED_100M = BIT(0), | |
190 | }; | |
191 | ||
192 | ret = clk_get_by_name(priv->phydev->dev, "clk_mac_speed", | |
193 | &clk_speed); | |
194 | if (ret) | |
195 | return ret; | |
196 | ||
197 | switch (priv->phydev->speed) { | |
198 | case 10: | |
199 | speed = RK3308_GMAC_SPEED_10M; | |
200 | ret = clk_set_rate(&clk_speed, 2500000); | |
201 | if (ret) | |
202 | return ret; | |
203 | break; | |
204 | case 100: | |
205 | speed = RK3308_GMAC_SPEED_100M; | |
206 | ret = clk_set_rate(&clk_speed, 25000000); | |
207 | if (ret) | |
208 | return ret; | |
209 | break; | |
210 | default: | |
211 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
212 | return -EINVAL; | |
213 | } | |
214 | ||
215 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
216 | rk_clrsetreg(&grf->mac_con0, RK3308_GMAC_SPEED_MASK, speed); | |
217 | ||
218 | return 0; | |
219 | } | |
220 | ||
b3d2a6df DW |
221 | static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
222 | { | |
223 | struct rk3328_grf_regs *grf; | |
224 | int clk; | |
225 | enum { | |
226 | RK3328_GMAC_CLK_SEL_SHIFT = 11, | |
227 | RK3328_GMAC_CLK_SEL_MASK = GENMASK(12, 11), | |
228 | RK3328_GMAC_CLK_SEL_125M = 0 << 11, | |
229 | RK3328_GMAC_CLK_SEL_25M = 3 << 11, | |
230 | RK3328_GMAC_CLK_SEL_2_5M = 2 << 11, | |
231 | }; | |
232 | ||
233 | switch (priv->phydev->speed) { | |
234 | case 10: | |
235 | clk = RK3328_GMAC_CLK_SEL_2_5M; | |
236 | break; | |
237 | case 100: | |
238 | clk = RK3328_GMAC_CLK_SEL_25M; | |
239 | break; | |
240 | case 1000: | |
241 | clk = RK3328_GMAC_CLK_SEL_125M; | |
242 | break; | |
243 | default: | |
244 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
245 | return -EINVAL; | |
246 | } | |
247 | ||
248 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
249 | rk_clrsetreg(&grf->mac_con[1], RK3328_GMAC_CLK_SEL_MASK, clk); | |
250 | ||
251 | return 0; | |
252 | } | |
253 | ||
793f2fd2 PT |
254 | static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
255 | { | |
256 | struct rk3368_grf *grf; | |
257 | int clk; | |
258 | enum { | |
259 | RK3368_GMAC_CLK_SEL_2_5M = 2 << 4, | |
260 | RK3368_GMAC_CLK_SEL_25M = 3 << 4, | |
261 | RK3368_GMAC_CLK_SEL_125M = 0 << 4, | |
262 | RK3368_GMAC_CLK_SEL_MASK = GENMASK(5, 4), | |
263 | }; | |
264 | ||
265 | switch (priv->phydev->speed) { | |
266 | case 10: | |
267 | clk = RK3368_GMAC_CLK_SEL_2_5M; | |
268 | break; | |
269 | case 100: | |
270 | clk = RK3368_GMAC_CLK_SEL_25M; | |
271 | break; | |
272 | case 1000: | |
273 | clk = RK3368_GMAC_CLK_SEL_125M; | |
274 | break; | |
275 | default: | |
276 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
277 | return -EINVAL; | |
278 | } | |
279 | ||
280 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
281 | rk_clrsetreg(&grf->soc_con15, RK3368_GMAC_CLK_SEL_MASK, clk); | |
282 | ||
283 | return 0; | |
284 | } | |
285 | ||
1f08aa1c PT |
286 | static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv) |
287 | { | |
288 | struct rk3399_grf_regs *grf; | |
289 | int clk; | |
290 | ||
291 | switch (priv->phydev->speed) { | |
292 | case 10: | |
293 | clk = RK3399_GMAC_CLK_SEL_2_5M; | |
294 | break; | |
295 | case 100: | |
296 | clk = RK3399_GMAC_CLK_SEL_25M; | |
297 | break; | |
298 | case 1000: | |
299 | clk = RK3399_GMAC_CLK_SEL_125M; | |
300 | break; | |
301 | default: | |
302 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
303 | return -EINVAL; | |
304 | } | |
305 | ||
306 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
307 | rk_clrsetreg(&grf->soc_con5, RK3399_GMAC_CLK_SEL_MASK, clk); | |
0125bcf0 SS |
308 | |
309 | return 0; | |
310 | } | |
311 | ||
caf74617 DW |
312 | static int rv1108_set_rmii_speed(struct dw_eth_dev *priv) |
313 | { | |
314 | struct rv1108_grf *grf; | |
315 | int clk, speed; | |
316 | enum { | |
317 | RV1108_GMAC_SPEED_MASK = BIT(2), | |
318 | RV1108_GMAC_SPEED_10M = 0 << 2, | |
319 | RV1108_GMAC_SPEED_100M = 1 << 2, | |
320 | RV1108_GMAC_CLK_SEL_MASK = BIT(7), | |
321 | RV1108_GMAC_CLK_SEL_2_5M = 0 << 7, | |
322 | RV1108_GMAC_CLK_SEL_25M = 1 << 7, | |
323 | }; | |
324 | ||
325 | switch (priv->phydev->speed) { | |
326 | case 10: | |
327 | clk = RV1108_GMAC_CLK_SEL_2_5M; | |
328 | speed = RV1108_GMAC_SPEED_10M; | |
329 | break; | |
330 | case 100: | |
331 | clk = RV1108_GMAC_CLK_SEL_25M; | |
332 | speed = RV1108_GMAC_SPEED_100M; | |
333 | break; | |
334 | default: | |
335 | debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
336 | return -EINVAL; | |
337 | } | |
338 | ||
339 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
340 | rk_clrsetreg(&grf->gmac_con0, | |
341 | RV1108_GMAC_CLK_SEL_MASK | RV1108_GMAC_SPEED_MASK, | |
342 | clk | speed); | |
343 | ||
344 | return 0; | |
345 | } | |
346 | ||
8a8d24bd | 347 | static void px30_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) |
b0791184 HS |
348 | { |
349 | struct px30_grf *grf; | |
350 | enum { | |
351 | PX30_GMAC_PHY_INTF_SEL_SHIFT = 4, | |
352 | PX30_GMAC_PHY_INTF_SEL_MASK = GENMASK(4, 6), | |
353 | PX30_GMAC_PHY_INTF_SEL_RMII = BIT(6), | |
354 | }; | |
355 | ||
356 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
357 | ||
358 | rk_clrsetreg(&grf->mac_con1, | |
359 | PX30_GMAC_PHY_INTF_SEL_MASK, | |
360 | PX30_GMAC_PHY_INTF_SEL_RMII); | |
361 | } | |
362 | ||
8a8d24bd | 363 | static void rk3228_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) |
d12d7c09 DW |
364 | { |
365 | struct rk322x_grf *grf; | |
366 | enum { | |
367 | RK3228_RMII_MODE_SHIFT = 10, | |
368 | RK3228_RMII_MODE_MASK = BIT(10), | |
369 | ||
370 | RK3228_GMAC_PHY_INTF_SEL_SHIFT = 4, | |
371 | RK3228_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), | |
372 | RK3228_GMAC_PHY_INTF_SEL_RGMII = BIT(4), | |
373 | ||
374 | RK3228_RXCLK_DLY_ENA_GMAC_MASK = BIT(1), | |
375 | RK3228_RXCLK_DLY_ENA_GMAC_DISABLE = 0, | |
376 | RK3228_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(1), | |
377 | ||
378 | RK3228_TXCLK_DLY_ENA_GMAC_MASK = BIT(0), | |
379 | RK3228_TXCLK_DLY_ENA_GMAC_DISABLE = 0, | |
380 | RK3228_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(0), | |
381 | }; | |
382 | enum { | |
383 | RK3228_CLK_RX_DL_CFG_GMAC_SHIFT = 0x7, | |
384 | RK3228_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(13, 7), | |
385 | ||
386 | RK3228_CLK_TX_DL_CFG_GMAC_SHIFT = 0x0, | |
387 | RK3228_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), | |
388 | }; | |
389 | ||
390 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
391 | rk_clrsetreg(&grf->mac_con[1], | |
392 | RK3228_RMII_MODE_MASK | | |
393 | RK3228_GMAC_PHY_INTF_SEL_MASK | | |
394 | RK3228_RXCLK_DLY_ENA_GMAC_MASK | | |
395 | RK3228_TXCLK_DLY_ENA_GMAC_MASK, | |
396 | RK3228_GMAC_PHY_INTF_SEL_RGMII | | |
3d1bd5b5 | 397 | DELAY_ENABLE(RK3228, pdata->tx_delay, pdata->rx_delay)); |
d12d7c09 DW |
398 | |
399 | rk_clrsetreg(&grf->mac_con[0], | |
400 | RK3228_CLK_RX_DL_CFG_GMAC_MASK | | |
401 | RK3228_CLK_TX_DL_CFG_GMAC_MASK, | |
402 | pdata->rx_delay << RK3228_CLK_RX_DL_CFG_GMAC_SHIFT | | |
403 | pdata->tx_delay << RK3228_CLK_TX_DL_CFG_GMAC_SHIFT); | |
404 | } | |
405 | ||
8a8d24bd | 406 | static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) |
1f08aa1c PT |
407 | { |
408 | struct rk3288_grf *grf; | |
409 | ||
410 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
411 | rk_clrsetreg(&grf->soc_con1, | |
412 | RK3288_RMII_MODE_MASK | RK3288_GMAC_PHY_INTF_SEL_MASK, | |
413 | RK3288_GMAC_PHY_INTF_SEL_RGMII); | |
414 | ||
415 | rk_clrsetreg(&grf->soc_con3, | |
416 | RK3288_RXCLK_DLY_ENA_GMAC_MASK | | |
417 | RK3288_TXCLK_DLY_ENA_GMAC_MASK | | |
418 | RK3288_CLK_RX_DL_CFG_GMAC_MASK | | |
419 | RK3288_CLK_TX_DL_CFG_GMAC_MASK, | |
3d1bd5b5 | 420 | DELAY_ENABLE(RK3288, pdata->rx_delay, pdata->tx_delay) | |
1f08aa1c PT |
421 | pdata->rx_delay << RK3288_CLK_RX_DL_CFG_GMAC_SHIFT | |
422 | pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT); | |
423 | } | |
424 | ||
8a8d24bd | 425 | static void rk3308_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) |
0ed8f1e5 DW |
426 | { |
427 | struct rk3308_grf *grf; | |
428 | enum { | |
429 | RK3308_GMAC_PHY_INTF_SEL_SHIFT = 2, | |
430 | RK3308_GMAC_PHY_INTF_SEL_MASK = GENMASK(4, 2), | |
431 | RK3308_GMAC_PHY_INTF_SEL_RMII = BIT(4), | |
432 | }; | |
433 | ||
434 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
435 | ||
436 | rk_clrsetreg(&grf->mac_con0, | |
437 | RK3308_GMAC_PHY_INTF_SEL_MASK, | |
438 | RK3308_GMAC_PHY_INTF_SEL_RMII); | |
439 | } | |
440 | ||
8a8d24bd | 441 | static void rk3328_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) |
b3d2a6df DW |
442 | { |
443 | struct rk3328_grf_regs *grf; | |
444 | enum { | |
445 | RK3328_RMII_MODE_SHIFT = 9, | |
446 | RK3328_RMII_MODE_MASK = BIT(9), | |
447 | ||
448 | RK3328_GMAC_PHY_INTF_SEL_SHIFT = 4, | |
449 | RK3328_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), | |
450 | RK3328_GMAC_PHY_INTF_SEL_RGMII = BIT(4), | |
451 | ||
452 | RK3328_RXCLK_DLY_ENA_GMAC_MASK = BIT(1), | |
453 | RK3328_RXCLK_DLY_ENA_GMAC_DISABLE = 0, | |
454 | RK3328_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(1), | |
455 | ||
456 | RK3328_TXCLK_DLY_ENA_GMAC_MASK = BIT(0), | |
457 | RK3328_TXCLK_DLY_ENA_GMAC_DISABLE = 0, | |
458 | RK3328_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(0), | |
459 | }; | |
460 | enum { | |
461 | RK3328_CLK_RX_DL_CFG_GMAC_SHIFT = 0x7, | |
462 | RK3328_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(13, 7), | |
463 | ||
464 | RK3328_CLK_TX_DL_CFG_GMAC_SHIFT = 0x0, | |
465 | RK3328_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), | |
466 | }; | |
467 | ||
468 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
469 | rk_clrsetreg(&grf->mac_con[1], | |
470 | RK3328_RMII_MODE_MASK | | |
471 | RK3328_GMAC_PHY_INTF_SEL_MASK | | |
472 | RK3328_RXCLK_DLY_ENA_GMAC_MASK | | |
473 | RK3328_TXCLK_DLY_ENA_GMAC_MASK, | |
474 | RK3328_GMAC_PHY_INTF_SEL_RGMII | | |
3d1bd5b5 | 475 | DELAY_ENABLE(RK3328, pdata->tx_delay, pdata->rx_delay)); |
b3d2a6df DW |
476 | |
477 | rk_clrsetreg(&grf->mac_con[0], | |
478 | RK3328_CLK_RX_DL_CFG_GMAC_MASK | | |
479 | RK3328_CLK_TX_DL_CFG_GMAC_MASK, | |
480 | pdata->rx_delay << RK3328_CLK_RX_DL_CFG_GMAC_SHIFT | | |
481 | pdata->tx_delay << RK3328_CLK_TX_DL_CFG_GMAC_SHIFT); | |
482 | } | |
483 | ||
8a8d24bd | 484 | static void rk3368_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) |
793f2fd2 PT |
485 | { |
486 | struct rk3368_grf *grf; | |
487 | enum { | |
488 | RK3368_GMAC_PHY_INTF_SEL_RGMII = 1 << 9, | |
489 | RK3368_GMAC_PHY_INTF_SEL_MASK = GENMASK(11, 9), | |
490 | RK3368_RMII_MODE_MASK = BIT(6), | |
491 | RK3368_RMII_MODE = BIT(6), | |
492 | }; | |
493 | enum { | |
494 | RK3368_RXCLK_DLY_ENA_GMAC_MASK = BIT(15), | |
495 | RK3368_RXCLK_DLY_ENA_GMAC_DISABLE = 0, | |
496 | RK3368_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(15), | |
497 | RK3368_TXCLK_DLY_ENA_GMAC_MASK = BIT(7), | |
498 | RK3368_TXCLK_DLY_ENA_GMAC_DISABLE = 0, | |
499 | RK3368_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(7), | |
500 | RK3368_CLK_RX_DL_CFG_GMAC_SHIFT = 8, | |
501 | RK3368_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(14, 8), | |
502 | RK3368_CLK_TX_DL_CFG_GMAC_SHIFT = 0, | |
503 | RK3368_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), | |
504 | }; | |
505 | ||
506 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
507 | rk_clrsetreg(&grf->soc_con15, | |
508 | RK3368_RMII_MODE_MASK | RK3368_GMAC_PHY_INTF_SEL_MASK, | |
509 | RK3368_GMAC_PHY_INTF_SEL_RGMII); | |
510 | ||
511 | rk_clrsetreg(&grf->soc_con16, | |
512 | RK3368_RXCLK_DLY_ENA_GMAC_MASK | | |
513 | RK3368_TXCLK_DLY_ENA_GMAC_MASK | | |
514 | RK3368_CLK_RX_DL_CFG_GMAC_MASK | | |
515 | RK3368_CLK_TX_DL_CFG_GMAC_MASK, | |
3d1bd5b5 | 516 | DELAY_ENABLE(RK3368, pdata->tx_delay, pdata->rx_delay) | |
793f2fd2 PT |
517 | pdata->rx_delay << RK3368_CLK_RX_DL_CFG_GMAC_SHIFT | |
518 | pdata->tx_delay << RK3368_CLK_TX_DL_CFG_GMAC_SHIFT); | |
519 | } | |
520 | ||
8a8d24bd | 521 | static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) |
1f08aa1c PT |
522 | { |
523 | struct rk3399_grf_regs *grf; | |
524 | ||
525 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
526 | ||
527 | rk_clrsetreg(&grf->soc_con5, | |
528 | RK3399_GMAC_PHY_INTF_SEL_MASK, | |
529 | RK3399_GMAC_PHY_INTF_SEL_RGMII); | |
530 | ||
531 | rk_clrsetreg(&grf->soc_con6, | |
532 | RK3399_RXCLK_DLY_ENA_GMAC_MASK | | |
533 | RK3399_TXCLK_DLY_ENA_GMAC_MASK | | |
534 | RK3399_CLK_RX_DL_CFG_GMAC_MASK | | |
535 | RK3399_CLK_TX_DL_CFG_GMAC_MASK, | |
3d1bd5b5 | 536 | DELAY_ENABLE(RK3399, pdata->tx_delay, pdata->rx_delay) | |
1f08aa1c PT |
537 | pdata->rx_delay << RK3399_CLK_RX_DL_CFG_GMAC_SHIFT | |
538 | pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT); | |
539 | } | |
540 | ||
8a8d24bd | 541 | static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) |
caf74617 DW |
542 | { |
543 | struct rv1108_grf *grf; | |
544 | ||
545 | enum { | |
546 | RV1108_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), | |
547 | RV1108_GMAC_PHY_INTF_SEL_RMII = 4 << 4, | |
548 | }; | |
549 | ||
550 | grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
551 | rk_clrsetreg(&grf->gmac_con0, | |
552 | RV1108_GMAC_PHY_INTF_SEL_MASK, | |
553 | RV1108_GMAC_PHY_INTF_SEL_RMII); | |
554 | } | |
555 | ||
0125bcf0 SS |
556 | static int gmac_rockchip_probe(struct udevice *dev) |
557 | { | |
8a8d24bd | 558 | struct gmac_rockchip_plat *pdata = dev_get_plat(dev); |
1f08aa1c PT |
559 | struct rk_gmac_ops *ops = |
560 | (struct rk_gmac_ops *)dev_get_driver_data(dev); | |
c69cda25 | 561 | struct dw_eth_pdata *dw_pdata = dev_get_plat(dev); |
caf74617 | 562 | struct eth_pdata *eth_pdata = &dw_pdata->eth_pdata; |
0125bcf0 | 563 | struct clk clk; |
caf74617 | 564 | ulong rate; |
0125bcf0 SS |
565 | int ret; |
566 | ||
b0791184 HS |
567 | ret = clk_set_defaults(dev, 0); |
568 | if (ret) | |
569 | debug("%s clk_set_defaults failed %d\n", __func__, ret); | |
570 | ||
0125bcf0 SS |
571 | ret = clk_get_by_index(dev, 0, &clk); |
572 | if (ret) | |
573 | return ret; | |
574 | ||
caf74617 DW |
575 | switch (eth_pdata->phy_interface) { |
576 | case PHY_INTERFACE_MODE_RGMII: | |
3d1bd5b5 JH |
577 | /* Set to RGMII mode */ |
578 | if (ops->set_to_rgmii) | |
579 | ops->set_to_rgmii(pdata); | |
580 | else | |
581 | return -EPERM; | |
582 | ||
caf74617 DW |
583 | /* |
584 | * If the gmac clock is from internal pll, need to set and | |
585 | * check the return value for gmac clock at RGMII mode. If | |
586 | * the gmac clock is from external source, the clock rate | |
587 | * is not set, because of it is bypassed. | |
588 | */ | |
3d1bd5b5 | 589 | |
caf74617 DW |
590 | if (!pdata->clock_input) { |
591 | rate = clk_set_rate(&clk, 125000000); | |
592 | if (rate != 125000000) | |
593 | return -EINVAL; | |
594 | } | |
3d1bd5b5 | 595 | break; |
caf74617 | 596 | |
3d1bd5b5 | 597 | case PHY_INTERFACE_MODE_RGMII_ID: |
caf74617 | 598 | /* Set to RGMII mode */ |
3d1bd5b5 JH |
599 | if (ops->set_to_rgmii) { |
600 | pdata->tx_delay = 0; | |
601 | pdata->rx_delay = 0; | |
caf74617 | 602 | ops->set_to_rgmii(pdata); |
3d1bd5b5 | 603 | } else |
caf74617 | 604 | return -EPERM; |
0125bcf0 | 605 | |
caf74617 | 606 | if (!pdata->clock_input) { |
3d1bd5b5 JH |
607 | rate = clk_set_rate(&clk, 125000000); |
608 | if (rate != 125000000) | |
caf74617 DW |
609 | return -EINVAL; |
610 | } | |
3d1bd5b5 | 611 | break; |
caf74617 | 612 | |
3d1bd5b5 | 613 | case PHY_INTERFACE_MODE_RMII: |
caf74617 DW |
614 | /* Set to RMII mode */ |
615 | if (ops->set_to_rmii) | |
616 | ops->set_to_rmii(pdata); | |
617 | else | |
618 | return -EPERM; | |
619 | ||
3d1bd5b5 JH |
620 | if (!pdata->clock_input) { |
621 | rate = clk_set_rate(&clk, 50000000); | |
622 | if (rate != 50000000) | |
623 | return -EINVAL; | |
624 | } | |
625 | break; | |
626 | ||
627 | case PHY_INTERFACE_MODE_RGMII_RXID: | |
628 | /* Set to RGMII_RXID mode */ | |
629 | if (ops->set_to_rgmii) { | |
630 | pdata->tx_delay = 0; | |
631 | ops->set_to_rgmii(pdata); | |
632 | } else | |
633 | return -EPERM; | |
634 | ||
635 | if (!pdata->clock_input) { | |
636 | rate = clk_set_rate(&clk, 125000000); | |
637 | if (rate != 125000000) | |
638 | return -EINVAL; | |
639 | } | |
caf74617 | 640 | break; |
3d1bd5b5 JH |
641 | |
642 | case PHY_INTERFACE_MODE_RGMII_TXID: | |
643 | /* Set to RGMII_TXID mode */ | |
644 | if (ops->set_to_rgmii) { | |
645 | pdata->rx_delay = 0; | |
646 | ops->set_to_rgmii(pdata); | |
647 | } else | |
648 | return -EPERM; | |
649 | ||
650 | if (!pdata->clock_input) { | |
651 | rate = clk_set_rate(&clk, 125000000); | |
652 | if (rate != 125000000) | |
653 | return -EINVAL; | |
654 | } | |
655 | break; | |
656 | ||
caf74617 DW |
657 | default: |
658 | debug("NO interface defined!\n"); | |
659 | return -ENXIO; | |
660 | } | |
0125bcf0 SS |
661 | |
662 | return designware_eth_probe(dev); | |
663 | } | |
664 | ||
665 | static int gmac_rockchip_eth_start(struct udevice *dev) | |
666 | { | |
c69cda25 | 667 | struct eth_pdata *pdata = dev_get_plat(dev); |
0125bcf0 | 668 | struct dw_eth_dev *priv = dev_get_priv(dev); |
1f08aa1c PT |
669 | struct rk_gmac_ops *ops = |
670 | (struct rk_gmac_ops *)dev_get_driver_data(dev); | |
0125bcf0 SS |
671 | int ret; |
672 | ||
673 | ret = designware_eth_init(priv, pdata->enetaddr); | |
674 | if (ret) | |
675 | return ret; | |
1f08aa1c | 676 | ret = ops->fix_mac_speed(priv); |
0125bcf0 SS |
677 | if (ret) |
678 | return ret; | |
679 | ret = designware_eth_enable(priv); | |
680 | if (ret) | |
681 | return ret; | |
682 | ||
683 | return 0; | |
684 | } | |
685 | ||
686 | const struct eth_ops gmac_rockchip_eth_ops = { | |
687 | .start = gmac_rockchip_eth_start, | |
688 | .send = designware_eth_send, | |
689 | .recv = designware_eth_recv, | |
690 | .free_pkt = designware_eth_free_pkt, | |
691 | .stop = designware_eth_stop, | |
692 | .write_hwaddr = designware_eth_write_hwaddr, | |
693 | }; | |
694 | ||
b0791184 HS |
695 | const struct rk_gmac_ops px30_gmac_ops = { |
696 | .fix_mac_speed = px30_gmac_fix_mac_speed, | |
697 | .set_to_rmii = px30_gmac_set_to_rmii, | |
698 | }; | |
699 | ||
d12d7c09 DW |
700 | const struct rk_gmac_ops rk3228_gmac_ops = { |
701 | .fix_mac_speed = rk3228_gmac_fix_mac_speed, | |
702 | .set_to_rgmii = rk3228_gmac_set_to_rgmii, | |
703 | }; | |
704 | ||
1f08aa1c PT |
705 | const struct rk_gmac_ops rk3288_gmac_ops = { |
706 | .fix_mac_speed = rk3288_gmac_fix_mac_speed, | |
707 | .set_to_rgmii = rk3288_gmac_set_to_rgmii, | |
708 | }; | |
709 | ||
0ed8f1e5 DW |
710 | const struct rk_gmac_ops rk3308_gmac_ops = { |
711 | .fix_mac_speed = rk3308_gmac_fix_mac_speed, | |
712 | .set_to_rmii = rk3308_gmac_set_to_rmii, | |
713 | }; | |
714 | ||
b3d2a6df DW |
715 | const struct rk_gmac_ops rk3328_gmac_ops = { |
716 | .fix_mac_speed = rk3328_gmac_fix_mac_speed, | |
717 | .set_to_rgmii = rk3328_gmac_set_to_rgmii, | |
718 | }; | |
719 | ||
793f2fd2 PT |
720 | const struct rk_gmac_ops rk3368_gmac_ops = { |
721 | .fix_mac_speed = rk3368_gmac_fix_mac_speed, | |
722 | .set_to_rgmii = rk3368_gmac_set_to_rgmii, | |
723 | }; | |
724 | ||
1f08aa1c PT |
725 | const struct rk_gmac_ops rk3399_gmac_ops = { |
726 | .fix_mac_speed = rk3399_gmac_fix_mac_speed, | |
727 | .set_to_rgmii = rk3399_gmac_set_to_rgmii, | |
728 | }; | |
729 | ||
caf74617 DW |
730 | const struct rk_gmac_ops rv1108_gmac_ops = { |
731 | .fix_mac_speed = rv1108_set_rmii_speed, | |
732 | .set_to_rmii = rv1108_gmac_set_to_rmii, | |
733 | }; | |
734 | ||
0125bcf0 | 735 | static const struct udevice_id rockchip_gmac_ids[] = { |
b0791184 HS |
736 | { .compatible = "rockchip,px30-gmac", |
737 | .data = (ulong)&px30_gmac_ops }, | |
d12d7c09 DW |
738 | { .compatible = "rockchip,rk3228-gmac", |
739 | .data = (ulong)&rk3228_gmac_ops }, | |
1f08aa1c PT |
740 | { .compatible = "rockchip,rk3288-gmac", |
741 | .data = (ulong)&rk3288_gmac_ops }, | |
0ed8f1e5 DW |
742 | { .compatible = "rockchip,rk3308-mac", |
743 | .data = (ulong)&rk3308_gmac_ops }, | |
b3d2a6df DW |
744 | { .compatible = "rockchip,rk3328-gmac", |
745 | .data = (ulong)&rk3328_gmac_ops }, | |
793f2fd2 PT |
746 | { .compatible = "rockchip,rk3368-gmac", |
747 | .data = (ulong)&rk3368_gmac_ops }, | |
1f08aa1c PT |
748 | { .compatible = "rockchip,rk3399-gmac", |
749 | .data = (ulong)&rk3399_gmac_ops }, | |
caf74617 DW |
750 | { .compatible = "rockchip,rv1108-gmac", |
751 | .data = (ulong)&rv1108_gmac_ops }, | |
0125bcf0 SS |
752 | { } |
753 | }; | |
754 | ||
755 | U_BOOT_DRIVER(eth_gmac_rockchip) = { | |
756 | .name = "gmac_rockchip", | |
757 | .id = UCLASS_ETH, | |
758 | .of_match = rockchip_gmac_ids, | |
d1998a9f | 759 | .of_to_plat = gmac_rockchip_of_to_plat, |
0125bcf0 SS |
760 | .probe = gmac_rockchip_probe, |
761 | .ops = &gmac_rockchip_eth_ops, | |
41575d8e | 762 | .priv_auto = sizeof(struct dw_eth_dev), |
8a8d24bd | 763 | .plat_auto = sizeof(struct gmac_rockchip_plat), |
0125bcf0 SS |
764 | .flags = DM_FLAG_ALLOC_PRIV_DMA, |
765 | }; |