xref: /linux/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c (revision 8f7aa3d3c7323f4ca2768a9e74ebbe359c4f8f88)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
3 
4 #include <linux/phylink.h>
5 #include <linux/iopoll.h>
6 #include <linux/pci.h>
7 #include <linux/phy.h>
8 
9 #include "../libwx/wx_type.h"
10 #include "../libwx/wx_lib.h"
11 #include "../libwx/wx_ptp.h"
12 #include "../libwx/wx_hw.h"
13 #include "../libwx/wx_sriov.h"
14 #include "txgbe_type.h"
15 #include "txgbe_aml.h"
16 #include "txgbe_hw.h"
17 
18 void txgbe_gpio_init_aml(struct wx *wx)
19 {
20 	u32 status, mod_rst;
21 
22 	if (wx->mac.type == wx_mac_aml40)
23 		mod_rst = TXGBE_GPIOBIT_4;
24 	else
25 		mod_rst = TXGBE_GPIOBIT_2;
26 
27 	wr32(wx, WX_GPIO_INTTYPE_LEVEL, mod_rst);
28 	wr32(wx, WX_GPIO_INTEN, mod_rst);
29 
30 	status = rd32(wx, WX_GPIO_INTSTATUS);
31 	for (int i = 0; i < 6; i++) {
32 		if (status & BIT(i))
33 			wr32(wx, WX_GPIO_EOI, BIT(i));
34 	}
35 }
36 
37 irqreturn_t txgbe_gpio_irq_handler_aml(int irq, void *data)
38 {
39 	struct txgbe *txgbe = data;
40 	struct wx *wx = txgbe->wx;
41 	u32 status, mod_rst;
42 
43 	if (wx->mac.type == wx_mac_aml40)
44 		mod_rst = TXGBE_GPIOBIT_4;
45 	else
46 		mod_rst = TXGBE_GPIOBIT_2;
47 
48 	wr32(wx, WX_GPIO_INTMASK, 0xFF);
49 	status = rd32(wx, WX_GPIO_INTSTATUS);
50 	if (status & mod_rst) {
51 		set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags);
52 		wr32(wx, WX_GPIO_EOI, mod_rst);
53 		wx_service_event_schedule(wx);
54 	}
55 
56 	wr32(wx, WX_GPIO_INTMASK, 0);
57 	return IRQ_HANDLED;
58 }
59 
60 int txgbe_test_hostif(struct wx *wx)
61 {
62 	struct txgbe_hic_ephy_getlink buffer;
63 
64 	if (wx->mac.type == wx_mac_sp)
65 		return 0;
66 
67 	buffer.hdr.cmd = FW_PHY_GET_LINK_CMD;
68 	buffer.hdr.buf_len = sizeof(struct txgbe_hic_ephy_getlink) -
69 			     sizeof(struct wx_hic_hdr);
70 	buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
71 
72 	return wx_host_interface_command(wx, (u32 *)&buffer, sizeof(buffer),
73 					WX_HI_COMMAND_TIMEOUT, true);
74 }
75 
76 int txgbe_read_eeprom_hostif(struct wx *wx,
77 			     struct txgbe_hic_i2c_read *buffer,
78 			     u32 length, u8 *data)
79 {
80 	u32 dword_len, offset, value, i;
81 	int err;
82 
83 	buffer->hdr.cmd = FW_READ_EEPROM_CMD;
84 	buffer->hdr.buf_len = sizeof(struct txgbe_hic_i2c_read) -
85 			      sizeof(struct wx_hic_hdr);
86 	buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
87 
88 	err = wx_host_interface_command(wx, (u32 *)buffer,
89 					sizeof(struct txgbe_hic_i2c_read),
90 					WX_HI_COMMAND_TIMEOUT, false);
91 	if (err != 0)
92 		return err;
93 
94 	/* buffer length offset to read return data */
95 	offset = sizeof(struct txgbe_hic_i2c_read) >> 2;
96 	dword_len = round_up(length, 4) >> 2;
97 
98 	for (i = 0; i < dword_len; i++) {
99 		value = rd32a(wx, WX_FW2SW_MBOX, i + offset);
100 		le32_to_cpus(&value);
101 
102 		memcpy(data, &value, 4);
103 		data += 4;
104 	}
105 
106 	return 0;
107 }
108 
109 static int txgbe_identify_module_hostif(struct wx *wx,
110 					struct txgbe_hic_get_module_info *buffer)
111 {
112 	buffer->hdr.cmd = FW_GET_MODULE_INFO_CMD;
113 	buffer->hdr.buf_len = sizeof(struct txgbe_hic_get_module_info) -
114 			      sizeof(struct wx_hic_hdr);
115 	buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
116 
117 	return wx_host_interface_command(wx, (u32 *)buffer,
118 					 sizeof(struct txgbe_hic_get_module_info),
119 					 WX_HI_COMMAND_TIMEOUT, true);
120 }
121 
122 static int txgbe_set_phy_link_hostif(struct wx *wx, int speed, int autoneg, int duplex)
123 {
124 	struct txgbe_hic_ephy_setlink buffer;
125 
126 	buffer.hdr.cmd = FW_PHY_SET_LINK_CMD;
127 	buffer.hdr.buf_len = sizeof(struct txgbe_hic_ephy_setlink) -
128 			     sizeof(struct wx_hic_hdr);
129 	buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
130 
131 	switch (speed) {
132 	case SPEED_40000:
133 		buffer.speed = TXGBE_LINK_SPEED_40GB_FULL;
134 		break;
135 	case SPEED_25000:
136 		buffer.speed = TXGBE_LINK_SPEED_25GB_FULL;
137 		break;
138 	case SPEED_10000:
139 		buffer.speed = TXGBE_LINK_SPEED_10GB_FULL;
140 		break;
141 	default:
142 		buffer.speed = TXGBE_LINK_SPEED_UNKNOWN;
143 		break;
144 	}
145 
146 	buffer.fec_mode = TXGBE_PHY_FEC_AUTO;
147 	buffer.autoneg = autoneg;
148 	buffer.duplex = duplex;
149 
150 	return wx_host_interface_command(wx, (u32 *)&buffer, sizeof(buffer),
151 					 WX_HI_COMMAND_TIMEOUT, true);
152 }
153 
154 static void txgbe_get_link_capabilities(struct wx *wx, int *speed,
155 					int *autoneg, int *duplex)
156 {
157 	struct txgbe *txgbe = wx->priv;
158 
159 	if (test_bit(PHY_INTERFACE_MODE_XLGMII, txgbe->link_interfaces))
160 		*speed = SPEED_40000;
161 	else if (test_bit(PHY_INTERFACE_MODE_25GBASER, txgbe->link_interfaces))
162 		*speed = SPEED_25000;
163 	else if (test_bit(PHY_INTERFACE_MODE_10GBASER, txgbe->link_interfaces))
164 		*speed = SPEED_10000;
165 	else
166 		*speed = SPEED_UNKNOWN;
167 
168 	*autoneg = phylink_test(txgbe->advertising, Autoneg);
169 	*duplex = *speed == SPEED_UNKNOWN ? DUPLEX_HALF : DUPLEX_FULL;
170 }
171 
172 static void txgbe_get_mac_link(struct wx *wx, int *speed)
173 {
174 	u32 status;
175 
176 	status = rd32(wx, TXGBE_CFG_PORT_ST);
177 	if (!(status & TXGBE_CFG_PORT_ST_LINK_UP))
178 		*speed = SPEED_UNKNOWN;
179 	else if (status & TXGBE_CFG_PORT_ST_LINK_AML_40G)
180 		*speed = SPEED_40000;
181 	else if (status & TXGBE_CFG_PORT_ST_LINK_AML_25G)
182 		*speed = SPEED_25000;
183 	else if (status & TXGBE_CFG_PORT_ST_LINK_AML_10G)
184 		*speed = SPEED_10000;
185 	else
186 		*speed = SPEED_UNKNOWN;
187 }
188 
189 int txgbe_set_phy_link(struct wx *wx)
190 {
191 	int speed, autoneg, duplex, err;
192 
193 	txgbe_get_link_capabilities(wx, &speed, &autoneg, &duplex);
194 
195 	err = txgbe_set_phy_link_hostif(wx, speed, autoneg, duplex);
196 	if (err) {
197 		wx_err(wx, "Failed to setup link\n");
198 		return err;
199 	}
200 
201 	return 0;
202 }
203 
204 static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
205 {
206 	__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
207 	DECLARE_PHY_INTERFACE_MASK(interfaces);
208 	struct txgbe *txgbe = wx->priv;
209 
210 	if (id->cable_tech & TXGBE_SFF_DA_PASSIVE_CABLE) {
211 		txgbe->link_port = PORT_DA;
212 		phylink_set(modes, Autoneg);
213 		if (id->com_25g_code == TXGBE_SFF_25GBASECR_91FEC ||
214 		    id->com_25g_code == TXGBE_SFF_25GBASECR_74FEC ||
215 		    id->com_25g_code == TXGBE_SFF_25GBASECR_NOFEC) {
216 			phylink_set(modes, 25000baseCR_Full);
217 			phylink_set(modes, 10000baseCR_Full);
218 			__set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
219 			__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
220 		} else {
221 			phylink_set(modes, 10000baseCR_Full);
222 			__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
223 		}
224 	} else if (id->cable_tech & TXGBE_SFF_DA_ACTIVE_CABLE) {
225 		txgbe->link_port = PORT_DA;
226 		phylink_set(modes, Autoneg);
227 		phylink_set(modes, 25000baseCR_Full);
228 		__set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
229 	} else {
230 		if (id->com_25g_code == TXGBE_SFF_25GBASESR_CAPABLE ||
231 		    id->com_25g_code == TXGBE_SFF_25GBASEER_CAPABLE ||
232 		    id->com_25g_code == TXGBE_SFF_25GBASELR_CAPABLE) {
233 			txgbe->link_port = PORT_FIBRE;
234 			phylink_set(modes, 25000baseSR_Full);
235 			__set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
236 		}
237 		if (id->com_10g_code & TXGBE_SFF_10GBASESR_CAPABLE) {
238 			txgbe->link_port = PORT_FIBRE;
239 			phylink_set(modes, 10000baseSR_Full);
240 			__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
241 		}
242 		if (id->com_10g_code & TXGBE_SFF_10GBASELR_CAPABLE) {
243 			txgbe->link_port = PORT_FIBRE;
244 			phylink_set(modes, 10000baseLR_Full);
245 			__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
246 		}
247 	}
248 
249 	if (phy_interface_empty(interfaces)) {
250 		wx_err(wx, "unsupported SFP module\n");
251 		return -EINVAL;
252 	}
253 
254 	phylink_set(modes, Pause);
255 	phylink_set(modes, Asym_Pause);
256 	phylink_set(modes, FIBRE);
257 
258 	if (!linkmode_equal(txgbe->link_support, modes)) {
259 		linkmode_copy(txgbe->link_support, modes);
260 		phy_interface_and(txgbe->link_interfaces,
261 				  wx->phylink_config.supported_interfaces,
262 				  interfaces);
263 		linkmode_copy(txgbe->advertising, modes);
264 
265 		set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags);
266 	}
267 
268 	return 0;
269 }
270 
271 static int txgbe_qsfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
272 {
273 	__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
274 	DECLARE_PHY_INTERFACE_MASK(interfaces);
275 	struct txgbe *txgbe = wx->priv;
276 
277 	if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) {
278 		txgbe->link_port = PORT_DA;
279 		phylink_set(modes, Autoneg);
280 		phylink_set(modes, 40000baseCR4_Full);
281 		phylink_set(modes, 10000baseCR_Full);
282 		__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
283 		__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
284 	}
285 	if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) {
286 		txgbe->link_port = PORT_FIBRE;
287 		phylink_set(modes, 40000baseSR4_Full);
288 		__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
289 	}
290 	if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) {
291 		txgbe->link_port = PORT_FIBRE;
292 		phylink_set(modes, 40000baseLR4_Full);
293 		__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
294 	}
295 	if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) {
296 		txgbe->link_port = PORT_DA;
297 		phylink_set(modes, Autoneg);
298 		phylink_set(modes, 40000baseCR4_Full);
299 		__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
300 	}
301 	if (id->transceiver_type & TXGBE_SFF_ETHERNET_RSRVD) {
302 		if (id->sff_opt1 & TXGBE_SFF_ETHERNET_100G_CR4) {
303 			txgbe->link_port = PORT_DA;
304 			phylink_set(modes, Autoneg);
305 			phylink_set(modes, 40000baseCR4_Full);
306 			phylink_set(modes, 25000baseCR_Full);
307 			phylink_set(modes, 10000baseCR_Full);
308 			__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
309 			__set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
310 			__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
311 		}
312 	}
313 
314 	if (phy_interface_empty(interfaces)) {
315 		wx_err(wx, "unsupported QSFP module\n");
316 		return -EINVAL;
317 	}
318 
319 	phylink_set(modes, Pause);
320 	phylink_set(modes, Asym_Pause);
321 	phylink_set(modes, FIBRE);
322 
323 	if (!linkmode_equal(txgbe->link_support, modes)) {
324 		linkmode_copy(txgbe->link_support, modes);
325 		phy_interface_and(txgbe->link_interfaces,
326 				  wx->phylink_config.supported_interfaces,
327 				  interfaces);
328 		linkmode_copy(txgbe->advertising, modes);
329 
330 		set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags);
331 	}
332 
333 	return 0;
334 }
335 
336 int txgbe_identify_module(struct wx *wx)
337 {
338 	struct txgbe_hic_get_module_info buffer;
339 	struct txgbe_sff_id *id;
340 	int err = 0;
341 	u32 mod_abs;
342 	u32 gpio;
343 
344 	if (wx->mac.type == wx_mac_aml40)
345 		mod_abs = TXGBE_GPIOBIT_4;
346 	else
347 		mod_abs = TXGBE_GPIOBIT_2;
348 
349 	gpio = rd32(wx, WX_GPIO_EXT);
350 	if (gpio & mod_abs)
351 		return -ENODEV;
352 
353 	err = txgbe_identify_module_hostif(wx, &buffer);
354 	if (err) {
355 		wx_err(wx, "Failed to identify module\n");
356 		return err;
357 	}
358 
359 	id = &buffer.id;
360 	if (id->identifier != TXGBE_SFF_IDENTIFIER_SFP &&
361 	    id->identifier != TXGBE_SFF_IDENTIFIER_QSFP &&
362 	    id->identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS &&
363 	    id->identifier != TXGBE_SFF_IDENTIFIER_QSFP28) {
364 		wx_err(wx, "Invalid module\n");
365 		return -ENODEV;
366 	}
367 
368 	if (id->transceiver_type == 0xFF)
369 		return txgbe_sfp_to_linkmodes(wx, id);
370 
371 	return txgbe_qsfp_to_linkmodes(wx, id);
372 }
373 
374 void txgbe_setup_link(struct wx *wx)
375 {
376 	struct txgbe *txgbe = wx->priv;
377 
378 	phy_interface_zero(txgbe->link_interfaces);
379 	linkmode_zero(txgbe->link_support);
380 
381 	set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags);
382 	wx_service_event_schedule(wx);
383 }
384 
385 static void txgbe_get_link_state(struct phylink_config *config,
386 				 struct phylink_link_state *state)
387 {
388 	struct wx *wx = phylink_to_wx(config);
389 	int speed;
390 
391 	txgbe_get_mac_link(wx, &speed);
392 	state->link = speed != SPEED_UNKNOWN;
393 	state->speed = speed;
394 	state->duplex = state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN;
395 }
396 
397 static void txgbe_reconfig_mac(struct wx *wx)
398 {
399 	u32 wdg, fc;
400 
401 	wdg = rd32(wx, WX_MAC_WDG_TIMEOUT);
402 	fc = rd32(wx, WX_MAC_RX_FLOW_CTRL);
403 
404 	wr32(wx, WX_MIS_RST, TXGBE_MIS_RST_MAC_RST(wx->bus.func));
405 	/* wait for MAC reset complete */
406 	usleep_range(1000, 1500);
407 
408 	wr32m(wx, TXGBE_MAC_MISC_CTL, TXGBE_MAC_MISC_CTL_LINK_STS_MOD,
409 	      TXGBE_MAC_MISC_CTL_LINK_BOTH);
410 	wx_reset_mac(wx);
411 
412 	wr32(wx, WX_MAC_WDG_TIMEOUT, wdg);
413 	wr32(wx, WX_MAC_RX_FLOW_CTRL, fc);
414 }
415 
416 static void txgbe_mac_link_up_aml(struct phylink_config *config,
417 				  struct phy_device *phy,
418 				  unsigned int mode,
419 				  phy_interface_t interface,
420 				  int speed, int duplex,
421 				  bool tx_pause, bool rx_pause)
422 {
423 	struct wx *wx = phylink_to_wx(config);
424 	u32 txcfg;
425 
426 	wx_fc_enable(wx, tx_pause, rx_pause);
427 
428 	txgbe_reconfig_mac(wx);
429 	txgbe_enable_sec_tx_path(wx);
430 
431 	txcfg = rd32(wx, TXGBE_AML_MAC_TX_CFG);
432 	txcfg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK;
433 
434 	switch (speed) {
435 	case SPEED_40000:
436 		txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_40G;
437 		break;
438 	case SPEED_25000:
439 		txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_25G;
440 		break;
441 	case SPEED_10000:
442 		txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_10G;
443 		break;
444 	default:
445 		break;
446 	}
447 
448 	wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE);
449 	wr32(wx, TXGBE_AML_MAC_TX_CFG, txcfg | TXGBE_AML_MAC_TX_CFG_TE);
450 
451 	wx->speed = speed;
452 	wx->last_rx_ptp_check = jiffies;
453 	if (test_bit(WX_STATE_PTP_RUNNING, wx->state))
454 		wx_ptp_reset_cyclecounter(wx);
455 	/* ping all the active vfs to let them know we are going up */
456 	wx_ping_all_vfs_with_link_status(wx, true);
457 }
458 
459 static void txgbe_mac_link_down_aml(struct phylink_config *config,
460 				    unsigned int mode,
461 				    phy_interface_t interface)
462 {
463 	struct wx *wx = phylink_to_wx(config);
464 
465 	wr32m(wx, TXGBE_AML_MAC_TX_CFG, TXGBE_AML_MAC_TX_CFG_TE, 0);
466 	wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, 0);
467 
468 	wx->speed = SPEED_UNKNOWN;
469 	if (test_bit(WX_STATE_PTP_RUNNING, wx->state))
470 		wx_ptp_reset_cyclecounter(wx);
471 	/* ping all the active vfs to let them know we are going down */
472 	wx_ping_all_vfs_with_link_status(wx, false);
473 }
474 
475 static void txgbe_mac_config_aml(struct phylink_config *config, unsigned int mode,
476 				 const struct phylink_link_state *state)
477 {
478 }
479 
480 static const struct phylink_mac_ops txgbe_mac_ops_aml = {
481 	.mac_config = txgbe_mac_config_aml,
482 	.mac_link_down = txgbe_mac_link_down_aml,
483 	.mac_link_up = txgbe_mac_link_up_aml,
484 };
485 
486 int txgbe_phylink_init_aml(struct txgbe *txgbe)
487 {
488 	struct phylink_link_state state;
489 	struct phylink_config *config;
490 	struct wx *wx = txgbe->wx;
491 	phy_interface_t phy_mode;
492 	struct phylink *phylink;
493 	int err;
494 
495 	config = &wx->phylink_config;
496 	config->dev = &wx->netdev->dev;
497 	config->type = PHYLINK_NETDEV;
498 	config->mac_capabilities = MAC_25000FD | MAC_10000FD |
499 				   MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
500 	config->get_fixed_state = txgbe_get_link_state;
501 
502 	if (wx->mac.type == wx_mac_aml40) {
503 		config->mac_capabilities |= MAC_40000FD;
504 		phy_mode = PHY_INTERFACE_MODE_XLGMII;
505 		__set_bit(PHY_INTERFACE_MODE_XLGMII, config->supported_interfaces);
506 		state.speed = SPEED_40000;
507 		state.duplex = DUPLEX_FULL;
508 	} else {
509 		phy_mode = PHY_INTERFACE_MODE_25GBASER;
510 		state.speed = SPEED_25000;
511 		state.duplex = DUPLEX_FULL;
512 	}
513 
514 	__set_bit(PHY_INTERFACE_MODE_25GBASER, config->supported_interfaces);
515 	__set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
516 
517 	phylink = phylink_create(config, NULL, phy_mode, &txgbe_mac_ops_aml);
518 	if (IS_ERR(phylink))
519 		return PTR_ERR(phylink);
520 
521 	err = phylink_set_fixed_link(phylink, &state);
522 	if (err) {
523 		wx_err(wx, "Failed to set fixed link\n");
524 		return err;
525 	}
526 
527 	wx->phylink = phylink;
528 
529 	return 0;
530 }
531