IPQ5018: Support for Linksys MX2000 Atlas 6 & MX5500 Atlas 6 Pro

Is QCA8337 connected to GMAC or is it connected via PHY-s in between?

as per my understanding:

IPQ50xx SOC has an integrated dummy switch with two GMACs (GMAC0, GMAC1), and the way they're connected is as follows:

IPQ50xx GMAC0 -> GE Phy7 ------------ Phy0 -> QCA8337 MAC1
IPQ50xx GMAC1 -> -------------- SGMII -------- -> QCA8337 MAC6 SerDes

and on the other side of QCA8337:
MAC2/phy1 -> WAN
MAC3/phy2 -> LAN1
MAC4/phy3 -> LAN2
MAC5/phy4 -> LAN3

mdio0 controls phy0 on IPQ50xx
mdio1 controls the phys on QCA8337

I'm not 100% sure whether the switches are properly connected.as the mdio command from mdio-tools shows the link is down on either side, but also not sure if it would ever show as UP either:

root@OpenWrt:/# mdio 9*       <-- mdio1 (for qca8337 phys) 
0x00  0x004dd036  down        <-- ID: #define F1V4_PHY 0x004DD036 (from SSDK)
0x01  0x004dd036  up          //WAN
0x02  0x004dd036  down        //LAN1
0x03  0x004dd036  down        //LAN2
0x04  0x004dd036  down        //LAN3


root@OpenWrt:/# mdio 8*    <--- mdio0 (for ipq50xx phys)
0x00  0x00000000  down
0x01  0x00000000  down
0x02  0x00000000  down
0x03  0x00000000  down
0x04  0x00000000  down
0x05  0x00000000  down
0x06  0x00000000  down
0x07  0x004dd0c0  down     <-- ID: #define MP_GEPHY 0x004DD0C0 (from SSDK )

the boot log shows the switches have initialized and have been reset.
Perhaps after initialization of the second switch, ipq50xx needs to be reset again?

Also, I had to comment out 'return -EFAULT' in nss_dp_main.c in qca-nss-dp because dp1 in stock does not specify a phy handle either (nor using the properties that were removed, using the patch I think you created)

dp_priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
	if (!dp_priv->phy_node) {
		pr_info("%s: no phy-handle specified\n", np->name);
		//return -EFAULT;

else it would error out if it can't find a phy-handle, and QCA8337 MAC6 mapped to the CPU is connected over SGMII to GMAC1 in ipq50xx

and this is the diagram for QCA8337

OK, so its similar to what they did with IPQ806x where 2 MAC-s on the switch are connected to increase the potential throughput.

The status interpretation via mdio command only works on ethernet C22 or C45 compliant PHY-s, for everything else its not valid.

Don’t know if they are, will check in the source to try and find out.
But if they are, should I explicitly add a compatible property to the ports under the switch definitions?

back to origins interesting...

@kirdes: I saw this post about resolving a reset issue. I'm looking into that direction now too, triggered by what I see in the boot log.

[    3.038354] ssdk_dt_parse_mac_mode[283]:INFO:mac mode1 doesn't exit!
[    3.038404] ssdk_dt_parse_mac_mode[291]:INFO:mac mode2 doesn't exit!
[    3.043994] ssdk_dt_parse_port_bmp[898]:INFO:port_bmp doesn't exist!
[    3.050215] ssdk_dt_parse_led[1095]:INFO:current dts led_source_num is 1
[    5.533055] ssdk_mp_reset_init[839]:INFO:MP reset successfully!
[    5.534596] mpge_phy_api_ops_init[1092]:INFO:qca probe mpge phy driver succeeded!
[    5.914064] _adpt_mp_uniphy_clk_output_ctrl_set[255]:INFO:uniphy will output clock as 25000000Hz
[    5.914256] ssdk_led_init[151]:INFO:ssdk_led_mode:3, ssdk_led_map:ffc, ssdk_led_src_id:0
[    5.924133] regi_init[4023]:INFO:Initializing SCOMPHY Done!!
[    5.930100] ssdk_dt_parse_mac_mode[275]:INFO:mac mode doesn't exit!
[    5.935696] ssdk_dt_parse_mac_mode[283]:INFO:mac mode1 doesn't exit!
[    5.941632] ssdk_dt_parse_mac_mode[291]:INFO:mac mode2 doesn't exit!
[    5.948300] ssdk_dt_parse[1223]:INFO:switch node is qca83xx!
[    6.026351] f1_phy_api_ops_init[1606]:INFO:qca probe f1 phy driver succeeded!
[    6.273032] qca_ar8327_gpio_reset[3892]:INFO:GPIO504 reset switch done
[    8.043035] regi_init[3963]:INFO:Initializing ISISC Done!!
[    8.043505] regi_init[4049]:INFO:qca-ssdk module init succeeded!
[    8.050537] dp2: error parsing phy-handle
[    8.053745] GMAC2(ffffff8003b90900) Invalid MAC@ - using 62:90:43:c7:48:72
[    8.060231] eth0: Registered netdev eth0(qcom-id:2)
[    8.064776] **********************************************************
[    8.069043] * NSS Data Plane driver
[    8.075682] **********************************************************

Stock DTS mentions the reset gpio of the external qca83xx switch is 39.
When I set the reset_gpio to <&tlmm 39 GPIO_ACTIVE_HIGH>, the bootlog shows GPIO504 (no idea where it gets that gpio number from).
When I set it to a decimal or hex value only (SSDK accepts that as a fallback), it shows:

[    6.026215] f1_phy_api_ops_init[1606]:INFO:qca probe f1 phy driver succeeded!
[    6.026273] OF: /soc@0/ess-instance/ess-switch1@1: could not get #gpio-cells for /reserved-memory/q6_mem_regions@4b000000
[    6.032347] qca_ar8327_gpio_reset[3885]:ERROR:gpio39 request failed, ret:-517
[    7.804342] regi_init[3963]:INFO:Initializing ISISC Done!!
[    7.804819] regi_init[4049]:INFO:qca-ssdk module init succeeded!

also notice the #gpio-cells mention relative to /reserved-memory/q6_mem_regions@4b000000

I've added compatible properties for the PHYs:

&mdio0 {
	status = "okay";

	resets = <&gcc GCC_GEPHY_MDC_SW_ARES>;
	reset-names = "gephy_mdc_rst";

	//IPQ5018 GE Phy -> QCA8337 Phy0
	ipq5018_0: ethernet-phy@0 {
		compatible = "ethernet-phy-id004d.d0c0";
		reg = <7>;

&mdio1 {
	status = "okay";

	pinctrl-0 = <&mdio1_pins>;
	pinctrl-names = "default";
	phy-reset-gpio = <&tlmm 39 GPIO_ACTIVE_HIGH>;

	// QCA8337 Phy0 -> IPQ5018 GE Phy
	qca8337_0: ethernet-phy@0 {
		compatible = "ethernet-phy-id004d.d036";
		reg = <0>;

	// QCA8337 Phy1 -> WAN
	qca8337_1: ethernet-phy@1 {
		reg = <1>;

	// QCA8337 Phy2 -> LAN1
	qca8337_2: ethernet-phy@2 {
		reg = <2>;

	// QCA8337 Phy3 -> LAN2
	qca8337_3: ethernet-phy@3 {
		reg = <3>;

	// QCA8337 Phy4 -> LAN3
	qca8337_4: ethernet-phy@4 {
		reg = <4>;

Have you got any ideas?

Don't rely to much on the stock DTS....it's better to look in the ipq 5.4 kernel repo:

mp03.1 should be the right model.

Why are u using GPIO_ACTIVE_HIGH for the reset? I'm pretty sure it's ACTIVE_LOW.

Furthermore remove the resets and reset-names properties from the mdio0 node.

In addition there seems to be a problem mit the DP2:

dp2: error parsing phy-handle

The resets for mdio0 are defined in ipq5018.dtsi [here.(https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4.r1/arch/arm64/boot/dts/qcom/ipq5018.dtsi#L153)

I’ll change the reset gpios back to ACTIVE_LOW.

On the phy-handle, there’s a patch that introduces using a phy-handle in nss-dp but it does so with returning an error if the property is not set.
I’ve commented the return statement out for it to continue as the dp for GMAC1 doesn’t use a PHY but SGMII instead.

Will report back tomorrow on status. Thanks so far!
And do you idea why the wrong gpio is being used (504 instead of 39)?

cat /sys/class/gpio/*/base should print 465 according to what you see.

1 Like

you're right, thanks! the base is 465 so that makes sense now.

changed back to ACTIVE_LOW, removed the reset properties, still no luck though.
pinging eth0 from the router terminal works, but no connection to any externally connected device when a cable is plugged in (although, mdio does detect the link status correctly).

Well, controlplane seems to be fine, you are missing a py-handle property on the dp2 node.
Is that intentional?
I think you need a phy-handle to qca8337_0

I tried both with a phy-handle and without. the stock DTS only uses 1 dp without any phy-handle or any of the 'older' proprties (qcom,link-poll, mdio-bus, etc.).

this is the stock dp node:

dp1 {
    device_type = "network";
    compatible = "qcom,nss-dp";
    clocks = <0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x71>;
    clock-names = "nss-snoc-gmac-axi-clk";
    qcom,id = <0x00 0x00 0x00 0x02>;
    reg = <0x39 0xD0 0x00 0x00 0x00 0x01 0x00 0x00>;
    interrupts = <0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x6D 0x00 0x00 0x00 0x04>;
    qcom,mactype = <0x00 0x00 0x00 0x02>;
    local-mac-address = <0x00 0x00 0x00 0x00 0x00 0x00>;
    phy-mode = "sgmii";

this is supposed to connect GMAC1 on the ipq50xx switch to PORT6 over SGMII on the switch which is the CPU port. The ports on the qca8337 are mapped as follows:

switch_cpu_bmp = <0x40>;  	/* cpu port bitmap: port 6 */
switch_lan_bmp = <0x38>; 	/* lan port bitmap: port 3 4 5 */
switch_wan_bmp = <0x04>;  	/* wan port bitmap: port 2 */

Something is weird in this dp node.
AFAIK angle brackets define cells (=32-bit ints), not single bytes.

That is from a decompiled stock dtb.

This is the dp2 node he is actual using:

1 Like

I wonder if the GMAC0 is even physically connected. I switched to 5.15 with swconfig and I can see that the PORT0 and PORT6 links on the qca8337 switch are up (which are connected to CPU through GMAC1, see diagram above):

root@OpenWrt:/# swconfig dev switch1 show | grep link
        link: port:0 link:up speed:1000baseT full-duplex    /* PORT0 -> CPU */
        link: port:1 link:down
        link: port:2 link:down
        link: port:3 link:down
        link: port:4 link:down
        link: port:5 link:up speed:1000baseT full-duplex txflow rxflow
        link: port:6 link:up speed:1000baseT full-duplex    /* PORT6 -> CPU */

even if I create a DP for GMAC0, mdio status always shows that the link between Phy7 on GMAC0 and Phy0 (PORT1) on QCA8337 are DOWN. I've also tried using the downstream qca-mdio driver but that didn't make any difference. Again, making me wonder if they're at all physically connected.

Anyway, so we have at least confirmed that the link is established between GMAC1 and the qca8337 switch. The problem remains that I can't get traffic through any of the ports.
If I ping from the router itself, the traffic counters update on the loopback device (lo), but not on eth0.

What should I look into next?

And does anyone know where Linksys has its default network config stored in stock firmware?

update: switch is working now, it was a config issue. Apparently it expects vlan 1 and 2 to be enabled and CPU traffic tagged on port 6.
It works on 5.15 with swconfig. Tried to enable in 6.1 but swconfig can't connect to the switches (enabled swconfig in kernel_menuconfig and menuconfig as a package), but receive this at boot time:

Failed to connect to the switch. Use the "list" command to see which switches are available.
Failed to connect to the switch. Use the "list" command to see which switches are available.
Failed to connect to the switch. Use the "list" command to see which switches are available.
Failed to connect to the switch. Use the "list" command to see which switches are available.

then swconfig list shows no entries. Any idea?

Hi, this is hzyitc, the author of https://github.com/hzyitc/openwrt-redmi-ax3000.

Here are some parts of the email I reply to @georgem83. I think this will help someone who are trying to support new ipq50xx device.


There are some points you may need to care about:

  1. The QCA8337 driver in kernel doesn't support multi CPU ports
  2. The QCA8337 driver in kernel doesn't support to use MAC0-5 as CPU
    port. But I think just a tiny patch can fix it.
  3. If you want to use the QCA8337 driver in QCA-SSDK, please disable
    the driver in kernel.
  4. The QCA8337 driver in QCA-SSDK doesn't support DSA, so we need to
    use swconfig.
  5. qca-nss-dp of IPQ5018 use phylib instand of phylink. This is why I
    roll back the netifd. This also led to no DSA support.

If you just want to let your device supported, you can fork my repo. But
due to Point5 (netifd need to be rolled back), it can't be merged to offical Openwrt.


thanks for your help so far @hzyitc.

On point 5, how do you disable netifd to get swconfig working? EDIT: never mind, you rolled it back to a previous verion, will try..

And I saw this commit for DSA support.
Will give it a try..