xref: /linux/drivers/net/dsa/mxl862xx/mxl862xx.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Driver for MaxLinear MxL862xx switch family
4  *
5  * Copyright (C) 2024 MaxLinear Inc.
6  * Copyright (C) 2025 John Crispin <john@phrozen.org>
7  * Copyright (C) 2025 Daniel Golle <daniel@makrotopia.org>
8  */
9 
10 #include <linux/module.h>
11 #include <linux/delay.h>
12 #include <linux/of_device.h>
13 #include <linux/of_mdio.h>
14 #include <linux/phy.h>
15 #include <linux/phylink.h>
16 #include <net/dsa.h>
17 
18 #include "mxl862xx.h"
19 #include "mxl862xx-api.h"
20 #include "mxl862xx-cmd.h"
21 #include "mxl862xx-host.h"
22 
23 #define MXL862XX_API_WRITE(dev, cmd, data) \
24 	mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), false, false)
25 #define MXL862XX_API_READ(dev, cmd, data) \
26 	mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), true, false)
27 #define MXL862XX_API_READ_QUIET(dev, cmd, data) \
28 	mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), true, true)
29 
30 #define MXL862XX_SDMA_PCTRLP(p)		(0xbc0 + ((p) * 0x6))
31 #define MXL862XX_SDMA_PCTRL_EN		BIT(0)
32 
33 #define MXL862XX_FDMA_PCTRLP(p)		(0xa80 + ((p) * 0x6))
34 #define MXL862XX_FDMA_PCTRL_EN		BIT(0)
35 
36 #define MXL862XX_READY_TIMEOUT_MS	10000
37 #define MXL862XX_READY_POLL_MS		100
38 
39 static enum dsa_tag_protocol mxl862xx_get_tag_protocol(struct dsa_switch *ds,
40 						       int port,
41 						       enum dsa_tag_protocol m)
42 {
43 	return DSA_TAG_PROTO_MXL862;
44 }
45 
46 /* PHY access via firmware relay */
47 static int mxl862xx_phy_read_mmd(struct mxl862xx_priv *priv, int port,
48 				 int devadd, int reg)
49 {
50 	struct mdio_relay_data param = {
51 		.phy = port,
52 		.mmd = devadd,
53 		.reg = cpu_to_le16(reg),
54 	};
55 	int ret;
56 
57 	ret = MXL862XX_API_READ(priv, INT_GPHY_READ, param);
58 	if (ret)
59 		return ret;
60 
61 	return le16_to_cpu(param.data);
62 }
63 
64 static int mxl862xx_phy_write_mmd(struct mxl862xx_priv *priv, int port,
65 				  int devadd, int reg, u16 data)
66 {
67 	struct mdio_relay_data param = {
68 		.phy = port,
69 		.mmd = devadd,
70 		.reg = cpu_to_le16(reg),
71 		.data = cpu_to_le16(data),
72 	};
73 
74 	return MXL862XX_API_WRITE(priv, INT_GPHY_WRITE, param);
75 }
76 
77 static int mxl862xx_phy_read_mii_bus(struct mii_bus *bus, int port, int regnum)
78 {
79 	return mxl862xx_phy_read_mmd(bus->priv, port, 0, regnum);
80 }
81 
82 static int mxl862xx_phy_write_mii_bus(struct mii_bus *bus, int port,
83 				      int regnum, u16 val)
84 {
85 	return mxl862xx_phy_write_mmd(bus->priv, port, 0, regnum, val);
86 }
87 
88 static int mxl862xx_phy_read_c45_mii_bus(struct mii_bus *bus, int port,
89 					 int devadd, int regnum)
90 {
91 	return mxl862xx_phy_read_mmd(bus->priv, port, devadd, regnum);
92 }
93 
94 static int mxl862xx_phy_write_c45_mii_bus(struct mii_bus *bus, int port,
95 					  int devadd, int regnum, u16 val)
96 {
97 	return mxl862xx_phy_write_mmd(bus->priv, port, devadd, regnum, val);
98 }
99 
100 static int mxl862xx_wait_ready(struct dsa_switch *ds)
101 {
102 	struct mxl862xx_sys_fw_image_version ver = {};
103 	unsigned long start = jiffies, timeout;
104 	struct mxl862xx_priv *priv = ds->priv;
105 	struct mxl862xx_cfg cfg = {};
106 	int ret;
107 
108 	timeout = start + msecs_to_jiffies(MXL862XX_READY_TIMEOUT_MS);
109 	msleep(2000); /* it always takes at least 2 seconds */
110 	do {
111 		ret = MXL862XX_API_READ_QUIET(priv, SYS_MISC_FW_VERSION, ver);
112 		if (ret || !ver.iv_major)
113 			goto not_ready_yet;
114 
115 		/* being able to perform CFGGET indicates that
116 		 * the firmware is ready
117 		 */
118 		ret = MXL862XX_API_READ_QUIET(priv,
119 					      MXL862XX_COMMON_CFGGET,
120 					      cfg);
121 		if (ret)
122 			goto not_ready_yet;
123 
124 		dev_info(ds->dev, "switch ready after %ums, firmware %u.%u.%u (build %u)\n",
125 			 jiffies_to_msecs(jiffies - start),
126 			 ver.iv_major, ver.iv_minor,
127 			 le16_to_cpu(ver.iv_revision),
128 			 le32_to_cpu(ver.iv_build_num));
129 		return 0;
130 
131 not_ready_yet:
132 		msleep(MXL862XX_READY_POLL_MS);
133 	} while (time_before(jiffies, timeout));
134 
135 	dev_err(ds->dev, "switch not responding after reset\n");
136 	return -ETIMEDOUT;
137 }
138 
139 static int mxl862xx_setup_mdio(struct dsa_switch *ds)
140 {
141 	struct mxl862xx_priv *priv = ds->priv;
142 	struct device *dev = ds->dev;
143 	struct device_node *mdio_np;
144 	struct mii_bus *bus;
145 	int ret;
146 
147 	bus = devm_mdiobus_alloc(dev);
148 	if (!bus)
149 		return -ENOMEM;
150 
151 	bus->priv = priv;
152 	ds->user_mii_bus = bus;
153 	bus->name = KBUILD_MODNAME "-mii";
154 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev));
155 	bus->read_c45 = mxl862xx_phy_read_c45_mii_bus;
156 	bus->write_c45 = mxl862xx_phy_write_c45_mii_bus;
157 	bus->read = mxl862xx_phy_read_mii_bus;
158 	bus->write = mxl862xx_phy_write_mii_bus;
159 	bus->parent = dev;
160 	bus->phy_mask = ~ds->phys_mii_mask;
161 
162 	mdio_np = of_get_child_by_name(dev->of_node, "mdio");
163 	if (!mdio_np)
164 		return -ENODEV;
165 
166 	ret = devm_of_mdiobus_register(dev, bus, mdio_np);
167 	of_node_put(mdio_np);
168 
169 	return ret;
170 }
171 
172 static int mxl862xx_setup(struct dsa_switch *ds)
173 {
174 	struct mxl862xx_priv *priv = ds->priv;
175 	int ret;
176 
177 	ret = mxl862xx_reset(priv);
178 	if (ret)
179 		return ret;
180 
181 	ret = mxl862xx_wait_ready(ds);
182 	if (ret)
183 		return ret;
184 
185 	return mxl862xx_setup_mdio(ds);
186 }
187 
188 static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable)
189 {
190 	struct mxl862xx_register_mod sdma = {
191 		.addr = cpu_to_le16(MXL862XX_SDMA_PCTRLP(port)),
192 		.data = cpu_to_le16(enable ? MXL862XX_SDMA_PCTRL_EN : 0),
193 		.mask = cpu_to_le16(MXL862XX_SDMA_PCTRL_EN),
194 	};
195 	struct mxl862xx_register_mod fdma = {
196 		.addr = cpu_to_le16(MXL862XX_FDMA_PCTRLP(port)),
197 		.data = cpu_to_le16(enable ? MXL862XX_FDMA_PCTRL_EN : 0),
198 		.mask = cpu_to_le16(MXL862XX_FDMA_PCTRL_EN),
199 	};
200 	int ret;
201 
202 	ret = MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, sdma);
203 	if (ret)
204 		return ret;
205 
206 	return MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, fdma);
207 }
208 
209 static int mxl862xx_port_enable(struct dsa_switch *ds, int port,
210 				struct phy_device *phydev)
211 {
212 	return mxl862xx_port_state(ds, port, true);
213 }
214 
215 static void mxl862xx_port_disable(struct dsa_switch *ds, int port)
216 {
217 	if (mxl862xx_port_state(ds, port, false))
218 		dev_err(ds->dev, "failed to disable port %d\n", port);
219 }
220 
221 static void mxl862xx_port_fast_age(struct dsa_switch *ds, int port)
222 {
223 	struct mxl862xx_mac_table_clear param = {
224 		.type = MXL862XX_MAC_CLEAR_PHY_PORT,
225 		.port_id = port,
226 	};
227 
228 	if (MXL862XX_API_WRITE(ds->priv, MXL862XX_MAC_TABLECLEARCOND, param))
229 		dev_err(ds->dev, "failed to clear fdb on port %d\n", port);
230 }
231 
232 static int mxl862xx_configure_ctp_port(struct dsa_switch *ds, int port,
233 				       u16 first_ctp_port_id,
234 				       u16 number_of_ctp_ports)
235 {
236 	struct mxl862xx_ctp_port_assignment ctp_assign = {
237 		.logical_port_id = port,
238 		.first_ctp_port_id = cpu_to_le16(first_ctp_port_id),
239 		.number_of_ctp_port = cpu_to_le16(number_of_ctp_ports),
240 		.mode = cpu_to_le32(MXL862XX_LOGICAL_PORT_ETHERNET),
241 	};
242 
243 	return MXL862XX_API_WRITE(ds->priv, MXL862XX_CTP_PORTASSIGNMENTSET,
244 				  ctp_assign);
245 }
246 
247 static int mxl862xx_configure_sp_tag_proto(struct dsa_switch *ds, int port,
248 					   bool enable)
249 {
250 	struct mxl862xx_ss_sp_tag tag = {
251 		.pid = port,
252 		.mask = MXL862XX_SS_SP_TAG_MASK_RX | MXL862XX_SS_SP_TAG_MASK_TX,
253 		.rx = enable ? MXL862XX_SS_SP_TAG_RX_TAG_NO_INSERT :
254 			       MXL862XX_SS_SP_TAG_RX_NO_TAG_INSERT,
255 		.tx = enable ? MXL862XX_SS_SP_TAG_TX_TAG_NO_REMOVE :
256 			       MXL862XX_SS_SP_TAG_TX_TAG_REMOVE,
257 	};
258 
259 	return MXL862XX_API_WRITE(ds->priv, MXL862XX_SS_SPTAG_SET, tag);
260 }
261 
262 static int mxl862xx_setup_cpu_bridge(struct dsa_switch *ds, int port)
263 {
264 	struct mxl862xx_bridge_port_config br_port_cfg = {};
265 	struct mxl862xx_priv *priv = ds->priv;
266 	u16 bridge_port_map = 0;
267 	struct dsa_port *dp;
268 
269 	/* CPU port bridge setup */
270 	br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP |
271 				       MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING |
272 				       MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING);
273 
274 	br_port_cfg.bridge_port_id = cpu_to_le16(port);
275 	br_port_cfg.src_mac_learning_disable = false;
276 	br_port_cfg.vlan_src_mac_vid_enable = true;
277 	br_port_cfg.vlan_dst_mac_vid_enable = true;
278 
279 	/* include all assigned user ports in the CPU portmap */
280 	dsa_switch_for_each_user_port(dp, ds) {
281 		/* it's safe to rely on cpu_dp being valid for user ports */
282 		if (dp->cpu_dp->index != port)
283 			continue;
284 
285 		bridge_port_map |= BIT(dp->index);
286 	}
287 	br_port_cfg.bridge_port_map[0] |= cpu_to_le16(bridge_port_map);
288 
289 	return MXL862XX_API_WRITE(priv, MXL862XX_BRIDGEPORT_CONFIGSET, br_port_cfg);
290 }
291 
292 static int mxl862xx_add_single_port_bridge(struct dsa_switch *ds, int port)
293 {
294 	struct mxl862xx_bridge_port_config br_port_cfg = {};
295 	struct dsa_port *dp = dsa_to_port(ds, port);
296 	struct mxl862xx_bridge_alloc br_alloc = {};
297 	int ret;
298 
299 	ret = MXL862XX_API_READ(ds->priv, MXL862XX_BRIDGE_ALLOC, br_alloc);
300 	if (ret) {
301 		dev_err(ds->dev, "failed to allocate a bridge for port %d\n", port);
302 		return ret;
303 	}
304 
305 	br_port_cfg.bridge_id = br_alloc.bridge_id;
306 	br_port_cfg.bridge_port_id = cpu_to_le16(port);
307 	br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID |
308 				       MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP |
309 				       MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING |
310 				       MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING);
311 	br_port_cfg.src_mac_learning_disable = true;
312 	br_port_cfg.vlan_src_mac_vid_enable = false;
313 	br_port_cfg.vlan_dst_mac_vid_enable = false;
314 	/* As this function is only called for user ports it is safe to rely on
315 	 * cpu_dp being valid
316 	 */
317 	br_port_cfg.bridge_port_map[0] = cpu_to_le16(BIT(dp->cpu_dp->index));
318 
319 	return MXL862XX_API_WRITE(ds->priv, MXL862XX_BRIDGEPORT_CONFIGSET, br_port_cfg);
320 }
321 
322 static int mxl862xx_port_setup(struct dsa_switch *ds, int port)
323 {
324 	struct dsa_port *dp = dsa_to_port(ds, port);
325 	bool is_cpu_port = dsa_port_is_cpu(dp);
326 	int ret;
327 
328 	/* disable port and flush MAC entries */
329 	ret = mxl862xx_port_state(ds, port, false);
330 	if (ret)
331 		return ret;
332 
333 	mxl862xx_port_fast_age(ds, port);
334 
335 	/* skip setup for unused and DSA ports */
336 	if (dsa_port_is_unused(dp) ||
337 	    dsa_port_is_dsa(dp))
338 		return 0;
339 
340 	/* configure tag protocol */
341 	ret = mxl862xx_configure_sp_tag_proto(ds, port, is_cpu_port);
342 	if (ret)
343 		return ret;
344 
345 	/* assign CTP port IDs */
346 	ret = mxl862xx_configure_ctp_port(ds, port, port,
347 					  is_cpu_port ? 32 - port : 1);
348 	if (ret)
349 		return ret;
350 
351 	if (is_cpu_port)
352 		/* assign user ports to CPU port bridge */
353 		return mxl862xx_setup_cpu_bridge(ds, port);
354 
355 	/* setup single-port bridge for user ports */
356 	return mxl862xx_add_single_port_bridge(ds, port);
357 }
358 
359 static void mxl862xx_phylink_get_caps(struct dsa_switch *ds, int port,
360 				      struct phylink_config *config)
361 {
362 	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 |
363 				   MAC_100 | MAC_1000 | MAC_2500FD;
364 
365 	__set_bit(PHY_INTERFACE_MODE_INTERNAL,
366 		  config->supported_interfaces);
367 }
368 
369 static const struct dsa_switch_ops mxl862xx_switch_ops = {
370 	.get_tag_protocol = mxl862xx_get_tag_protocol,
371 	.setup = mxl862xx_setup,
372 	.port_setup = mxl862xx_port_setup,
373 	.phylink_get_caps = mxl862xx_phylink_get_caps,
374 	.port_enable = mxl862xx_port_enable,
375 	.port_disable = mxl862xx_port_disable,
376 	.port_fast_age = mxl862xx_port_fast_age,
377 };
378 
379 static void mxl862xx_phylink_mac_config(struct phylink_config *config,
380 					unsigned int mode,
381 					const struct phylink_link_state *state)
382 {
383 }
384 
385 static void mxl862xx_phylink_mac_link_down(struct phylink_config *config,
386 					   unsigned int mode,
387 					   phy_interface_t interface)
388 {
389 }
390 
391 static void mxl862xx_phylink_mac_link_up(struct phylink_config *config,
392 					 struct phy_device *phydev,
393 					 unsigned int mode,
394 					 phy_interface_t interface,
395 					 int speed, int duplex,
396 					 bool tx_pause, bool rx_pause)
397 {
398 }
399 
400 static const struct phylink_mac_ops mxl862xx_phylink_mac_ops = {
401 	.mac_config = mxl862xx_phylink_mac_config,
402 	.mac_link_down = mxl862xx_phylink_mac_link_down,
403 	.mac_link_up = mxl862xx_phylink_mac_link_up,
404 };
405 
406 static int mxl862xx_probe(struct mdio_device *mdiodev)
407 {
408 	struct device *dev = &mdiodev->dev;
409 	struct mxl862xx_priv *priv;
410 	struct dsa_switch *ds;
411 
412 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
413 	if (!priv)
414 		return -ENOMEM;
415 
416 	priv->mdiodev = mdiodev;
417 
418 	ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
419 	if (!ds)
420 		return -ENOMEM;
421 
422 	priv->ds = ds;
423 	ds->dev = dev;
424 	ds->priv = priv;
425 	ds->ops = &mxl862xx_switch_ops;
426 	ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops;
427 	ds->num_ports = MXL862XX_MAX_PORTS;
428 
429 	dev_set_drvdata(dev, ds);
430 
431 	return dsa_register_switch(ds);
432 }
433 
434 static void mxl862xx_remove(struct mdio_device *mdiodev)
435 {
436 	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
437 
438 	if (!ds)
439 		return;
440 
441 	dsa_unregister_switch(ds);
442 }
443 
444 static void mxl862xx_shutdown(struct mdio_device *mdiodev)
445 {
446 	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
447 
448 	if (!ds)
449 		return;
450 
451 	dsa_switch_shutdown(ds);
452 
453 	dev_set_drvdata(&mdiodev->dev, NULL);
454 }
455 
456 static const struct of_device_id mxl862xx_of_match[] = {
457 	{ .compatible = "maxlinear,mxl86282" },
458 	{ .compatible = "maxlinear,mxl86252" },
459 	{ /* sentinel */ }
460 };
461 MODULE_DEVICE_TABLE(of, mxl862xx_of_match);
462 
463 static struct mdio_driver mxl862xx_driver = {
464 	.probe  = mxl862xx_probe,
465 	.remove = mxl862xx_remove,
466 	.shutdown = mxl862xx_shutdown,
467 	.mdiodrv.driver = {
468 		.name = "mxl862xx",
469 		.of_match_table = mxl862xx_of_match,
470 	},
471 };
472 
473 mdio_module_driver(mxl862xx_driver);
474 
475 MODULE_DESCRIPTION("Driver for MaxLinear MxL862xx switch family");
476 MODULE_LICENSE("GPL");
477