Linux Audio

Check our new training course

Loading...
v6.8
  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
 49enum ingenic_mac_version {
 50	ID_JZ4775,
 51	ID_X1000,
 52	ID_X1600,
 53	ID_X1830,
 54	ID_X2000,
 55};
 56
 57struct 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
 66struct 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
 73static 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
 87static 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
129static 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
147static 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
167static 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
188static 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
231static 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
298static int ingenic_mac_suspend(struct device *dev)
299{
300	int ret;
301
302	ret = stmmac_suspend(dev);
303
304	return ret;
305}
306
307static 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
323static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume);
324
325static 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
332static 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
339static 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
346static 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
353static 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
361static 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};
369MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
370
371static 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};
380module_platform_driver(ingenic_mac_driver);
381
382MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
383MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer");
384MODULE_LICENSE("GPL v2");
v6.2
  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
 50enum ingenic_mac_version {
 51	ID_JZ4775,
 52	ID_X1000,
 53	ID_X1600,
 54	ID_X1830,
 55	ID_X2000,
 56};
 57
 58struct 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
 67struct 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
 74static 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
 88static 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
130static 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
148static 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
168static 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
189static 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
232static 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
307err_remove_config_dt:
308	stmmac_remove_config_dt(pdev, plat_dat);
309
310	return ret;
311}
312
313#ifdef CONFIG_PM_SLEEP
314static int ingenic_mac_suspend(struct device *dev)
315{
316	int ret;
317
318	ret = stmmac_suspend(dev);
319
320	return ret;
321}
322
323static 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
339static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume);
340
341static 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
348static 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
355static 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
362static 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
369static 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
377static 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};
385MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
386
387static 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};
396module_platform_driver(ingenic_mac_driver);
397
398MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
399MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer");
400MODULE_LICENSE("GPL v2");