xref: /linux/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c (revision 8a5f956a9fb7d74fff681145082acfad5afa6bb8)
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 plat_stmmacenet_data *plat_dat;
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 platform_device *pdev, void *bsp_priv)
75 {
76 	struct ingenic_mac *mac = bsp_priv;
77 	int ret;
78 
79 	if (mac->soc_info->set_mode) {
80 		ret = mac->soc_info->set_mode(mac->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->phy_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 %s\n",
123 			phy_modes(plat_dat->phy_interface));
124 		return -EINVAL;
125 	}
126 
127 	/* Update MAC PHY control register */
128 	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
129 }
130 
131 static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
132 {
133 	struct ingenic_mac *mac = plat_dat->bsp_priv;
134 
135 	switch (plat_dat->phy_interface) {
136 	case PHY_INTERFACE_MODE_RMII:
137 		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
138 		break;
139 
140 	default:
141 		dev_err(mac->dev, "Unsupported interface %s\n",
142 			phy_modes(plat_dat->phy_interface));
143 		return -EINVAL;
144 	}
145 
146 	/* Update MAC PHY control register */
147 	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, 0);
148 }
149 
150 static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
151 {
152 	struct ingenic_mac *mac = plat_dat->bsp_priv;
153 	unsigned int val;
154 
155 	switch (plat_dat->phy_interface) {
156 	case PHY_INTERFACE_MODE_RMII:
157 		val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
158 		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
159 		break;
160 
161 	default:
162 		dev_err(mac->dev, "Unsupported interface %s\n",
163 			phy_modes(plat_dat->phy_interface));
164 		return -EINVAL;
165 	}
166 
167 	/* Update MAC PHY control register */
168 	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
169 }
170 
171 static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
172 {
173 	struct ingenic_mac *mac = plat_dat->bsp_priv;
174 	unsigned int val;
175 
176 	switch (plat_dat->phy_interface) {
177 	case PHY_INTERFACE_MODE_RMII:
178 		val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) |
179 			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
180 		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
181 		break;
182 
183 	default:
184 		dev_err(mac->dev, "Unsupported interface %s\n",
185 			phy_modes(plat_dat->phy_interface));
186 		return -EINVAL;
187 	}
188 
189 	/* Update MAC PHY control register */
190 	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
191 }
192 
193 static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
194 {
195 	struct ingenic_mac *mac = plat_dat->bsp_priv;
196 	unsigned int val;
197 
198 	switch (plat_dat->phy_interface) {
199 	case PHY_INTERFACE_MODE_RMII:
200 		val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) |
201 			  FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) |
202 			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
203 		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
204 		break;
205 
206 	case PHY_INTERFACE_MODE_RGMII:
207 	case PHY_INTERFACE_MODE_RGMII_ID:
208 	case PHY_INTERFACE_MODE_RGMII_TXID:
209 	case PHY_INTERFACE_MODE_RGMII_RXID:
210 		val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
211 
212 		if (mac->tx_delay == 0)
213 			val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN);
214 		else
215 			val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY) |
216 				   FIELD_PREP(MACPHYC_TX_DELAY_MASK, (mac->tx_delay + 9750) / 19500 - 1);
217 
218 		if (mac->rx_delay == 0)
219 			val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN);
220 		else
221 			val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY) |
222 				   FIELD_PREP(MACPHYC_RX_DELAY_MASK, (mac->rx_delay + 9750) / 19500 - 1);
223 
224 		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
225 		break;
226 
227 	default:
228 		dev_err(mac->dev, "Unsupported interface %s\n",
229 			phy_modes(plat_dat->phy_interface));
230 		return -EINVAL;
231 	}
232 
233 	/* Update MAC PHY control register */
234 	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
235 }
236 
237 static int ingenic_mac_probe(struct platform_device *pdev)
238 {
239 	struct plat_stmmacenet_data *plat_dat;
240 	struct stmmac_resources stmmac_res;
241 	struct ingenic_mac *mac;
242 	const struct ingenic_soc_info *data;
243 	u32 tx_delay_ps, rx_delay_ps;
244 	int ret;
245 
246 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
247 	if (ret)
248 		return ret;
249 
250 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
251 	if (IS_ERR(plat_dat))
252 		return PTR_ERR(plat_dat);
253 
254 	mac = devm_kzalloc(&pdev->dev, sizeof(*mac), GFP_KERNEL);
255 	if (!mac)
256 		return -ENOMEM;
257 
258 	data = of_device_get_match_data(&pdev->dev);
259 	if (!data) {
260 		dev_err(&pdev->dev, "No of match data provided\n");
261 		return -EINVAL;
262 	}
263 
264 	/* Get MAC PHY control register */
265 	mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg");
266 	if (IS_ERR(mac->regmap)) {
267 		dev_err(&pdev->dev, "%s: Failed to get syscon regmap\n", __func__);
268 		return PTR_ERR(mac->regmap);
269 	}
270 
271 	if (!of_property_read_u32(pdev->dev.of_node, "tx-clk-delay-ps", &tx_delay_ps)) {
272 		if (tx_delay_ps >= MACPHYC_TX_DELAY_PS_MIN &&
273 			tx_delay_ps <= MACPHYC_TX_DELAY_PS_MAX) {
274 			mac->tx_delay = tx_delay_ps * 1000;
275 		} else {
276 			dev_err(&pdev->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps);
277 			return -EINVAL;
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 			return -EINVAL;
288 		}
289 	}
290 
291 	mac->soc_info = data;
292 	mac->dev = &pdev->dev;
293 	mac->plat_dat = plat_dat;
294 
295 	plat_dat->bsp_priv = mac;
296 	plat_dat->init = ingenic_mac_init;
297 
298 	return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
299 }
300 
301 static struct ingenic_soc_info jz4775_soc_info = {
302 	.version = ID_JZ4775,
303 	.mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
304 
305 	.set_mode = jz4775_mac_set_mode,
306 };
307 
308 static struct ingenic_soc_info x1000_soc_info = {
309 	.version = ID_X1000,
310 	.mask = MACPHYC_SOFT_RST_MASK,
311 
312 	.set_mode = x1000_mac_set_mode,
313 };
314 
315 static struct ingenic_soc_info x1600_soc_info = {
316 	.version = ID_X1600,
317 	.mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
318 
319 	.set_mode = x1600_mac_set_mode,
320 };
321 
322 static struct ingenic_soc_info x1830_soc_info = {
323 	.version = ID_X1830,
324 	.mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
325 
326 	.set_mode = x1830_mac_set_mode,
327 };
328 
329 static struct ingenic_soc_info x2000_soc_info = {
330 	.version = ID_X2000,
331 	.mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK |
332 			MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
333 
334 	.set_mode = x2000_mac_set_mode,
335 };
336 
337 static const struct of_device_id ingenic_mac_of_matches[] = {
338 	{ .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info },
339 	{ .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info },
340 	{ .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info },
341 	{ .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info },
342 	{ .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info },
343 	{ }
344 };
345 MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
346 
347 static struct platform_driver ingenic_mac_driver = {
348 	.probe		= ingenic_mac_probe,
349 	.driver		= {
350 		.name	= "ingenic-mac",
351 		.pm		= &stmmac_pltfr_pm_ops,
352 		.of_match_table = ingenic_mac_of_matches,
353 	},
354 };
355 module_platform_driver(ingenic_mac_driver);
356 
357 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
358 MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer");
359 MODULE_LICENSE("GPL v2");
360