summaryrefslogtreecommitdiffstats
path: root/configs/platform-v7a/patches/barebox-2021.11.0/0001-net-cpsw-add-support-for-new-binding-in-Linux-v5.15-.patch
blob: 287f052d5fd20d9c522fbced87b57c12fd7a2ad7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
From ed7f3fd5b5e2088f04d2f5d615d71cf6e6507509 Mon Sep 17 00:00:00 2001
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
Date: Fri, 3 Dec 2021 21:50:35 +0100
Subject: [PATCH 1/2] net: cpsw: add support for new binding in Linux v5.15-rc1
 DTs

As is customary, upstream OMAP DTs have yet again added a new binding
breaking compatibility with a barebox driver. This time, the old Ethernet
node was disabled in favor of a new node that is matched by the new Linux
cpsw driver introduced with Linux commit ed3525eda4c4 ("net: ethernet:
ti: introduce cpsw switchdev based driver part 1 - dual-emac").

Add support for the new binding to restore working Beaglebone Black
networking. These changes have been tested against both the old and new
bindings.

Fixes: 618948e4e5b3 ("dts: update to v5.15-rc1")
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Link: https://lore.barebox.org/20211203205035.555285-1-a.fatoum@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/cpsw.c | 120 +++++++++++++++++++++++++++++++++------------
 1 file changed, 89 insertions(+), 31 deletions(-)

diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 4a8f9e67d6f0..6725c7b9bdb4 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -592,7 +592,12 @@ static int cpsw_mdio_probe(struct device_d *dev)
 
 	priv = xzalloc(sizeof(*priv));
 
+	/* If we can't request I/O memory region, we'll assume parent did
+	 * it for us
+	 */
 	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores) && PTR_ERR(iores) == -EBUSY)
+		iores = dev_get_resource(dev, IORESOURCE_MEM, 0);
 	if (IS_ERR(iores))
 		return PTR_ERR(iores);
 	priv->mdio_regs = IOMEM(iores->start);
@@ -1214,11 +1219,27 @@ static void cpsw_gmii_sel_am335x(struct cpsw_slave *slave)
 	writel(reg, phy_sel_addr);
 }
 
-static int cpsw_probe_dt(struct cpsw_priv *priv)
+static void cpsw_add_slave(struct cpsw_slave *slave, struct device_node *child, int i)
+{
+	uint32_t phy_id[2] = {-1, -1};
+	int ret;
+
+	if (!of_find_node_by_name(child, "fixed-link")) {
+		ret = of_property_read_u32_array(child, "phy_id", phy_id, 2);
+		if (!ret)
+			dev_warn(slave->cpsw->dev, "phy_id is deprecated, use phy-handle\n");
+	}
+
+	slave->dev.device_node = child;
+	slave->phy_id = phy_id[1];
+	slave->phy_if = of_get_phy_mode(child);
+	slave->slave_num = i;
+}
+
+static int cpsw_legacy_probe_dt(struct cpsw_priv *priv)
 {
 	struct device_d *dev = priv->dev;
 	struct device_node *np = dev->device_node, *child;
-	struct device_node *physel;
 	int ret, i = 0;
 
 	ret = of_property_read_u32(np, "slaves", &priv->num_slaves);
@@ -1227,15 +1248,6 @@ static int cpsw_probe_dt(struct cpsw_priv *priv)
 
 	priv->slaves = xzalloc(sizeof(struct cpsw_slave) * priv->num_slaves);
 
-	physel = of_find_compatible_node(NULL, NULL, "ti,am3352-phy-gmii-sel");
-	if (!physel) {
-		dev_err(dev, "Cannot find ti,am3352-phy-gmii-sel node\n");
-		return -EINVAL;
-	}
-	ret = cpsw_phy_sel_init(priv, physel);
-	if (ret)
-		return ret;
-
 	for_each_child_of_node(np, child) {
 		if (of_device_is_compatible(child, "ti,davinci_mdio")) {
 			ret = of_pinctrl_select_state_default(child);
@@ -1244,29 +1256,73 @@ static int cpsw_probe_dt(struct cpsw_priv *priv)
 		}
 
 		if (i < priv->num_slaves && !strncmp(child->name, "slave", 5)) {
-			struct cpsw_slave *slave = &priv->slaves[i];
-			uint32_t phy_id[2] = {-1, -1};
+			cpsw_add_slave(&priv->slaves[i], child, i);
+			i++;
+		}
+	}
 
-			if (!of_find_node_by_name(child, "fixed-link")) {
-				ret = of_property_read_u32_array(child, "phy_id", phy_id, 2);
-				if (!ret)
-					dev_warn(dev, "phy_id is deprecated, use phy-handle\n");
-			}
+	return 0;
+}
+
+static int cpsw_switch_probe_dt(struct cpsw_priv *priv)
+{
+	struct device_d *dev = priv->dev;
+	struct device_node *np = dev->device_node, *child;
+	struct device_node *ports = NULL;
+	int ret, i = 0;
 
-			slave->dev.device_node = child;
-			slave->phy_id = phy_id[1];
-			slave->phy_if = of_get_phy_mode(child);
-			slave->slave_num = i;
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, "ti,davinci_mdio")) {
+			ret = of_pinctrl_select_state_default(child);
+			if (ret)
+				return ret;
+		}
 
-			i++;
+		if (!strcmp(child->name, "ethernet-ports")) {
+			ports = child;
+			priv->num_slaves = of_get_available_child_count(ports);
 		}
 	}
 
-	for (i = 0; i < priv->num_slaves; i++) {
-		struct cpsw_slave *slave = &priv->slaves[i];
+	if (!ports)
+		return -EINVAL;
+
+	priv->slaves = xzalloc(sizeof(struct cpsw_slave) * priv->num_slaves);
+
+	for_each_available_child_of_node(ports, child) {
+		cpsw_add_slave(&priv->slaves[i], child, i);
+		i++;
+	}
+
+	return 0;
+}
 
-		cpsw_gmii_sel_am335x(slave);
+static int cpsw_probe_dt(struct cpsw_priv *priv)
+{
+	struct device_d *dev = priv->dev;
+	struct device_node *physel;
+	int (*probe_slaves_dt)(struct cpsw_priv *priv);
+	int ret, i = 0;
+
+	physel = of_find_compatible_node(NULL, NULL, "ti,am3352-phy-gmii-sel");
+	if (!physel) {
+		dev_err(dev, "Cannot find ti,am3352-phy-gmii-sel node\n");
+		return -EINVAL;
 	}
+	ret = cpsw_phy_sel_init(priv, physel);
+	if (ret)
+		return ret;
+
+	probe_slaves_dt = device_get_match_data(dev);
+	if (!probe_slaves_dt)
+		return -EINVAL;
+
+	ret = probe_slaves_dt(priv);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < priv->num_slaves; i++)
+		cpsw_gmii_sel_am335x(&priv->slaves[i]);
 
 	return 0;
 }
@@ -1282,15 +1338,15 @@ static int cpsw_probe(struct device_d *dev)
 
 	dev_dbg(dev, "* %s\n", __func__);
 
-	ret = of_platform_populate(dev->device_node, NULL, dev);
-	if (ret)
-		return ret;
-
 	iores = dev_request_mem_resource(dev, 0);
 	if (IS_ERR(iores))
 		return PTR_ERR(iores);
 	regs = IOMEM(iores->start);
 
+	ret = of_platform_populate(dev->device_node, NULL, dev);
+	if (ret)
+		return ret;
+
 	priv = xzalloc(sizeof(*priv));
 	priv->dev = dev;
 
@@ -1371,7 +1427,9 @@ static void cpsw_remove(struct device_d *dev)
 
 static __maybe_unused struct of_device_id cpsw_dt_ids[] = {
 	{
-		.compatible = "ti,cpsw",
+		.compatible = "ti,cpsw", .data = cpsw_legacy_probe_dt
+	}, {
+		.compatible = "ti,cpsw-switch", .data = cpsw_switch_probe_dt
 	}, {
 		/* sentinel */
 	}
-- 
2.30.2