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 		if (state->interface == PHY_INTERFACE_MODE_10GBASER)
144 			break;
145 		phylink_set(mask, 5000baseT_Full);
146 		phylink_set(mask, 2500baseT_Full);
147 		fallthrough;
148 	case PHY_INTERFACE_MODE_SGMII:
149 	case PHY_INTERFACE_MODE_QSGMII:
150 	case PHY_INTERFACE_MODE_1000BASEX:
151 	case PHY_INTERFACE_MODE_RGMII:
152 	case PHY_INTERFACE_MODE_RGMII_ID:
153 	case PHY_INTERFACE_MODE_RGMII_RXID:
154 	case PHY_INTERFACE_MODE_RGMII_TXID:
155 		phylink_set(mask, 1000baseX_Full);
156 		phylink_set(mask, 1000baseT_Full);
157 		if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
158 			break;
159 		phylink_set(mask, 100baseT_Full);
160 		phylink_set(mask, 10baseT_Full);
161 		break;
162 	default:
163 		goto empty_set;
164 	}
165 
166 	linkmode_and(supported, supported, mask);
167 	linkmode_and(state->advertising, state->advertising, mask);
168 
169 	return;
170 
171 empty_set:
172 	linkmode_zero(supported);
173 }
174 
175 static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
176 			     const struct phylink_link_state *state)
177 {
178 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
179 	struct dpmac_link_state *dpmac_state = &mac->state;
180 	int err;
181 
182 	if (state->an_enabled)
183 		dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG;
184 	else
185 		dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG;
186 
187 	err = dpmac_set_link_state(mac->mc_io, 0,
188 				   mac->mc_dev->mc_handle, dpmac_state);
189 	if (err)
190 		netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
191 			   __func__, err);
192 }
193 
194 static void dpaa2_mac_link_up(struct phylink_config *config,
195 			      struct phy_device *phy,
196 			      unsigned int mode, phy_interface_t interface,
197 			      int speed, int duplex,
198 			      bool tx_pause, bool rx_pause)
199 {
200 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
201 	struct dpmac_link_state *dpmac_state = &mac->state;
202 	int err;
203 
204 	dpmac_state->up = 1;
205 
206 	dpmac_state->rate = speed;
207 
208 	if (duplex == DUPLEX_HALF)
209 		dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
210 	else if (duplex == DUPLEX_FULL)
211 		dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX;
212 
213 	if (rx_pause)
214 		dpmac_state->options |= DPMAC_LINK_OPT_PAUSE;
215 	else
216 		dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE;
217 
218 	if (rx_pause ^ tx_pause)
219 		dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE;
220 	else
221 		dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE;
222 
223 	err = dpmac_set_link_state(mac->mc_io, 0,
224 				   mac->mc_dev->mc_handle, dpmac_state);
225 	if (err)
226 		netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
227 			   __func__, err);
228 }
229 
230 static void dpaa2_mac_link_down(struct phylink_config *config,
231 				unsigned int mode,
232 				phy_interface_t interface)
233 {
234 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
235 	struct dpmac_link_state *dpmac_state = &mac->state;
236 	int err;
237 
238 	dpmac_state->up = 0;
239 	err = dpmac_set_link_state(mac->mc_io, 0,
240 				   mac->mc_dev->mc_handle, dpmac_state);
241 	if (err)
242 		netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err);
243 }
244 
245 static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
246 	.validate = dpaa2_mac_validate,
247 	.mac_config = dpaa2_mac_config,
248 	.mac_link_up = dpaa2_mac_link_up,
249 	.mac_link_down = dpaa2_mac_link_down,
250 };
251 
252 static int dpaa2_pcs_create(struct dpaa2_mac *mac,
253 			    struct fwnode_handle *dpmac_node,
254 			    int id)
255 {
256 	struct mdio_device *mdiodev;
257 	struct fwnode_handle *node;
258 
259 	node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
260 	if (IS_ERR(node)) {
261 		/* do not error out on old DTS files */
262 		netdev_warn(mac->net_dev, "pcs-handle node not found\n");
263 		return 0;
264 	}
265 
266 	if (!fwnode_device_is_available(node)) {
267 		netdev_err(mac->net_dev, "pcs-handle node not available\n");
268 		fwnode_handle_put(node);
269 		return -ENODEV;
270 	}
271 
272 	mdiodev = fwnode_mdio_find_device(node);
273 	fwnode_handle_put(node);
274 	if (!mdiodev)
275 		return -EPROBE_DEFER;
276 
277 	mac->pcs = lynx_pcs_create(mdiodev);
278 	if (!mac->pcs) {
279 		netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
280 		put_device(&mdiodev->dev);
281 		return -ENOMEM;
282 	}
283 
284 	return 0;
285 }
286 
287 static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
288 {
289 	struct lynx_pcs *pcs = mac->pcs;
290 
291 	if (pcs) {
292 		struct device *dev = &pcs->mdio->dev;
293 		lynx_pcs_destroy(pcs);
294 		put_device(dev);
295 		mac->pcs = NULL;
296 	}
297 }
298 
299 int dpaa2_mac_connect(struct dpaa2_mac *mac)
300 {
301 	struct net_device *net_dev = mac->net_dev;
302 	struct fwnode_handle *dpmac_node;
303 	struct phylink *phylink;
304 	int err;
305 
306 	mac->if_link_type = mac->attr.link_type;
307 
308 	dpmac_node = mac->fw_node;
309 	if (!dpmac_node) {
310 		netdev_err(net_dev, "No dpmac@%d node found.\n", mac->attr.id);
311 		return -ENODEV;
312 	}
313 
314 	err = dpaa2_mac_get_if_mode(dpmac_node, mac->attr);
315 	if (err < 0)
316 		return -EINVAL;
317 	mac->if_mode = err;
318 
319 	/* The MAC does not have the capability to add RGMII delays so
320 	 * error out if the interface mode requests them and there is no PHY
321 	 * to act upon them
322 	 */
323 	if (of_phy_is_fixed_link(to_of_node(dpmac_node)) &&
324 	    (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID ||
325 	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
326 	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) {
327 		netdev_err(net_dev, "RGMII delay not supported\n");
328 		return -EINVAL;
329 	}
330 
331 	if ((mac->attr.link_type == DPMAC_LINK_TYPE_PHY &&
332 	     mac->attr.eth_if != DPMAC_ETH_IF_RGMII) ||
333 	    mac->attr.link_type == DPMAC_LINK_TYPE_BACKPLANE) {
334 		err = dpaa2_pcs_create(mac, dpmac_node, mac->attr.id);
335 		if (err)
336 			return err;
337 	}
338 
339 	mac->phylink_config.dev = &net_dev->dev;
340 	mac->phylink_config.type = PHYLINK_NETDEV;
341 
342 	phylink = phylink_create(&mac->phylink_config,
343 				 dpmac_node, mac->if_mode,
344 				 &dpaa2_mac_phylink_ops);
345 	if (IS_ERR(phylink)) {
346 		err = PTR_ERR(phylink);
347 		goto err_pcs_destroy;
348 	}
349 	mac->phylink = phylink;
350 
351 	if (mac->pcs)
352 		phylink_set_pcs(mac->phylink, &mac->pcs->pcs);
353 
354 	err = phylink_fwnode_phy_connect(mac->phylink, dpmac_node, 0);
355 	if (err) {
356 		netdev_err(net_dev, "phylink_fwnode_phy_connect() = %d\n", err);
357 		goto err_phylink_destroy;
358 	}
359 
360 	return 0;
361 
362 err_phylink_destroy:
363 	phylink_destroy(mac->phylink);
364 err_pcs_destroy:
365 	dpaa2_pcs_destroy(mac);
366 
367 	return err;
368 }
369 
370 void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
371 {
372 	if (!mac->phylink)
373 		return;
374 
375 	phylink_disconnect_phy(mac->phylink);
376 	phylink_destroy(mac->phylink);
377 	dpaa2_pcs_destroy(mac);
378 }
379 
380 int dpaa2_mac_open(struct dpaa2_mac *mac)
381 {
382 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
383 	struct net_device *net_dev = mac->net_dev;
384 	int err;
385 
386 	err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id,
387 			 &dpmac_dev->mc_handle);
388 	if (err || !dpmac_dev->mc_handle) {
389 		netdev_err(net_dev, "dpmac_open() = %d\n", err);
390 		return -ENODEV;
391 	}
392 
393 	err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle,
394 				   &mac->attr);
395 	if (err) {
396 		netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err);
397 		goto err_close_dpmac;
398 	}
399 
400 	/* Find the device node representing the MAC device and link the device
401 	 * behind the associated netdev to it.
402 	 */
403 	mac->fw_node = dpaa2_mac_get_node(&mac->mc_dev->dev, mac->attr.id);
404 	net_dev->dev.of_node = to_of_node(mac->fw_node);
405 
406 	return 0;
407 
408 err_close_dpmac:
409 	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
410 	return err;
411 }
412 
413 void dpaa2_mac_close(struct dpaa2_mac *mac)
414 {
415 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
416 
417 	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
418 	if (mac->fw_node)
419 		fwnode_handle_put(mac->fw_node);
420 }
421 
422 static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
423 	[DPMAC_CNT_ING_ALL_FRAME]		= "[mac] rx all frames",
424 	[DPMAC_CNT_ING_GOOD_FRAME]		= "[mac] rx frames ok",
425 	[DPMAC_CNT_ING_ERR_FRAME]		= "[mac] rx frame errors",
426 	[DPMAC_CNT_ING_FRAME_DISCARD]		= "[mac] rx frame discards",
427 	[DPMAC_CNT_ING_UCAST_FRAME]		= "[mac] rx u-cast",
428 	[DPMAC_CNT_ING_BCAST_FRAME]		= "[mac] rx b-cast",
429 	[DPMAC_CNT_ING_MCAST_FRAME]		= "[mac] rx m-cast",
430 	[DPMAC_CNT_ING_FRAME_64]		= "[mac] rx 64 bytes",
431 	[DPMAC_CNT_ING_FRAME_127]		= "[mac] rx 65-127 bytes",
432 	[DPMAC_CNT_ING_FRAME_255]		= "[mac] rx 128-255 bytes",
433 	[DPMAC_CNT_ING_FRAME_511]		= "[mac] rx 256-511 bytes",
434 	[DPMAC_CNT_ING_FRAME_1023]		= "[mac] rx 512-1023 bytes",
435 	[DPMAC_CNT_ING_FRAME_1518]		= "[mac] rx 1024-1518 bytes",
436 	[DPMAC_CNT_ING_FRAME_1519_MAX]		= "[mac] rx 1519-max bytes",
437 	[DPMAC_CNT_ING_FRAG]			= "[mac] rx frags",
438 	[DPMAC_CNT_ING_JABBER]			= "[mac] rx jabber",
439 	[DPMAC_CNT_ING_ALIGN_ERR]		= "[mac] rx align errors",
440 	[DPMAC_CNT_ING_OVERSIZED]		= "[mac] rx oversized",
441 	[DPMAC_CNT_ING_VALID_PAUSE_FRAME]	= "[mac] rx pause",
442 	[DPMAC_CNT_ING_BYTE]			= "[mac] rx bytes",
443 	[DPMAC_CNT_EGR_GOOD_FRAME]		= "[mac] tx frames ok",
444 	[DPMAC_CNT_EGR_UCAST_FRAME]		= "[mac] tx u-cast",
445 	[DPMAC_CNT_EGR_MCAST_FRAME]		= "[mac] tx m-cast",
446 	[DPMAC_CNT_EGR_BCAST_FRAME]		= "[mac] tx b-cast",
447 	[DPMAC_CNT_EGR_ERR_FRAME]		= "[mac] tx frame errors",
448 	[DPMAC_CNT_EGR_UNDERSIZED]		= "[mac] tx undersized",
449 	[DPMAC_CNT_EGR_VALID_PAUSE_FRAME]	= "[mac] tx b-pause",
450 	[DPMAC_CNT_EGR_BYTE]			= "[mac] tx bytes",
451 };
452 
453 #define DPAA2_MAC_NUM_STATS	ARRAY_SIZE(dpaa2_mac_ethtool_stats)
454 
455 int dpaa2_mac_get_sset_count(void)
456 {
457 	return DPAA2_MAC_NUM_STATS;
458 }
459 
460 void dpaa2_mac_get_strings(u8 *data)
461 {
462 	u8 *p = data;
463 	int i;
464 
465 	for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
466 		strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
467 		p += ETH_GSTRING_LEN;
468 	}
469 }
470 
471 void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
472 {
473 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
474 	int i, err;
475 	u64 value;
476 
477 	for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
478 		err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle,
479 					i, &value);
480 		if (err) {
481 			netdev_err_once(mac->net_dev,
482 					"dpmac_get_counter error %d\n", err);
483 			*(data + i) = U64_MAX;
484 			continue;
485 		}
486 		*(data + i) = value;
487 	}
488 }
489