port: add a cable test command

"port <port> cabletest" runs the cable diagnostic of the copper PHYs
and reports one line per pair: ok, or open, short, short to another
pair or impedance mismatch with the distance to the fault.

The PHY part follows the cable_test_start and cable_test_get_status
ops of the Linux phy_driver and takes the port number:
rtl_phy_cable_test_start() triggers the test and
rtl_phy_cable_test_get_status() returns true once all four pairs are
done, with a result code and a length per pair. The decode order is
the one of the Linux driver. The same two functions drive the RTL8224
and the internal PHYs of the RTL8372 and RTL8373.

The command only powers the port down and returns. A state machine
called from handle_tick() calls the start op after one second, polls
the status op, stores the result, clears the trigger, also after a
timeout, and restores the control register, so the main loop never
waits. The result is printed when it is ready and "port <port>
cabletest show" prints it again. One test runs at a time.

The result flags are the low byte of the per-pair status word. The
vendor code reads the high byte, which is always zero on the RTL8373.

A link partner that keeps transmitting makes the PHY report an
inter-pair short on every pair, and forcing the speed with
autonegotiation off, as the Linux driver does, does not take the link
down. The port is therefore powered down for a second before the
test. The control register is restored afterwards with an
autonegotiation restart, so speed settings survive and the link
returns.

A test started on a port that is switched off never finishes and
leaves the PHY unusable until the switch is reset, so such a port is
refused, and a test is dropped if the port is switched off during the
wait. SFP ports are refused by the existing check. The external copper
PHYs of the RTL8372 boards are refused because the test has not been
run on one.

The distance is the raw length word minus 150, at 43 counts per 50 cm.
Fitted on open cables of 0.9 m, 2 m and 7.6 m; the pairs of one cable
differ by about 0.2 m. The Linux formula, raw minus 620 at 78 counts
per metre, gives 0, 0 and 2.4 m for these cables.

An unplugged port has no defined result: some pairs report open at
about 0.5 m and others a short or a mismatch at 2 to 3 m.
This commit is contained in:
bloqaudio committed 2026-10-14 12:42:27 -05:00
1 parent 8224b06f9e
commit 4050555667
5 files changed
+247

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
#ifndef _RTL837X_CABLETEST_H_
#define _RTL837X_CABLETEST_H_
#include <stdint.h>
#include <stdbool.h>
#define CABLE_RESULT_UNSPEC 0
#define CABLE_RESULT_OK 1
#define CABLE_RESULT_OPEN 2
#define CABLE_RESULT_SAME_SHORT 3
#define CABLE_RESULT_CROSS_SHORT 4
#define CABLE_RESULT_MISMATCH 5
void rtl_phy_cable_test_start(uint8_t port) __banked;
bool rtl_phy_cable_test_get_status(uint8_t port) __banked;
void cabletest_run(void) __banked;
void cabletest_show(void) __banked;
void cabletest_tick(void) __banked;
#endif