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