1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2019 NXP */
3 
4 #include "dpaa2-eth.h"
5 #include "dpaa2-mac.h"
6 
7 #define phylink_to_dpaa2_mac(config) \
8 	container_of((config), struct dpaa2_mac, phylink_config)
9 
10 static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
11 {
12 	*if_mode = PHY_INTERFACE_MODE_NA;
13 
14 	switch (eth_if) {
15 	case DPMAC_ETH_IF_RGMII:
16 		*if_mode = PHY_INTERFACE_MODE_RGMII;
17 		break;
18 	default:
19 		return -EINVAL;
20 	}
21 
22 	return 0;
23 }
24 
25 /* Caller must call of_node_put on the returned value */
26 static struct device_node *dpaa2_mac_get_node(u16 dpmac_id)
27 {
28 	struct device_node *dpmacs, *dpmac = NULL;
29 	u32 id;
30 	int err;
31 
32 	dpmacs = of_find_node_by_name(NULL, "dpmacs");
33 	if (!dpmacs)
34 		return NULL;
35 
36 	while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) {
37 		err = of_property_read_u32(dpmac, "reg", &id);
38 		if (err)
39 			continue;
40 		if (id == dpmac_id)
41 			break;
42 	}
43 
44 	of_node_put(dpmacs);
45 
46 	return dpmac;
47 }
48 
49 static int dpaa2_mac_get_if_mode(struct device_node *node,
50 				 struct dpmac_attr attr)
51 {
52 	phy_interface_t if_mode;
53 	int err;
54 
55 	err = of_get_phy_mode(node, &if_mode);
56 	if (!err)
57 		return if_mode;
58 
59 	err = phy_mode(attr.eth_if, &if_mode);
60 	if (!err)
61 		return if_mode;
62 
63 	return err;
64 }
65 
66 static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac,
67 					phy_interface_t interface)
68 {
69 	switch (interface) {
70 	case PHY_INTERFACE_MODE_RGMII:
71 	case PHY_INTERFACE_MODE_RGMII_ID:
72 	case PHY_INTERFACE_MODE_RGMII_RXID:
73 	case PHY_INTERFACE_MODE_RGMII_TXID:
74 		return (interface != mac->if_mode);
75 	default:
76 		return true;
77 	}
78 }
79 
80 static void dpaa2_mac_validate(struct phylink_config *config,
81 			       unsigned long *supported,
82 			       struct phylink_link_state *state)
83 {
84 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
85 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
86 
87 	if (state->interface != PHY_INTERFACE_MODE_NA &&
88 	    dpaa2_mac_phy_mode_mismatch(mac, state->interface)) {
89 		goto empty_set;
90 	}
91 
92 	phylink_set_port_modes(mask);
93 	phylink_set(mask, Autoneg);
94 	phylink_set(mask, Pause);
95 	phylink_set(mask, Asym_Pause);
96 
97 	switch (state->interface) {
98 	case PHY_INTERFACE_MODE_RGMII:
99 	case PHY_INTERFACE_MODE_RGMII_ID:
100 	case PHY_INTERFACE_MODE_RGMII_RXID:
101 	case PHY_INTERFACE_MODE_RGMII_TXID:
102 		phylink_set(mask, 10baseT_Full);
103 		phylink_set(mask, 100baseT_Full);
104 		phylink_set(mask, 1000baseT_Full);
105 		break;
106 	default:
107 		goto empty_set;
108 	}
109 
110 	linkmode_and(supported, supported, mask);
111 	linkmode_and(state->advertising, state->advertising, mask);
112 
113 	return;
114 
115 empty_set:
116 	linkmode_zero(supported);
117 }
118 
119 static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
120 			     const struct phylink_link_state *state)
121 {
122 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
123 	struct dpmac_link_state *dpmac_state = &mac->state;
124 	int err;
125 
126 	if (state->an_enabled)
127 		dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG;
128 	else
129 		dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG;
130 
131 	err = dpmac_set_link_state(mac->mc_io, 0,
132 				   mac->mc_dev->mc_handle, dpmac_state);
133 	if (err)
134 		netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
135 			   __func__, err);
136 }
137 
138 static void dpaa2_mac_link_up(struct phylink_config *config,
139 			      struct phy_device *phy,
140 			      unsigned int mode, phy_interface_t interface,
141 			      int speed, int duplex,
142 			      bool tx_pause, bool rx_pause)
143 {
144 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
145 	struct dpmac_link_state *dpmac_state = &mac->state;
146 	int err;
147 
148 	dpmac_state->up = 1;
149 
150 	if (mac->if_link_type == DPMAC_LINK_TYPE_PHY) {
151 		/* If the DPMAC is configured for PHY mode, we need
152 		 * to pass the link parameters to the MC firmware.
153 		 */
154 		dpmac_state->rate = speed;
155 
156 		if (duplex == DUPLEX_HALF)
157 			dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
158 		else if (duplex == DUPLEX_FULL)
159 			dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX;
160 
161 		/* This is lossy; the firmware really should take the pause
162 		 * enablement status rather than pause/asym pause status.
163 		 */
164 		if (rx_pause)
165 			dpmac_state->options |= DPMAC_LINK_OPT_PAUSE;
166 		else
167 			dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE;
168 
169 		if (rx_pause ^ tx_pause)
170 			dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE;
171 		else
172 			dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE;
173 	}
174 
175 	err = dpmac_set_link_state(mac->mc_io, 0,
176 				   mac->mc_dev->mc_handle, dpmac_state);
177 	if (err)
178 		netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
179 			   __func__, err);
180 }
181 
182 static void dpaa2_mac_link_down(struct phylink_config *config,
183 				unsigned int mode,
184 				phy_interface_t interface)
185 {
186 	struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
187 	struct dpmac_link_state *dpmac_state = &mac->state;
188 	int err;
189 
190 	dpmac_state->up = 0;
191 	err = dpmac_set_link_state(mac->mc_io, 0,
192 				   mac->mc_dev->mc_handle, dpmac_state);
193 	if (err)
194 		netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err);
195 }
196 
197 static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
198 	.validate = dpaa2_mac_validate,
199 	.mac_config = dpaa2_mac_config,
200 	.mac_link_up = dpaa2_mac_link_up,
201 	.mac_link_down = dpaa2_mac_link_down,
202 };
203 
204 bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
205 			     struct fsl_mc_io *mc_io)
206 {
207 	struct dpmac_attr attr;
208 	bool fixed = false;
209 	u16 mc_handle = 0;
210 	int err;
211 
212 	err = dpmac_open(mc_io, 0, dpmac_dev->obj_desc.id,
213 			 &mc_handle);
214 	if (err || !mc_handle)
215 		return false;
216 
217 	err = dpmac_get_attributes(mc_io, 0, mc_handle, &attr);
218 	if (err)
219 		goto out;
220 
221 	if (attr.link_type == DPMAC_LINK_TYPE_FIXED)
222 		fixed = true;
223 
224 out:
225 	dpmac_close(mc_io, 0, mc_handle);
226 
227 	return fixed;
228 }
229 
230 int dpaa2_mac_connect(struct dpaa2_mac *mac)
231 {
232 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
233 	struct net_device *net_dev = mac->net_dev;
234 	struct device_node *dpmac_node;
235 	struct phylink *phylink;
236 	struct dpmac_attr attr;
237 	int err;
238 
239 	err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id,
240 			 &dpmac_dev->mc_handle);
241 	if (err || !dpmac_dev->mc_handle) {
242 		netdev_err(net_dev, "dpmac_open() = %d\n", err);
243 		return -ENODEV;
244 	}
245 
246 	err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle, &attr);
247 	if (err) {
248 		netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err);
249 		goto err_close_dpmac;
250 	}
251 
252 	mac->if_link_type = attr.link_type;
253 
254 	dpmac_node = dpaa2_mac_get_node(attr.id);
255 	if (!dpmac_node) {
256 		netdev_err(net_dev, "No dpmac@%d node found.\n", attr.id);
257 		err = -ENODEV;
258 		goto err_close_dpmac;
259 	}
260 
261 	err = dpaa2_mac_get_if_mode(dpmac_node, attr);
262 	if (err < 0) {
263 		err = -EINVAL;
264 		goto err_put_node;
265 	}
266 	mac->if_mode = err;
267 
268 	/* The MAC does not have the capability to add RGMII delays so
269 	 * error out if the interface mode requests them and there is no PHY
270 	 * to act upon them
271 	 */
272 	if (of_phy_is_fixed_link(dpmac_node) &&
273 	    (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID ||
274 	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
275 	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) {
276 		netdev_err(net_dev, "RGMII delay not supported\n");
277 		err = -EINVAL;
278 		goto err_put_node;
279 	}
280 
281 	mac->phylink_config.dev = &net_dev->dev;
282 	mac->phylink_config.type = PHYLINK_NETDEV;
283 
284 	phylink = phylink_create(&mac->phylink_config,
285 				 of_fwnode_handle(dpmac_node), mac->if_mode,
286 				 &dpaa2_mac_phylink_ops);
287 	if (IS_ERR(phylink)) {
288 		err = PTR_ERR(phylink);
289 		goto err_put_node;
290 	}
291 	mac->phylink = phylink;
292 
293 	err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
294 	if (err) {
295 		netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err);
296 		goto err_phylink_destroy;
297 	}
298 
299 	of_node_put(dpmac_node);
300 
301 	return 0;
302 
303 err_phylink_destroy:
304 	phylink_destroy(mac->phylink);
305 err_put_node:
306 	of_node_put(dpmac_node);
307 err_close_dpmac:
308 	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
309 	return err;
310 }
311 
312 void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
313 {
314 	if (!mac->phylink)
315 		return;
316 
317 	phylink_disconnect_phy(mac->phylink);
318 	phylink_destroy(mac->phylink);
319 	dpmac_close(mac->mc_io, 0, mac->mc_dev->mc_handle);
320 }
321 
322 static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
323 	[DPMAC_CNT_ING_ALL_FRAME]		= "[mac] rx all frames",
324 	[DPMAC_CNT_ING_GOOD_FRAME]		= "[mac] rx frames ok",
325 	[DPMAC_CNT_ING_ERR_FRAME]		= "[mac] rx frame errors",
326 	[DPMAC_CNT_ING_FRAME_DISCARD]		= "[mac] rx frame discards",
327 	[DPMAC_CNT_ING_UCAST_FRAME]		= "[mac] rx u-cast",
328 	[DPMAC_CNT_ING_BCAST_FRAME]		= "[mac] rx b-cast",
329 	[DPMAC_CNT_ING_MCAST_FRAME]		= "[mac] rx m-cast",
330 	[DPMAC_CNT_ING_FRAME_64]		= "[mac] rx 64 bytes",
331 	[DPMAC_CNT_ING_FRAME_127]		= "[mac] rx 65-127 bytes",
332 	[DPMAC_CNT_ING_FRAME_255]		= "[mac] rx 128-255 bytes",
333 	[DPMAC_CNT_ING_FRAME_511]		= "[mac] rx 256-511 bytes",
334 	[DPMAC_CNT_ING_FRAME_1023]		= "[mac] rx 512-1023 bytes",
335 	[DPMAC_CNT_ING_FRAME_1518]		= "[mac] rx 1024-1518 bytes",
336 	[DPMAC_CNT_ING_FRAME_1519_MAX]		= "[mac] rx 1519-max bytes",
337 	[DPMAC_CNT_ING_FRAG]			= "[mac] rx frags",
338 	[DPMAC_CNT_ING_JABBER]			= "[mac] rx jabber",
339 	[DPMAC_CNT_ING_ALIGN_ERR]		= "[mac] rx align errors",
340 	[DPMAC_CNT_ING_OVERSIZED]		= "[mac] rx oversized",
341 	[DPMAC_CNT_ING_VALID_PAUSE_FRAME]	= "[mac] rx pause",
342 	[DPMAC_CNT_ING_BYTE]			= "[mac] rx bytes",
343 	[DPMAC_CNT_EGR_GOOD_FRAME]		= "[mac] tx frames ok",
344 	[DPMAC_CNT_EGR_UCAST_FRAME]		= "[mac] tx u-cast",
345 	[DPMAC_CNT_EGR_MCAST_FRAME]		= "[mac] tx m-cast",
346 	[DPMAC_CNT_EGR_BCAST_FRAME]		= "[mac] tx b-cast",
347 	[DPMAC_CNT_EGR_ERR_FRAME]		= "[mac] tx frame errors",
348 	[DPMAC_CNT_EGR_UNDERSIZED]		= "[mac] tx undersized",
349 	[DPMAC_CNT_EGR_VALID_PAUSE_FRAME]	= "[mac] tx b-pause",
350 	[DPMAC_CNT_EGR_BYTE]			= "[mac] tx bytes",
351 };
352 
353 #define DPAA2_MAC_NUM_STATS	ARRAY_SIZE(dpaa2_mac_ethtool_stats)
354 
355 int dpaa2_mac_get_sset_count(void)
356 {
357 	return DPAA2_MAC_NUM_STATS;
358 }
359 
360 void dpaa2_mac_get_strings(u8 *data)
361 {
362 	u8 *p = data;
363 	int i;
364 
365 	for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
366 		strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
367 		p += ETH_GSTRING_LEN;
368 	}
369 }
370 
371 void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
372 {
373 	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
374 	int i, err;
375 	u64 value;
376 
377 	for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
378 		err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle,
379 					i, &value);
380 		if (err) {
381 			netdev_err_once(mac->net_dev,
382 					"dpmac_get_counter error %d\n", err);
383 			*(data + i) = U64_MAX;
384 			continue;
385 		}
386 		*(data + i) = value;
387 	}
388 }
389