qca-ssdk: fix unsupported scenario with PORT1 not declared in switch bmp
[openwrt/staging/hauke.git] / package / kernel / qca-ssdk / patches / 100-malibu-phy-add-support-for-manual-define-of-first-ph.patch
1 From a651d10fbd880098d7b98dee27dfd1eb15146fb2 Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Sun, 12 Nov 2023 18:40:22 +0100
4 Subject: [PATCH] malibu-phy: add support for manual define of first phy addr
5
6 The usage of first_phy_addr is EXTREMELY FRAGILE and results
7 in dangerous results if the OEM (or anyone that by chance try to
8 implement things in a logical manner) deviates from the default values
9 from the "magical template".
10
11 To be in more details. With QSDK 12.4, some tweaks were done to improve
12 autoneg and now on every call of port status, the phydev is tried to
13 add. This resulted in the call and log spam of an error with ports that
14 are actually not present on the system with qsdk reporting phydev is
15 NULL. This itself is not an error and printing the error is correct.
16
17 What is actually an error from ages is setting generic bitmap reporting
18 presence of port that are actually not present. This is very common on
19 OEM where the switch_lan_bmp is always a variant of 0x1e (that on bitmap
20 results in PORT1 PORT2 PORT3 PORT4 present) or 0x3e (PORT1 PORT2 PORT3
21 PORT4 PORT5). Reality is that many device are used as AP with one LAN
22 port or one WAN port. (or even exotic configuration with PORT1 not
23 present and PORT2 PORT3 PORT4 present (Xiaomi 3600)
24
25 With this finding one can say... ok nice, then lets update the DT and
26 set the correct bitmap...
27
28 Again world is a bad place and reality is that this cause wonderful
29 regression in some case of by extreme luck the first ever connected
30 port working and the rest of the switch dead.
31
32 The problem has been bisected to all the device that doesn't have the
33 PORT1 declared in any of the bitmap.
34
35 With this prefaction in mind, on to the REAL problem.
36
37 malibu_phy_hw_init FOR SOME REASON, set a global variable first_phy_addr
38 to the first detected PHY addr that coincidentally is always PORT1.
39 PORT1 addr is 0x0. The entire code in malibu_phy use this variable to
40 derive the phy addrs in some function.
41
42 Declaring a bitmap where the PORT1 is missing (or worse PORT4 the only
43 one connected) result in first_phy_addr set to 1 or whatever phy addr is
44 detected first setting wrong value all over the init stage.
45
46 To fix this, introduce a new binding malibu_first_phy_addr to manually
47 declare the first phy that the malibu PHY driver should use and permit
48 to detach it from port bmp detection. The legacy detection is kept for
49 compatibility reason.
50
51 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
52 ---
53 include/init/ssdk_dts.h | 1 +
54 include/init/ssdk_init.h | 2 ++
55 src/hsl/phy/malibu_phy.c | 5 +++++
56 src/init/ssdk_dts.c | 15 +++++++++++++++
57 4 files changed, 23 insertions(+)
58
59 --- a/include/init/ssdk_dts.h
60 +++ b/include/init/ssdk_dts.h
61 @@ -146,6 +146,7 @@ a_uint32_t ssdk_wan_bmp_get(a_uint32_t d
62 sw_error_t ssdk_lan_bmp_set(a_uint32_t dev_id, a_uint32_t lan_bmp);
63 sw_error_t ssdk_wan_bmp_set(a_uint32_t dev_id, a_uint32_t wan_bmp);
64 a_uint32_t ssdk_inner_bmp_get(a_uint32_t dev_id);
65 +a_uint32_t ssdk_malibu_first_phy_addr_get(a_uint32_t dev_id);
66 hsl_reg_mode ssdk_switch_reg_access_mode_get(a_uint32_t dev_id);
67 void ssdk_switch_reg_map_info_get(a_uint32_t dev_id, ssdk_reg_map_info *info);
68 a_uint32_t ssdk_switch_pcie_base_get(a_uint32_t dev_id);
69 --- a/include/init/ssdk_init.h
70 +++ b/include/init/ssdk_init.h
71 @@ -194,6 +194,7 @@ enum ssdk_port_wrapper_cfg {
72 a_uint32_t lan_bmp;
73 a_uint32_t wan_bmp;
74 a_uint32_t inner_bmp;
75 + a_uint32_t malibu_first_phy_addr;
76 } ssdk_port_cfg;
77
78 typedef struct
79 @@ -384,6 +385,7 @@ ssdk_hsl_access_mode_set(a_uint32_t dev_
80
81 a_uint32_t ssdk_dt_global_get_mac_mode(a_uint32_t dev_id, a_uint32_t index);
82 a_uint32_t ssdk_dt_global_set_mac_mode(a_uint32_t dev_id, a_uint32_t index, a_uint32_t mode);
83 +a_uint32_t ssdk_malibu_first_phy_addr_get(a_uint32_t dev_id);
84
85 a_uint32_t
86 qca_hppe_port_mac_type_get(a_uint32_t dev_id, a_uint32_t port_id);
87 --- a/src/hsl/phy/malibu_phy.c
88 +++ b/src/hsl/phy/malibu_phy.c
89 @@ -1945,6 +1945,11 @@ static int malibu_phy_api_ops_init(void)
90 int malibu_phy_init(a_uint32_t dev_id, a_uint32_t port_bmp)
91 {
92 static a_uint32_t phy_ops_flag = 0;
93 + a_uint32_t malibu_first_phy_addr;
94 +
95 + malibu_first_phy_addr = ssdk_malibu_first_phy_addr_get(dev_id);
96 + if (malibu_first_phy_addr != MAX_PHY_ADDR)
97 + first_phy_addr = malibu_first_phy_addr;
98
99 if(phy_ops_flag == 0) {
100 malibu_phy_api_ops_init();
101 --- a/src/init/ssdk_dts.c
102 +++ b/src/init/ssdk_dts.c
103 @@ -186,6 +186,13 @@ a_uint32_t ssdk_inner_bmp_get(a_uint32_t
104 return cfg->port_cfg.inner_bmp;
105 }
106
107 +a_uint32_t ssdk_malibu_first_phy_addr_get(a_uint32_t dev_id)
108 +{
109 + ssdk_dt_cfg* cfg = ssdk_dt_global.ssdk_dt_switch_nodes[dev_id];
110 +
111 + return cfg->port_cfg.malibu_first_phy_addr;
112 +}
113 +
114 hsl_reg_mode ssdk_switch_reg_access_mode_get(a_uint32_t dev_id)
115 {
116 ssdk_dt_cfg* cfg = ssdk_dt_global.ssdk_dt_switch_nodes[dev_id];
117 @@ -1039,6 +1046,14 @@ static void ssdk_dt_parse_port_bmp(a_uin
118 cfg->port_cfg.inner_bmp;
119 }
120
121 + /* Permit to manually declare start phy addr for malibu PHY. If not found set to legacy detection. */
122 + if (!of_property_read_u32(switch_node, "malibu_first_phy_addr", &cfg->port_cfg.malibu_first_phy_addr)) {
123 + ssdk_dt_global.ssdk_dt_switch_nodes[dev_id]->port_cfg.malibu_first_phy_addr =
124 + cfg->port_cfg.malibu_first_phy_addr;
125 + } else {
126 + ssdk_dt_global.ssdk_dt_switch_nodes[dev_id]->port_cfg.malibu_first_phy_addr = MAX_PHY_ADDR;
127 + }
128 +
129 ssdk_dt_global.ssdk_dt_switch_nodes[dev_id]->port_cfg.cpu_bmp = cfg->port_cfg.cpu_bmp;
130 ssdk_dt_global.ssdk_dt_switch_nodes[dev_id]->port_cfg.lan_bmp = cfg->port_cfg.lan_bmp;
131 ssdk_dt_global.ssdk_dt_switch_nodes[dev_id]->port_cfg.wan_bmp = cfg->port_cfg.wan_bmp;