xref: /openbmc/u-boot/drivers/net/dwmac_socfpga.c (revision c507d306)
1215a0656SMarek Vasut // SPDX-License-Identifier: GPL-2.0+
2215a0656SMarek Vasut /*
3215a0656SMarek Vasut  * Copyright (C) 2018 Marek Vasut <marex@denx.de>
4215a0656SMarek Vasut  *
5215a0656SMarek Vasut  * Altera SoCFPGA EMAC extras
6215a0656SMarek Vasut  */
7215a0656SMarek Vasut 
8215a0656SMarek Vasut #include <common.h>
9215a0656SMarek Vasut #include <asm/io.h>
10215a0656SMarek Vasut #include <dm.h>
11215a0656SMarek Vasut #include <clk.h>
12215a0656SMarek Vasut #include <phy.h>
13215a0656SMarek Vasut #include <regmap.h>
14215a0656SMarek Vasut #include <reset.h>
15215a0656SMarek Vasut #include <syscon.h>
16215a0656SMarek Vasut #include "designware.h"
17215a0656SMarek Vasut 
18215a0656SMarek Vasut #include <asm/arch/system_manager.h>
19215a0656SMarek Vasut 
20215a0656SMarek Vasut struct dwmac_socfpga_platdata {
21215a0656SMarek Vasut 	struct dw_eth_pdata	dw_eth_pdata;
22215a0656SMarek Vasut 	void			*phy_intf;
23*4f1267ceSSimon Goldschmidt 	u32			reg_shift;
24215a0656SMarek Vasut };
25215a0656SMarek Vasut 
dwmac_socfpga_ofdata_to_platdata(struct udevice * dev)26215a0656SMarek Vasut static int dwmac_socfpga_ofdata_to_platdata(struct udevice *dev)
27215a0656SMarek Vasut {
28215a0656SMarek Vasut 	struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev);
29215a0656SMarek Vasut 	struct regmap *regmap;
30215a0656SMarek Vasut 	struct ofnode_phandle_args args;
31215a0656SMarek Vasut 	void *range;
32215a0656SMarek Vasut 	int ret;
33215a0656SMarek Vasut 
34215a0656SMarek Vasut 	ret = dev_read_phandle_with_args(dev, "altr,sysmgr-syscon", NULL,
35215a0656SMarek Vasut 					 2, 0, &args);
36215a0656SMarek Vasut 	if (ret) {
37215a0656SMarek Vasut 		dev_err(dev, "Failed to get syscon: %d\n", ret);
38215a0656SMarek Vasut 		return ret;
39215a0656SMarek Vasut 	}
40215a0656SMarek Vasut 
41215a0656SMarek Vasut 	if (args.args_count != 2) {
42215a0656SMarek Vasut 		dev_err(dev, "Invalid number of syscon args\n");
43215a0656SMarek Vasut 		return -EINVAL;
44215a0656SMarek Vasut 	}
45215a0656SMarek Vasut 
46215a0656SMarek Vasut 	regmap = syscon_node_to_regmap(args.node);
47215a0656SMarek Vasut 	if (IS_ERR(regmap)) {
48215a0656SMarek Vasut 		ret = PTR_ERR(regmap);
49215a0656SMarek Vasut 		dev_err(dev, "Failed to get regmap: %d\n", ret);
50215a0656SMarek Vasut 		return ret;
51215a0656SMarek Vasut 	}
52215a0656SMarek Vasut 
53215a0656SMarek Vasut 	range = regmap_get_range(regmap, 0);
54215a0656SMarek Vasut 	if (!range) {
55215a0656SMarek Vasut 		dev_err(dev, "Failed to get regmap range\n");
56215a0656SMarek Vasut 		return -ENOMEM;
57215a0656SMarek Vasut 	}
58215a0656SMarek Vasut 
59215a0656SMarek Vasut 	pdata->phy_intf = range + args.args[0];
60*4f1267ceSSimon Goldschmidt 	pdata->reg_shift = args.args[1];
61215a0656SMarek Vasut 
62215a0656SMarek Vasut 	return designware_eth_ofdata_to_platdata(dev);
63215a0656SMarek Vasut }
64215a0656SMarek Vasut 
dwmac_socfpga_probe(struct udevice * dev)65215a0656SMarek Vasut static int dwmac_socfpga_probe(struct udevice *dev)
66215a0656SMarek Vasut {
67215a0656SMarek Vasut 	struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev);
68215a0656SMarek Vasut 	struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata;
69215a0656SMarek Vasut 	struct reset_ctl_bulk reset_bulk;
70215a0656SMarek Vasut 	int ret;
71*4f1267ceSSimon Goldschmidt 	u32 modereg;
72*4f1267ceSSimon Goldschmidt 	u32 modemask;
73215a0656SMarek Vasut 
74215a0656SMarek Vasut 	switch (edata->phy_interface) {
75215a0656SMarek Vasut 	case PHY_INTERFACE_MODE_MII:
76215a0656SMarek Vasut 	case PHY_INTERFACE_MODE_GMII:
77215a0656SMarek Vasut 		modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
78215a0656SMarek Vasut 		break;
79215a0656SMarek Vasut 	case PHY_INTERFACE_MODE_RMII:
80215a0656SMarek Vasut 		modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII;
81215a0656SMarek Vasut 		break;
82215a0656SMarek Vasut 	case PHY_INTERFACE_MODE_RGMII:
83215a0656SMarek Vasut 		modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
84215a0656SMarek Vasut 		break;
85215a0656SMarek Vasut 	default:
86215a0656SMarek Vasut 		dev_err(dev, "Unsupported PHY mode\n");
87215a0656SMarek Vasut 		return -EINVAL;
88215a0656SMarek Vasut 	}
89215a0656SMarek Vasut 
90215a0656SMarek Vasut 	ret = reset_get_bulk(dev, &reset_bulk);
91215a0656SMarek Vasut 	if (ret) {
92215a0656SMarek Vasut 		dev_err(dev, "Failed to get reset: %d\n", ret);
93215a0656SMarek Vasut 		return ret;
94215a0656SMarek Vasut 	}
95215a0656SMarek Vasut 
96215a0656SMarek Vasut 	reset_assert_bulk(&reset_bulk);
97215a0656SMarek Vasut 
98*4f1267ceSSimon Goldschmidt 	modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift;
99*4f1267ceSSimon Goldschmidt 	clrsetbits_le32(pdata->phy_intf, modemask,
100*4f1267ceSSimon Goldschmidt 			modereg << pdata->reg_shift);
101215a0656SMarek Vasut 
102215a0656SMarek Vasut 	reset_release_bulk(&reset_bulk);
103215a0656SMarek Vasut 
104215a0656SMarek Vasut 	return designware_eth_probe(dev);
105215a0656SMarek Vasut }
106215a0656SMarek Vasut 
107215a0656SMarek Vasut static const struct udevice_id dwmac_socfpga_ids[] = {
108215a0656SMarek Vasut 	{ .compatible = "altr,socfpga-stmmac" },
109215a0656SMarek Vasut 	{ }
110215a0656SMarek Vasut };
111215a0656SMarek Vasut 
112215a0656SMarek Vasut U_BOOT_DRIVER(dwmac_socfpga) = {
113215a0656SMarek Vasut 	.name		= "dwmac_socfpga",
114215a0656SMarek Vasut 	.id		= UCLASS_ETH,
115215a0656SMarek Vasut 	.of_match	= dwmac_socfpga_ids,
116215a0656SMarek Vasut 	.ofdata_to_platdata = dwmac_socfpga_ofdata_to_platdata,
117215a0656SMarek Vasut 	.probe		= dwmac_socfpga_probe,
118215a0656SMarek Vasut 	.ops		= &designware_eth_ops,
119215a0656SMarek Vasut 	.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
120215a0656SMarek Vasut 	.platdata_auto_alloc_size = sizeof(struct dwmac_socfpga_platdata),
121215a0656SMarek Vasut 	.flags		= DM_FLAG_ALLOC_PRIV_DMA,
122215a0656SMarek Vasut };
123