1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2019 NXP */
3 
4 #include <linux/acpi.h>
5 #include <linux/property.h>
6 
7 #include "dpaa2-eth.h"
8 #include "dpaa2-mac.h"
9 
10 #define phylink_to_dpaa2_mac(config) \
11 	container_of((config), struct dpaa2_mac, phylink_config)
12 
13 static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
14 {
15 	*if_mode = PHY_INTERFACE_MODE_NA;
16 
17 	switch (eth_if) {
18 	case DPMAC_ETH_IF_RGMII:
19 		*if_mode = PHY_INTERFACE_MODE_RGMII;
20 		break;
21 	case DPMAC_ETH_IF_USXGMII:
22 		*if_mode = PHY_INTERFACE_MODE_USXGMII;
23 		break;
24 	case DPMAC_ETH_IF_QSGMII:
25 		*if_mode = PHY_INTERFACE_MODE_QSGMII;
26 		break;
27 	case DPMAC_ETH_IF_SGMII:
28 		*if_mode = PHY_INTERFACE_MODE_SGMII;
29 		break;
30 	case DPMAC_ETH_IF_XFI:
31 		*if_mode = PHY_INTERFACE_MODE_10GBASER;
32 		break;
33 	default:
34 		return -EINVAL;
35 	}
36 
37 	return 0;
38 }
39 
40 static struct fwnode_handle *dpaa2_mac_get_node(struct device *dev,
41 						u16 dpmac_id)
42 {
43 	struct fwnode_handle *fwnode, *parent, *child  = NULL;
44 	struct device_node *dpmacs = NULL;
45 	int err;
46 	u32 id;
47 
48 	fwnode = dev_fwnode(dev->parent);
49 	if (is_of_node(fwnode)) {
50 		dpmacs = of_find_node_by_name(NULL, "dpmacs");
51 		if (!dpmacs)
52 			return NULL;
53 		parent = of_fwnode_handle(dpmacs);
54 	} else if (is_acpi_node(fwnode)) {
55 		parent = fwnode;
56 	}
57 
58 	fwnode_for_each_child_node(parent, child) {
59 		err = -EINVAL;
60 		if (is_acpi_device_node(child))
61 			err = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &id);
62 		else if (is_of_node(child))
63 			err = of_property_read_u32(to_of_node(child), "reg", &id);
64 		if (err)
65 			continue;
66 
67 		if (id == dpmac_id) {
68 			of_node_put(dpmacs);
69 			return child;
70 		}
71 	}
72 	of_node_put(dpmacs);
73 	return NULL;
74 }
75 
76 static int dpaa2_mac_get_if_mode(struct fwnode_handle *dpmac_node,
77 				 struct dpmac_attr attr)
78 {
79 	phy_interface_t if_mode;
80 	int err;
81 
82 	err = fwnode_get_phy_mode(dpmac_node);
83 	if (err > 0)
84 		return err;
85 
86 	err = phy_mode(attr.eth_if, &if_mode);
87 	if (!err)
88 		return if_mode;
89 
90 	return err;
91 }
92 
93 static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac,
94 					phy_interface_t interface)
95 {
96 	switch (interface) {
97 	/* We can switch between SGMII and 1000BASE-X at runtime with
98 	 * pcs-lynx
99 	 */
100 	case PHY_INTERFACE_MODE_SGMII:
101 	case PHY_INTERFACE_MODE_1000BASEX:
102 		if (mac->pcs &&
103 		    (mac->if_mode == PHY_INTERFACE_MODE_SGMII ||
104 		     mac->if_mode == PHY_INTERFACE_MODE_1000BASEX))
105 			return false;
106 		return interface != mac->if_mode;
107 
108 	case PHY_INTERFACE_MODE_10GBASER:
109 	case PHY_INTERFACE_MODE_USXGMII:
110 	case PHY_INTERFACE_MODE_QSGMII:
111 	case PHY_INTERFACE_MODE_RGMII:
112 	case PHY_INTERFACE_MODE_RGMII_ID:
113 	case PHY_INTERFACE_MODE_RGMII_RXID:
114 	case PHY_INTERFACE_MODE_RGMII_TXID:
115 		return (interface != mac->if_mode);
116 	default:
117 		return true;
118 	}
119 }
120 
121 static void dpaa2_mac_validate(struct phylink_config *config,
122 			       unsigned long *supported,
123 			       struct phylink_link_state *state)
124 {
125 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
126 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
127 
128 	if (state->interface != PHY_INTERFACE_MODE_NA &&
129 	    dpaa2_mac_phy_mode_mismatch(mac, state->interface)) {
130 		goto empty_set;
131 	}
132 
133 	phylink_set_port_modes(mask);
134 	phylink_set(mask, Autoneg);
135 	phylink_set(mask, Pause);
136 	phylink_set(mask, Asym_Pause);
137 
138 	switch (state->interface) {
139 	case PHY_INTERFACE_MODE_NA:
140 	case PHY_INTERFACE_MODE_10GBASER:
141 	case PHY_INTERFACE_MODE_USXGMII:
142 		phylink_set(mask, 10000baseT_Full);
143 		phylink_set(mask, 10000baseCR_Full);
144 		phylink_set(mask, 10000baseSR_Full);
145 		phylink_set(mask, 10000baseLR_Full);
146 		phylink_set(mask, 10000baseLRM_Full);
147 		phylink_set(mask, 10000baseER_Full);
148 		if (state->interface == PHY_INTERFACE_MODE_10GBASER)
149 			break;
150 		phylink_set(mask, 5000baseT_Full);
151 		phylink_set(mask, 2500baseT_Full);
152 		fallthrough;
153 	case PHY_INTERFACE_MODE_SGMII:
154 	case PHY_INTERFACE_MODE_QSGMII:
155 	case PHY_INTERFACE_MODE_1000BASEX:
156 	case PHY_INTERFACE_MODE_RGMII:
157 	case PHY_INTERFACE_MODE_RGMII_ID:
158 	case PHY_INTERFACE_MODE_RGMII_RXID:
159 	case PHY_INTERFACE_MODE_RGMII_TXID:
160 		phylink_set(mask, 1000baseX_Full);
161 		phylink_set(mask, 1000baseT_Full);
162 		if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
163 			break;
164 		phylink_set(mask, 100baseT_Full);
165 		phylink_set(mask, 10baseT_Full);
166 		break;
167 	default:
168 		goto empty_set;
169 	}
170 
171 	linkmode_and(supported, supported, mask);
172 	linkmode_and(state->advertising, state->advertising, mask);
173 
174 	return;
175 
176 empty_set:
177 	linkmode_zero(supported);
178 }
179 
180 static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
181 			     const struct phylink_link_state *state)
182 {
183 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
184 	struct dpmac_link_state *dpmac_state = &mac->state;
185 	int err;
186 
187 	if (state->an_enabled)
188 		dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG;
189 	else
190 		dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG;
191 
192 	err = dpmac_set_link_state(mac->mc_io, 0,
193 				   mac->mc_dev->mc_handle, dpmac_state);
194 	if (err)
195 		netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
196 			   __func__, err);
197 }
198 
199 static void dpaa2_mac_link_up(struct phylink_config *config,
200 			      struct phy_device *phy,
201 			      unsigned int mode, phy_interface_t interface,
202 			      int speed, int duplex,
203 			      bool tx_pause, bool rx_pause)
204 {
205 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
206 	struct dpmac_link_state *dpmac_state = &mac->state;
207 	int err;
208 
209 	dpmac_state->up = 1;
210 
211 	dpmac_state->rate = speed;
212 
213 	if (duplex == DUPLEX_HALF)
214 		dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
215 	else if (duplex == DUPLEX_FULL)
216 		dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX;
217 
218 	if (rx_pause)
219 		dpmac_state->options |= DPMAC_LINK_OPT_PAUSE;
220 	else
221 		dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE;
222 
223 	if (rx_pause ^ tx_pause)
224 		dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE;
225 	else
226 		dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE;
227 
228 	err = dpmac_set_link_state(mac->mc_io, 0,
229 				   mac->mc_dev->mc_handle, dpmac_state);
230 	if (err)
231 		netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
232 			   __func__, err);
233 }
234 
235 static void dpaa2_mac_link_down(struct phylink_config *config,
236 				unsigned int mode,
237 				phy_interface_t interface)
238 {
239 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
240 	struct dpmac_link_state *dpmac_state = &mac->state;
241 	int err;
242 
243 	dpmac_state->up = 0;
244 	err = dpmac_set_link_state(mac->mc_io, 0,
245 				   mac->mc_dev->mc_handle, dpmac_state);
246 	if (err)
247 		netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err);
248 }
249 
250 static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
251 	.validate = dpaa2_mac_validate,
252 	.mac_config = dpaa2_mac_config,
253 	.mac_link_up = dpaa2_mac_link_up,
254 	.mac_link_down = dpaa2_mac_link_down,
255 };
256 
257 static int dpaa2_pcs_create(struct dpaa2_mac *mac,
258 			    struct fwnode_handle *dpmac_node,
259 			    int id)
260 {
261 	struct mdio_device *mdiodev;
262 	struct fwnode_handle *node;
263 
264 	node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
265 	if (IS_ERR(node)) {
266 		/* do not error out on old DTS files */
267 		netdev_warn(mac->net_dev, "pcs-handle node not found\n");
268 		return 0;
269 	}
270 
271 	if (!fwnode_device_is_available(node)) {
272 		netdev_err(mac->net_dev, "pcs-handle node not available\n");
273 		fwnode_handle_put(node);
274 		return -ENODEV;
275 	}
276 
277 	mdiodev = fwnode_mdio_find_device(node);
278 	fwnode_handle_put(node);
279 	if (!mdiodev)
280 		return -EPROBE_DEFER;
281 
282 	mac->pcs = lynx_pcs_create(mdiodev);
283 	if (!mac->pcs) {
284 		netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
285 		put_device(&mdiodev->dev);
286 		return -ENOMEM;
287 	}
288 
289 	return 0;
290 }
291 
292 static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
293 {
294 	struct lynx_pcs *pcs = mac->pcs;
295 
296 	if (pcs) {
297 		struct device *dev = &pcs->mdio->dev;
298 		lynx_pcs_destroy(pcs);
299 		put_device(dev);
300 		mac->pcs = NULL;
301 	}
302 }
303 
304 int dpaa2_mac_connect(struct dpaa2_mac *mac)
305 {
306 	struct net_device *net_dev = mac->net_dev;
307 	struct fwnode_handle *dpmac_node;
308 	struct phylink *phylink;
309 	int err;
310 
311 	mac->if_link_type = mac->attr.link_type;
312 
313 	dpmac_node = mac->fw_node;
314 	if (!dpmac_node) {
315 		netdev_err(net_dev, "No dpmac@%d node found.\n", mac->attr.id);
316 		return -ENODEV;
317 	}
318 
319 	err = dpaa2_mac_get_if_mode(dpmac_node, mac->attr);
320 	if (err < 0)
321 		return -EINVAL;
322 	mac->if_mode = err;
323 
324 	/* The MAC does not have the capability to add RGMII delays so
325 	 * error out if the interface mode requests them and there is no PHY
326 	 * to act upon them
327 	 */
328 	if (of_phy_is_fixed_link(to_of_node(dpmac_node)) &&
329 	    (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID ||
330 	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
331 	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) {
332 		netdev_err(net_dev, "RGMII delay not supported\n");
333 		return -EINVAL;
334 	}
335 
336 	if ((mac->attr.link_type == DPMAC_LINK_TYPE_PHY &&
337 	     mac->attr.eth_if != DPMAC_ETH_IF_RGMII) ||
338 	    mac->attr.link_type == DPMAC_LINK_TYPE_BACKPLANE) {
339 		err = dpaa2_pcs_create(mac, dpmac_node, mac->attr.id);
340 		if (err)
341 			return err;
342 	}
343 
344 	mac->phylink_config.dev = &net_dev->dev;
345 	mac->phylink_config.type = PHYLINK_NETDEV;
346 
347 	phylink = phylink_create(&mac->phylink_config,
348 				 dpmac_node, mac->if_mode,
349 				 &dpaa2_mac_phylink_ops);
350 	if (IS_ERR(phylink)) {
351 		err = PTR_ERR(phylink);
352 		goto err_pcs_destroy;
353 	}
354 	mac->phylink = phylink;
355 
356 	if (mac->pcs)
357 		phylink_set_pcs(mac->phylink, &mac->pcs->pcs);
358 
359 	err = phylink_fwnode_phy_connect(mac->phylink, dpmac_node, 0);
360 	if (err) {
361 		netdev_err(net_dev, "phylink_fwnode_phy_connect() = %d\n", err);
362 		goto err_phylink_destroy;
363 	}
364 
365 	return 0;
366 
367 err_phylink_destroy:
368 	phylink_destroy(mac->phylink);
369 err_pcs_destroy:
370 	dpaa2_pcs_destroy(mac);
371 
372 	return err;
373 }
374 
375 void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
376 {
377 	if (!mac->phylink)
378 		return;
379 
380 	phylink_disconnect_phy(mac->phylink);
381 	phylink_destroy(mac->phylink);
382 	dpaa2_pcs_destroy(mac);
383 }
384 
385 int dpaa2_mac_open(struct dpaa2_mac *mac)
386 {
387 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
388 	struct net_device *net_dev = mac->net_dev;
389 	int err;
390 
391 	err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id,
392 			 &dpmac_dev->mc_handle);
393 	if (err || !dpmac_dev->mc_handle) {
394 		netdev_err(net_dev, "dpmac_open() = %d\n", err);
395 		return -ENODEV;
396 	}
397 
398 	err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle,
399 				   &mac->attr);
400 	if (err) {
401 		netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err);
402 		goto err_close_dpmac;
403 	}
404 
405 	/* Find the device node representing the MAC device and link the device
406 	 * behind the associated netdev to it.
407 	 */
408 	mac->fw_node = dpaa2_mac_get_node(&mac->mc_dev->dev, mac->attr.id);
409 	net_dev->dev.of_node = to_of_node(mac->fw_node);
410 
411 	return 0;
412 
413 err_close_dpmac:
414 	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
415 	return err;
416 }
417 
418 void dpaa2_mac_close(struct dpaa2_mac *mac)
419 {
420 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
421 
422 	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
423 	if (mac->fw_node)
424 		fwnode_handle_put(mac->fw_node);
425 }
426 
427 static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
428 	[DPMAC_CNT_ING_ALL_FRAME]		= "[mac] rx all frames",
429 	[DPMAC_CNT_ING_GOOD_FRAME]		= "[mac] rx frames ok",
430 	[DPMAC_CNT_ING_ERR_FRAME]		= "[mac] rx frame errors",
431 	[DPMAC_CNT_ING_FRAME_DISCARD]		= "[mac] rx frame discards",
432 	[DPMAC_CNT_ING_UCAST_FRAME]		= "[mac] rx u-cast",
433 	[DPMAC_CNT_ING_BCAST_FRAME]		= "[mac] rx b-cast",
434 	[DPMAC_CNT_ING_MCAST_FRAME]		= "[mac] rx m-cast",
435 	[DPMAC_CNT_ING_FRAME_64]		= "[mac] rx 64 bytes",
436 	[DPMAC_CNT_ING_FRAME_127]		= "[mac] rx 65-127 bytes",
437 	[DPMAC_CNT_ING_FRAME_255]		= "[mac] rx 128-255 bytes",
438 	[DPMAC_CNT_ING_FRAME_511]		= "[mac] rx 256-511 bytes",
439 	[DPMAC_CNT_ING_FRAME_1023]		= "[mac] rx 512-1023 bytes",
440 	[DPMAC_CNT_ING_FRAME_1518]		= "[mac] rx 1024-1518 bytes",
441 	[DPMAC_CNT_ING_FRAME_1519_MAX]		= "[mac] rx 1519-max bytes",
442 	[DPMAC_CNT_ING_FRAG]			= "[mac] rx frags",
443 	[DPMAC_CNT_ING_JABBER]			= "[mac] rx jabber",
444 	[DPMAC_CNT_ING_ALIGN_ERR]		= "[mac] rx align errors",
445 	[DPMAC_CNT_ING_OVERSIZED]		= "[mac] rx oversized",
446 	[DPMAC_CNT_ING_VALID_PAUSE_FRAME]	= "[mac] rx pause",
447 	[DPMAC_CNT_ING_BYTE]			= "[mac] rx bytes",
448 	[DPMAC_CNT_EGR_GOOD_FRAME]		= "[mac] tx frames ok",
449 	[DPMAC_CNT_EGR_UCAST_FRAME]		= "[mac] tx u-cast",
450 	[DPMAC_CNT_EGR_MCAST_FRAME]		= "[mac] tx m-cast",
451 	[DPMAC_CNT_EGR_BCAST_FRAME]		= "[mac] tx b-cast",
452 	[DPMAC_CNT_EGR_ERR_FRAME]		= "[mac] tx frame errors",
453 	[DPMAC_CNT_EGR_UNDERSIZED]		= "[mac] tx undersized",
454 	[DPMAC_CNT_EGR_VALID_PAUSE_FRAME]	= "[mac] tx b-pause",
455 	[DPMAC_CNT_EGR_BYTE]			= "[mac] tx bytes",
456 };
457 
458 #define DPAA2_MAC_NUM_STATS	ARRAY_SIZE(dpaa2_mac_ethtool_stats)
459 
460 int dpaa2_mac_get_sset_count(void)
461 {
462 	return DPAA2_MAC_NUM_STATS;
463 }
464 
465 void dpaa2_mac_get_strings(u8 *data)
466 {
467 	u8 *p = data;
468 	int i;
469 
470 	for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
471 		strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
472 		p += ETH_GSTRING_LEN;
473 	}
474 }
475 
476 void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
477 {
478 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
479 	int i, err;
480 	u64 value;
481 
482 	for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
483 		err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle,
484 					i, &value);
485 		if (err) {
486 			netdev_err_once(mac->net_dev,
487 					"dpmac_get_counter error %d\n", err);
488 			*(data + i) = U64_MAX;
489 			continue;
490 		}
491 		*(data + i) = value;
492 	}
493 }
494