octeon: force pcs reset to fix qca833x traffic
There is a known bug with qca833x switches where they fail to pass traffic without first resetting the PCS. U-Boot already has this fix, though it uses a much newer networking stack from Marvell. This commit backports the fix for OpenWrt. References: - https://github.com/u-boot/u-boot/blob/master/arch/mips/mach-octeon/cvmx-helper-sgmii.c#L197-L225 - https://github.com/u-boot/u-boot/blob/master/arch/mips/mach-octeon/cvmx-helper-sgmii.c#L701-L737 Signed-off-by: Andrew LaMarche <andrewjlamarche@gmail.com> Link: https://github.com/openwrt/openwrt/pull/18385 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
e37ad78539
commit
ce1991cd64
@ -0,0 +1,123 @@
|
||||
From: Andrew LaMarche <andrewjlamarche@gmail.com>
|
||||
Date: Mon, 31 Mar 2025 13:00:00 +0000
|
||||
Subject: [PATCH] octeon: force pcs reset
|
||||
|
||||
QCA833x devices misbehave with SGMII until a PCS reset is triggered. U-boot has
|
||||
a newer vendor GPL dump that contains logic to reset the PCS. This patch
|
||||
backports that functionality so that Octeon devices with QCA833{4/7} switchs
|
||||
pass traffic between the switch and CPU.
|
||||
|
||||
References:
|
||||
- https://github.com/u-boot/u-boot/blob/master/arch/mips/mach-octeon/cvmx-helper-sgmii.c#L197-L225
|
||||
- https://github.com/u-boot/u-boot/blob/master/arch/mips/mach-octeon/cvmx-helper-sgmii.c#L701-L737
|
||||
|
||||
Signed-off-by: Andrew LaMarche <andrewjlamarche@gmail.com>
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c
|
||||
@@ -125,6 +125,17 @@ static int __cvmx_helper_sgmii_hardware_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __cvmx_helper_need_g15618(void)
|
||||
+{
|
||||
+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM ||
|
||||
+ OCTEON_IS_MODEL(OCTEON_CN63XX) ||
|
||||
+ OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X) ||
|
||||
+ OCTEON_IS_MODEL(OCTEON_CN68XX))
|
||||
+ return 1;
|
||||
+ else
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* Initialize the SERTES link for the first time or after a loss
|
||||
* of link.
|
||||
@@ -172,6 +183,39 @@ static int __cvmx_helper_sgmii_hardware_
|
||||
cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
|
||||
control_reg.u64);
|
||||
|
||||
+ /* Force a PCS reset by powering down the PCS interface
|
||||
+ * This is needed to deal with broken Qualcomm/Atheros PHYs and switches
|
||||
+ * which never recover if PCS is not power cycled. The alternative
|
||||
+ * is to power cycle or hardware reset the Qualcomm devices whenever
|
||||
+ * SGMII is initialized.
|
||||
+ *
|
||||
+ * This is needed for the QCA8033 PHYs as well as the QCA833X switches
|
||||
+ * to work. The QCA8337 switch has additional SGMII problems and is
|
||||
+ * best avoided if at all possible. Failure to power cycle PCS prevents
|
||||
+ * any traffic from flowing between Octeon and Qualcomm devices if there
|
||||
+ * is a warm reset. Even a software reset to the Qualcomm device will
|
||||
+ * not work.
|
||||
+ *
|
||||
+ * Note that this problem has been reported between Qualcomm and other
|
||||
+ * vendor's processors as well so this problem is not unique to
|
||||
+ * Qualcomm and Octeon.
|
||||
+ *
|
||||
+ * Power cycling PCS doesn't hurt anything with non-Qualcomm devices
|
||||
+ * other than adding a 25ms delay during initialization.
|
||||
+ */
|
||||
+ control_reg.s.pwr_dn = 1;
|
||||
+ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
|
||||
+ control_reg.u64);
|
||||
+ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
|
||||
+
|
||||
+ if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
|
||||
+ /* 25ms should be enough, 10ms is too short */
|
||||
+ mdelay(25);
|
||||
+
|
||||
+ control_reg.s.pwr_dn = 0;
|
||||
+ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
|
||||
+ control_reg.u64);
|
||||
+
|
||||
/*
|
||||
* Wait for PCS*_MR*_STATUS_REG[AN_CPT] to be set, indicating
|
||||
* that sgmii autonegotiation is complete. In MAC mode this
|
||||
@@ -507,9 +551,47 @@ union cvmx_helper_link_info __cvmx_helpe
|
||||
int __cvmx_helper_sgmii_link_set(int ipd_port,
|
||||
union cvmx_helper_link_info link_info)
|
||||
{
|
||||
+ union cvmx_pcsx_mrx_control_reg control_reg;
|
||||
int interface = cvmx_helper_get_interface_num(ipd_port);
|
||||
int index = cvmx_helper_get_interface_index_num(ipd_port);
|
||||
- __cvmx_helper_sgmii_hardware_init_link(interface, index);
|
||||
+
|
||||
+ /* For some devices, i.e. the Qualcomm QCA8337 switch we need to power
|
||||
+ * down the PCS interface when the link goes down and power it back
|
||||
+ * up when the link returns.
|
||||
+ */
|
||||
+ if (link_info.s.link_up || !__cvmx_helper_need_g15618()) {
|
||||
+ __cvmx_helper_sgmii_hardware_init_link(interface, index);
|
||||
+ } else {
|
||||
+ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
|
||||
+
|
||||
+ pcsx_miscx_ctl_reg.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
|
||||
+
|
||||
+ /* Disable autonegotiation when MAC mode is enabled or
|
||||
+ * autonegotiation is disabled.
|
||||
+ */
|
||||
+ control_reg.u64 = cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
|
||||
+ if (pcsx_miscx_ctl_reg.s.mac_phy == 0 ||
|
||||
+ !cvmx_read_csr(CVMX_PCSX_ANX_RESULTS_REG(index, interface))) {
|
||||
+
|
||||
+ control_reg.s.an_en = 0;
|
||||
+ control_reg.s.spdmsb = 1;
|
||||
+ control_reg.s.spdlsb = 0;
|
||||
+ control_reg.s.dup = 1;
|
||||
+
|
||||
+ }
|
||||
+ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
|
||||
+ control_reg.u64);
|
||||
+ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
|
||||
+ /*
|
||||
+ * Use GMXENO to force the link down it will get
|
||||
+ * reenabled later...
|
||||
+ */
|
||||
+ pcsx_miscx_ctl_reg.s.gmxeno = 1;
|
||||
+ cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
|
||||
+ pcsx_miscx_ctl_reg.u64);
|
||||
+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
|
||||
+ return 0;
|
||||
+ }
|
||||
return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index,
|
||||
link_info);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user