diff options
author | Roger Chen <roger.chen@rock-chips.com> | 2014-12-29 04:43:36 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-31 19:14:05 -0500 |
commit | 7ad269ea1a2b7ddc8ae26794162c21bad2d9b2e5 (patch) | |
tree | 4b0a83d8ade4bb3fd5282e74775cca205ae54ec6 | |
parent | 9aacfb2023c67c8e797bf1f9ba5e095c5a09d296 (diff) |
GMAC: add driver for Rockchip RK3288 SoCs integrated GMAC
This driver is based on stmmac driver.
changes since v2:
- use tab instead of space for macros
- use HIWORD_UPDATE macro for GMAC_CLK_RX_DL_CFG and GMAC_CLK_TX_DL_CFG
- remove drive-strength setting in the driver and set it in the pinctrl settings
- use dev_err instead of pr_err
- remove clock names's macros, just use the real name of the clock
- use devm_clk_get() instead of clk_get()
- remove clk_set_parent(bsp_priv->clk_mac, bsp_priv->clk_mac_pll)
- remove gpio setting for LDO, just use regulator API
- remove phy reset using gpio in the glue layer, it has been handled in the stmmac driver
- remove handling phy interrupt (mii interrupt)
changes since v1:
- use BIT() to set register
- combine two remap_write() operations into one for the same register
- use macros for register value setting
- remove grf fail check in rk_gmac_setup() and save all the check in set_rgmii_speed()
- remove .tx_coe=1 in rk_gmac_data
Signed-off-by: Roger Chen <roger.chen@rock-chips.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 459 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 1 |
4 files changed, 462 insertions, 1 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index ac4d5629d905..73c2715a27f3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile | |||
@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ | |||
6 | 6 | ||
7 | obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o | 7 | obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o |
8 | stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o \ | 8 | stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o \ |
9 | dwmac-sti.o dwmac-socfpga.o | 9 | dwmac-sti.o dwmac-socfpga.o dwmac-rk.o |
10 | 10 | ||
11 | obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o | 11 | obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o |
12 | stmmac-pci-objs:= stmmac_pci.o | 12 | stmmac-pci-objs:= stmmac_pci.o |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c new file mode 100644 index 000000000000..35f9b86bc9e5 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | |||
@@ -0,0 +1,459 @@ | |||
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> | ||
25 | #include <linux/of_gpio.h> | ||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/regulator/consumer.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/mfd/syscon.h> | ||
30 | #include <linux/regmap.h> | ||
31 | |||
32 | struct rk_priv_data { | ||
33 | struct platform_device *pdev; | ||
34 | int phy_iface; | ||
35 | char regulator[32]; | ||
36 | |||
37 | bool clk_enabled; | ||
38 | bool clock_input; | ||
39 | |||
40 | struct clk *clk_mac; | ||
41 | struct clk *clk_mac_pll; | ||
42 | struct clk *gmac_clkin; | ||
43 | struct clk *mac_clk_rx; | ||
44 | struct clk *mac_clk_tx; | ||
45 | struct clk *clk_mac_ref; | ||
46 | struct clk *clk_mac_refout; | ||
47 | struct clk *aclk_mac; | ||
48 | struct clk *pclk_mac; | ||
49 | |||
50 | int tx_delay; | ||
51 | int rx_delay; | ||
52 | |||
53 | struct regmap *grf; | ||
54 | }; | ||
55 | |||
56 | #define HIWORD_UPDATE(val, mask, shift) \ | ||
57 | ((val) << (shift) | (mask) << ((shift) + 16)) | ||
58 | |||
59 | #define GRF_BIT(nr) (BIT(nr) | BIT(nr+16)) | ||
60 | #define GRF_CLR_BIT(nr) (BIT(nr+16)) | ||
61 | |||
62 | #define RK3288_GRF_SOC_CON1 0x0248 | ||
63 | #define RK3288_GRF_SOC_CON3 0x0250 | ||
64 | #define RK3288_GRF_GPIO3D_E 0x01ec | ||
65 | #define RK3288_GRF_GPIO4A_E 0x01f0 | ||
66 | #define RK3288_GRF_GPIO4B_E 0x01f4 | ||
67 | |||
68 | /*RK3288_GRF_SOC_CON1*/ | ||
69 | #define GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8)) | ||
70 | #define GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8)) | ||
71 | #define GMAC_FLOW_CTRL GRF_BIT(9) | ||
72 | #define GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9) | ||
73 | #define GMAC_SPEED_10M GRF_CLR_BIT(10) | ||
74 | #define GMAC_SPEED_100M GRF_BIT(10) | ||
75 | #define GMAC_RMII_CLK_25M GRF_BIT(11) | ||
76 | #define GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11) | ||
77 | #define GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13)) | ||
78 | #define GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13)) | ||
79 | #define GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13)) | ||
80 | #define GMAC_RMII_MODE GRF_BIT(14) | ||
81 | #define GMAC_RMII_MODE_CLR GRF_CLR_BIT(14) | ||
82 | |||
83 | /*RK3288_GRF_SOC_CON3*/ | ||
84 | #define GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) | ||
85 | #define GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) | ||
86 | #define GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) | ||
87 | #define GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) | ||
88 | #define GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) | ||
89 | #define GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) | ||
90 | |||
91 | static void set_to_rgmii(struct rk_priv_data *bsp_priv, | ||
92 | int tx_delay, int rx_delay) | ||
93 | { | ||
94 | struct device *dev = &bsp_priv->pdev->dev; | ||
95 | |||
96 | if (IS_ERR(bsp_priv->grf)) { | ||
97 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | ||
102 | GMAC_PHY_INTF_SEL_RGMII | GMAC_RMII_MODE_CLR); | ||
103 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3, | ||
104 | GMAC_RXCLK_DLY_ENABLE | GMAC_TXCLK_DLY_ENABLE | | ||
105 | GMAC_CLK_RX_DL_CFG(rx_delay) | | ||
106 | GMAC_CLK_TX_DL_CFG(tx_delay)); | ||
107 | } | ||
108 | |||
109 | static void set_to_rmii(struct rk_priv_data *bsp_priv) | ||
110 | { | ||
111 | struct device *dev = &bsp_priv->pdev->dev; | ||
112 | |||
113 | if (IS_ERR(bsp_priv->grf)) { | ||
114 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | ||
119 | GMAC_PHY_INTF_SEL_RMII | GMAC_RMII_MODE); | ||
120 | } | ||
121 | |||
122 | static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) | ||
123 | { | ||
124 | struct device *dev = &bsp_priv->pdev->dev; | ||
125 | |||
126 | if (IS_ERR(bsp_priv->grf)) { | ||
127 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | if (speed == 10) | ||
132 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_2_5M); | ||
133 | else if (speed == 100) | ||
134 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_25M); | ||
135 | else if (speed == 1000) | ||
136 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_125M); | ||
137 | else | ||
138 | dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); | ||
139 | } | ||
140 | |||
141 | static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) | ||
142 | { | ||
143 | struct device *dev = &bsp_priv->pdev->dev; | ||
144 | |||
145 | if (IS_ERR(bsp_priv->grf)) { | ||
146 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | if (speed == 10) { | ||
151 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | ||
152 | GMAC_RMII_CLK_2_5M | GMAC_SPEED_10M); | ||
153 | } else if (speed == 100) { | ||
154 | regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, | ||
155 | GMAC_RMII_CLK_25M | GMAC_SPEED_100M); | ||
156 | } else { | ||
157 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | static int gmac_clk_init(struct rk_priv_data *bsp_priv) | ||
162 | { | ||
163 | struct device *dev = &bsp_priv->pdev->dev; | ||
164 | |||
165 | bsp_priv->clk_enabled = false; | ||
166 | |||
167 | bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx"); | ||
168 | if (IS_ERR(bsp_priv->mac_clk_rx)) | ||
169 | dev_err(dev, "%s: cannot get clock %s\n", | ||
170 | __func__, "mac_clk_rx"); | ||
171 | |||
172 | bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx"); | ||
173 | if (IS_ERR(bsp_priv->mac_clk_tx)) | ||
174 | dev_err(dev, "%s: cannot get clock %s\n", | ||
175 | __func__, "mac_clk_tx"); | ||
176 | |||
177 | bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac"); | ||
178 | if (IS_ERR(bsp_priv->aclk_mac)) | ||
179 | dev_err(dev, "%s: cannot get clock %s\n", | ||
180 | __func__, "aclk_mac"); | ||
181 | |||
182 | bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac"); | ||
183 | if (IS_ERR(bsp_priv->pclk_mac)) | ||
184 | dev_err(dev, "%s: cannot get clock %s\n", | ||
185 | __func__, "pclk_mac"); | ||
186 | |||
187 | bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth"); | ||
188 | if (IS_ERR(bsp_priv->clk_mac)) | ||
189 | dev_err(dev, "%s: cannot get clock %s\n", | ||
190 | __func__, "stmmaceth"); | ||
191 | |||
192 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { | ||
193 | bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref"); | ||
194 | if (IS_ERR(bsp_priv->clk_mac_ref)) | ||
195 | dev_err(dev, "%s: cannot get clock %s\n", | ||
196 | __func__, "clk_mac_ref"); | ||
197 | |||
198 | if (!bsp_priv->clock_input) { | ||
199 | bsp_priv->clk_mac_refout = | ||
200 | devm_clk_get(dev, "clk_mac_refout"); | ||
201 | if (IS_ERR(bsp_priv->clk_mac_refout)) | ||
202 | dev_err(dev, "%s: cannot get clock %s\n", | ||
203 | __func__, "clk_mac_refout"); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | if (bsp_priv->clock_input) { | ||
208 | dev_info(dev, "%s: clock input from PHY\n", __func__); | ||
209 | } else { | ||
210 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) | ||
211 | clk_set_rate(bsp_priv->clk_mac_pll, 50000000); | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) | ||
218 | { | ||
219 | int phy_iface = phy_iface = bsp_priv->phy_iface; | ||
220 | |||
221 | if (enable) { | ||
222 | if (!bsp_priv->clk_enabled) { | ||
223 | if (phy_iface == PHY_INTERFACE_MODE_RMII) { | ||
224 | if (!IS_ERR(bsp_priv->mac_clk_rx)) | ||
225 | clk_prepare_enable( | ||
226 | bsp_priv->mac_clk_rx); | ||
227 | |||
228 | if (!IS_ERR(bsp_priv->clk_mac_ref)) | ||
229 | clk_prepare_enable( | ||
230 | bsp_priv->clk_mac_ref); | ||
231 | |||
232 | if (!IS_ERR(bsp_priv->clk_mac_refout)) | ||
233 | clk_prepare_enable( | ||
234 | bsp_priv->clk_mac_refout); | ||
235 | } | ||
236 | |||
237 | if (!IS_ERR(bsp_priv->aclk_mac)) | ||
238 | clk_prepare_enable(bsp_priv->aclk_mac); | ||
239 | |||
240 | if (!IS_ERR(bsp_priv->pclk_mac)) | ||
241 | clk_prepare_enable(bsp_priv->pclk_mac); | ||
242 | |||
243 | if (!IS_ERR(bsp_priv->mac_clk_tx)) | ||
244 | clk_prepare_enable(bsp_priv->mac_clk_tx); | ||
245 | |||
246 | /** | ||
247 | * if (!IS_ERR(bsp_priv->clk_mac)) | ||
248 | * clk_prepare_enable(bsp_priv->clk_mac); | ||
249 | */ | ||
250 | mdelay(5); | ||
251 | bsp_priv->clk_enabled = true; | ||
252 | } | ||
253 | } else { | ||
254 | if (bsp_priv->clk_enabled) { | ||
255 | if (phy_iface == PHY_INTERFACE_MODE_RMII) { | ||
256 | if (!IS_ERR(bsp_priv->mac_clk_rx)) | ||
257 | clk_disable_unprepare( | ||
258 | bsp_priv->mac_clk_rx); | ||
259 | |||
260 | if (!IS_ERR(bsp_priv->clk_mac_ref)) | ||
261 | clk_disable_unprepare( | ||
262 | bsp_priv->clk_mac_ref); | ||
263 | |||
264 | if (!IS_ERR(bsp_priv->clk_mac_refout)) | ||
265 | clk_disable_unprepare( | ||
266 | bsp_priv->clk_mac_refout); | ||
267 | } | ||
268 | |||
269 | if (!IS_ERR(bsp_priv->aclk_mac)) | ||
270 | clk_disable_unprepare(bsp_priv->aclk_mac); | ||
271 | |||
272 | if (!IS_ERR(bsp_priv->pclk_mac)) | ||
273 | clk_disable_unprepare(bsp_priv->pclk_mac); | ||
274 | |||
275 | if (!IS_ERR(bsp_priv->mac_clk_tx)) | ||
276 | clk_disable_unprepare(bsp_priv->mac_clk_tx); | ||
277 | /** | ||
278 | * if (!IS_ERR(bsp_priv->clk_mac)) | ||
279 | * clk_disable_unprepare(bsp_priv->clk_mac); | ||
280 | */ | ||
281 | bsp_priv->clk_enabled = false; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable) | ||
289 | { | ||
290 | struct regulator *ldo; | ||
291 | char *ldostr = bsp_priv->regulator; | ||
292 | int ret; | ||
293 | struct device *dev = &bsp_priv->pdev->dev; | ||
294 | |||
295 | if (!ldostr) { | ||
296 | dev_err(dev, "%s: no ldo found\n", __func__); | ||
297 | return -1; | ||
298 | } | ||
299 | |||
300 | ldo = regulator_get(NULL, ldostr); | ||
301 | if (!ldo) { | ||
302 | dev_err(dev, "\n%s get ldo %s failed\n", __func__, ldostr); | ||
303 | } else { | ||
304 | if (enable) { | ||
305 | if (!regulator_is_enabled(ldo)) { | ||
306 | regulator_set_voltage(ldo, 3300000, 3300000); | ||
307 | ret = regulator_enable(ldo); | ||
308 | if (ret != 0) | ||
309 | dev_err(dev, "%s: fail to enable %s\n", | ||
310 | __func__, ldostr); | ||
311 | else | ||
312 | dev_info(dev, "turn on ldo done.\n"); | ||
313 | } else { | ||
314 | dev_warn(dev, "%s is enabled before enable", | ||
315 | ldostr); | ||
316 | } | ||
317 | } else { | ||
318 | if (regulator_is_enabled(ldo)) { | ||
319 | ret = regulator_disable(ldo); | ||
320 | if (ret != 0) | ||
321 | dev_err(dev, "%s: fail to disable %s\n", | ||
322 | __func__, ldostr); | ||
323 | else | ||
324 | dev_info(dev, "turn off ldo done.\n"); | ||
325 | } else { | ||
326 | dev_warn(dev, "%s is disabled before disable", | ||
327 | ldostr); | ||
328 | } | ||
329 | } | ||
330 | regulator_put(ldo); | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static void *rk_gmac_setup(struct platform_device *pdev) | ||
337 | { | ||
338 | struct rk_priv_data *bsp_priv; | ||
339 | struct device *dev = &pdev->dev; | ||
340 | int ret; | ||
341 | const char *strings = NULL; | ||
342 | int value; | ||
343 | |||
344 | bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL); | ||
345 | if (!bsp_priv) | ||
346 | return ERR_PTR(-ENOMEM); | ||
347 | |||
348 | bsp_priv->phy_iface = of_get_phy_mode(dev->of_node); | ||
349 | |||
350 | ret = of_property_read_string(dev->of_node, "phy_regulator", &strings); | ||
351 | if (ret) { | ||
352 | dev_warn(dev, "%s: Can not read property: phy_regulator.\n", | ||
353 | __func__); | ||
354 | } else { | ||
355 | dev_info(dev, "%s: PHY power controlled by regulator(%s).\n", | ||
356 | __func__, strings); | ||
357 | strcpy(bsp_priv->regulator, strings); | ||
358 | } | ||
359 | |||
360 | ret = of_property_read_string(dev->of_node, "clock_in_out", &strings); | ||
361 | if (ret) { | ||
362 | dev_err(dev, "%s: Can not read property: clock_in_out.\n", | ||
363 | __func__); | ||
364 | bsp_priv->clock_input = true; | ||
365 | } else { | ||
366 | dev_info(dev, "%s: clock input or output? (%s).\n", | ||
367 | __func__, strings); | ||
368 | if (!strcmp(strings, "input")) | ||
369 | bsp_priv->clock_input = true; | ||
370 | else | ||
371 | bsp_priv->clock_input = false; | ||
372 | } | ||
373 | |||
374 | ret = of_property_read_u32(dev->of_node, "tx_delay", &value); | ||
375 | if (ret) { | ||
376 | bsp_priv->tx_delay = 0x30; | ||
377 | dev_err(dev, "%s: Can not read property: tx_delay.", __func__); | ||
378 | dev_err(dev, "%s: set tx_delay to 0x%x\n", | ||
379 | __func__, bsp_priv->tx_delay); | ||
380 | } else { | ||
381 | dev_info(dev, "%s: TX delay(0x%x).\n", __func__, value); | ||
382 | bsp_priv->tx_delay = value; | ||
383 | } | ||
384 | |||
385 | ret = of_property_read_u32(dev->of_node, "rx_delay", &value); | ||
386 | if (ret) { | ||
387 | bsp_priv->rx_delay = 0x10; | ||
388 | dev_err(dev, "%s: Can not read property: rx_delay.", __func__); | ||
389 | dev_err(dev, "%s: set rx_delay to 0x%x\n", | ||
390 | __func__, bsp_priv->rx_delay); | ||
391 | } else { | ||
392 | dev_info(dev, "%s: RX delay(0x%x).\n", __func__, value); | ||
393 | bsp_priv->rx_delay = value; | ||
394 | } | ||
395 | |||
396 | bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
397 | "rockchip,grf"); | ||
398 | bsp_priv->pdev = pdev; | ||
399 | |||
400 | /*rmii or rgmii*/ | ||
401 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) { | ||
402 | dev_info(dev, "%s: init for RGMII\n", __func__); | ||
403 | set_to_rgmii(bsp_priv, bsp_priv->tx_delay, bsp_priv->rx_delay); | ||
404 | } else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { | ||
405 | dev_info(dev, "%s: init for RMII\n", __func__); | ||
406 | set_to_rmii(bsp_priv); | ||
407 | } else { | ||
408 | dev_err(dev, "%s: NO interface defined!\n", __func__); | ||
409 | } | ||
410 | |||
411 | gmac_clk_init(bsp_priv); | ||
412 | |||
413 | return bsp_priv; | ||
414 | } | ||
415 | |||
416 | static int rk_gmac_init(struct platform_device *pdev, void *priv) | ||
417 | { | ||
418 | struct rk_priv_data *bsp_priv = priv; | ||
419 | int ret; | ||
420 | |||
421 | ret = phy_power_on(bsp_priv, true); | ||
422 | if (ret) | ||
423 | return ret; | ||
424 | |||
425 | ret = gmac_clk_enable(bsp_priv, true); | ||
426 | if (ret) | ||
427 | return ret; | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static void rk_gmac_exit(struct platform_device *pdev, void *priv) | ||
433 | { | ||
434 | struct rk_priv_data *gmac = priv; | ||
435 | |||
436 | phy_power_on(gmac, false); | ||
437 | gmac_clk_enable(gmac, false); | ||
438 | } | ||
439 | |||
440 | static void rk_fix_speed(void *priv, unsigned int speed) | ||
441 | { | ||
442 | struct rk_priv_data *bsp_priv = priv; | ||
443 | struct device *dev = &bsp_priv->pdev->dev; | ||
444 | |||
445 | if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) | ||
446 | set_rgmii_speed(bsp_priv, speed); | ||
447 | else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) | ||
448 | set_rmii_speed(bsp_priv, speed); | ||
449 | else | ||
450 | dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); | ||
451 | } | ||
452 | |||
453 | const struct stmmac_of_data rk3288_gmac_data = { | ||
454 | .has_gmac = 1, | ||
455 | .fix_mac_speed = rk_fix_speed, | ||
456 | .setup = rk_gmac_setup, | ||
457 | .init = rk_gmac_init, | ||
458 | .exit = rk_gmac_exit, | ||
459 | }; | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 3039de2465ba..879e29f48a89 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | static const struct of_device_id stmmac_dt_ids[] = { | 34 | static const struct of_device_id stmmac_dt_ids[] = { |
35 | /* SoC specific glue layers should come before generic bindings */ | 35 | /* SoC specific glue layers should come before generic bindings */ |
36 | { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data}, | ||
36 | { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, | 37 | { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, |
37 | { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, | 38 | { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, |
38 | { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data}, | 39 | { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data}, |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index 25dd1f7ace02..093eb99e5ffd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | |||
@@ -24,5 +24,6 @@ extern const struct stmmac_of_data sun7i_gmac_data; | |||
24 | extern const struct stmmac_of_data stih4xx_dwmac_data; | 24 | extern const struct stmmac_of_data stih4xx_dwmac_data; |
25 | extern const struct stmmac_of_data stid127_dwmac_data; | 25 | extern const struct stmmac_of_data stid127_dwmac_data; |
26 | extern const struct stmmac_of_data socfpga_gmac_data; | 26 | extern const struct stmmac_of_data socfpga_gmac_data; |
27 | extern const struct stmmac_of_data rk3288_gmac_data; | ||
27 | 28 | ||
28 | #endif /* __STMMAC_PLATFORM_H__ */ | 29 | #endif /* __STMMAC_PLATFORM_H__ */ |