1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * dwmac-ingenic.c - Ingenic SoCs DWMAC specific glue layer
4 *
5 * Copyright (c) 2021 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
6 */
7
8 #include <linux/bitfield.h>
9 #include <linux/clk.h>
10 #include <linux/kernel.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_net.h>
15 #include <linux/phy.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/slab.h>
19 #include <linux/stmmac.h>
20
21 #include "stmmac_platform.h"
22
23 #define MACPHYC_TXCLK_SEL_MASK GENMASK(31, 31)
24 #define MACPHYC_TXCLK_SEL_OUTPUT 0x1
25 #define MACPHYC_TXCLK_SEL_INPUT 0x0
26 #define MACPHYC_MODE_SEL_MASK GENMASK(31, 31)
27 #define MACPHYC_MODE_SEL_RMII 0x0
28 #define MACPHYC_TX_SEL_MASK GENMASK(19, 19)
29 #define MACPHYC_TX_SEL_ORIGIN 0x0
30 #define MACPHYC_TX_SEL_DELAY 0x1
31 #define MACPHYC_TX_DELAY_MASK GENMASK(18, 12)
32 #define MACPHYC_RX_SEL_MASK GENMASK(11, 11)
33 #define MACPHYC_RX_SEL_ORIGIN 0x0
34 #define MACPHYC_RX_SEL_DELAY 0x1
35 #define MACPHYC_RX_DELAY_MASK GENMASK(10, 4)
36 #define MACPHYC_SOFT_RST_MASK GENMASK(3, 3)
37 #define MACPHYC_PHY_INFT_MASK GENMASK(2, 0)
38 #define MACPHYC_PHY_INFT_RMII 0x4
39 #define MACPHYC_PHY_INFT_RGMII 0x1
40 #define MACPHYC_PHY_INFT_GMII 0x0
41 #define MACPHYC_PHY_INFT_MII 0x0
42
43 #define MACPHYC_TX_DELAY_PS_MAX 2496
44 #define MACPHYC_TX_DELAY_PS_MIN 20
45
46 #define MACPHYC_RX_DELAY_PS_MAX 2496
47 #define MACPHYC_RX_DELAY_PS_MIN 20
48
49 enum ingenic_mac_version {
50 ID_JZ4775,
51 ID_X1000,
52 ID_X1600,
53 ID_X1830,
54 ID_X2000,
55 };
56
57 struct ingenic_mac {
58 const struct ingenic_soc_info *soc_info;
59 struct device *dev;
60 struct regmap *regmap;
61
62 int rx_delay;
63 int tx_delay;
64 };
65
66 struct ingenic_soc_info {
67 enum ingenic_mac_version version;
68 u32 mask;
69
70 int (*set_mode)(struct plat_stmmacenet_data *plat_dat);
71 };
72
ingenic_mac_init(struct plat_stmmacenet_data * plat_dat)73 static int ingenic_mac_init(struct plat_stmmacenet_data *plat_dat)
74 {
75 struct ingenic_mac *mac = plat_dat->bsp_priv;
76 int ret;
77
78 if (mac->soc_info->set_mode) {
79 ret = mac->soc_info->set_mode(plat_dat);
80 if (ret)
81 return ret;
82 }
83
84 return 0;
85 }
86
jz4775_mac_set_mode(struct plat_stmmacenet_data * plat_dat)87 static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
88 {
89 struct ingenic_mac *mac = plat_dat->bsp_priv;
90 unsigned int val;
91
92 switch (plat_dat->mac_interface) {
93 case PHY_INTERFACE_MODE_MII:
94 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
95 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII);
96 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_MII\n");
97 break;
98
99 case PHY_INTERFACE_MODE_GMII:
100 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
101 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_GMII);
102 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_GMII\n");
103 break;
104
105 case PHY_INTERFACE_MODE_RMII:
106 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
107 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
108 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
109 break;
110
111 case PHY_INTERFACE_MODE_RGMII:
112 case PHY_INTERFACE_MODE_RGMII_ID:
113 case PHY_INTERFACE_MODE_RGMII_TXID:
114 case PHY_INTERFACE_MODE_RGMII_RXID:
115 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
116 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
117 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
118 break;
119
120 default:
121 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface);
122 return -EINVAL;
123 }
124
125 /* Update MAC PHY control register */
126 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
127 }
128
x1000_mac_set_mode(struct plat_stmmacenet_data * plat_dat)129 static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
130 {
131 struct ingenic_mac *mac = plat_dat->bsp_priv;
132
133 switch (plat_dat->mac_interface) {
134 case PHY_INTERFACE_MODE_RMII:
135 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
136 break;
137
138 default:
139 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface);
140 return -EINVAL;
141 }
142
143 /* Update MAC PHY control register */
144 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, 0);
145 }
146
x1600_mac_set_mode(struct plat_stmmacenet_data * plat_dat)147 static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
148 {
149 struct ingenic_mac *mac = plat_dat->bsp_priv;
150 unsigned int val;
151
152 switch (plat_dat->mac_interface) {
153 case PHY_INTERFACE_MODE_RMII:
154 val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
155 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
156 break;
157
158 default:
159 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface);
160 return -EINVAL;
161 }
162
163 /* Update MAC PHY control register */
164 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
165 }
166
x1830_mac_set_mode(struct plat_stmmacenet_data * plat_dat)167 static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
168 {
169 struct ingenic_mac *mac = plat_dat->bsp_priv;
170 unsigned int val;
171
172 switch (plat_dat->mac_interface) {
173 case PHY_INTERFACE_MODE_RMII:
174 val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) |
175 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
176 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
177 break;
178
179 default:
180 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface);
181 return -EINVAL;
182 }
183
184 /* Update MAC PHY control register */
185 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
186 }
187
x2000_mac_set_mode(struct plat_stmmacenet_data * plat_dat)188 static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
189 {
190 struct ingenic_mac *mac = plat_dat->bsp_priv;
191 unsigned int val;
192
193 switch (plat_dat->mac_interface) {
194 case PHY_INTERFACE_MODE_RMII:
195 val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) |
196 FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) |
197 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
198 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
199 break;
200
201 case PHY_INTERFACE_MODE_RGMII:
202 case PHY_INTERFACE_MODE_RGMII_ID:
203 case PHY_INTERFACE_MODE_RGMII_TXID:
204 case PHY_INTERFACE_MODE_RGMII_RXID:
205 val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
206
207 if (mac->tx_delay == 0)
208 val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN);
209 else
210 val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY) |
211 FIELD_PREP(MACPHYC_TX_DELAY_MASK, (mac->tx_delay + 9750) / 19500 - 1);
212
213 if (mac->rx_delay == 0)
214 val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN);
215 else
216 val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY) |
217 FIELD_PREP(MACPHYC_RX_DELAY_MASK, (mac->rx_delay + 9750) / 19500 - 1);
218
219 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
220 break;
221
222 default:
223 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface);
224 return -EINVAL;
225 }
226
227 /* Update MAC PHY control register */
228 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
229 }
230
ingenic_mac_probe(struct platform_device * pdev)231 static int ingenic_mac_probe(struct platform_device *pdev)
232 {
233 struct plat_stmmacenet_data *plat_dat;
234 struct stmmac_resources stmmac_res;
235 struct ingenic_mac *mac;
236 const struct ingenic_soc_info *data;
237 u32 tx_delay_ps, rx_delay_ps;
238 int ret;
239
240 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
241 if (ret)
242 return ret;
243
244 plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
245 if (IS_ERR(plat_dat))
246 return PTR_ERR(plat_dat);
247
248 mac = devm_kzalloc(&pdev->dev, sizeof(*mac), GFP_KERNEL);
249 if (!mac)
250 return -ENOMEM;
251
252 data = of_device_get_match_data(&pdev->dev);
253 if (!data) {
254 dev_err(&pdev->dev, "No of match data provided\n");
255 return -EINVAL;
256 }
257
258 /* Get MAC PHY control register */
259 mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg");
260 if (IS_ERR(mac->regmap)) {
261 dev_err(&pdev->dev, "%s: Failed to get syscon regmap\n", __func__);
262 return PTR_ERR(mac->regmap);
263 }
264
265 if (!of_property_read_u32(pdev->dev.of_node, "tx-clk-delay-ps", &tx_delay_ps)) {
266 if (tx_delay_ps >= MACPHYC_TX_DELAY_PS_MIN &&
267 tx_delay_ps <= MACPHYC_TX_DELAY_PS_MAX) {
268 mac->tx_delay = tx_delay_ps * 1000;
269 } else {
270 dev_err(&pdev->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps);
271 return -EINVAL;
272 }
273 }
274
275 if (!of_property_read_u32(pdev->dev.of_node, "rx-clk-delay-ps", &rx_delay_ps)) {
276 if (rx_delay_ps >= MACPHYC_RX_DELAY_PS_MIN &&
277 rx_delay_ps <= MACPHYC_RX_DELAY_PS_MAX) {
278 mac->rx_delay = rx_delay_ps * 1000;
279 } else {
280 dev_err(&pdev->dev, "Invalid RX clock delay: %dps\n", rx_delay_ps);
281 return -EINVAL;
282 }
283 }
284
285 mac->soc_info = data;
286 mac->dev = &pdev->dev;
287
288 plat_dat->bsp_priv = mac;
289
290 ret = ingenic_mac_init(plat_dat);
291 if (ret)
292 return ret;
293
294 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
295 }
296
297 #ifdef CONFIG_PM_SLEEP
ingenic_mac_suspend(struct device * dev)298 static int ingenic_mac_suspend(struct device *dev)
299 {
300 int ret;
301
302 ret = stmmac_suspend(dev);
303
304 return ret;
305 }
306
ingenic_mac_resume(struct device * dev)307 static int ingenic_mac_resume(struct device *dev)
308 {
309 struct net_device *ndev = dev_get_drvdata(dev);
310 struct stmmac_priv *priv = netdev_priv(ndev);
311 int ret;
312
313 ret = ingenic_mac_init(priv->plat);
314 if (ret)
315 return ret;
316
317 ret = stmmac_resume(dev);
318
319 return ret;
320 }
321 #endif /* CONFIG_PM_SLEEP */
322
323 static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume);
324
325 static struct ingenic_soc_info jz4775_soc_info = {
326 .version = ID_JZ4775,
327 .mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
328
329 .set_mode = jz4775_mac_set_mode,
330 };
331
332 static struct ingenic_soc_info x1000_soc_info = {
333 .version = ID_X1000,
334 .mask = MACPHYC_SOFT_RST_MASK,
335
336 .set_mode = x1000_mac_set_mode,
337 };
338
339 static struct ingenic_soc_info x1600_soc_info = {
340 .version = ID_X1600,
341 .mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
342
343 .set_mode = x1600_mac_set_mode,
344 };
345
346 static struct ingenic_soc_info x1830_soc_info = {
347 .version = ID_X1830,
348 .mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
349
350 .set_mode = x1830_mac_set_mode,
351 };
352
353 static struct ingenic_soc_info x2000_soc_info = {
354 .version = ID_X2000,
355 .mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK |
356 MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
357
358 .set_mode = x2000_mac_set_mode,
359 };
360
361 static const struct of_device_id ingenic_mac_of_matches[] = {
362 { .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info },
363 { .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info },
364 { .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info },
365 { .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info },
366 { .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info },
367 { }
368 };
369 MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
370
371 static struct platform_driver ingenic_mac_driver = {
372 .probe = ingenic_mac_probe,
373 .remove_new = stmmac_pltfr_remove,
374 .driver = {
375 .name = "ingenic-mac",
376 .pm = pm_ptr(&ingenic_mac_pm_ops),
377 .of_match_table = ingenic_mac_of_matches,
378 },
379 };
380 module_platform_driver(ingenic_mac_driver);
381
382 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
383 MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer");
384 MODULE_LICENSE("GPL v2");
385