Merge tag 'mips-pull-2019-04-12' of git://git.denx.de/u-boot-mips
authorTom Rini <trini@konsulko.com>
Sat, 13 Apr 2019 12:27:26 +0000 (08:27 -0400)
committerTom Rini <trini@konsulko.com>
Sat, 13 Apr 2019 12:27:26 +0000 (08:27 -0400)
- mt76xx: add USB support, small fixes
- ath79: small fixes, add support for QCA9563 SoC and AP152 reference board
- mscc: small fixes, add network support for JR2 and ServalT SoCs
- bmips: small fixes, enable more drivers for ARM specific BCM6858 and BCM63158 SoCs
- MIPS: fix redundant relocation of initrd images

61 files changed:
arch/arm/dts/bcm63158.dtsi
arch/arm/dts/bcm6858.dtsi
arch/arm/dts/bcm963158.dts
arch/arm/dts/bcm968580xref.dts
arch/arm/include/asm/gpio.h
arch/mips/dts/Makefile
arch/mips/dts/ap143.dts
arch/mips/dts/ap152.dts [new file with mode: 0644]
arch/mips/dts/brcm,bcm6838.dtsi
arch/mips/dts/brcm,bcm968380gerg.dts
arch/mips/dts/gardena-smart-gateway-mt7688.dts
arch/mips/dts/jr2_pcb110.dts
arch/mips/dts/jr2_pcb111.dts
arch/mips/dts/mscc,jr2.dtsi
arch/mips/dts/mscc,servalt.dtsi
arch/mips/dts/qca953x.dtsi
arch/mips/dts/qca956x.dtsi [new file with mode: 0644]
arch/mips/dts/serval2_pcb112.dts
arch/mips/dts/servalt_pcb116.dts
arch/mips/lib/bootm.c
arch/mips/mach-ath79/Kconfig
arch/mips/mach-ath79/Makefile
arch/mips/mach-ath79/include/mach/ar71xx_regs.h
arch/mips/mach-ath79/include/mach/ath79.h
arch/mips/mach-ath79/qca956x/Makefile [new file with mode: 0644]
arch/mips/mach-ath79/qca956x/clk.c [new file with mode: 0644]
arch/mips/mach-ath79/qca956x/cpu.c [new file with mode: 0644]
arch/mips/mach-ath79/qca956x/ddr.c [new file with mode: 0644]
arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S [new file with mode: 0644]
arch/mips/mach-ath79/reset.c
arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h
arch/mips/mach-mt7620/Kconfig
board/mscc/jr2/jr2.c
board/qca/ap152/Kconfig [new file with mode: 0644]
board/qca/ap152/MAINTAINERS [new file with mode: 0644]
board/qca/ap152/Makefile [new file with mode: 0644]
board/qca/ap152/ap152.c [new file with mode: 0644]
configs/ap152_defconfig [new file with mode: 0644]
configs/bcm963158_ram_defconfig
configs/bcm968380gerg_ram_defconfig
configs/bcm968580xref_ram_defconfig
configs/linkit-smart-7688-ram_defconfig
configs/linkit-smart-7688_defconfig
configs/mscc_jr2_defconfig
configs/mscc_servalt_defconfig
drivers/dma/bcm6348-iudma.c
drivers/gpio/Kconfig
drivers/gpio/bcm6345_gpio.c
drivers/net/ag7xxx.c
drivers/net/mscc_eswitch/Kconfig
drivers/net/mscc_eswitch/Makefile
drivers/net/mscc_eswitch/jr2_switch.c [new file with mode: 0644]
drivers/net/mscc_eswitch/ocelot_switch.c
drivers/net/mscc_eswitch/servalt_switch.c [new file with mode: 0644]
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/mt76x8-usb-phy.c [new file with mode: 0644]
drivers/pinctrl/ath79/Makefile
include/configs/ap152.h [new file with mode: 0644]
include/configs/vcoreiii.h
include/dt-bindings/mscc/jr2_data.h [new file with mode: 0644]

index 6a3fbc90939b22cdba221b1d601293fce511e453..4f41f6273872c2f228c4f2c6af42f62e64fe0d1a 100644 (file)
                        compatible = "wdt-reboot";
                        wdt = <&wdt1>;
                };
+
+               gpio0: gpio-controller@0xff800500 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800500 0x0 0x4>,
+                             <0x0 0xff800520 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio1: gpio-controller@0xff800504 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800504 0x0 0x4>,
+                             <0x0 0xff800524 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio2: gpio-controller@0xff800508 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800508 0x0 0x4>,
+                             <0x0 0xff800528 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio3: gpio-controller@0xff80050c {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff80050c 0x0 0x4>,
+                             <0x0 0xff80052c 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio4: gpio-controller@0xff800510 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800510 0x0 0x4>,
+                             <0x0 0xff800530 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio5: gpio-controller@0xff800514 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800514 0x0 0x4>,
+                             <0x0 0xff800534 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio6: gpio-controller@0xff800518 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800518 0x0 0x4>,
+                             <0x0 0xff800538 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio7: gpio-controller@0xff80051c {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff80051c 0x0 0x4>,
+                             <0x0 0xff80053c 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
        };
 };
index 23b80c67a64a6db77569c86851220693a0c736bc..5d5e64db0812ff0c0caf190976cd62c778fefc26 100644 (file)
                        compatible = "wdt-reboot";
                        wdt = <&wdt1>;
                };
+
+               gpio0: gpio-controller@0xff800500 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800500 0x0 0x4>,
+                             <0x0 0xff800520 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio1: gpio-controller@0xff800504 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800504 0x0 0x4>,
+                             <0x0 0xff800524 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio2: gpio-controller@0xff800508 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800508 0x0 0x4>,
+                             <0x0 0xff800528 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio3: gpio-controller@0xff80050c {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff80050c 0x0 0x4>,
+                             <0x0 0xff80052c 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio4: gpio-controller@0xff800510 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800510 0x0 0x4>,
+                             <0x0 0xff800530 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio5: gpio-controller@0xff800514 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800514 0x0 0x4>,
+                             <0x0 0xff800534 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio6: gpio-controller@0xff800518 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff800518 0x0 0x4>,
+                             <0x0 0xff800538 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio7: gpio-controller@0xff80051c {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x0 0xff80051c 0x0 0x4>,
+                             <0x0 0xff80053c 0x0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
        };
 };
index dc5afb5a24afa4641891f421266ff841c7cf09ea..b5c825b052bc3181de2634d8729acc55f15a716d 100644 (file)
        u-boot,dm-pre-reloc;
        status = "okay";
 };
+
+&gpio0 {
+       status = "okay";
+};
+
+&gpio1 {
+       status = "okay";
+};
+
+&gpio2 {
+       status = "okay";
+};
+
+&gpio3 {
+       status = "okay";
+};
+
+&gpio4 {
+       status = "okay";
+};
+
+&gpio5 {
+       status = "okay";
+};
+
+&gpio6 {
+       status = "okay";
+};
+
+&gpio7 {
+       status = "okay";
+};
index 0c59f94710c97925d9e05b6390c42be3f80d3a5f..15febb030f11f9e1c384399905f95fab454335b5 100644 (file)
        u-boot,dm-pre-reloc;
        status = "okay";
 };
+
+&gpio0 {
+       status = "okay";
+};
+
+&gpio1 {
+       status = "okay";
+};
+
+&gpio2 {
+       status = "okay";
+};
+
+&gpio3 {
+       status = "okay";
+};
+
+&gpio4 {
+       status = "okay";
+};
+
+&gpio5 {
+       status = "okay";
+};
+
+&gpio6 {
+       status = "okay";
+};
+
+&gpio7 {
+       status = "okay";
+};
index 3039e66bf9f2250117d075667a3f3dea5f108607..992a84152cfae333edd0606912e6e1533276714b 100644 (file)
@@ -1,5 +1,6 @@
 #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \
-       !defined(CONFIG_ARCH_K3)
+       !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \
+       !defined(CONFIG_ARCH_BCM63158)
 #include <asm/arch/gpio.h>
 #endif
 #include <asm-generic/gpio.h>
index 665d3cc8c1ca71d81aaebfdfa9a5513a317c4fd3..3522e6cdc82e5662424569a471d3202a11ce082f 100644 (file)
@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_MT7620) += \
        linkit-smart-7688.dtb
 dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
 dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
+dtb-$(CONFIG_TARGET_AP152) += ap152.dtb
 dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb
 dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb
 dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
index 6aedd87db9a85595f00f3c701f51c9094da2c1d3..2e23225f12921ac355bf3ce27bf3e265f8c110ff 100644 (file)
@@ -40,3 +40,8 @@
                reg = <0>;
        };
 };
+
+&gmac1 {
+       status = "okay";
+       phy-mode = "rgmii";
+};
diff --git a/arch/mips/dts/ap152.dts b/arch/mips/dts/ap152.dts
new file mode 100644 (file)
index 0000000..1722290
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+/dts-v1/;
+#include "qca956x.dtsi"
+
+/ {
+       model = "AP152 Reference Board";
+       compatible = "qca,ap152", "qca,qca956x";
+
+       aliases {
+               spi0 = &spi0;
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&gmac0 {
+       phy-mode = "sgmii";
+       status = "okay";
+};
+
+&xtal {
+       clock-frequency = <25000000>;
+};
+
+&uart0 {
+       clock-frequency = <25000000>;
+       status = "okay";
+};
+
+&spi0 {
+       spi-max-frequency = <25000000>;
+       status = "okay";
+       spi-flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spi-flash";
+               memory-map = <0x9f000000 0x01000000>;
+               spi-max-frequency = <25000000>;
+               reg = <0>;
+       };
+};
index b6f95591476d8ac32901d4ad258dc92948130300..c060802e8a450bf0085ad75610b67a02c0b2e8c1 100644 (file)
 
                        status = "disabled";
                };
+
+               gpio_lo: gpio-controller@14e00100 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x14e00100 0x4>, <0x14e0012c 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio_mid0: gpio-controller@14e00104 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x14e00104 0x4>, <0x14e00130 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
+
+               gpio_mid1: gpio-controller@14e00108 {
+                       compatible = "brcm,bcm6345-gpio";
+                       reg = <0x14e00108 0x4>, <0x14e00134 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       status = "disabled";
+               };
        };
 };
index 513045ee0519d81c28dda66da06c99a478d8c65a..98471e3894de4fa2544dfbd525fd9b17c0ac279f 100644 (file)
                label = "bcm968380gerg:green:usb";
        };
 };
+
+&gpio_lo {
+       status = "okay";
+};
+
+&gpio_mid0 {
+       status = "okay";
+};
+
+&gpio_mid1 {
+       status = "okay";
+};
index 75f6037e96a8d4a55b4ef306e9be1f5c509408ba..897064dd9c08c992df2b3d77bb00dfd14824c049 100644 (file)
@@ -10,7 +10,7 @@
 
 / {
        compatible = "gardena,smart-gateway-mt7688", "ralink,mt7628a-soc";
-       model = "Gardena smart-Gateway-MT7688";
+       model = "GARDENA smart Gateway (MT7688)";
 
        aliases {
                serial0 = &uart0;
index ddc30ff76a9b89a775732498ac31a0a5b3bca976..4a5a5848b9f1a841a617dca64afe1b77fa4eaff0 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,jr2.dtsi"
+#include <dt-bindings/mscc/jr2_data.h>
 
 / {
        model = "Jaguar2 Cu8-Sfp16 PCB110 Reference Board";
        sgpio-ports = <0x3f00ffff>;
        gpio-ranges = <&sgpio2 0 0 96>;
 };
+
+&mdio1 {
+       status = "okay";
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+       phy2: ethernet-phy@2 {
+               reg = <2>;
+       };
+       phy3: ethernet-phy@3 {
+               reg = <3>;
+       };
+       phy4: ethernet-phy@4 {
+               reg = <4>;
+       };
+       phy5: ethernet-phy@5 {
+               reg = <5>;
+       };
+       phy6: ethernet-phy@6 {
+               reg = <6>;
+       };
+       phy7: ethernet-phy@7 {
+               reg = <7>;
+       };
+};
+
+&switch {
+       ethernet-ports {
+
+               port0: port@0 {
+                       reg = <0>;
+                       phy-handle = <&phy0>;
+                       phys = <&serdes_hsio 0 SERDES1G(1) PHY_MODE_SGMII>;
+               };
+               port1: port@1 {
+                       reg = <1>;
+                       phy-handle = <&phy1>;
+                       phys = <&serdes_hsio 1 SERDES1G(2) PHY_MODE_SGMII>;
+               };
+               port2: port@2 {
+                       reg = <2>;
+                       phy-handle = <&phy2>;
+                       phys = <&serdes_hsio 2 SERDES1G(3) PHY_MODE_SGMII>;
+               };
+               port3: port@3 {
+                       reg = <3>;
+                       phy-handle = <&phy3>;
+                       phys = <&serdes_hsio 3 SERDES1G(4) PHY_MODE_SGMII>;
+               };
+               port4: port@4 {
+                       reg = <4>;
+                       phy-handle = <&phy4>;
+                       phys = <&serdes_hsio 4 SERDES1G(5) PHY_MODE_SGMII>;
+               };
+               port5: port@5 {
+                       reg = <5>;
+                       phy-handle = <&phy5>;
+                       phys = <&serdes_hsio 5 SERDES1G(6) PHY_MODE_SGMII>;
+               };
+               port6: port@6 {
+                       reg = <6>;
+                       phy-handle = <&phy6>;
+                       phys = <&serdes_hsio 6 SERDES1G(7) PHY_MODE_SGMII>;
+               };
+               port7: port@7 {
+                       reg = <7>;
+                       phy-handle = <&phy7>;
+                       phys = <&serdes_hsio 7 SERDES1G(8) PHY_MODE_SGMII>;
+               };
+       };
+};
index 4d411b6dc4ea4df18e0c637232ae494e010ed19c..f37ebc760168723749c278b8214c594f02f8ee9c 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,jr2.dtsi"
+#include <dt-bindings/mscc/jr2_data.h>
 
 / {
        model = "Jaguar2 Cu48 PCB111 Reference Board";
        sgpio-ports = <0xff000000>;
        gpio-ranges = <&sgpio2 0 0 96>;
 };
+
+&mdio1 {
+       status = "okay";
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+       phy2: ethernet-phy@2 {
+               reg = <2>;
+       };
+       phy3: ethernet-phy@3 {
+               reg = <3>;
+       };
+       phy4: ethernet-phy@4 {
+               reg = <4>;
+       };
+       phy5: ethernet-phy@5 {
+               reg = <5>;
+       };
+       phy6: ethernet-phy@6 {
+               reg = <6>;
+       };
+       phy7: ethernet-phy@7 {
+               reg = <7>;
+       };
+       phy8: ethernet-phy@8 {
+               reg = <8>;
+       };
+       phy9: ethernet-phy@9 {
+               reg = <9>;
+       };
+       phy10: ethernet-phy@10 {
+               reg = <10>;
+       };
+       phy11: ethernet-phy@11 {
+               reg = <11>;
+       };
+       phy12: ethernet-phy@12 {
+               reg = <12>;
+       };
+       phy13: ethernet-phy@13 {
+               reg = <13>;
+       };
+       phy14: ethernet-phy@14 {
+               reg = <14>;
+       };
+       phy15: ethernet-phy@15 {
+               reg = <15>;
+       };
+       phy16: ethernet-phy@16 {
+               reg = <16>;
+       };
+       phy17: ethernet-phy@17 {
+               reg = <17>;
+       };
+       phy18: ethernet-phy@18 {
+               reg = <18>;
+       };
+       phy19: ethernet-phy@19 {
+               reg = <19>;
+       };
+       phy20: ethernet-phy@20 {
+               reg = <20>;
+       };
+       phy21: ethernet-phy@21 {
+               reg = <21>;
+       };
+       phy22: ethernet-phy@22 {
+               reg = <22>;
+       };
+       phy23: ethernet-phy@23 {
+               reg = <23>;
+       };
+};
+
+&mdio2 {
+       status = "okay";
+
+       phy24: ethernet-phy@24 {
+               reg = <0>;
+       };
+       phy25: ethernet-phy@25 {
+               reg = <1>;
+       };
+       phy26: ethernet-phy@26 {
+               reg = <2>;
+       };
+       phy27: ethernet-phy@27 {
+               reg = <3>;
+       };
+       phy28: ethernet-phy@28 {
+               reg = <4>;
+       };
+       phy29: ethernet-phy@29 {
+               reg = <5>;
+       };
+       phy30: ethernet-phy@30 {
+               reg = <6>;
+       };
+       phy31: ethernet-phy@31 {
+               reg = <7>;
+       };
+       phy32: ethernet-phy@32 {
+               reg = <8>;
+       };
+       phy33: ethernet-phy@33 {
+               reg = <9>;
+       };
+       phy34: ethernet-phy@34 {
+               reg = <10>;
+       };
+       phy35: ethernet-phy@35 {
+               reg = <11>;
+       };
+       phy36: ethernet-phy@36 {
+               reg = <12>;
+       };
+       phy37: ethernet-phy@37 {
+               reg = <13>;
+       };
+       phy38: ethernet-phy@38 {
+               reg = <14>;
+       };
+       phy39: ethernet-phy@39 {
+               reg = <15>;
+       };
+       phy40: ethernet-phy@40 {
+               reg = <16>;
+       };
+       phy41: ethernet-phy@41 {
+               reg = <17>;
+       };
+       phy42: ethernet-phy@42 {
+               reg = <18>;
+       };
+       phy43: ethernet-phy@43 {
+               reg = <19>;
+       };
+       phy44: ethernet-phy@44 {
+               reg = <20>;
+       };
+       phy45: ethernet-phy@45 {
+               reg = <21>;
+       };
+       phy46: ethernet-phy@46 {
+               reg = <22>;
+       };
+       phy47: ethernet-phy@47 {
+               reg = <23>;
+       };
+};
+
+&switch {
+       ethernet-ports {
+               port0: port@0 {
+                       reg = <0>;
+                       phy-handle = <&phy0>;
+                       phys = <&serdes_hsio 0 SERDES6G(4) PHY_MODE_QSGMII>;
+               };
+               port1: port@1 {
+                       reg = <1>;
+                       phy-handle = <&phy1>;
+                       phys = <&serdes_hsio 1 0xff PHY_MODE_QSGMII>;
+               };
+               port2: port@2 {
+                       reg = <2>;
+                       phy-handle = <&phy2>;
+                       phys = <&serdes_hsio 2 0xff PHY_MODE_QSGMII>;
+               };
+               port3: port@3 {
+                       reg = <3>;
+                       phy-handle = <&phy3>;
+                       phys = <&serdes_hsio 3 0xff PHY_MODE_QSGMII>;
+               };
+               port4: port@4 {
+                       reg = <4>;
+                       phy-handle = <&phy4>;
+                       phys = <&serdes_hsio 4 SERDES6G(5) PHY_MODE_QSGMII>;
+               };
+               port5: port@5 {
+                       reg = <5>;
+                       phy-handle = <&phy5>;
+                       phys = <&serdes_hsio 5 0xff PHY_MODE_QSGMII>;
+               };
+               port6: port@6 {
+                       reg = <6>;
+                       phy-handle = <&phy6>;
+                       phys = <&serdes_hsio 6 0xff PHY_MODE_QSGMII>;
+               };
+               port7: port@7 {
+                       reg = <7>;
+                       phy-handle = <&phy7>;
+                       phys = <&serdes_hsio 7 0xff PHY_MODE_QSGMII>;
+               };
+               port8: port@8 {
+                       reg = <8>;
+                       phy-handle = <&phy8>;
+                       phys = <&serdes_hsio 8 SERDES6G(6) PHY_MODE_QSGMII>;
+               };
+               port9: port@9 {
+                       reg = <9>;
+                       phy-handle = <&phy9>;
+                       phys = <&serdes_hsio 9 0xff PHY_MODE_QSGMII>;
+               };
+               port10: port@10 {
+                       reg = <10>;
+                       phy-handle = <&phy10>;
+                       phys = <&serdes_hsio 10 0xff PHY_MODE_QSGMII>;
+               };
+               port11: port@11 {
+                       reg = <11>;
+                       phy-handle = <&phy11>;
+                       phys = <&serdes_hsio 11 0xff PHY_MODE_QSGMII>;
+               };
+               port12: port@12 {
+                       reg = <12>;
+                       phy-handle = <&phy12>;
+                       phys = <&serdes_hsio 12 SERDES6G(7) PHY_MODE_QSGMII>;
+               };
+               port13: port@13 {
+                       reg = <13>;
+                       phy-handle = <&phy13>;
+                       phys = <&serdes_hsio 13 0xff PHY_MODE_QSGMII>;
+               };
+               port14: port@14 {
+                       reg = <14>;
+                       phy-handle = <&phy14>;
+                       phys = <&serdes_hsio 14 0xff PHY_MODE_QSGMII>;
+               };
+               port15: port@15 {
+                       reg = <15>;
+                       phy-handle = <&phy15>;
+                       phys = <&serdes_hsio 15 0xff PHY_MODE_QSGMII>;
+               };
+               port16: port@16 {
+                       reg = <16>;
+                       phy-handle = <&phy16>;
+                       phys = <&serdes_hsio 16 SERDES6G(8) PHY_MODE_QSGMII>;
+               };
+               port17: port@17 {
+                       reg = <17>;
+                       phy-handle = <&phy17>;
+                       phys = <&serdes_hsio 17 0xff PHY_MODE_QSGMII>;
+               };
+               port18: port@18 {
+                       reg = <18>;
+                       phy-handle = <&phy18>;
+                       phys = <&serdes_hsio 18 0xff PHY_MODE_QSGMII>;
+               };
+               port19: port@19 {
+                       reg = <19>;
+                       phy-handle = <&phy19>;
+                       phys = <&serdes_hsio 19 0xff PHY_MODE_QSGMII>;
+               };
+               port20: port@20 {
+                       reg = <20>;
+                       phy-handle = <&phy20>;
+                       phys = <&serdes_hsio 20 SERDES6G(9) PHY_MODE_QSGMII>;
+               };
+               port21: port@21 {
+                       reg = <21>;
+                       phy-handle = <&phy21>;
+                       phys = <&serdes_hsio 21 0xff PHY_MODE_QSGMII>;
+               };
+               port22: port@22 {
+                       reg = <22>;
+                       phy-handle = <&phy22>;
+                       phys = <&serdes_hsio 22 0xff PHY_MODE_QSGMII>;
+               };
+               port23: port@23 {
+                       reg = <23>;
+                       phy-handle = <&phy23>;
+                       phys = <&serdes_hsio 23 0xff PHY_MODE_QSGMII>;
+               };
+               port24: port@24 {
+                       reg = <24>;
+                       phy-handle = <&phy24>;
+                       phys = <&serdes_hsio 24 SERDES6G(10) PHY_MODE_QSGMII>;
+               };
+               port25: port@25 {
+                       reg = <25>;
+                       phy-handle = <&phy25>;
+                       phys = <&serdes_hsio 25 0xff PHY_MODE_QSGMII>;
+               };
+               port26: port@26 {
+                       reg = <26>;
+                       phy-handle = <&phy26>;
+                       phys = <&serdes_hsio 26 0xff PHY_MODE_QSGMII>;
+               };
+               port27: port@27 {
+                       reg = <27>;
+                       phy-handle = <&phy27>;
+                       phys = <&serdes_hsio 27 0xff PHY_MODE_QSGMII>;
+               };
+               port28: port@28 {
+                       reg = <28>;
+                       phy-handle = <&phy28>;
+                       phys = <&serdes_hsio 28 SERDES6G(11) PHY_MODE_QSGMII>;
+               };
+               port29: port@29 {
+                       reg = <29>;
+                       phy-handle = <&phy29>;
+                       phys = <&serdes_hsio 29 0xff PHY_MODE_QSGMII>;
+               };
+               port30: port@30 {
+                       reg = <30>;
+                       phy-handle = <&phy30>;
+                       phys = <&serdes_hsio 30 0xff PHY_MODE_QSGMII>;
+               };
+               port31: port@31 {
+                       reg = <31>;
+                       phy-handle = <&phy31>;
+                       phys = <&serdes_hsio 31 0xff PHY_MODE_QSGMII>;
+               };
+               port32: port@32 {
+                       reg = <32>;
+                       phy-handle = <&phy32>;
+                       phys = <&serdes_hsio 32 SERDES6G(12) PHY_MODE_QSGMII>;
+               };
+               port33: port@33 {
+                       reg = <33>;
+                       phy-handle = <&phy33>;
+                       phys = <&serdes_hsio 33 0xff PHY_MODE_QSGMII>;
+               };
+               port34: port@34 {
+                       reg = <34>;
+                       phy-handle = <&phy34>;
+                       phys = <&serdes_hsio 34 0xff PHY_MODE_QSGMII>;
+               };
+               port35: port@35 {
+                       reg = <35>;
+                       phy-handle = <&phy35>;
+                       phys = <&serdes_hsio 35 0xff PHY_MODE_QSGMII>;
+               };
+               port36: port@36 {
+                       reg = <36>;
+                       phy-handle = <&phy36>;
+                       phys = <&serdes_hsio 36 SERDES6G(13) PHY_MODE_QSGMII>;
+               };
+               port37: port@37 {
+                       reg = <37>;
+                       phy-handle = <&phy37>;
+                       phys = <&serdes_hsio 37 0xff PHY_MODE_QSGMII>;
+               };
+               port38: port@38 {
+                       reg = <38>;
+                       phy-handle = <&phy38>;
+                       phys = <&serdes_hsio 38 0xff PHY_MODE_QSGMII>;
+               };
+               port39: port@39 {
+                       reg = <39>;
+                       phy-handle = <&phy39>;
+                       phys = <&serdes_hsio 39 0xff PHY_MODE_QSGMII>;
+               };
+               port40: port@40 {
+                       reg = <40>;
+                       phy-handle = <&phy40>;
+                       phys = <&serdes_hsio 40 SERDES6G(14) PHY_MODE_QSGMII>;
+               };
+               port41: port@41 {
+                       reg = <41>;
+                       phy-handle = <&phy41>;
+                       phys = <&serdes_hsio 41 0xff PHY_MODE_QSGMII>;
+               };
+               port42: port@42 {
+                       reg = <42>;
+                       phy-handle = <&phy42>;
+                       phys = <&serdes_hsio 42 0xff PHY_MODE_QSGMII>;
+               };
+               port43: port@43 {
+                       reg = <43>;
+                       phy-handle = <&phy43>;
+                       phys = <&serdes_hsio 43 0xff PHY_MODE_QSGMII>;
+               };
+               port44: port@44 {
+                       reg = <44>;
+                       phy-handle = <&phy44>;
+                       phys = <&serdes_hsio 44 SERDES6G(15) PHY_MODE_QSGMII>;
+               };
+               port45: port@45 {
+                       reg = <45>;
+                       phy-handle = <&phy45>;
+                       phys = <&serdes_hsio 45 0xff PHY_MODE_QSGMII>;
+               };
+               port46: port@46 {
+                       reg = <46>;
+                       phy-handle = <&phy46>;
+                       phys = <&serdes_hsio 46 0xff PHY_MODE_QSGMII>;
+               };
+               port47: port@47 {
+                       reg = <47>;
+                       phy-handle = <&phy47>;
+                       phys = <&serdes_hsio 47 0xff PHY_MODE_QSGMII>;
+               };
+       };
+};
index 090092607b52010247acf05ec0fed439aad6082c..7f5a96fecdc625b307beaed8470d26d404af3c86 100644 (file)
                        gpio-bank-name = "sgpio2_";
                        sgpio-clock = <0x14>;
                };
+
+               switch: switch@1010000 {
+                       compatible = "mscc,vsc7454-switch";
+                       reg = <0x01040000 0x0100>,   // VTSS_TO_DEV_0
+                             <0x01050000 0x0100>,   // VTSS_TO_DEV_1
+                             <0x01060000 0x0100>,   // VTSS_TO_DEV_2
+                             <0x01070000 0x0100>,   // VTSS_TO_DEV_3
+                             <0x01080000 0x0100>,   // VTSS_TO_DEV_4
+                             <0x01090000 0x0100>,   // VTSS_TO_DEV_5
+                             <0x010a0000 0x0100>,   // VTSS_TO_DEV_6
+                             <0x010b0000 0x0100>,   // VTSS_TO_DEV_7
+                             <0x010c0000 0x0100>,   // VTSS_TO_DEV_8
+                             <0x010d0000 0x0100>,   // VTSS_TO_DEV_9
+                             <0x010e0000 0x0100>,   // VTSS_TO_DEV_10
+                             <0x010f0000 0x0100>,   // VTSS_TO_DEV_11
+                             <0x01100000 0x0100>,   // VTSS_TO_DEV_12
+                             <0x01110000 0x0100>,   // VTSS_TO_DEV_13
+                             <0x01120000 0x0100>,   // VTSS_TO_DEV_14
+                             <0x01130000 0x0100>,   // VTSS_TO_DEV_15
+                             <0x01140000 0x0100>,   // VTSS_TO_DEV_16
+                             <0x01150000 0x0100>,   // VTSS_TO_DEV_17
+                             <0x01160000 0x0100>,   // VTSS_TO_DEV_18
+                             <0x01170000 0x0100>,   // VTSS_TO_DEV_19
+                             <0x01180000 0x0100>,   // VTSS_TO_DEV_20
+                             <0x01190000 0x0100>,   // VTSS_TO_DEV_21
+                             <0x011a0000 0x0100>,   // VTSS_TO_DEV_22
+                             <0x011b0000 0x0100>,   // VTSS_TO_DEV_23
+                             <0x011c0000 0x0100>,   // VTSS_TO_DEV_24
+                             <0x011d0000 0x0100>,   // VTSS_TO_DEV_25
+                             <0x011e0000 0x0100>,   // VTSS_TO_DEV_26
+                             <0x011f0000 0x0100>,   // VTSS_TO_DEV_27
+                             <0x01200000 0x0100>,   // VTSS_TO_DEV_28
+                             <0x01210000 0x0100>,   // VTSS_TO_DEV_29
+                             <0x01220000 0x0100>,   // VTSS_TO_DEV_30
+                             <0x01230000 0x0100>,   // VTSS_TO_DEV_31
+                             <0x01240000 0x0100>,   // VTSS_TO_DEV_32
+                             <0x01250000 0x0100>,   // VTSS_TO_DEV_33
+                             <0x01260000 0x0100>,   // VTSS_TO_DEV_34
+                             <0x01270000 0x0100>,   // VTSS_TO_DEV_35
+                             <0x01280000 0x0100>,   // VTSS_TO_DEV_36
+                             <0x01290000 0x0100>,   // VTSS_TO_DEV_37
+                             <0x012a0000 0x0100>,   // VTSS_TO_DEV_38
+                             <0x012b0000 0x0100>,   // VTSS_TO_DEV_39
+                             <0x012c0000 0x0100>,   // VTSS_TO_DEV_40
+                             <0x012d0000 0x0100>,   // VTSS_TO_DEV_41
+                             <0x012e0000 0x0100>,   // VTSS_TO_DEV_42
+                             <0x012f0000 0x0100>,   // VTSS_TO_DEV_43
+                             <0x01300000 0x0100>,   // VTSS_TO_DEV_44
+                             <0x01310000 0x0100>,   // VTSS_TO_DEV_45
+                             <0x01320000 0x0100>,   // VTSS_TO_DEV_46
+                             <0x01330000 0x0100>,   // VTSS_TO_DEV_47
+                             <0x01f00000 0x100000>, // ANA_AC
+                             <0x01d00000 0x100000>, // ANA_CL
+                             <0x01e00000 0x100000>, // ANA_L2
+                             <0x01410000 0x10000>,  // ASM
+                             <0x01460000 0x10000>,  // HSIO
+                             <0x01420000 0x00000>,  // LRN
+                             <0x017d0000 0x10000>,  // QFWD
+                             <0x01020000 0x20000>,  // QS
+                             <0x017e0000 0x10000>,  // QSYS
+                             <0x01b00000 0x80000>;  // REW
+                       reg-names = "port0", "port1", "port2", "port3", "port4",
+                                   "port5", "port6", "port7", "port8", "port9",
+                                   "port10", "port11", "port12", "port13",
+                                   "port14", "port15", "port16", "port17",
+                                   "port18", "port19", "port20", "port21",
+                                   "port22", "port23", "port24", "port25",
+                                   "port26", "port27", "port28", "port29",
+                                   "port30", "port31", "port32", "port33",
+                                   "port34", "port35", "port36", "port37",
+                                   "port38", "port39", "port40", "port41",
+                                   "port42", "port43", "port44", "port45",
+                                   "port46", "port47", "ana_ac", "ana_cl",
+                                   "ana_l2", "asm", "hsio", "lrn", "qfwd",
+                                   "qs", "qsys", "rew";
+                       status = "okay";
+
+                       ethernet-ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+
+               mdio0: mdio@010100c8 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,jr2-miim";
+                       reg = <0x010100c8 0x24>;
+                       status = "disabled";
+               };
+
+               mdio1: mdio@010100ec {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,jr2-miim";
+                       reg = <0x010100ec 0x24>;
+                       status = "disabled";
+               };
+
+               mdio2: mdio@01010110 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,jr2-miim";
+                       reg = <0x01010110 0x24>;
+                       status = "disabled";
+               };
+
+               hsio: syscon@10d0000 {
+                       compatible = "mscc,jr2-hsio", "syscon", "simple-mfd";
+                       reg = <0x10d0000 0x10000>;
+
+                       serdes_hsio: serdes_hsio {
+                               compatible = "mscc,vsc7454-serdes";
+                               #phy-cells = <3>;
+                       };
+               };
        };
 };
index 4beb7a38d0cedaf59acd8fa06c2e42302c3b301f..45ae2de5e876a1420294a9314fce7625b2e6e07b 100644 (file)
                        #gpio-cells = <2>;
                        gpio-ranges = <&sgpio 0 0 128>;
                };
+
+               switch: switch@1010000 {
+                       compatible = "mscc,vsc7437-switch";
+                       reg = <0x01030000 0x0100>,   // VTSS_TO_DEV_0
+                             <0x01040000 0x0100>,   // VTSS_TO_DEV_1
+                             <0x01f00000 0x100000>, // ANA_AC
+                             <0x01d00000 0x100000>, // ANA_CL
+                             <0x01e00000 0x100000>, // ANA_L2
+                             <0x01120000 0x10000>,  // ASM
+                             <0x01130000 0x00000>,  // LRN
+                             <0x017d0000 0x10000>,  // QFWD
+                             <0x01020000 0x20000>,  // QS
+                             <0x017e0000 0x10000>,  // QSYS
+                             <0x01b00000 0x80000>;  // REW
+                       reg-names = "port0", "port1",
+                                   "ana_ac", "ana_cl", "ana_l2", "asm", "lrn",
+                                   "qfwd", "qs", "qsys", "rew";
+                       status = "okay";
+
+                       ethernet-ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+
+               mdio0: mdio@010100c4 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,jr2-miim";
+                       reg = <0x010100c4 0x24>;
+                       status = "disabled";
+               };
+
+               mdio1: mdio@010100e8 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,jr2-miim";
+                       reg = <0x010100e8 0x24>;
+                       status = "disabled";
+               };
        };
 };
index ba29ea287e2bab3dfaddd3b6fdd2ac9740d7c4eb..90d34ddbbfbcabdf8829e68fd002ccbfa3e8979a 100644 (file)
 
                                status = "disabled";
                        };
+
+                       gmac0: eth0@0x19000000 {
+                               compatible = "qca,ag953x-mac";
+                               reg = <0x19000000 0x200>;
+                               phy = <&phy4>;
+                               phy-mode = "rmii";
+
+                               status = "disabled";
+                       };
+
+                       gmac1: eth1@0x1a000000 {
+                               compatible = "qca,ag953x-mac";
+                               reg = <0x1a000000 0x200>;
+                               phy = <&phy0>;
+                               phy-mode = "rgmii";
+
+                               status = "disabled";
+
+                               mdio {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       phy0: ethernet-phy@0 {
+                                               reg = <0>;
+                                               phy-mode = "rmii";
+                                       };
+                                       phy4: ethernet-phy@4 {
+                                               reg = <4>;
+                                               phy-mode = "rmii";
+                                       };
+                               };
+                       };
                };
 
                spi0: spi@1f000000 {
diff --git a/arch/mips/dts/qca956x.dtsi b/arch/mips/dts/qca956x.dtsi
new file mode 100644 (file)
index 0000000..6cb360b
--- /dev/null
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+       compatible = "qca,qca956x";
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,mips74Kc";
+                       reg = <0>;
+               };
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               xtal: xtal {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-output-names = "xtal";
+               };
+       };
+
+       ahb {
+               compatible = "simple-bus";
+               ranges;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               apb {
+                       compatible = "simple-bus";
+                       ranges;
+
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       uart0: uart@18020000 {
+                               compatible = "ns16550";
+                               reg = <0x18020000 0x20>;
+                               reg-shift = <2>;
+
+                               status = "disabled";
+                       };
+
+                       gmac0: eth@0x19000000 {
+                               compatible = "qca,ag956x-mac";
+                               reg = <0x19000000 0x200>;
+                               phy = <&phy0>;
+                               phy-mode = "sgmii";
+
+                               status = "disabled";
+
+                               mdio {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       phy0: ethernet-phy@0 {
+                                               reg = <0>;
+                                       };
+                               };
+                       };
+               };
+
+               spi0: spi@1f000000 {
+                       compatible = "qca,ar7100-spi";
+                       reg = <0x1f000000 0x10>;
+
+                       status = "disabled";
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+};
index fe025f4c42a7185a23155348512785e477063c3d..7a9d595433d347a724b92598138854d1840aaeb9 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,jr2.dtsi"
+#include <dt-bindings/mscc/jr2_data.h>
 
 / {
        model = "Serval2 NID PCB112 Reference Board";
        status = "okay";
        sgpio-ports = <0x3fe0ffff>;
 };
+
+&mdio0 {
+       status = "okay";
+
+       phy16: ethernet-phy@16 {
+               reg = <16>;
+       };
+       phy17: ethernet-phy@17 {
+               reg = <17>;
+       };
+       phy18: ethernet-phy@18 {
+               reg = <18>;
+       };
+       phy19: ethernet-phy@19 {
+               reg = <19>;
+       };
+};
+
+&switch {
+       ethernet-ports {
+
+               port0: port@0 {
+                       reg = <24>;
+                       phy-handle = <&phy16>;
+                       phys = <&serdes_hsio 24 SERDES6G(0) PHY_MODE_SGMII>;
+               };
+               port1: port@1 {
+                       reg = <25>;
+                       phy-handle = <&phy17>;
+                       phys = <&serdes_hsio 25 SERDES6G(1) PHY_MODE_SGMII>;
+               };
+               port2: port@2 {
+                       reg = <26>;
+                       phy-handle = <&phy18>;
+                       phys = <&serdes_hsio 26 SERDES6G(2) PHY_MODE_SGMII>;
+               };
+               port3: port@3 {
+                       reg = <27>;
+                       phy-handle = <&phy19>;
+                       phys = <&serdes_hsio 27 SERDES6G(3) PHY_MODE_SGMII>;
+               };
+       };
+};
index fb3331204b3e80f52a507ea87088a2d3f9a964cf..9d4921504d3d02fe2de9e7ae9ff9abd79f80d7fc 100644 (file)
        status = "okay";
        sgpio-ports = <0x0000fe7f>;
 };
+
+&mdio0 {
+       status = "okay";
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
+&switch {
+       ethernet-ports {
+
+               port0: port@0 {
+                       reg = <0>;
+                       phy-handle = <&phy0>;
+               };
+               port1: port@1 {
+                       reg = <1>;
+                       phy-handle = <&phy1>;
+               };
+       };
+};
index deca5189e33f93c285c7cc68596e9a4c916187c3..35152cb3f64afe122c1defb58b40fa006fe38d8a 100644 (file)
@@ -215,23 +215,6 @@ static void linux_env_legacy(bootm_headers_t *images)
        }
 }
 
-static int boot_reloc_ramdisk(bootm_headers_t *images)
-{
-       ulong rd_len = images->rd_end - images->rd_start;
-
-       /*
-        * In case of legacy uImage's, relocation of ramdisk is already done
-        * by do_bootm_states() and should not repeated in 'bootm prep'.
-        */
-       if (images->state & BOOTM_STATE_RAMDISK) {
-               debug("## Ramdisk already relocated\n");
-               return 0;
-       }
-
-       return boot_ramdisk_high(&images->lmb, images->rd_start,
-               rd_len, &images->initrd_start, &images->initrd_end);
-}
-
 static int boot_reloc_fdt(bootm_headers_t *images)
 {
        /*
@@ -270,8 +253,6 @@ static int boot_setup_fdt(bootm_headers_t *images)
 
 static void boot_prep_linux(bootm_headers_t *images)
 {
-       boot_reloc_ramdisk(images);
-
        if (CONFIG_IS_ENABLED(MIPS_BOOT_FDT) && images->ft_len) {
                boot_reloc_fdt(images);
                boot_setup_fdt(images);
index bc86f591df83a342f85440d59709cdfa1be8fc37..bdb23b57658fb77bee2681943f9cf4f1785b5a49 100644 (file)
@@ -33,6 +33,15 @@ config SOC_QCA953X
        help
          This supports QCA/Atheros qca953x family SOCs.
 
+config SOC_QCA956X
+       bool
+       select MIPS_TUNE_74KC
+       select SUPPORTS_BIG_ENDIAN
+       select SUPPORTS_CPU_MIPS32_R1
+       select SUPPORTS_CPU_MIPS32_R2
+       help
+         This supports QCA/Atheros qca956x family SOCs.
+
 choice
        prompt "Board select"
 
@@ -44,6 +53,10 @@ config TARGET_AP143
        bool "AP143 Reference Board"
        select SOC_QCA953X
 
+config TARGET_AP152
+       bool "AP152 Reference Board"
+       select SOC_QCA956X
+
 config BOARD_TPLINK_WDR4300
        bool "TP-Link WDR4300 Board"
        select SOC_AR934X
@@ -52,6 +65,7 @@ endchoice
 
 source "board/qca/ap121/Kconfig"
 source "board/qca/ap143/Kconfig"
+source "board/qca/ap152/Kconfig"
 source "board/tplink/wdr4300/Kconfig"
 
 endmenu
index 7aa40c65d3005be867f1b2257ec515ed946b2040..fbd40c02becb9f4123426b66709ceeffbff21589 100644 (file)
@@ -7,3 +7,4 @@ obj-y += dram.o
 obj-$(CONFIG_SOC_AR933X)       += ar933x/
 obj-$(CONFIG_SOC_AR934X)       += ar934x/
 obj-$(CONFIG_SOC_QCA953X)      += qca953x/
+obj-$(CONFIG_SOC_QCA956X)      += qca956x/
index 5d371bb5828d013898a78c45085f036d213b19a3..5888f6eb288d303cb9fb1a3dc312141e76e1c58c 100644 (file)
 #define QCA956X_WMAC_BASE \
        (AR71XX_APB_BASE + 0x00100000)
 #define QCA956X_WMAC_SIZE                              0x20000
+#define QCA956X_RTC_BASE \
+       (AR71XX_APB_BASE + 0x00107000)
+#define QCA956X_RTC_SIZE                                       0x1000
 #define QCA956X_EHCI0_BASE                             0x1b000000
 #define QCA956X_EHCI1_BASE                             0x1b400000
 #define QCA956X_EHCI_SIZE                              0x200
        (AR71XX_APB_BASE + 0x00070000)
 #define QCA956X_GMAC_SIZE                              0x64
 
+#define QCA956X_SRIF_BASE \
+       (AR71XX_APB_BASE + 0x00116000)
+#define QCA956X_SRIF_SIZE                              0x1000
+
 /*
  * DDR_CTRL block
  */
 #define QCA953X_DDR_REG_CTL_CONF                       0x108
 #define QCA953X_DDR_REG_CONFIG3                                0x15c
 
+#define QCA956X_DDR_REG_TAP_CTRL2                      0x24
+#define QCA956X_DDR_REG_TAP_CTRL3                      0x28
+#define QCA956X_DDR_REG_DDR2_CONFIG                    0xb8
+#define QCA956X_DDR_REG_DDR2_EMR2                      0xbc
+#define QCA956X_DDR_REG_DDR2_EMR3                      0xc0
+#define QCA956X_DDR_REG_BURST                          0xc4
+#define QCA956X_DDR_REG_BURST2                         0xc8
+#define QCA956X_DDR_REG_TIMEOUT_MAX                    0xcc
+#define QCA956X_DDR_REG_FSM_WAIT_CTRL                  0xe4
+#define QCA956X_DDR_REG_CTL_CONF                       0x108
+#define QCA956X_DDR_REG_DDR3_CONFIG                    0x15c
+
 /*
  * PLL block
  */
 #define QCA956X_PLL_DDR_CONFIG_REG                     0x08
 #define QCA956X_PLL_DDR_CONFIG1_REG                    0x0c
 #define QCA956X_PLL_CLK_CTRL_REG                       0x10
+#define QCA956X_PLL_SWITCH_CLK_CTRL_REG                        0x28
+#define QCA956X_PLL_ETH_XMII_CTRL_REG                  0x30
+#define QCA956X_PLL_DDR_DIT_FRAC_REG                   0x38
+#define QCA956X_PLL_DDR_DIT2_FRAC_REG                  0x3c
+#define QCA956X_PLL_CPU_DIT_FRAC_REG                   0x40
+#define QCA956X_PLL_CPU_DIT2_FRAC_REG                  0x44
+#define QCA956X_PLL_ETH_SGMII_SERDES_REG               0x4c
 
 #define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT            12
 #define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK             0x1f
 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT          0
 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK           0x1f
 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT          5
-#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK           0x3fff
+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK           0x1fff
 #define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT             18
 #define QCA956X_PLL_CPU_CONFIG1_NINT_MASK              0x1ff
 
 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT          0
 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK           0x1f
 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT          5
-#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK           0x3fff
+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK           0x1fff
 #define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT             18
 #define QCA956X_PLL_DDR_CONFIG1_NINT_MASK              0x1ff
 
 #define QCA955X_RESET_MBOX                             BIT(1)
 #define QCA955X_RESET_I2S                              BIT(0)
 
+#define QCA956X_RESET_EXTERNAL                         BIT(28)
+#define QCA956X_RESET_FULL_CHIP                                BIT(24)
+#define QCA956X_RESET_GE1_MDIO                         BIT(23) /* Reserved in datasheet */
+#define QCA956X_RESET_GE0_MDIO                         BIT(22)
+#define QCA956X_RESET_GE1_MAC                          BIT(13) /* Reserved in datasheet */
+#define QCA956X_RESET_SGMII_ASSERT                     BIT(12)
+#define QCA956X_RESET_GE0_MAC                          BIT(9)
+#define QCA956X_RESET_SGMII                            BIT(8)
+#define QCA956X_RESET_SGMII_ANALOG                             BIT(2)
+#define QCA956X_RESET_SWITCH                           BIT(0)
+
 #define AR933X_BOOTSTRAP_MDIO_GPIO_EN                  BIT(18)
 #define AR933X_BOOTSTRAP_DDR2                          BIT(13)
 #define AR933X_BOOTSTRAP_EEPBUSY                       BIT(4)
 #define QCA953X_GPIO_IN_MUX_UART0_SIN                  9
 #define QCA953X_GPIO_IN_MUX_SPI_DATA_IN                        8
 
+#define QCA956X_GPIO(x)                                        BIT(x)
+#define QCA956X_GPIO_MUX_MASK(x)                       (0xff << (x))
 #define QCA956X_GPIO_OUT_MUX_GE0_MDO                   32
 #define QCA956X_GPIO_OUT_MUX_GE0_MDC                   33
+#define QCA956X_GPIO_IN_MUX_UART0_SIN                  0x12
+#define QCA956X_GPIO_OUT_MUX_UART0_SOUT                        0x16
 
 #define AR71XX_GPIO_COUNT                              16
 #define AR7240_GPIO_COUNT                              18
 #define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT                        13
 #define QCA953X_SRIF_DPLL2_OUTDIV_MASK                 0x7
 
+#define QCA956X_SRIF_BB_DPLL1_REG                      0x180
+#define QCA956X_SRIF_BB_DPLL2_REG                      0x184
+#define QCA956X_SRIF_BB_DPLL3_REG                      0x188
+
+#define QCA956X_SRIF_CPU_DPLL1_REG                     0xf00
+#define QCA956X_SRIF_CPU_DPLL2_REG                     0xf04
+#define QCA956X_SRIF_CPU_DPLL3_REG                     0xf08
+
+#define QCA956X_SRIF_DDR_DPLL1_REG                     0xec0
+#define QCA956X_SRIF_DDR_DPLL2_REG                     0xec4
+#define QCA956X_SRIF_DDR_DPLL3_REG                     0xec8
+
+#define QCA956X_SRIF_PCIE_DPLL1_REG                    0xc80
+#define QCA956X_SRIF_PCIE_DPLL2_REG                    0xc84
+#define QCA956X_SRIF_PCIE_DPLL3_REG                    0xc88
+
+#define QCA956X_SRIF_PMU1_REG                          0xcc0
+#define QCA956X_SRIF_PMU2_REG                          0xcc4
+
 /*
  * MII_CTRL block
  */
 #define QCA955X_ETH_CFG_RGMII_EN                       BIT(0)
 #define QCA955X_ETH_CFG_GE0_SGMII                      BIT(6)
 
+/*
+ * QCA956X GMAC Interface
+ */
+
+#define QCA956X_GMAC_REG_ETH_CFG                       0x00
+#define QCA956X_GMAC_REG_SGMII_RESET                   0x14
+#define QCA956X_GMAC_REG_SGMII_SERDES                  0x18
+#define QCA956X_GMAC_REG_MR_AN_CTRL                    0x1c
+#define QCA956X_GMAC_REG_SGMII_CONFIG                  0x34
+#define QCA956X_GMAC_REG_SGMII_DEBUG                   0x58
+
+#define QCA956X_ETH_CFG_GE0_SGMII                      BIT(6)
+
 #endif /* __ASM_AR71XX_H */
index 5de7a43f79ead4e0f0c39a1f0635920b78294f98..0fde5079b16780c5da07dededcc0fd518af9ded7 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * Atheros AR71XX/AR724X/AR913X common definitions
  *
+ * Copyright (C) 2018-2019 Rosy Song <rosysong@rosinson.com>
  * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
@@ -146,4 +147,6 @@ int ath79_usb_reset(void);
 void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
 void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
 
+void qca956x_pll_init(void);
+void qca956x_ddr_init(void);
 #endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/mach-ath79/qca956x/Makefile b/arch/mips/mach-ath79/qca956x/Makefile
new file mode 100644 (file)
index 0000000..3f5fc03
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-y += clk.o
+obj-y += ddr.o qca956x-ddr-tap.o
diff --git a/arch/mips/mach-ath79/qca956x/clk.c b/arch/mips/mach-ath79/qca956x/clk.c
new file mode 100644 (file)
index 0000000..33a44cf
--- /dev/null
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ath79.h>
+#include <wait_bit.h>
+
+#define PLL_SRIF_DPLL2_KI_LSB 29
+#define PLL_SRIF_DPLL2_KI_MASK 0x60000000
+#define PLL_SRIF_DPLL2_KI_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_KI_LSB) & PLL_SRIF_DPLL2_KI_MASK)
+#define PLL_SRIF_DPLL2_KD_LSB 25
+#define PLL_SRIF_DPLL2_KD_MASK 0x1e000000
+#define PLL_SRIF_DPLL2_KD_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_KD_LSB) & PLL_SRIF_DPLL2_KD_MASK)
+#define PLL_SRIF_DPLL2_PLL_PWD_LSB 22
+#define PLL_SRIF_DPLL2_PLL_PWD_MASK 0x00400000
+#define PLL_SRIF_DPLL2_PLL_PWD_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_PLL_PWD_LSB) & PLL_SRIF_DPLL2_PLL_PWD_MASK)
+#define PLL_SRIF_DPLL2_OUTDIV_LSB 19
+#define PLL_SRIF_DPLL2_OUTDIV_MASK 0x00380000
+#define PLL_SRIF_DPLL2_OUTDIV_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_OUTDIV_LSB) & PLL_SRIF_DPLL2_OUTDIV_MASK)
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_LSB 12
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_MASK 0x0007f000
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_PHASE_SHIFT_LSB) & PLL_SRIF_DPLL2_PHASE_SHIFT_MASK)
+#define CPU_PLL_CONFIG_PLLPWD_LSB 30
+#define CPU_PLL_CONFIG_PLLPWD_MASK 0x40000000
+#define CPU_PLL_CONFIG_PLLPWD_SET(x) \
+       (((x) << CPU_PLL_CONFIG_PLLPWD_LSB) & CPU_PLL_CONFIG_PLLPWD_MASK)
+#define CPU_PLL_CONFIG_OUTDIV_LSB 19
+#define CPU_PLL_CONFIG_OUTDIV_MASK 0x00380000
+#define CPU_PLL_CONFIG_OUTDIV_SET(x) \
+       (((x) << CPU_PLL_CONFIG_OUTDIV_LSB) & CPU_PLL_CONFIG_OUTDIV_MASK)
+#define CPU_PLL_CONFIG_RANGE_LSB 17
+#define CPU_PLL_CONFIG_RANGE_MASK 0x00060000
+#define CPU_PLL_CONFIG_RANGE_SET(x) \
+       (((x) << CPU_PLL_CONFIG_RANGE_LSB) & CPU_PLL_CONFIG_RANGE_MASK)
+#define CPU_PLL_CONFIG_REFDIV_LSB 12
+#define CPU_PLL_CONFIG_REFDIV_MASK 0x0001f000
+#define CPU_PLL_CONFIG_REFDIV_SET(x) \
+       (((x) << CPU_PLL_CONFIG_REFDIV_LSB) & CPU_PLL_CONFIG_REFDIV_MASK)
+#define CPU_PLL_CONFIG1_NINT_LSB 18
+#define CPU_PLL_CONFIG1_NINT_MASK 0x07fc0000
+#define CPU_PLL_CONFIG1_NINT_SET(x) \
+       (((x) << CPU_PLL_CONFIG1_NINT_LSB) & CPU_PLL_CONFIG1_NINT_MASK)
+#define CPU_PLL_DITHER1_DITHER_EN_LSB 31
+#define CPU_PLL_DITHER1_DITHER_EN_MASK 0x80000000
+#define CPU_PLL_DITHER1_DITHER_EN_SET(x) \
+       (((x) << CPU_PLL_DITHER1_DITHER_EN_LSB) & CPU_PLL_DITHER1_DITHER_EN_MASK)
+#define CPU_PLL_DITHER1_UPDATE_COUNT_LSB 24
+#define CPU_PLL_DITHER1_UPDATE_COUNT_MASK 0x3f000000
+#define CPU_PLL_DITHER1_UPDATE_COUNT_SET(x) \
+       (((x) << CPU_PLL_DITHER1_UPDATE_COUNT_LSB) & CPU_PLL_DITHER1_UPDATE_COUNT_MASK)
+#define CPU_PLL_DITHER1_NFRAC_STEP_LSB 18
+#define CPU_PLL_DITHER1_NFRAC_STEP_MASK 0x00fc0000
+#define CPU_PLL_DITHER1_NFRAC_STEP_SET(x) \
+       (((x) << CPU_PLL_DITHER1_NFRAC_STEP_LSB) & CPU_PLL_DITHER1_NFRAC_STEP_MASK)
+#define CPU_PLL_DITHER1_NFRAC_MIN_LSB 0
+#define CPU_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff
+#define CPU_PLL_DITHER1_NFRAC_MIN_SET(x) \
+       (((x) << CPU_PLL_DITHER1_NFRAC_MIN_LSB) & CPU_PLL_DITHER1_NFRAC_MIN_MASK)
+#define CPU_PLL_DITHER2_NFRAC_MAX_LSB 0
+#define CPU_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff
+#define CPU_PLL_DITHER2_NFRAC_MAX_SET(x) \
+       (((x) << CPU_PLL_DITHER2_NFRAC_MAX_LSB) & CPU_PLL_DITHER2_NFRAC_MAX_MASK)
+#define DDR_PLL_CONFIG_PLLPWD_LSB 30
+#define DDR_PLL_CONFIG_PLLPWD_MASK 0x40000000
+#define DDR_PLL_CONFIG_PLLPWD_SET(x) \
+       (((x) << DDR_PLL_CONFIG_PLLPWD_LSB) & DDR_PLL_CONFIG_PLLPWD_MASK)
+#define DDR_PLL_CONFIG_OUTDIV_LSB 23
+#define DDR_PLL_CONFIG_OUTDIV_MASK 0x03800000
+#define DDR_PLL_CONFIG_OUTDIV_SET(x) \
+       (((x) << DDR_PLL_CONFIG_OUTDIV_LSB) & DDR_PLL_CONFIG_OUTDIV_MASK)
+#define DDR_PLL_CONFIG_RANGE_LSB 21
+#define DDR_PLL_CONFIG_RANGE_MASK 0x00600000
+#define DDR_PLL_CONFIG_RANGE_SET(x) \
+       (((x) << DDR_PLL_CONFIG_RANGE_LSB) & DDR_PLL_CONFIG_RANGE_MASK)
+#define DDR_PLL_CONFIG_REFDIV_LSB 16
+#define DDR_PLL_CONFIG_REFDIV_MASK 0x001f0000
+#define DDR_PLL_CONFIG_REFDIV_SET(x) \
+       (((x) << DDR_PLL_CONFIG_REFDIV_LSB) & DDR_PLL_CONFIG_REFDIV_MASK)
+#define DDR_PLL_CONFIG1_NINT_LSB 18
+#define DDR_PLL_CONFIG1_NINT_MASK 0x07fc0000
+#define DDR_PLL_CONFIG1_NINT_SET(x) \
+       (((x) << DDR_PLL_CONFIG1_NINT_LSB) & DDR_PLL_CONFIG1_NINT_MASK)
+#define DDR_PLL_DITHER1_DITHER_EN_LSB 31
+#define DDR_PLL_DITHER1_DITHER_EN_MASK 0x80000000
+#define DDR_PLL_DITHER1_DITHER_EN_SET(x) \
+       (((x) << DDR_PLL_DITHER1_DITHER_EN_LSB) & DDR_PLL_DITHER1_DITHER_EN_MASK)
+#define DDR_PLL_DITHER1_UPDATE_COUNT_LSB 27
+#define DDR_PLL_DITHER1_UPDATE_COUNT_MASK 0x78000000
+#define DDR_PLL_DITHER1_UPDATE_COUNT_SET(x) \
+       (((x) << DDR_PLL_DITHER1_UPDATE_COUNT_LSB) & DDR_PLL_DITHER1_UPDATE_COUNT_MASK)
+#define DDR_PLL_DITHER1_NFRAC_STEP_LSB 20
+#define DDR_PLL_DITHER1_NFRAC_STEP_MASK 0x07f00000
+#define DDR_PLL_DITHER1_NFRAC_STEP_SET(x) \
+       (((x) << DDR_PLL_DITHER1_NFRAC_STEP_LSB) & DDR_PLL_DITHER1_NFRAC_STEP_MASK)
+#define DDR_PLL_DITHER1_NFRAC_MIN_LSB 0
+#define DDR_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff
+#define DDR_PLL_DITHER1_NFRAC_MIN_SET(x) \
+       (((x) << DDR_PLL_DITHER1_NFRAC_MIN_LSB) & DDR_PLL_DITHER1_NFRAC_MIN_MASK)
+#define DDR_PLL_DITHER2_NFRAC_MAX_LSB 0
+#define DDR_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff
+#define DDR_PLL_DITHER2_NFRAC_MAX_SET(x) \
+       (((x) << DDR_PLL_DITHER2_NFRAC_MAX_LSB) & DDR_PLL_DITHER2_NFRAC_MAX_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB 24
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK 0x01000000
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB) & CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB 21
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK 0x00200000
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB 20
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK 0x00100000
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB 15
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK 0x000f8000
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB 10
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK 0x00007c00
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB 5
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK 0x000003e0
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB 4
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK 0x00000010
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK)
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB 3
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK 0x00000008
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB 2
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK 0x00000004
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK)
+
+#define CPU_PLL_CONFIG1_NINT_VAL CPU_PLL_CONFIG1_NINT_SET(0x1f)
+#define CPU_PLL_CONFIG_REF_DIV_VAL CPU_PLL_CONFIG_REFDIV_SET(0x1)
+#define CPU_PLL_CONFIG_RANGE_VAL CPU_PLL_CONFIG_RANGE_SET(0)
+#define CPU_PLL_CONFIG_OUT_DIV_VAL1 CPU_PLL_CONFIG_OUTDIV_SET(0)
+#define CPU_PLL_CONFIG_OUT_DIV_VAL2 CPU_PLL_CONFIG_OUTDIV_SET(0)
+#define CPU_PLL_DITHER1_VAL CPU_PLL_DITHER1_DITHER_EN_SET(0) | \
+       CPU_PLL_DITHER1_NFRAC_MIN_SET(0) | \
+       CPU_PLL_DITHER1_NFRAC_STEP_SET(0) | \
+       CPU_PLL_DITHER1_UPDATE_COUNT_SET(0x0)
+#define CPU_PLL_DITHER2_VAL CPU_PLL_DITHER2_NFRAC_MAX_SET(0x0)
+#define DDR_PLL_CONFIG1_NINT_VAL DDR_PLL_CONFIG1_NINT_SET(0x1a)
+#define DDR_PLL_CONFIG_REF_DIV_VAL DDR_PLL_CONFIG_REFDIV_SET(0x1)
+#define DDR_PLL_CONFIG_RANGE_VAL DDR_PLL_CONFIG_RANGE_SET(0)
+#define DDR_PLL_CONFIG_OUT_DIV_VAL1 DDR_PLL_CONFIG_OUTDIV_SET(0)
+#define DDR_PLL_CONFIG_OUT_DIV_VAL2 DDR_PLL_CONFIG_OUTDIV_SET(0)
+#define DDR_PLL_DITHER1_VAL DDR_PLL_DITHER1_DITHER_EN_SET(0) | \
+       DDR_PLL_DITHER1_NFRAC_MIN_SET(0) | \
+       DDR_PLL_DITHER1_NFRAC_STEP_SET(0) | \
+       DDR_PLL_DITHER1_UPDATE_COUNT_SET(0x0)
+#define DDR_PLL_DITHER2_VAL DDR_PLL_DITHER2_NFRAC_MAX_SET(0x0)
+#define AHB_CLK_FROM_DDR CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(0)
+#define CPU_AND_DDR_CLK_FROM_DDR \
+       CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(0)
+#define CPU_AND_DDR_CLK_FROM_CPU \
+       CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(0)
+#define CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL \
+       CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(0x2)
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV \
+       CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(0)
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV \
+       CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(0)
+
+static inline void set_val(u32 _reg, u32 _mask, u32 _val)
+{
+       void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
+                                            AR71XX_PLL_SIZE, MAP_NOCACHE);
+       writel((readl(pll_regs + _reg) & (~(_mask))) | _val, pll_regs + _reg);
+}
+
+#define cpu_pll_set(_mask, _val)       \
+       set_val(QCA956X_PLL_CPU_CONFIG_REG, _mask, _val)
+
+#define ddr_pll_set(_mask, _val)       \
+       set_val(QCA956X_PLL_DDR_CONFIG_REG, _mask, _val)
+
+#define cpu_ddr_control_set(_mask, _val)       \
+       set_val(QCA956X_PLL_CLK_CTRL_REG, _mask, _val)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static u32 qca956x_get_xtal(void)
+{
+       u32 val;
+
+       val = ath79_get_bootstrap();
+       if (val & QCA956X_BOOTSTRAP_REF_CLK_40)
+               return 40000000;
+       else
+               return 25000000;
+}
+
+int get_serial_clock(void)
+{
+       return qca956x_get_xtal();
+}
+
+void qca956x_pll_init(void)
+{
+       void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE,
+                                             QCA956X_SRIF_SIZE, MAP_NOCACHE);
+       void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
+                                            AR71XX_PLL_SIZE, MAP_NOCACHE);
+
+       /* 8.16.2 Baseband DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+               PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(1) |
+               PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + QCA956X_SRIF_BB_DPLL2_REG);
+
+       /* 8.16.2 PCIE DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+               PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(3) |
+               PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + QCA956X_SRIF_PCIE_DPLL2_REG);
+
+       /* 8.16.2 DDR DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+               PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6),
+               srif_regs + QCA956X_SRIF_DDR_DPLL2_REG);
+
+       /* 8.16.2 CPU DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(1) | PLL_SRIF_DPLL2_KD_SET(7) |
+                         PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6),
+                         srif_regs + QCA956X_SRIF_CPU_DPLL2_REG);
+
+       /* pll_bypass_set */
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK,
+                           CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK,
+                           CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK,
+                           CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1));
+
+       /* init_cpu_pll */
+       cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK,  CPU_PLL_CONFIG_PLLPWD_SET(1));
+       cpu_pll_set(CPU_PLL_CONFIG_REFDIV_MASK, CPU_PLL_CONFIG_REF_DIV_VAL);
+       cpu_pll_set(CPU_PLL_CONFIG_RANGE_MASK, CPU_PLL_CONFIG_RANGE_VAL);
+       cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL1);
+       set_val(QCA956X_PLL_CPU_CONFIG1_REG, CPU_PLL_CONFIG1_NINT_MASK, \
+               CPU_PLL_CONFIG1_NINT_VAL);
+
+       /* init_ddr_pll */
+       ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK,  DDR_PLL_CONFIG_PLLPWD_SET(1));
+       ddr_pll_set(DDR_PLL_CONFIG_REFDIV_MASK, DDR_PLL_CONFIG_REF_DIV_VAL);
+       ddr_pll_set(DDR_PLL_CONFIG_RANGE_MASK, DDR_PLL_CONFIG_RANGE_VAL);
+       ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL1);
+       set_val(QCA956X_PLL_DDR_CONFIG1_REG, DDR_PLL_CONFIG1_NINT_MASK,
+               DDR_PLL_CONFIG1_NINT_VAL);
+
+       /* init_ahb_pll */
+       writel(CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL | AHB_CLK_FROM_DDR |
+               CPU_AND_DDR_CLK_FROM_DDR | CPU_AND_DDR_CLK_FROM_CPU |
+               CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV | CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV |
+               CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1) |
+               CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1) |
+               CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1), pll_regs + QCA956X_PLL_CLK_CTRL_REG);
+
+       /* ddr_pll_dither_unset */
+       writel(DDR_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_DDR_DIT_FRAC_REG);
+       writel(DDR_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_DDR_DIT2_FRAC_REG);
+
+       /* cpu_pll_dither_unset */
+       writel(CPU_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_CPU_DIT_FRAC_REG);
+       writel(CPU_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_CPU_DIT2_FRAC_REG);
+
+       /* pll_pwd_unset */
+       cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK, CPU_PLL_CONFIG_PLLPWD_SET(0));
+       ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK, DDR_PLL_CONFIG_PLLPWD_SET(0));
+
+       /* outdiv_unset */
+       cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL2);
+       ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL2);
+
+       /* pll_bypass_unset */
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK,
+                           CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(0));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK,
+                           CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(0));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK,
+                           CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(0));
+
+       while (readl(pll_regs + QCA956X_PLL_CPU_CONFIG_REG) & 0x8000000)
+               /* NOP */;
+
+       while (readl(pll_regs + QCA956X_PLL_DDR_CONFIG_REG) & 0x8000000)
+               /* NOP */;
+}
+
+int get_clocks(void)
+{
+       void __iomem *regs;
+       u32 ref_rate, cpu_rate, ddr_rate, ahb_rate;
+       u32 out_div, ref_div, postdiv, nint, hfrac, lfrac, clk_ctrl;
+       u32 pll, cpu_pll, ddr_pll, misc;
+
+       /*
+        * QCA956x timer init workaround has to be applied right before setting
+        * up the clock. Else, there will be no jiffies
+        */
+       regs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                          MAP_NOCACHE);
+       misc = readl(regs + AR71XX_RESET_REG_MISC_INT_ENABLE);
+       misc |= MISC_INT_MIPS_SI_TIMERINT_MASK;
+       writel(misc, regs + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+       regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+                          MAP_NOCACHE);
+       pll = readl(regs + QCA956X_PLL_CPU_CONFIG_REG);
+       out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
+       ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG_REFDIV_MASK;
+
+       pll = readl(regs + QCA956X_PLL_CPU_CONFIG1_REG);
+       nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG1_NINT_MASK;
+       hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK;
+       lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK;
+
+       ref_rate = qca956x_get_xtal();
+
+       cpu_pll = nint * ref_rate / ref_div;
+       cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
+       cpu_pll += (hfrac >> 13) * ref_rate / ref_div;
+       cpu_pll /= (1 << out_div);
+
+       pll = readl(regs + QCA956X_PLL_DDR_CONFIG_REG);
+       out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+                         QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK;
+       ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+                         QCA956X_PLL_DDR_CONFIG_REFDIV_MASK;
+       pll = readl(regs + QCA956X_PLL_DDR_CONFIG1_REG);
+       nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) &
+               QCA956X_PLL_DDR_CONFIG1_NINT_MASK;
+       hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) &
+               QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK;
+       lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) &
+               QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK;
+
+       ddr_pll = nint * ref_rate / ref_div;
+       ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
+       ddr_pll += (hfrac >> 13) * ref_rate / ref_div;
+       ddr_pll /= (1 << out_div);
+
+       clk_ctrl = readl(regs + QCA956X_PLL_CLK_CTRL_REG);
+
+       postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+                 QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+
+       if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
+               cpu_rate = ref_rate;
+       else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL)
+               cpu_rate = ddr_pll / (postdiv + 1);
+       else
+               cpu_rate = cpu_pll / (postdiv + 1);
+
+       postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+                 QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
+
+       if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
+               ddr_rate = ref_rate;
+       else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL)
+               ddr_rate = cpu_pll / (postdiv + 1);
+       else
+               ddr_rate = ddr_pll / (postdiv + 1);
+
+       postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+                 QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
+
+       if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
+               ahb_rate = ref_rate;
+       else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+               ahb_rate = ddr_pll / (postdiv + 1);
+       else
+               ahb_rate = cpu_pll / (postdiv + 1);
+
+       gd->cpu_clk = cpu_rate;
+       gd->mem_clk = ddr_rate;
+       gd->bus_clk = ahb_rate;
+
+       debug("cpu_clk=%u, ddr_clk=%u, bus_clk=%u\n",
+             cpu_rate, ddr_rate, ahb_rate);
+
+       return 0;
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+       if (!gd->bus_clk)
+               get_clocks();
+       return gd->bus_clk;
+}
+
+ulong get_ddr_freq(ulong dummy)
+{
+       if (!gd->mem_clk)
+               get_clocks();
+       return gd->mem_clk;
+}
diff --git a/arch/mips/mach-ath79/qca956x/cpu.c b/arch/mips/mach-ath79/qca956x/cpu.c
new file mode 100644 (file)
index 0000000..08a8c84
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include <common.h>
+
+/* The lowlevel_init() is not needed on QCA956X */
+void lowlevel_init(void) {}
diff --git a/arch/mips/mach-ath79/qca956x/ddr.c b/arch/mips/mach-ath79/qca956x/ddr.c
new file mode 100644 (file)
index 0000000..fb22304
--- /dev/null
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ *
+ * Based on QSDK
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ath79.h>
+
+#define DDR_FSM_WAIT_CTRL_VAL 0xa12
+#define DDR_CTL_CONFIG_SRAM_TSEL_LSB 30
+#define DDR_CTL_CONFIG_SRAM_TSEL_MASK 0xc0000000
+#define DDR_CTL_CONFIG_SRAM_TSEL_SET(x) \
+       (((x) << DDR_CTL_CONFIG_SRAM_TSEL_LSB) & DDR_CTL_CONFIG_SRAM_TSEL_MASK)
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB 20
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK 0x00100000
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB 19
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK 0x00080000
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB 18
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK 0x00040000
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB 17
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK 0x00020000
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB 16
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK 0x00010000
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB 15
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK 0x00008000
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB 14
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK 0x00004000
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB 6
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK 0x00000040
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(x) \
+       (((x) << DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB) & DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK)
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB 2
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK 0x00000004
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB) & DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK)
+#define DDR_CTL_CONFIG_HALF_WIDTH_LSB 1
+#define DDR_CTL_CONFIG_HALF_WIDTH_MASK 0x00000002
+#define DDR_CTL_CONFIG_HALF_WIDTH_SET(x) \
+       (((x) << DDR_CTL_CONFIG_HALF_WIDTH_LSB) & DDR_CTL_CONFIG_HALF_WIDTH_MASK)
+#define DDR_CONFIG_CAS_LATENCY_MSB_LSB 31
+#define DDR_CONFIG_CAS_LATENCY_MSB_MASK 0x80000000
+#define DDR_CONFIG_CAS_LATENCY_MSB_SET(x) \
+       (((x) << DDR_CONFIG_CAS_LATENCY_MSB_LSB) & DDR_CONFIG_CAS_LATENCY_MSB_MASK)
+#define DDR_CONFIG_OPEN_PAGE_LSB 30
+#define DDR_CONFIG_OPEN_PAGE_MASK 0x40000000
+#define DDR_CONFIG_OPEN_PAGE_SET(x) \
+       (((x) << DDR_CONFIG_OPEN_PAGE_LSB) & DDR_CONFIG_OPEN_PAGE_MASK)
+#define DDR_CONFIG_CAS_LATENCY_LSB 27
+#define DDR_CONFIG_CAS_LATENCY_MASK 0x38000000
+#define DDR_CONFIG_CAS_LATENCY_SET(x) \
+       (((x) << DDR_CONFIG_CAS_LATENCY_LSB) & DDR_CONFIG_CAS_LATENCY_MASK)
+#define DDR_CONFIG_TMRD_LSB 23
+#define DDR_CONFIG_TMRD_MASK 0x07800000
+#define DDR_CONFIG_TMRD_SET(x) \
+       (((x) << DDR_CONFIG_TMRD_LSB) & DDR_CONFIG_TMRD_MASK)
+#define DDR_CONFIG_TRFC_LSB 17
+#define DDR_CONFIG_TRFC_MASK 0x007e0000
+#define DDR_CONFIG_TRFC_SET(x) \
+       (((x) << DDR_CONFIG_TRFC_LSB) & DDR_CONFIG_TRFC_MASK)
+#define DDR_CONFIG_TRRD_LSB 13
+#define DDR_CONFIG_TRRD_MASK 0x0001e000
+#define DDR_CONFIG_TRRD_SET(x) \
+       (((x) << DDR_CONFIG_TRRD_LSB) & DDR_CONFIG_TRRD_MASK)
+#define DDR_CONFIG_TRP_LSB 9
+#define DDR_CONFIG_TRP_MASK 0x00001e00
+#define DDR_CONFIG_TRP_SET(x) \
+       (((x) << DDR_CONFIG_TRP_LSB) & DDR_CONFIG_TRP_MASK)
+#define DDR_CONFIG_TRCD_LSB 5
+#define DDR_CONFIG_TRCD_MASK 0x000001e0
+#define DDR_CONFIG_TRCD_SET(x) \
+       (((x) << DDR_CONFIG_TRCD_LSB) & DDR_CONFIG_TRCD_MASK)
+#define DDR_CONFIG_TRAS_LSB 0
+#define DDR_CONFIG_TRAS_MASK 0x0000001f
+#define DDR_CONFIG_TRAS_SET(x) \
+       (((x) << DDR_CONFIG_TRAS_LSB) & DDR_CONFIG_TRAS_MASK)
+#define DDR_CONFIG2_HALF_WIDTH_LOW_LSB 31
+#define DDR_CONFIG2_HALF_WIDTH_LOW_MASK 0x80000000
+#define DDR_CONFIG2_HALF_WIDTH_LOW_SET(x) \
+       (((x) << DDR_CONFIG2_HALF_WIDTH_LOW_LSB) & DDR_CONFIG2_HALF_WIDTH_LOW_MASK)
+#define DDR_CONFIG2_SWAP_A26_A27_LSB 30
+#define DDR_CONFIG2_SWAP_A26_A27_MASK 0x40000000
+#define DDR_CONFIG2_SWAP_A26_A27_SET(x) \
+       (((x) << DDR_CONFIG2_SWAP_A26_A27_LSB) & DDR_CONFIG2_SWAP_A26_A27_MASK)
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_LSB 26
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_MASK 0x3c000000
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_SET(x) \
+       (((x) << DDR_CONFIG2_GATE_OPEN_LATENCY_LSB) & DDR_CONFIG2_GATE_OPEN_LATENCY_MASK)
+#define DDR_CONFIG2_TWTR_LSB 21
+#define DDR_CONFIG2_TWTR_MASK 0x03e00000
+#define DDR_CONFIG2_TWTR_SET(x) \
+       (((x) << DDR_CONFIG2_TWTR_LSB) & DDR_CONFIG2_TWTR_MASK)
+#define DDR_CONFIG2_TRTP_LSB 17
+#define DDR_CONFIG2_TRTP_MASK 0x001e0000
+#define DDR_CONFIG2_TRTP_SET(x) \
+       (((x) << DDR_CONFIG2_TRTP_LSB) & DDR_CONFIG2_TRTP_MASK)
+#define DDR_CONFIG2_TRTW_LSB 12
+#define DDR_CONFIG2_TRTW_MASK 0x0001f000
+#define DDR_CONFIG2_TRTW_SET(x) \
+       (((x) << DDR_CONFIG2_TRTW_LSB) & DDR_CONFIG2_TRTW_MASK)
+#define DDR_CONFIG2_TWR_LSB 8
+#define DDR_CONFIG2_TWR_MASK 0x00000f00
+#define DDR_CONFIG2_TWR_SET(x) \
+       (((x) << DDR_CONFIG2_TWR_LSB) & DDR_CONFIG2_TWR_MASK)
+#define DDR_CONFIG2_CKE_LSB 7
+#define DDR_CONFIG2_CKE_MASK 0x00000080
+#define DDR_CONFIG2_CKE_SET(x) \
+       (((x) << DDR_CONFIG2_CKE_LSB) & DDR_CONFIG2_CKE_MASK)
+#define DDR_CONFIG2_CNTL_OE_EN_LSB 5
+#define DDR_CONFIG2_CNTL_OE_EN_MASK 0x00000020
+#define DDR_CONFIG2_CNTL_OE_EN_SET(x) \
+       (((x) << DDR_CONFIG2_CNTL_OE_EN_LSB) & DDR_CONFIG2_CNTL_OE_EN_MASK)
+#define DDR_CONFIG2_BURST_LENGTH_LSB 0
+#define DDR_CONFIG2_BURST_LENGTH_MASK 0x0000000f
+#define DDR_CONFIG2_BURST_LENGTH_SET(x) \
+       (((x) << DDR_CONFIG2_BURST_LENGTH_LSB) & DDR_CONFIG2_BURST_LENGTH_MASK)
+#define RST_BOOTSTRAP_ADDRESS          0x180600b0
+#define PMU2_SWREGMSB_LSB 22
+#define PMU2_SWREGMSB_MASK 0xffc00000
+#define PMU2_SWREGMSB_SET(x) \
+       (((x) << PMU2_SWREGMSB_LSB) & PMU2_SWREGMSB_MASK)
+#define PMU2_PGM_LSB 21
+#define PMU2_PGM_MASK 0x00200000
+#define PMU2_PGM_SET(x) \
+       (((x) << PMU2_PGM_LSB) & PMU2_PGM_MASK)
+
+#define CPU_DDR_SYNC_MODE DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(0)
+
+/*
+* DDR2                      DDR1
+* 0x40c3   25MHz            0x4186   25Mhz
+* 0x4138   40MHz            0x4270   40Mhz
+*/
+#define CFG_DDR2_REFRESH_VAL 0x40c3
+#define CFG_DDR2_CONFIG_VAL DDR_CONFIG_CAS_LATENCY_MSB_SET(0x1) | \
+       DDR_CONFIG_OPEN_PAGE_SET(0x1) | DDR_CONFIG_CAS_LATENCY_SET(0x4) | \
+       DDR_CONFIG_TMRD_SET(0x6) | DDR_CONFIG_TRFC_SET(0x16) | \
+       DDR_CONFIG_TRRD_SET(0x7) | DDR_CONFIG_TRP_SET(0xb) | \
+       DDR_CONFIG_TRCD_SET(0xb) | DDR_CONFIG_TRAS_SET(0)
+#define CFG_DDR2_CONFIG2_VAL DDR_CONFIG2_HALF_WIDTH_LOW_SET(0x1) | \
+       DDR_CONFIG2_SWAP_A26_A27_SET(0x0) | DDR_CONFIG2_GATE_OPEN_LATENCY_SET(0xa) | \
+       DDR_CONFIG2_TWTR_SET(0x16) | DDR_CONFIG2_TRTP_SET(0xa) | \
+       DDR_CONFIG2_TRTW_SET(0xe) | DDR_CONFIG2_TWR_SET(0x2) | \
+       DDR_CONFIG2_CKE_SET(0x1) | DDR_CONFIG2_CNTL_OE_EN_SET(0x1) | \
+       DDR_CONFIG2_BURST_LENGTH_SET(0x8)
+
+#define CFG_DDR2_CONFIG3_VAL 0x0000000e
+#define CFG_DDR2_EXT_MODE_VAL1 0x782
+#define CFG_DDR2_EXT_MODE_VAL2 0x402
+#define CFG_DDR2_MODE_VAL_INIT 0xb53
+#define CFG_DDR2_MODE_VAL 0xa53
+#define CFG_DDR2_TAP_VAL 0x10
+#define CFG_DDR2_EN_TWL_VAL 0x00001e91
+#define CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16 0xffff
+
+#define CFG_DDR_CTL_CONFIG DDR_CTL_CONFIG_SRAM_TSEL_SET(0x1) | \
+       DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(0x1)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void qca956x_ddr_init(void)
+{
+       u32 ddr_config, ddr_config2, ddr_config3, mod_val, \
+               mod_val_init, cycle_val, tap_val, ctl_config;
+       void __iomem *ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
+                              MAP_NOCACHE);
+       void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE, QCA956X_SRIF_SIZE,
+                              MAP_NOCACHE);
+
+       ddr_config = CFG_DDR2_CONFIG_VAL;
+       ddr_config2 = CFG_DDR2_CONFIG2_VAL;
+       ddr_config3 = CFG_DDR2_CONFIG3_VAL;
+       mod_val_init = CFG_DDR2_MODE_VAL_INIT;
+       mod_val = CFG_DDR2_MODE_VAL;
+       tap_val = CFG_DDR2_TAP_VAL;
+       cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16;
+       ctl_config = CFG_DDR_CTL_CONFIG | DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(0x1) |
+                        DDR_CTL_CONFIG_HALF_WIDTH_SET(0x1) | CPU_DDR_SYNC_MODE;
+
+       writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);
+       udelay(10);
+
+       writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);
+       udelay(10);
+
+       writel(ctl_config, ddr_regs + QCA956X_DDR_REG_CTL_CONF);
+       udelay(10);
+
+       writel(cycle_val, ddr_regs + AR71XX_DDR_REG_RD_CYCLE);
+       udelay(100);
+
+       writel(0x74444444, ddr_regs + QCA956X_DDR_REG_BURST);
+       udelay(100);
+
+       writel(0x44444444, ddr_regs + QCA956X_DDR_REG_BURST2);
+       udelay(100);
+
+       writel(DDR_FSM_WAIT_CTRL_VAL, ddr_regs + QCA956X_DDR_REG_FSM_WAIT_CTRL);
+       udelay(100);
+
+       writel(0xfffff, ddr_regs + QCA956X_DDR_REG_TIMEOUT_MAX);
+       udelay(100);
+
+       writel(ddr_config, ddr_regs + AR71XX_DDR_REG_CONFIG);
+       udelay(100);
+
+       writel(ddr_config2, ddr_regs + AR71XX_DDR_REG_CONFIG2);
+       udelay(100);
+
+       writel(ddr_config3, ddr_regs + QCA956X_DDR_REG_DDR3_CONFIG);
+       udelay(100);
+
+       writel(CFG_DDR2_EN_TWL_VAL, ddr_regs + QCA956X_DDR_REG_DDR2_CONFIG);
+       udelay(100);
+
+       writel(ddr_config2 | 0x80, ddr_regs + AR71XX_DDR_REG_CONFIG2);  /* CKE Enable */
+       udelay(100);
+
+       writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */
+       udelay(10);
+
+       writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR2);
+       writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);        /* EMR2 */
+       udelay(10);
+
+       writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR3);
+       writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);        /* EMR3 */
+       udelay(10);
+
+       /* EMR DLL enable, Reduced Driver Impedance control, Differential DQS disabled */
+       writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR);
+       udelay(100);
+
+       writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+       udelay(10);
+
+       writel(mod_val_init, ddr_regs + AR71XX_DDR_REG_MODE);
+       udelay(1000);
+
+       writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR Write */
+       udelay(10);
+
+       writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */
+       udelay(10);
+
+       writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Auto Refresh */
+       udelay(10);
+
+       writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Auto Refresh */
+       udelay(10);
+
+       /* Issue MRS to remove DLL out-of-reset */
+       writel(mod_val, ddr_regs + AR71XX_DDR_REG_MODE);
+       udelay(100);
+
+       writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR write */
+       udelay(100);
+
+       writel(CFG_DDR2_EXT_MODE_VAL1, ddr_regs + AR71XX_DDR_REG_EMR);
+       udelay(100);
+
+       writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+       udelay(100);
+
+       writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR);
+       udelay(100);
+
+       writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+       udelay(100);
+
+       writel(CFG_DDR2_REFRESH_VAL, ddr_regs + AR71XX_DDR_REG_REFRESH);
+       udelay(100);
+
+       writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0);
+       writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1);
+       writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL2);
+       writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL3);
+
+       writel(0x633c8176, srif_regs + QCA956X_SRIF_PMU1_REG);
+       /* Set DDR2 Voltage to 1.8 volts */
+       writel(PMU2_SWREGMSB_SET(0x40) | PMU2_PGM_SET(0x1),
+              srif_regs + QCA956X_SRIF_PMU2_REG);
+}
diff --git a/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S
new file mode 100644 (file)
index 0000000..db54b57
--- /dev/null
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ *
+ * Based on QSDK
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <mach/ar71xx_regs.h>
+
+    .set noreorder
+
+LEAF(ddr_tap_tuning)
+       li      a0, 0xbd001f00
+       sw      zero, 0x0(a0)                   /* Place where the tap values are saved and used for SWEEP */
+       sw      zero, 0x4(a0)                   /* Place where the number of passing taps are saved. */
+       sw      zero, 0x14(a0)          /* Place where the last pass tap value is stored */
+       li      a1, 0xaa55aa55          /* Indicates that the First pass tap value is not found */
+       sw      a1, 0x10(a0)            /* Place where the First pass tap value is stored */
+        nop
+
+       li      a0, CKSEG1ADDR(AR71XX_RESET_BASE)               /* RESET_BASE_ADDRESS */
+       lw      a1, 0x1c(a0)            /* Reading the RST_RESET_ADDRESS */
+       li      a2, 0x08000000          /* Setting the RST_RESET_RTC_RESET */
+       or      a1, a1, a2
+       sw      a1, 0x1c(a0)
+
+       li      a3, 0xffffffff
+       xor     a2, a2, a3
+       and     a1, a1, a2
+       sw      a1, 0x1c(a0)            /* Taking the RTC out of RESET */
+        nop
+
+       li      a0, CKSEG1ADDR(QCA956X_RTC_BASE)                /* RTC_BASE_ADDRESS */
+       li      a1, 0x1
+       sw      a1, 0x0040(a0)          /* RTC_SYNC_RESET_ADDRESS */
+
+       li      a2, 0x2
+
+_poll_for_RTC_ON:
+       lw      a1, 0x0044(a0)          /* RTC_SYNC_STATUS_ADDRESS */
+       and     a1, a2, a1
+       bne     a1, a2, _poll_for_RTC_ON
+         nop
+
+_CHANGE_TAPS:
+       li      t0, 0xbd001f00          /* Read the current value of the TAP for programming */
+       lw      t1, 0x0(t0)
+       li      t2, 0x00000000
+       or      t3, t1, t2
+
+       li      t0, 0xb8000000          /* DDR_BASE_ADDRESS */
+       sw      t3, 0x1c(t0)            /* TAP_CONTROL_0_ADDRESS */
+       sw      t3, 0x20(t0)            /* TAP_CONTROL_1_ADDRESS */
+       sw      t3, 0x24(t0)            /* TAP_CONTROL_2_ADDRESS */
+       sw      t3, 0x28(t0)            /* TAP_CONTROL_3_ADDRESS */
+
+       li      t1, 0x00000010          /* Running the test 8 times */
+       sw      t1, 0x0068(t0)          /* PERF_COMP_ADDR_1_ADDRESS */
+
+       li      t1, 0xfa5de83f          /* 4 Row Address Bits, 4 Column Address Bits, 2 BA bits */
+       sw      t1, 0x002c(t0)          /* PERF_MASK_ADDR_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0070(t0)          /* PERF_COMP_AHB_GE0_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0040(t0)          /* PERF_COMP_AHB_GE1_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0078(t0)          /* PERF_COMP_AHB_GE1_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0034(t0)          /* PERF_MASK_AHB_GE0_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x006c(t0)          /* PERF_MASK_AHB_GE0_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x003c(t0)          /* PERF_MASK_AHB_GE1_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0074(t0)          /* PERF_MASK_AHB_GE1_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0038(t0)          /* PERF_COMP_AHB_GE0_0_ADDRESS */
+
+       li      t1, 0x00000001
+       sw      t1, 0x011c(t0)          /* DDR_BIST_ADDRESS */
+
+       li      t2, 0x1
+
+_bist_done_poll:
+       lw      t1, 0x0120(t0)          /* DDR_BIST_STATUS_ADDRESS */
+       and     t1, t1, t2
+       bne     t1, t2, _bist_done_poll
+        nop
+
+       lw      t1, 0x0120(t0)          /* DDR_BIST_STATUS_ADDRESS */
+       li      t4, 0x000001fe
+       and     t2, t1, t4
+       srl     t2, t2, 0x1             /* no. of Pass Runs */
+
+       li      t5, 0x00000000
+       sw      t5, 0x011c(t0)          /* DDR_BIST_ADDRESS     - Stop the DDR BIST test */
+
+       li      t5, 0x0001fe00
+       and     t5, t5, t1
+       bnez    t5, _iterate_tap                /* This is a redundant compare but nevertheless - Comparing the FAILS */
+        nop
+
+       lw      t1, 0x0068(t0)          /* PERF_COMP_ADDR_1_ADDRESS */
+       li      t3, 0x000001fe
+       and     t3, t3, t1
+       srl     t3, t3, 0x1             /* No. of runs in the config register. */
+       bne     t3, t2, _iterate_tap
+        nop
+
+pass_tap:
+       li      t0, 0xbd001f00
+       lw      t1, 0x4(t0)
+       addiu   t1, t1, 0x1
+       sw      t1, 0x4(t0)
+
+       li      t0, 0xbd001f10
+       lw      t1, 0x0(t0)
+       li      t2, 0xaa55aa55
+       beq     t1, t2, _first_pass
+        nop
+
+       li      t0, 0xbd001f00
+       lw      t1, 0x0(t0)
+       li      t0, 0xbd001f10
+       sw      t1, 0x4(t0)
+        nop
+       b       _iterate_tap
+        nop
+
+_first_pass:
+       li      t0, 0xbd001f00
+       lw      t1, 0x0(t0)
+       li      t0, 0xbd001f10
+       sw      t1, 0x0(t0)
+       sw      t1, 0x4(t0)
+        nop
+
+_iterate_tap:
+       li      t0, 0xbd001f00
+       lw      t1, 0x0(t0)
+       li      t2, 0x3f
+       beq     t1, t2, _STOP_TEST
+        nop
+
+       addiu   t1, t1, 0x1
+       sw      t1, 0x0(t0)
+        nop
+       b       _CHANGE_TAPS
+        nop
+
+_STOP_TEST:
+       li      t0, 0xbd001f00
+       lw      t1, 0x4(t0)
+       bnez    t1, _load_center_tap
+        nop
+
+       li      t3, 0x8                 /* Default Tap to be used */
+       b       _load_tap_into_reg
+        nop
+
+_load_center_tap:
+       li      t0, 0xbd001f10
+       lw      t1, 0x0(t0)
+       lw      t2, 0x4(t0)
+       add     t3, t1, t2
+       srl     t3, t3, 0x1
+       li      t4, 0x3f
+       and     t3, t3, t4
+
+_load_tap_into_reg:
+       li      t0, 0xb8000000
+       sw      t3, 0x1c(t0)            /* TAP_CONTROL_0_ADDRESS */
+       sw      t3, 0x20(t0)            /* TAP_CONTROL_1_ADDRESS */
+       sw      t3, 0x24(t0)            /* TAP_CONTROL_2_ADDRESS */
+       sw      t3, 0x28(t0)            /* TAP_CONTROL_3_ADDRESS */
+
+        nop
+       jr ra
+        nop
+    END(ddr_tap_tuning)
index 6a94d886f94ff7832fc8ef3a2fd1598391c8d57a..0ab3ab6383c8cb33b8f5eecb24d30e4fd2de9b77 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
+ * Copyright (C) 2018-2019 Rosy Song <rosysong@rosinson.com>
  */
 
 #include <common.h>
 #include <mach/ath79.h>
 #include <mach/ar71xx_regs.h>
 
+/* QCA956X ETH_SGMII_SERDES Registers */
+#define SGMII_SERDES_RES_CALIBRATION_LSB 23
+#define SGMII_SERDES_RES_CALIBRATION_MASK 0x07800000
+#define SGMII_SERDES_RES_CALIBRATION_SET(x) \
+       (((x) << SGMII_SERDES_RES_CALIBRATION_LSB) & SGMII_SERDES_RES_CALIBRATION_MASK)
+#define SGMII_SERDES_CDR_BW_LSB 1
+#define SGMII_SERDES_CDR_BW_MASK 0x00000006
+#define SGMII_SERDES_CDR_BW_SET(x) \
+       (((x) << SGMII_SERDES_CDR_BW_LSB) & SGMII_SERDES_CDR_BW_MASK)
+#define SGMII_SERDES_TX_DR_CTRL_LSB 4
+#define SGMII_SERDES_TX_DR_CTRL_MASK 0x00000070
+#define SGMII_SERDES_TX_DR_CTRL_SET(x) \
+       (((x) << SGMII_SERDES_TX_DR_CTRL_LSB) & SGMII_SERDES_TX_DR_CTRL_MASK)
+#define SGMII_SERDES_PLL_BW_LSB 8
+#define SGMII_SERDES_PLL_BW_MASK 0x00000100
+#define SGMII_SERDES_PLL_BW_SET(x) \
+       (((x) << SGMII_SERDES_PLL_BW_LSB) & SGMII_SERDES_PLL_BW_MASK)
+#define SGMII_SERDES_EN_SIGNAL_DETECT_LSB 16
+#define SGMII_SERDES_EN_SIGNAL_DETECT_MASK 0x00010000
+#define SGMII_SERDES_EN_SIGNAL_DETECT_SET(x) \
+       (((x) << SGMII_SERDES_EN_SIGNAL_DETECT_LSB) & SGMII_SERDES_EN_SIGNAL_DETECT_MASK)
+#define SGMII_SERDES_FIBER_SDO_LSB 17
+#define SGMII_SERDES_FIBER_SDO_MASK 0x00020000
+#define SGMII_SERDES_FIBER_SDO_SET(x) \
+       (((x) << SGMII_SERDES_FIBER_SDO_LSB) & SGMII_SERDES_FIBER_SDO_MASK)
+#define SGMII_SERDES_VCO_REG_LSB 27
+#define SGMII_SERDES_VCO_REG_MASK 0x78000000
+#define SGMII_SERDES_VCO_REG_SET(x) \
+       (((x) << SGMII_SERDES_VCO_REG_LSB) & SGMII_SERDES_VCO_REG_MASK)
+#define SGMII_SERDES_VCO_FAST_LSB 9
+#define SGMII_SERDES_VCO_FAST_MASK 0x00000200
+#define SGMII_SERDES_VCO_FAST_GET(x) \
+       (((x) & SGMII_SERDES_VCO_FAST_MASK) >> SGMII_SERDES_VCO_FAST_LSB)
+#define SGMII_SERDES_VCO_SLOW_LSB 10
+#define SGMII_SERDES_VCO_SLOW_MASK 0x00000400
+#define SGMII_SERDES_VCO_SLOW_GET(x) \
+       (((x) & SGMII_SERDES_VCO_SLOW_MASK) >> SGMII_SERDES_VCO_SLOW_LSB)
+
 void _machine_restart(void)
 {
        void __iomem *base;
@@ -152,6 +191,236 @@ static int eth_init_qca953x(void)
        return 0;
 }
 
+static int qca956x_sgmii_cal(void)
+{
+       int i;
+       u32 reg, rev_sgmii_val;
+       u32 vco_fast, vco_slow;
+       u32 start_val = 0, end_val = 0;
+       void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                                         MAP_NOCACHE);
+       const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII;
+
+       writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG);
+
+       reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+       vco_fast = SGMII_SERDES_VCO_FAST_GET(reg);
+       vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg);
+
+       /* Set resistor calibration from 0000 to 1111 */
+       for (i = 0; i < 0x10; i++) {
+               reg = (readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) &
+                     ~SGMII_SERDES_RES_CALIBRATION_MASK) |
+                     SGMII_SERDES_RES_CALIBRATION_SET(i);
+               writel(reg, gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+               udelay(50);
+
+               reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+               if (vco_fast != SGMII_SERDES_VCO_FAST_GET(reg) ||
+                   vco_slow != SGMII_SERDES_VCO_SLOW_GET(reg)) {
+                       if (start_val == 0) {
+                               start_val = i;
+                               end_val = i;
+                       } else {
+                               end_val = i;
+                       }
+               }
+               vco_fast = SGMII_SERDES_VCO_FAST_GET(reg);
+               vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg);
+       }
+
+       if (start_val == 0)
+               rev_sgmii_val = 0x7;
+       else
+               rev_sgmii_val = (start_val + end_val) >> 1;
+
+       writel((readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) &
+              ~SGMII_SERDES_RES_CALIBRATION_MASK) |
+              SGMII_SERDES_RES_CALIBRATION_SET(rev_sgmii_val),
+              gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+       writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG);
+
+       reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+       writel(SGMII_SERDES_CDR_BW_SET(3) | SGMII_SERDES_TX_DR_CTRL_SET(1) |
+              SGMII_SERDES_PLL_BW_SET(1) | SGMII_SERDES_EN_SIGNAL_DETECT_SET(1) |
+              SGMII_SERDES_FIBER_SDO_SET(1) | SGMII_SERDES_VCO_REG_SET(3) | reg,
+              gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+       setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+       clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+
+       while (!(readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) & BIT(15)))
+               /* NOP */;
+
+       return 0;
+}
+
+static int qca956x_sgmii_setup(void)
+{
+       int i;
+       u32 s = 0, reg = 0;
+       u32 _regs[] = {
+               BIT(4), /* HW_RX_125M_N */
+               BIT(2), /* RX_125M_N */
+               BIT(3), /* TX_125M_N */
+               BIT(0), /* RX_CLK_N */
+               BIT(1), /* TX_CLK_N */
+       };
+       void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+                                         MAP_NOCACHE);
+
+       /* Force sgmii mode */
+       writel(BIT(6) | BIT(15) | BIT(8), gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+       udelay(10);
+       writel(0x2 | BIT(5) | (0x2 << 6), gregs + QCA956X_GMAC_REG_SGMII_CONFIG);
+
+       /* SGMII reset sequence sugguest by qca systems team. */
+       writel(0, gregs + QCA956X_GMAC_REG_SGMII_RESET);
+       for (i = 0; i < ARRAY_SIZE(_regs); i++) {
+               reg |= _regs[i];
+               writel(reg, gregs + QCA956X_GMAC_REG_SGMII_RESET);
+       }
+
+       writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15),
+              gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+
+       /*
+        * WARNING: Across resets SGMII link status goes to weird state.
+        * if 0xb8070058 (SGMII_DEBUG Register) reads other than 0xf or 0x10
+        * for sure we are in bad state.
+        * Issue a PHY RESET in MR_AN_CONTROL_ADDRESS to keep going.
+        */
+       i = 0;
+       s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff);
+       while (!(s == 0xf || s == 0x10)) {
+               writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) | BIT(15),
+                      gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+               udelay(100);
+               writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15),
+                      gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+               if (i++ == 10)
+                       break;
+               s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff);
+       }
+
+       return 0;
+}
+
+static int qca956x_s17_reset(void)
+{
+       void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                                         MAP_NOCACHE);
+       const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII |
+                        QCA956X_RESET_EXTERNAL | QCA956X_RESET_SGMII_ANALOG |
+                        QCA956X_RESET_SWITCH;
+       /* Bits(Reserved in datasheet) should be set to 1 */
+       const u32 mask_r = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII |
+                        QCA956X_RESET_EXTERNAL;
+
+       setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+       clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask_r);
+       mdelay(1);
+
+       /* Reset s17 switch(GPIO11) SYS_RST_L */
+       writel(readl(regs + AR71XX_GPIO_REG_OE) & ~BIT(11),
+              regs + AR71XX_GPIO_REG_OE);
+       udelay(100);
+
+       writel(readl(regs + AR71XX_GPIO_REG_OUT) & ~BIT(11),
+              regs + AR71XX_GPIO_REG_OUT);
+       udelay(100);
+       writel(readl(regs + AR71XX_GPIO_REG_OUT) | BIT(11),
+              regs + AR71XX_GPIO_REG_OUT);
+
+       return 0;
+}
+
+static int qca956x_init_mdio(void)
+{
+       u32 reg;
+       void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+                                               MAP_NOCACHE);
+       void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                                         MAP_NOCACHE);
+       const u32 mask = QCA956X_RESET_GE0_MDIO | QCA956X_RESET_GE0_MAC |
+                        QCA956X_RESET_GE1_MDIO | QCA956X_RESET_GE1_MAC;
+
+       setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+       clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+
+       /* GPIO4 as MDI */
+       reg = readl(regs + QCA956X_GPIO_REG_IN_ENABLE3);
+       reg &= ~(0xff << 16);
+       reg |= (0x4 << 16);
+       writel(reg, regs + QCA956X_GPIO_REG_IN_ENABLE3);
+
+       /* GPIO4 as MDO */
+       reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC1);
+       reg &= ~0xff;
+       reg |= 0x20;
+       writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC1);
+
+       /* Init MDC(GPIO3) / MDIO(GPIO4) */
+       reg = readl(regs + AR71XX_GPIO_REG_OE);
+       reg &= ~BIT(4);
+       writel(reg, regs + AR71XX_GPIO_REG_OE);
+       udelay(100);
+
+       reg = readl(regs + AR71XX_GPIO_REG_OE);
+       reg &= ~BIT(3);
+       writel(reg, regs + AR71XX_GPIO_REG_OE);
+       udelay(100);
+
+       /* GPIO3 as MDI */
+       reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC0);
+       reg &= ~(0xff << 24);
+       reg |= (0x21 << 24);
+       writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC0);
+
+       return 0;
+}
+
+static int eth_init_qca956x(void)
+{
+       void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+                                         MAP_NOCACHE);
+
+       qca956x_sgmii_cal();
+       qca956x_s17_reset();
+       qca956x_init_mdio();
+
+       if (ath79_get_bootstrap() & QCA956X_BOOTSTRAP_REF_CLK_40)
+               writel(0x45500, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG);
+       else
+               writel(0xc5200, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG);
+
+       qca956x_sgmii_setup();
+
+       writel((3 << 16) | (3 << 14) | (1 << 0) | (1 << 6),
+              gregs + QCA956X_GMAC_REG_ETH_CFG);
+
+       writel((1 << 31) | (2 << 28) | (2 << 26) | (1 << 25),
+              pregs + QCA956X_PLL_ETH_XMII_CTRL_REG);
+       mdelay(1);
+
+       return 0;
+}
+
 int ath79_eth_reset(void)
 {
        /*
@@ -164,6 +433,8 @@ int ath79_eth_reset(void)
                return eth_init_ar934x();
        if (soc_is_qca953x())
                return eth_init_qca953x();
+       if (soc_is_qca956x())
+               return eth_init_qca956x();
 
        return -EINVAL;
 }
index f6e724588a9c5fcb0b4617719e418a7352228ea1..493eaad1df7fdc4e93b4e6ebd12032944070850b 100644 (file)
@@ -17,4 +17,6 @@
 #define GPIO_GPIO_ALT(x)                                  (0x74 + 4 * (x))
 #define GPIO_GPIO_ALT1(x)                                 (0x7c + 4 * (x))
 
+#define GCB_PHY_CFG                                       0x118
+
 #endif
index 4ebcb4b053cb16a08c549309d46ea9440268d7ac..a9834439993de448bd132a8edade956fe0ea9885 100644 (file)
@@ -22,12 +22,12 @@ choice
        prompt "Board select"
 
 config BOARD_GARDENA_SMART_GATEWAY_MT7688
-       bool "Gardena Smart Gateway"
+       bool "GARDENA smart Gateway"
        depends on SOC_MT7620
        select BOARD_LATE_INIT
        select SUPPORTS_BOOT_RAM
        help
-         Gardena Smart Gateway boards have a MT7688 SoC with 128 MiB of RAM
+         GARDENA smart Gateway boards have a MT7688 SoC with 128 MiB of RAM
          and 8 MiB of flash (SPI NOR) and additional SPI NAND storage.
 
 config BOARD_LINKIT_SMART_7688
index 58a4a04162b2e371bf8f5ef2be7d3159d1b579a4..6e5ef4c97f47e48fd9b07b0d76a7b7f837d6612e 100644 (file)
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <led.h>
+#include <miiphy.h>
 
 enum {
        BOARD_TYPE_PCB110 = 0xAABBCE00,
@@ -64,6 +65,28 @@ static void vcoreiii_gpio_set_alternate(int gpio, int mode)
        }
 }
 
+int board_phy_config(struct phy_device *phydev)
+{
+       if (gd->board_type == BOARD_TYPE_PCB110 ||
+           gd->board_type == BOARD_TYPE_PCB112) {
+               phy_write(phydev, 0, 31, 0x10);
+               phy_write(phydev, 0, 18, 0x80F0);
+               while (phy_read(phydev, 0, 18) & 0x8000)
+                       ;
+               phy_write(phydev, 0, 31, 0);
+       }
+       if (gd->board_type == BOARD_TYPE_PCB111) {
+               phy_write(phydev, 0, 31, 0x10);
+               phy_write(phydev, 0, 18, 0x80A0);
+               while (phy_read(phydev, 0, 18) & 0x8000)
+                       ;
+               phy_write(phydev, 0, 14, 0x800);
+               phy_write(phydev, 0, 31, 0);
+       }
+
+       return 0;
+}
+
 void board_debug_uart_init(void)
 {
        /* too early for the pinctrl driver, so configure the UART pins here */
diff --git a/board/qca/ap152/Kconfig b/board/qca/ap152/Kconfig
new file mode 100644 (file)
index 0000000..f6ad498
--- /dev/null
@@ -0,0 +1,15 @@
+if TARGET_AP152
+
+config SYS_VENDOR
+       default "qca"
+
+config SYS_BOARD
+       default "ap152"
+
+config SYS_CONFIG_NAME
+       default "ap152"
+
+config SYS_TEXT_BASE
+       default 0x9f000000
+
+endif
diff --git a/board/qca/ap152/MAINTAINERS b/board/qca/ap152/MAINTAINERS
new file mode 100644 (file)
index 0000000..785ec27
--- /dev/null
@@ -0,0 +1,6 @@
+AP152 BOARD
+M:     Rosy Song <rosysong@rosinson.com>
+S:     Maintained
+F:     board/qca/ap152/
+F:     include/configs/ap152.h
+F:     configs/ap152_defconfig
diff --git a/board/qca/ap152/Makefile b/board/qca/ap152/Makefile
new file mode 100644 (file)
index 0000000..4270afa
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y  = ap152.o
diff --git a/board/qca/ap152/ap152.c b/board/qca/ap152/ap152.c
new file mode 100644 (file)
index 0000000..30cd565
--- /dev/null
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ddr.h>
+#include <mach/ath79.h>
+#include <debug_uart.h>
+
+#define RST_RESET_RTC_RESET_LSB 27
+#define RST_RESET_RTC_RESET_MASK 0x08000000
+#define RST_RESET_RTC_RESET_SET(x) \
+       (((x) << RST_RESET_RTC_RESET_LSB) & RST_RESET_RTC_RESET_MASK)
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
+{
+       void __iomem *regs;
+       u32 val;
+
+       regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+                          MAP_NOCACHE);
+
+       /* UART : RX18, TX22 done
+        * GPIO18 as input, GPIO22 as output
+        */
+       val = readl(regs + AR71XX_GPIO_REG_OE);
+       val |= QCA956X_GPIO(18);
+       val &= ~QCA956X_GPIO(22);
+       writel(val, regs + AR71XX_GPIO_REG_OE);
+
+       /*
+        * Enable GPIO22 as UART0_SOUT
+        */
+       val = readl(regs + QCA956X_GPIO_REG_OUT_FUNC5);
+       val &= ~QCA956X_GPIO_MUX_MASK(16);
+       val |= QCA956X_GPIO_OUT_MUX_UART0_SOUT << 16;
+       writel(val, regs + QCA956X_GPIO_REG_OUT_FUNC5);
+
+       /*
+        * Enable GPIO18 as UART0_SIN
+        */
+       val = readl(regs + QCA956X_GPIO_REG_IN_ENABLE0);
+       val &= ~QCA956X_GPIO_MUX_MASK(8);
+       val |= QCA956X_GPIO_IN_MUX_UART0_SIN << 8;
+       writel(val, regs + QCA956X_GPIO_REG_IN_ENABLE0);
+
+       /*
+        * Enable GPIO22 output
+        */
+       val = readl(regs + AR71XX_GPIO_REG_OUT);
+       val |= QCA956X_GPIO(22);
+       writel(val, regs + AR71XX_GPIO_REG_OUT);
+}
+#endif
+
+int board_early_init_f(void)
+{
+       u32 reg;
+       void __iomem *rst_regs = map_physmem(AR71XX_RESET_BASE,
+                                                        AR71XX_RESET_SIZE, MAP_NOCACHE);
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+       /* CPU:775, DDR:650, AHB:258 */
+       qca956x_pll_init();
+       qca956x_ddr_init();
+#endif
+
+       /* Take WMAC out of reset */
+       reg = readl(rst_regs + QCA956X_RESET_REG_RESET_MODULE);
+       reg &= (~RST_RESET_RTC_RESET_SET(1));
+       writel(reg, rst_regs + QCA956X_RESET_REG_RESET_MODULE);
+
+       ath79_eth_reset();
+       return 0;
+}
diff --git a/configs/ap152_defconfig b/configs/ap152_defconfig
new file mode 100644 (file)
index 0000000..21cb6eb
--- /dev/null
@@ -0,0 +1,49 @@
+CONFIG_MIPS=y
+CONFIG_SYS_TEXT_BASE=0x9F000000
+CONFIG_SYS_MALLOC_F_LEN=0x800
+CONFIG_SYS_CACHE_SIZE_AUTO=y
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xb8020000
+CONFIG_DEBUG_UART_CLOCK=25000000
+CONFIG_ARCH_ATH79=y
+CONFIG_TARGET_AP152=y
+CONFIG_DEBUG_UART=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs"
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="ap152 # "
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi-flash.0"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-flash.0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1472k(uImage),64k(ART)"
+# CONFIG_ISO_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="ap152"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+# CONFIG_NET is not set
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_DATAFLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PINCTRL=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_ATH79_SPI=y
+CONFIG_LZMA=y
index fc55e98550a2f1dc6aa199c04a07882045e5ca4e..5659249fdf3d692fbc154a6a4d0669e3fb0bc071 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_CMD_BOOTEFI_SELFTEST=y
 # CONFIG_CMD_LZMADEC is not set
 # CONFIG_CMD_UNZIP is not set
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
 CONFIG_CMD_CACHE=y
 CONFIG_DOS_PARTITION=y
 CONFIG_ISO_PARTITION=y
@@ -28,6 +29,8 @@ CONFIG_DEFAULT_DEVICE_TREE="bcm963158"
 # CONFIG_NET is not set
 CONFIG_BLK=y
 CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_BCM6345_GPIO=y
 # CONFIG_MMC is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
index 61661bd756c7ef8de95e2dcef83f8ff0be71d6c4..fa9dc85d638d42da5fa5c3b89c6b7b11671a9d7b 100644 (file)
@@ -24,6 +24,7 @@ CONFIG_CMD_LICENSE=y
 # CONFIG_CMD_CRC32 is not set
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 # CONFIG_CMD_MISC is not set
 CONFIG_DEFAULT_DEVICE_TREE="brcm,bcm968380gerg"
@@ -31,6 +32,7 @@ CONFIG_DEFAULT_DEVICE_TREE="brcm,bcm968380gerg"
 # CONFIG_DM_DEVICE_REMOVE is not set
 CONFIG_HAVE_BLOCK_DEVICE=y
 CONFIG_DM_GPIO=y
+CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
index e8cb3a0d2a9bcc4d304bfbf0e58929445bc71afd..456ece72d5cbbe970eaa71da8c9a9c3721aaa1ad 100644 (file)
@@ -15,6 +15,7 @@ CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
+CONFIG_CMD_GPIO=y
 CONFIG_DOS_PARTITION=y
 CONFIG_ISO_PARTITION=y
 CONFIG_EFI_PARTITION=y
@@ -22,6 +23,8 @@ CONFIG_DEFAULT_DEVICE_TREE="bcm968580xref"
 # CONFIG_NET is not set
 CONFIG_BLK=y
 CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_BCM6345_GPIO=y
 # CONFIG_MMC is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
index 2d3ab7e35c3ca0cdabf821e13d141842f8034164..649db0f67d01075aac9067290a910480c6af2017 100644 (file)
@@ -20,17 +20,22 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
-CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_BLK=y
 CONFIG_CLK=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
@@ -46,6 +51,7 @@ CONFIG_PHYLIB=y
 CONFIG_PHY_FIXED=y
 CONFIG_MT7628_ETH=y
 CONFIG_PHY=y
+CONFIG_MT76X8_USB_PHY=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_RAM=y
 CONFIG_DM_RESET=y
@@ -54,5 +60,12 @@ CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_MT7621_SPI=y
 CONFIG_SYSRESET_SYSCON=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_FAT=y
 CONFIG_LZMA=y
 CONFIG_LZO=y
index ad34aaf640c41b157e684e7b1c4b5d61b6d8d80d..41aa900e562f142b50641a64d56f169fb2689a33 100644 (file)
@@ -24,17 +24,22 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
-CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_BLK=y
 CONFIG_CLK=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
@@ -50,6 +55,7 @@ CONFIG_PHYLIB=y
 CONFIG_PHY_FIXED=y
 CONFIG_MT7628_ETH=y
 CONFIG_PHY=y
+CONFIG_MT76X8_USB_PHY=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_RAM=y
 CONFIG_DM_RESET=y
@@ -58,5 +64,12 @@ CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_MT7621_SPI=y
 CONFIG_SYSRESET_SYSCON=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_FAT=y
 CONFIG_LZMA=y
 CONFIG_LZO=y
index 95562b7cd85f1bf46083402aa768f33a52a458c8..92c22b8a84ee962015427c7f845841c9c2f3db5a 100644 (file)
@@ -28,7 +28,10 @@ CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)"
@@ -66,3 +69,4 @@ CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_LZMA=y
+CONFIG_MSCC_JR2_SWITCH=y
index 027aaa44d562fbb541ee0c9e747ae77381b7516c..33d43dede5e63067107a9fc16688a33ab7531061 100644 (file)
@@ -24,7 +24,6 @@ CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)"
@@ -59,3 +58,8 @@ CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_LZMA=y
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_MSCC_SERVALT_SWITCH=y
index 1d3c192cfe5bb983bcd49168d3f1b558c20bac5f..e7bd1b2350f48f4bb83581edb768c5a75d6b2d81 100644 (file)
@@ -324,6 +324,9 @@ static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
        struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
        int ret;
 
+       if (!ch_priv->running)
+               return -EINVAL;
+
        /* get dma ring descriptor address */
        dma_desc += ch_priv->desc_id;
 
@@ -369,6 +372,9 @@ static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
        struct bcm6348_dma_desc *dma_desc;
        uint16_t status;
 
+       if (!ch_priv->running)
+                return -EINVAL;
+
        /* flush cache */
        bcm6348_iudma_fdc(src, len);
 
index b103180cf3778f103575d7a7d740525993070a78..b3e4ecc50e1e23b5a66e152b5e6acd2359645f74 100644 (file)
@@ -23,7 +23,7 @@ config ALTERA_PIO
 
 config BCM6345_GPIO
        bool "BCM6345 GPIO driver"
-       depends on DM_GPIO && ARCH_BMIPS
+       depends on DM_GPIO && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158)
        help
          This driver supports the GPIO banks on BCM6345 SoCs.
 
index d1f6cfa8405d6f0e4ae9ff184f8fc3dfa37e7904..71a978cf4077880b18ecef073b166c5e4ef34d84 100644 (file)
@@ -22,7 +22,7 @@ static int bcm6345_gpio_get_value(struct udevice *dev, unsigned offset)
 {
        struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
 
-       return !!(readl_be(priv->reg_data) & BIT(offset));
+       return !!(readl(priv->reg_data) & BIT(offset));
 }
 
 static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset,
@@ -31,9 +31,9 @@ static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset,
        struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
 
        if (value)
-               setbits_be32(priv->reg_data, BIT(offset));
+               setbits_32(priv->reg_data, BIT(offset));
        else
-               clrbits_be32(priv->reg_data, BIT(offset));
+               clrbits_32(priv->reg_data, BIT(offset));
 
        return 0;
 }
@@ -42,9 +42,9 @@ static int bcm6345_gpio_set_direction(void __iomem *dirout, unsigned offset,
                                      bool input)
 {
        if (input)
-               clrbits_be32(dirout, BIT(offset));
+               clrbits_32(dirout, BIT(offset));
        else
-               setbits_be32(dirout, BIT(offset));
+               setbits_32(dirout, BIT(offset));
 
        return 0;
 }
@@ -70,7 +70,7 @@ static int bcm6345_gpio_get_function(struct udevice *dev, unsigned offset)
 {
        struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
 
-       if (readl_be(priv->reg_dirout) & BIT(offset))
+       if (readl(priv->reg_dirout) & BIT(offset))
                return GPIOF_OUTPUT;
        else
                return GPIOF_INPUT;
index 8146c3170e1643e293cb2e22d0e06fbed00718eb..7f1dee4b3e4d5b9e6a5b35cf34dde9f6136f05a0 100644 (file)
@@ -3,6 +3,7 @@
  * Atheros AR71xx / AR9xxx GMAC driver
  *
  * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
  */
 
 #include <common.h>
@@ -23,6 +24,8 @@ DECLARE_GLOBAL_DATA_PTR;
 enum ag7xxx_model {
        AG7XXX_MODEL_AG933X,
        AG7XXX_MODEL_AG934X,
+       AG7XXX_MODEL_AG953X,
+       AG7XXX_MODEL_AG956X
 };
 
 /* MAC Configuration 1 */
@@ -99,8 +102,29 @@ enum ag7xxx_model {
 /* Rx Status */
 #define AG7XXX_ETH_DMA_RX_STATUS               0x194
 
+/* Custom register at 0x1805002C */
+#define AG7XXX_ETH_XMII                        0x2C
+#define AG7XXX_ETH_XMII_TX_INVERT              BIT(31)
+#define AG7XXX_ETH_XMII_RX_DELAY_LSB           28
+#define AG7XXX_ETH_XMII_RX_DELAY_MASK          0x30000000
+#define AG7XXX_ETH_XMII_RX_DELAY_SET(x) \
+       (((x) << AG7XXX_ETH_XMII_RX_DELAY_LSB) & AG7XXX_ETH_XMII_RX_DELAY_MASK)
+#define AG7XXX_ETH_XMII_TX_DELAY_LSB           26
+#define AG7XXX_ETH_XMII_TX_DELAY_MASK          0x0c000000
+#define AG7XXX_ETH_XMII_TX_DELAY_SET(x) \
+       (((x) << AG7XXX_ETH_XMII_TX_DELAY_LSB) & AG7XXX_ETH_XMII_TX_DELAY_MASK)
+#define AG7XXX_ETH_XMII_GIGE           BIT(25)
+
 /* Custom register at 0x18070000 */
 #define AG7XXX_GMAC_ETH_CFG                    0x00
+#define AG7XXX_ETH_CFG_RXDV_DELAY_LSB          16
+#define AG7XXX_ETH_CFG_RXDV_DELAY_MASK         0x00030000
+#define AG7XXX_ETH_CFG_RXDV_DELAY_SET(x) \
+       (((x) << AG7XXX_ETH_CFG_RXDV_DELAY_LSB) & AG7XXX_ETH_CFG_RXDV_DELAY_MASK)
+#define AG7XXX_ETH_CFG_RXD_DELAY_LSB           14
+#define AG7XXX_ETH_CFG_RXD_DELAY_MASK          0x0000c000
+#define AG7XXX_ETH_CFG_RXD_DELAY_SET(x)        \
+       (((x) << AG7XXX_ETH_CFG_RXD_DELAY_LSB) & AG7XXX_ETH_CFG_RXD_DELAY_MASK)
 #define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP                BIT(8)
 #define AG7XXX_ETH_CFG_SW_PHY_SWAP             BIT(7)
 #define AG7XXX_ETH_CFG_SW_ONLY_MODE            BIT(6)
@@ -197,24 +221,33 @@ static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val)
        u32 reg_addr;
        u32 phy_temp;
        u32 reg_temp;
+       u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
        u16 rv = 0;
        int ret;
 
-       if (priv->model == AG7XXX_MODEL_AG933X) {
+       if (priv->model == AG7XXX_MODEL_AG933X ||
+           priv->model == AG7XXX_MODEL_AG953X) {
                phy_addr = 0x1f;
                reg_addr = 0x10;
-       } else if (priv->model == AG7XXX_MODEL_AG934X) {
+       } else if (priv->model == AG7XXX_MODEL_AG934X ||
+                  priv->model == AG7XXX_MODEL_AG956X) {
                phy_addr = 0x18;
                reg_addr = 0x00;
        } else
                return -EINVAL;
 
-       ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
+       if (priv->model == AG7XXX_MODEL_AG956X)
+               ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
+       else
+               ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
        if (ret)
                return ret;
 
        phy_temp = ((reg >> 6) & 0x7) | 0x10;
-       reg_temp = (reg >> 1) & 0x1e;
+       if (priv->model == AG7XXX_MODEL_AG956X)
+               reg_temp = reg_temp_w & 0x1f;
+       else
+               reg_temp = (reg >> 1) & 0x1e;
        *val = 0;
 
        ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv);
@@ -222,7 +255,13 @@ static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val)
                return ret;
        *val |= rv;
 
-       ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
+       if (priv->model == AG7XXX_MODEL_AG956X) {
+               phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
+               reg_temp = (reg_temp_w + 1) & 0x1f;
+               ret = ag7xxx_switch_read(bus, phy_temp, reg_temp, &rv);
+       } else {
+               ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
+       }
        if (ret < 0)
                return ret;
        *val |= (rv << 16);
@@ -237,23 +276,34 @@ static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val)
        u32 reg_addr;
        u32 phy_temp;
        u32 reg_temp;
+       u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
        int ret;
 
-       if (priv->model == AG7XXX_MODEL_AG933X) {
+       if (priv->model == AG7XXX_MODEL_AG933X ||
+           priv->model == AG7XXX_MODEL_AG953X) {
                phy_addr = 0x1f;
                reg_addr = 0x10;
-       } else if (priv->model == AG7XXX_MODEL_AG934X) {
+       } else if (priv->model == AG7XXX_MODEL_AG934X ||
+                  priv->model == AG7XXX_MODEL_AG956X) {
                phy_addr = 0x18;
                reg_addr = 0x00;
        } else
                return -EINVAL;
 
-       ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
+       if (priv->model == AG7XXX_MODEL_AG956X)
+               ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
+       else
+               ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
        if (ret)
                return ret;
 
-       phy_temp = ((reg >> 6) & 0x7) | 0x10;
-       reg_temp = (reg >> 1) & 0x1e;
+       if (priv->model == AG7XXX_MODEL_AG956X) {
+               reg_temp = (reg_temp_w + 1) & 0x1f;
+               phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
+       } else {
+               phy_temp = ((reg >> 6) & 0x7) | 0x10;
+               reg_temp = (reg >> 1) & 0x1e;
+       }
 
        /*
         * The switch on AR933x has some special register behavior, which
@@ -272,10 +322,18 @@ static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val)
                if (ret < 0)
                        return ret;
        } else {
-               ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
+               if (priv->model == AG7XXX_MODEL_AG956X)
+                       ret = ag7xxx_switch_write(bus, phy_temp, reg_temp, val >> 16);
+               else
+                       ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
                if (ret < 0)
                        return ret;
 
+               if (priv->model == AG7XXX_MODEL_AG956X) {
+                       phy_temp = ((reg_temp_w >> 5) & 0x7) | 0x10;
+                       reg_temp = reg_temp_w & 0x1f;
+               }
+
                ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
                if (ret < 0)
                        return ret;
@@ -598,10 +656,19 @@ static int ag7xxx_mii_setup(struct udevice *dev)
                        return 0;
        }
 
-       if (priv->model == AG7XXX_MODEL_AG934X) {
-               writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | 0x4,
+       if (priv->model == AG7XXX_MODEL_AG934X)
+               reg = 0x4;
+       else if (priv->model == AG7XXX_MODEL_AG953X)
+               reg = 0x2;
+       else if (priv->model == AG7XXX_MODEL_AG956X)
+               reg = 0x7;
+
+       if (priv->model == AG7XXX_MODEL_AG934X ||
+           priv->model == AG7XXX_MODEL_AG953X ||
+           priv->model == AG7XXX_MODEL_AG956X) {
+               writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | reg,
                       priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
-               writel(0x4, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
+               writel(reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
                return 0;
        }
 
@@ -698,14 +765,126 @@ static int ag933x_phy_setup_lan(struct udevice *dev)
        return 0;
 }
 
+static int ag953x_phy_setup_wan(struct udevice *dev)
+{
+       int ret;
+       u32 reg = 0;
+       struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
+
+       /* Set wan port connect to GE0 */
+       ret = ag7xxx_switch_reg_read(priv->bus, 0x8, &reg);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x8, reg | BIT(28));
+       if (ret)
+               return ret;
+
+       /* Configure switch port 4 (GMAC0) */
+       ret = ag7xxx_switch_write(priv->bus, 4, MII_BMCR, 0x9000);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int ag953x_phy_setup_lan(struct udevice *dev)
+{
+       struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
+       int i, ret;
+       u32 reg = 0;
+
+       /* Reset the switch */
+       ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0, reg | BIT(31));
+       if (ret)
+               return ret;
+
+       do {
+               ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
+               if (ret)
+                       return ret;
+       } while (reg & BIT(31));
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x100, 0x4e);
+       if (ret)
+               return ret;
+
+       /* Set GMII mode */
+       ret = ag7xxx_switch_reg_read(priv->bus, 0x4, &reg);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x4, reg | BIT(6));
+       if (ret)
+               return ret;
+
+       /* Configure switch ports 0...4 (GMAC1) */
+       for (i = 0; i < 5; i++) {
+               ret = ag7xxx_switch_write(priv->bus, i, MII_BMCR, 0x9000);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < 5; i++) {
+               ret = ag7xxx_switch_reg_write(priv->bus, (i + 2) * 0x100, BIT(9));
+               if (ret)
+                       return ret;
+       }
+
+       /* QM Control */
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
+       if (ret)
+               return ret;
+
+       /* Disable Atheros header */
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
+       if (ret)
+               return ret;
+
+       /* Tag priority mapping */
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
+       if (ret)
+               return ret;
+
+       /* Enable ARP packets to the CPU */
+       ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg | 0x100000);
+       if (ret)
+               return ret;
+
+       /* Enable broadcast packets to the CPU */
+       ret = ag7xxx_switch_reg_read(priv->bus, 0x2c, &reg);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x2c, reg | BIT(25) | BIT(26));
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int ag933x_phy_setup_reset_set(struct udevice *dev, int port)
 {
        struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
        int ret;
 
-       ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
-                               ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
-                               ADVERTISE_PAUSE_ASYM);
+       if (priv->model == AG7XXX_MODEL_AG953X ||
+           priv->model == AG7XXX_MODEL_AG956X) {
+               ret = ag7xxx_switch_write(priv->bus, port, MII_ADVERTISE,
+                                       ADVERTISE_ALL);
+       } else {
+               ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
+                                       ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
+                                       ADVERTISE_PAUSE_ASYM);
+       }
        if (ret)
                return ret;
 
@@ -714,8 +893,18 @@ static int ag933x_phy_setup_reset_set(struct udevice *dev, int port)
                                        ADVERTISE_1000FULL);
                if (ret)
                        return ret;
+       } else if (priv->model == AG7XXX_MODEL_AG956X) {
+               ret = ag7xxx_switch_write(priv->bus, port, MII_CTRL1000,
+                                         ADVERTISE_1000FULL);
+               if (ret)
+                       return ret;
        }
 
+       if (priv->model == AG7XXX_MODEL_AG953X ||
+           priv->model == AG7XXX_MODEL_AG956X)
+               return ag7xxx_switch_write(priv->bus, port, MII_BMCR,
+                                        BMCR_ANENABLE | BMCR_RESET);
+
        return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR,
                                 BMCR_ANENABLE | BMCR_RESET);
 }
@@ -724,13 +913,24 @@ static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port)
 {
        struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
        int ret;
+       u16 reg;
 
-       do {
-               ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
-               if (ret < 0)
-                       return ret;
-               mdelay(10);
-       } while (ret & BMCR_RESET);
+       if (priv->model == AG7XXX_MODEL_AG953X ||
+           priv->model == AG7XXX_MODEL_AG956X) {
+               do {
+                       ret = ag7xxx_switch_read(priv->bus, port, MII_BMCR, &reg);
+                       if (ret < 0)
+                               return ret;
+                       mdelay(10);
+               } while (reg & BMCR_RESET);
+       } else {
+               do {
+                       ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
+                       if (ret < 0)
+                               return ret;
+                       mdelay(10);
+               } while (ret & BMCR_RESET);
+       }
 
        return 0;
 }
@@ -739,10 +939,13 @@ static int ag933x_phy_setup_common(struct udevice *dev)
 {
        struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
        int i, ret, phymax;
+       u16 reg;
 
        if (priv->model == AG7XXX_MODEL_AG933X)
                phymax = 4;
-       else if (priv->model == AG7XXX_MODEL_AG934X)
+       else if (priv->model == AG7XXX_MODEL_AG934X ||
+               priv->model == AG7XXX_MODEL_AG953X ||
+               priv->model == AG7XXX_MODEL_AG956X)
                phymax = 5;
        else
                return -EINVAL;
@@ -757,7 +960,10 @@ static int ag933x_phy_setup_common(struct udevice *dev)
                        return ret;
 
                /* Read out link status */
-               ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
+               if (priv->model == AG7XXX_MODEL_AG953X)
+                       ret = ag7xxx_switch_read(priv->bus, phymax, MII_MIPSCR, &reg);
+               else
+                       ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
                if (ret < 0)
                        return ret;
 
@@ -779,7 +985,11 @@ static int ag933x_phy_setup_common(struct udevice *dev)
 
        for (i = 0; i < phymax; i++) {
                /* Read out link status */
-               ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
+               if (priv->model == AG7XXX_MODEL_AG953X ||
+                   priv->model == AG7XXX_MODEL_AG956X)
+                       ret = ag7xxx_switch_read(priv->bus, i, MII_MIPSCR, &reg);
+               else
+                       ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
                if (ret < 0)
                        return ret;
        }
@@ -841,6 +1051,63 @@ static int ag934x_phy_setup(struct udevice *dev)
        return 0;
 }
 
+static int ag956x_phy_setup(struct udevice *dev)
+{
+       struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
+       int i, ret;
+       u32 reg, ctrl;
+
+       ret = ag7xxx_switch_reg_read(priv->bus, 0x0, &reg);
+       if (ret)
+               return ret;
+       if ((reg & 0xffff) >= 0x1301)
+               ctrl = 0xc74164de;
+       else
+               ctrl = 0xc74164d0;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x4, BIT(7));
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0xe0, ctrl);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
+       if (ret)
+               return ret;
+
+       /*
+        * Values suggested by the switch team when s17 in sgmii
+        * configuration. 0x10(S17_PWS_REG) = 0x602613a0
+        */
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x602613a0);
+       if (ret)
+               return ret;
+
+       ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
+       if (ret)
+               return ret;
+
+       /* AR8337/AR8334 v1.0 fixup */
+       ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
+       if (ret)
+               return ret;
+       if ((reg & 0xffff) == 0x1301) {
+               for (i = 0; i < 5; i++) {
+                       /* Turn on Gigabit clock */
+                       ret = ag7xxx_switch_write(priv->bus, i, 0x1d, 0x3d);
+                       if (ret)
+                               return ret;
+                       ret = ag7xxx_switch_write(priv->bus, i, 0x1e, 0x6820);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
 static int ag7xxx_mac_probe(struct udevice *dev)
 {
        struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
@@ -858,8 +1125,15 @@ static int ag7xxx_mac_probe(struct udevice *dev)
                        ret = ag933x_phy_setup_wan(dev);
                else
                        ret = ag933x_phy_setup_lan(dev);
+       } else if (priv->model == AG7XXX_MODEL_AG953X) {
+               if (priv->interface == PHY_INTERFACE_MODE_RMII)
+                       ret = ag953x_phy_setup_wan(dev);
+               else
+                       ret = ag953x_phy_setup_lan(dev);
        } else if (priv->model == AG7XXX_MODEL_AG934X) {
                ret = ag934x_phy_setup(dev);
+       } else if (priv->model == AG7XXX_MODEL_AG956X) {
+               ret = ag956x_phy_setup(dev);
        } else {
                return -EINVAL;
        }
@@ -997,6 +1271,8 @@ static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev)
 static const struct udevice_id ag7xxx_eth_ids[] = {
        { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
        { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },
+       { .compatible = "qca,ag953x-mac", .data = AG7XXX_MODEL_AG953X },
+       { .compatible = "qca,ag956x-mac", .data = AG7XXX_MODEL_AG956X },
        { }
 };
 
index 88e5a97c4bfa982ae16c726b4d40d2c3f9cb9836..6359d0b61015915b7a0f63cdff9bd056e77fed3f 100644 (file)
@@ -15,3 +15,17 @@ config MSCC_LUTON_SWITCH
        select PHYLIB
        help
          This driver supports the Luton network switch device.
+
+config MSCC_JR2_SWITCH
+       bool "Jaguar2 switch driver"
+       depends on DM_ETH && ARCH_MSCC
+       select PHYLIB
+       help
+         This driver supports the Jaguar2 network switch device.
+
+config MSCC_SERVALT_SWITCH
+       bool "Servalt switch driver"
+       depends on DM_ETH && ARCH_MSCC
+       select PHYLIB
+       help
+         This driver supports the Servalt network switch device.
index 751a839a5f00b1208f60a808b8f1552a876d5299..bffd8ec77b0f6a11f00c12db1df91ac9b3f6be24 100644 (file)
@@ -1,3 +1,5 @@
 
 obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o
 obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o
+obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o
+obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o
diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c
new file mode 100644 (file)
index 0000000..60d408f
--- /dev/null
@@ -0,0 +1,1075 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <dm/of_addr.h>
+#include <fdt_support.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <miiphy.h>
+#include <net.h>
+#include <wait_bit.h>
+
+#include <dt-bindings/mscc/jr2_data.h>
+#include "mscc_xfer.h"
+
+#define GCB_MIIM_MII_STATUS            0x0
+#define                GCB_MIIM_STAT_BUSY              BIT(3)
+#define GCB_MIIM_MII_CMD               0x8
+#define                GCB_MIIM_MII_CMD_SCAN           BIT(0)
+#define                GCB_MIIM_MII_CMD_OPR_WRITE      BIT(1)
+#define                GCB_MIIM_MII_CMD_OPR_READ       BIT(2)
+#define                GCB_MIIM_MII_CMD_SINGLE_SCAN    BIT(3)
+#define                GCB_MIIM_MII_CMD_WRDATA(x)      ((x) << 4)
+#define                GCB_MIIM_MII_CMD_REGAD(x)       ((x) << 20)
+#define                GCB_MIIM_MII_CMD_PHYAD(x)       ((x) << 25)
+#define                GCB_MIIM_MII_CMD_VLD            BIT(31)
+#define GCB_MIIM_DATA                  0xC
+#define                GCB_MIIM_DATA_ERROR             (0x3 << 16)
+
+#define ANA_AC_RAM_CTRL_RAM_INIT               0x94358
+#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET      0x94370
+
+#define ANA_CL_PORT_VLAN_CFG(x)                        (0x24018 + 0xc8 * (x))
+#define                ANA_CL_PORT_VLAN_CFG_AWARE_ENA                  BIT(19)
+#define                ANA_CL_PORT_VLAN_CFG_POP_CNT(x)                 ((x) << 17)
+
+#define ANA_L2_COMMON_FWD_CFG                  0x8a2a8
+#define                ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
+
+#define ASM_CFG_STAT_CFG                       0x3508
+#define ASM_CFG_PORT(x)                                (0x36c4 + 0x4 * (x))
+#define                ASM_CFG_PORT_NO_PREAMBLE_ENA            BIT(8)
+#define                ASM_CFG_PORT_INJ_FORMAT_CFG(x)          ((x) << 1)
+#define ASM_RAM_CTRL_RAM_INIT                  0x39b8
+
+#define DEV_DEV_CFG_DEV_RST_CTRL               0x0
+#define                DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x)   ((x) << 20)
+#define DEV_MAC_CFG_MAC_ENA            0x1c
+#define                DEV_MAC_CFG_MAC_ENA_RX_ENA              BIT(4)
+#define                DEV_MAC_CFG_MAC_ENA_TX_ENA              BIT(0)
+#define        DEV_MAC_CFG_MAC_IFG             0x34
+#define                DEV_MAC_CFG_MAC_IFG_TX_IFG(x)           ((x) << 8)
+#define                DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)          ((x) << 4)
+#define                DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)          (x)
+#define        DEV_PCS1G_CFG_PCS1G_CFG         0x40
+#define                DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA         BIT(0)
+#define        DEV_PCS1G_CFG_PCS1G_MODE        0x44
+#define        DEV_PCS1G_CFG_PCS1G_SD          0x48
+#define        DEV_PCS1G_CFG_PCS1G_ANEG        0x4c
+#define                DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
+
+#define DSM_RAM_CTRL_RAM_INIT          0x8
+
+#define HSIO_ANA_SERDES1G_DES_CFG              0xac
+#define                HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x)            ((x) << 1)
+#define                HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x)             ((x) << 5)
+#define                HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x)          ((x) << 8)
+#define                HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x)           ((x) << 13)
+#define HSIO_ANA_SERDES1G_IB_CFG               0xb0
+#define                HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x)       (x)
+#define                HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x)             ((x) << 6)
+#define                HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP        BIT(9)
+#define                HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV             BIT(11)
+#define                HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM           BIT(13)
+#define                HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x)             ((x) << 19)
+#define                HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x)         ((x) << 24)
+#define HSIO_ANA_SERDES1G_OB_CFG               0xb4
+#define                HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x)       (x)
+#define                HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x)            ((x) << 4)
+#define                HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x)       ((x) << 10)
+#define                HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x)            ((x) << 13)
+#define                HSIO_ANA_SERDES1G_OB_CFG_SLP(x)                 ((x) << 17)
+#define HSIO_ANA_SERDES1G_SER_CFG              0xb8
+#define HSIO_ANA_SERDES1G_COMMON_CFG           0xbc
+#define                HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE            BIT(0)
+#define                HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE           BIT(18)
+#define                HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST            BIT(31)
+#define HSIO_ANA_SERDES1G_PLL_CFG              0xc0
+#define                HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA               BIT(7)
+#define                HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x)      ((x) << 8)
+#define                HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2           BIT(21)
+#define HSIO_DIG_SERDES1G_DFT_CFG0             0xc8
+#define HSIO_DIG_SERDES1G_TP_CFG               0xd4
+#define HSIO_DIG_SERDES1G_MISC_CFG             0xdc
+#define                HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST             BIT(0)
+#define HSIO_MCB_SERDES1G_CFG                  0xe8
+#define                HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT               BIT(31)
+#define                HSIO_MCB_SERDES1G_CFG_ADDR(x)                   (x)
+
+#define HSIO_ANA_SERDES6G_DES_CFG              0x11c
+#define                HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA              BIT(0)
+#define                HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x)             ((x) << 1)
+#define                HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST             BIT(4)
+#define                HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x)            ((x) << 5)
+#define                HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x)           ((x) << 8)
+#define                HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x)          ((x) << 10)
+#define                HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x)           ((x) << 13)
+#define HSIO_ANA_SERDES6G_IB_CFG               0x120
+#define                HSIO_ANA_SERDES6G_IB_CFG_REG_ENA                BIT(0)
+#define                HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA                BIT(1)
+#define                HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA                BIT(2)
+#define                HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x)             ((x) << 3)
+#define                HSIO_ANA_SERDES6G_IB_CFG_CONCUR                 BIT(4)
+#define                HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA            BIT(5)
+#define                HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x)     ((x) << 7)
+#define                HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x)      ((x) << 9)
+#define                HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x)     ((x) << 11)
+#define                HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x)      ((x) << 13)
+#define                HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x)     ((x) << 15)
+#define                HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x)       ((x) << 18)
+#define                HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x)            ((x) << 20)
+#define                HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x)            ((x) << 24)
+#define                HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL              BIT(28)
+#define                HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x)               ((x) << 29)
+#define HSIO_ANA_SERDES6G_IB_CFG1              0x124
+#define                HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET           BIT(4)
+#define                HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP               BIT(5)
+#define                HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID              BIT(6)
+#define                HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP               BIT(7)
+#define                HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x)              ((x) << 8)
+#define                HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x)              ((x) << 12)
+#define                HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x)              ((x) << 17)
+#define HSIO_ANA_SERDES6G_IB_CFG2              0x128
+#define                HSIO_ANA_SERDES6G_IB_CFG2_UREG(x)               (x)
+#define                HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x)               ((x) << 3)
+#define                HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x)              ((x) << 5)
+#define                HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x)              ((x) << 10)
+#define                HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x)              ((x) << 16)
+#define                HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x)              ((x) << 22)
+#define                HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x)              ((x) << 27)
+#define HSIO_ANA_SERDES6G_IB_CFG3              0x12c
+#define                HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x)         (x)
+#define                HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x)             ((x) << 6)
+#define                HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x)            ((x) << 12)
+#define                HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x)             ((x) << 18)
+#define HSIO_ANA_SERDES6G_IB_CFG4              0x130
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x)         (x)
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x)             ((x) << 6)
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x)            ((x) << 12)
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x)             ((x) << 18)
+#define HSIO_ANA_SERDES6G_IB_CFG5              0x134
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x)         (x)
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x)             ((x) << 6)
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x)            ((x) << 12)
+#define                HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x)             ((x) << 18)
+#define HSIO_ANA_SERDES6G_OB_CFG               0x138
+#define                HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x)       (x)
+#define                HSIO_ANA_SERDES6G_OB_CFG_SR(x)                  ((x) << 4)
+#define                HSIO_ANA_SERDES6G_OB_CFG_SR_H                   BIT(8)
+#define                HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL              BIT(9)
+#define                HSIO_ANA_SERDES6G_OB_CFG_R_COR                  BIT(10)
+#define                HSIO_ANA_SERDES6G_OB_CFG_POST1(x)               ((x) << 11)
+#define                HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR              BIT(16)
+#define                HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX              BIT(17)
+#define                HSIO_ANA_SERDES6G_OB_CFG_PREC(x)                ((x) << 18)
+#define                HSIO_ANA_SERDES6G_OB_CFG_POST0(x)               ((x) << 23)
+#define                HSIO_ANA_SERDES6G_OB_CFG_POL                    BIT(29)
+#define                HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x)          ((x) << 30)
+#define                HSIO_ANA_SERDES6G_OB_CFG_IDLE                   BIT(31)
+#define HSIO_ANA_SERDES6G_OB_CFG1              0x13c
+#define                HSIO_ANA_SERDES6G_OB_CFG1_LEV(x)                (x)
+#define                HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x)            ((x) << 6)
+#define HSIO_ANA_SERDES6G_SER_CFG              0x140
+#define HSIO_ANA_SERDES6G_COMMON_CFG           0x144
+#define                HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x)         (x)
+#define                HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x)           (x << 2)
+#define                HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE           BIT(14)
+#define                HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST            BIT(16)
+#define HSIO_ANA_SERDES6G_PLL_CFG              0x148
+#define                HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ               BIT(0)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR               BIT(1)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL           BIT(2)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA     BIT(3)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA     BIT(4)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA               BIT(5)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x)      ((x) << 6)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT               BIT(14)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_DIV4                  BIT(15)
+#define                HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x)           ((x) << 16)
+#define HSIO_DIG_SERDES6G_MISC_CFG             0x108
+#define                HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST             BIT(0)
+#define HSIO_MCB_SERDES6G_CFG                  0x168
+#define                HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT               BIT(31)
+#define                HSIO_MCB_SERDES6G_CFG_ADDR(x)                   (x)
+#define HSIO_HW_CFGSTAT_HW_CFG                 0x16c
+
+#define LRN_COMMON_ACCESS_CTRL                 0x0
+#define                LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT    BIT(0)
+#define LRN_COMMON_MAC_ACCESS_CFG0             0x4
+#define LRN_COMMON_MAC_ACCESS_CFG1             0x8
+#define LRN_COMMON_MAC_ACCESS_CFG2             0xc
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x)    (x)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x)    ((x) << 12)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD        BIT(15)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED     BIT(16)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY   BIT(23)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x)  ((x) << 24)
+
+#define QFWD_SYSTEM_SWITCH_PORT_MODE(x)                (0x4 * (x))
+#define                QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA           BIT(17)
+
+#define QS_XTR_GRP_CFG(x)              (0x0 + 4 * (x))
+#define QS_INJ_GRP_CFG(x)              (0x24 + (x) * 4)
+
+#define QSYS_SYSTEM_RESET_CFG                  0xf0
+#define QSYS_CALCFG_CAL_AUTO(x)                        (0x3d4 + 4 * (x))
+#define QSYS_CALCFG_CAL_CTRL                   0x3e8
+#define                QSYS_CALCFG_CAL_CTRL_CAL_MODE(x)                ((x) << 11)
+#define QSYS_RAM_CTRL_RAM_INIT                 0x3ec
+
+#define REW_RAM_CTRL_RAM_INIT                  0x53528
+
+#define VOP_RAM_CTRL_RAM_INIT                  0x43638
+
+#define XTR_VALID_BYTES(x)     (4 - ((x) & 3))
+#define MAC_VID                        0
+#define CPU_PORT               53
+#define IFH_LEN                        7
+#define JR2_BUF_CELL_SZ                60
+#define ETH_ALEN               6
+#define PGID_BROADCAST         510
+#define PGID_UNICAST           511
+
+static const char * const regs_names[] = {
+       "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
+       "port8", "port9", "port10", "port11", "port12", "port13", "port14",
+       "port15", "port16", "port17", "port18", "port19", "port20", "port21",
+       "port22", "port23", "port24", "port25", "port26", "port27", "port28",
+       "port29", "port30", "port31", "port32", "port33", "port34", "port35",
+       "port36", "port37", "port38", "port39", "port40", "port41", "port42",
+       "port43", "port44", "port45", "port46", "port47",
+       "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
+       "qfwd", "qs", "qsys", "rew",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 48
+
+enum jr2_ctrl_regs {
+       ANA_AC = MAX_PORT,
+       ANA_CL,
+       ANA_L2,
+       ASM,
+       HSIO,
+       LRN,
+       QFWD,
+       QS,
+       QSYS,
+       REW,
+};
+
+#define JR2_MIIM_BUS_COUNT 3
+
+struct jr2_phy_port_t {
+       size_t phy_addr;
+       struct mii_dev *bus;
+       u8 serdes_index;
+       u8 phy_mode;
+};
+
+struct jr2_private {
+       void __iomem *regs[REGS_NAMES_COUNT];
+       struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
+       struct jr2_phy_port_t ports[MAX_PORT];
+};
+
+struct jr2_miim_dev {
+       void __iomem *regs;
+       phys_addr_t miim_base;
+       unsigned long miim_size;
+       struct mii_dev *bus;
+};
+
+static const unsigned long jr2_regs_qs[] = {
+       [MSCC_QS_XTR_RD] = 0x8,
+       [MSCC_QS_XTR_FLUSH] = 0x18,
+       [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
+       [MSCC_QS_INJ_WR] = 0x2c,
+       [MSCC_QS_INJ_CTRL] = 0x34,
+};
+
+static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT];
+static int miim_count = -1;
+
+static int mscc_miim_wait_ready(struct jr2_miim_dev *miim)
+{
+       unsigned long deadline;
+       u32 val;
+
+       deadline = timer_get_us() + 250000;
+
+       do {
+               val = readl(miim->regs + GCB_MIIM_MII_STATUS);
+       } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
+
+       if (val & GCB_MIIM_STAT_BUSY)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+       struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
+       u32 val;
+       int ret;
+
+       ret = mscc_miim_wait_ready(miim);
+       if (ret)
+               goto out;
+
+       writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+              GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
+              miim->regs + GCB_MIIM_MII_CMD);
+
+       ret = mscc_miim_wait_ready(miim);
+       if (ret)
+               goto out;
+
+       val = readl(miim->regs + GCB_MIIM_DATA);
+       if (val & GCB_MIIM_DATA_ERROR) {
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = val & 0xFFFF;
+ out:
+       return ret;
+}
+
+static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
+                          u16 val)
+{
+       struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
+       int ret;
+
+       ret = mscc_miim_wait_ready(miim);
+       if (ret < 0)
+               goto out;
+
+       writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+              GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
+              GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
+
+ out:
+       return ret;
+}
+
+static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
+                                       unsigned long miim_size)
+{
+       struct mii_dev *bus;
+
+       bus = mdio_alloc();
+       if (!bus)
+               return NULL;
+
+       ++miim_count;
+       sprintf(bus->name, "miim-bus%d", miim_count);
+
+       miim[miim_count].regs = ioremap(miim_base, miim_size);
+       miim[miim_count].miim_base = miim_base;
+       miim[miim_count].miim_size = miim_size;
+       bus->priv = &miim[miim_count];
+       bus->read = mscc_miim_read;
+       bus->write = mscc_miim_write;
+
+       if (mdio_register(bus))
+               return NULL;
+
+       miim[miim_count].bus = bus;
+       return bus;
+}
+
+static void jr2_cpu_capture_setup(struct jr2_private *priv)
+{
+       /* ASM: No preamble and IFH prefix on CPU injected frames */
+       writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
+              ASM_CFG_PORT_INJ_FORMAT_CFG(1),
+              priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
+
+       /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
+       writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
+
+       /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
+       writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
+
+       /* Enable CPU port for any frame transfer */
+       setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
+                    QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+
+       /* Send a copy to CPU when found as forwarding entry */
+       setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
+                    ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
+}
+
+static void jr2_port_init(struct jr2_private *priv, int port)
+{
+       void __iomem *regs = priv->regs[port];
+
+       /* Enable PCS */
+       writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
+              regs + DEV_PCS1G_CFG_PCS1G_CFG);
+
+       /* Disable Signal Detect */
+       writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
+
+       /* Enable MAC RX and TX */
+       writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
+              DEV_MAC_CFG_MAC_ENA_TX_ENA,
+              regs + DEV_MAC_CFG_MAC_ENA);
+
+       /* Clear sgmii_mode_ena */
+       writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
+
+       /*
+        * Clear sw_resolve_ena(bit 0) and set adv_ability to
+        * something meaningful just in case
+        */
+       writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
+              regs + DEV_PCS1G_CFG_PCS1G_ANEG);
+
+       /* Set MAC IFG Gaps */
+       writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
+              DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
+              DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
+              regs + DEV_MAC_CFG_MAC_IFG);
+
+       /* Set link speed and release all resets */
+       writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
+              regs + DEV_DEV_CFG_DEV_RST_CTRL);
+
+       /* Make VLAN aware for CPU traffic */
+       writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
+              ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
+              MAC_VID,
+              priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
+
+       /* Enable CPU port for any frame transfer */
+       setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
+                    QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+}
+
+static void serdes6g_write(void __iomem *base, u32 addr)
+{
+       u32 data;
+
+       writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
+              HSIO_MCB_SERDES6G_CFG_ADDR(addr),
+              base + HSIO_MCB_SERDES6G_CFG);
+
+       do {
+               data = readl(base + HSIO_MCB_SERDES6G_CFG);
+       } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
+}
+
+static void serdes6g_setup(void __iomem *base, uint32_t addr,
+                          phy_interface_t interface)
+{
+       u32 ib_if_mode = 0;
+       u32 ib_qrate = 0;
+       u32 ib_cal_ena = 0;
+       u32 ib1_tsdet = 0;
+       u32 ob_lev = 0;
+       u32 ob_ena_cas = 0;
+       u32 ob_ena1v_mode = 0;
+       u32 des_bw_ana = 0;
+       u32 pll_fsm_ctrl_data = 0;
+
+       switch (interface) {
+       case PHY_INTERFACE_MODE_SGMII:
+               ib_if_mode = 1;
+               ib_qrate = 1;
+               ib_cal_ena = 1;
+               ib1_tsdet = 3;
+               ob_lev = 48;
+               ob_ena_cas = 2;
+               ob_ena1v_mode = 1;
+               des_bw_ana = 3;
+               pll_fsm_ctrl_data = 60;
+               break;
+       case PHY_INTERFACE_MODE_QSGMII:
+               ib_if_mode = 3;
+               ib1_tsdet = 16;
+               ob_lev = 24;
+               des_bw_ana = 5;
+               pll_fsm_ctrl_data = 120;
+               break;
+       default:
+               pr_err("Interface not supported\n");
+               return;
+       }
+
+       if (interface == PHY_INTERFACE_MODE_QSGMII)
+               writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
+
+       writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
+              base + HSIO_ANA_SERDES6G_COMMON_CFG);
+       writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
+              HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
+              base + HSIO_ANA_SERDES6G_PLL_CFG);
+       writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
+              HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+              HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+              HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+              HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+              base + HSIO_ANA_SERDES6G_IB_CFG);
+       writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
+              HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
+              HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
+              HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
+              base + HSIO_ANA_SERDES6G_IB_CFG1);
+       writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
+              base + HSIO_DIG_SERDES6G_MISC_CFG);
+
+       serdes6g_write(base, addr);
+
+       writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
+              HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+              HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+              HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+              HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+              base + HSIO_ANA_SERDES6G_IB_CFG);
+       writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
+              HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
+              HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
+              HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
+              base + HSIO_ANA_SERDES6G_IB_CFG1);
+
+       writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
+       writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
+              HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
+              HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
+              HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
+              base + HSIO_ANA_SERDES6G_COMMON_CFG);
+       writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
+              base + HSIO_DIG_SERDES6G_MISC_CFG);
+
+       writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
+              HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
+              HSIO_ANA_SERDES6G_OB_CFG_SR_H |
+              HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
+              HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
+       writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
+              HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
+              base + HSIO_ANA_SERDES6G_OB_CFG1);
+
+       writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
+              HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
+              HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
+              HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
+              base + HSIO_ANA_SERDES6G_DES_CFG);
+       writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
+              HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
+              base + HSIO_ANA_SERDES6G_PLL_CFG);
+
+       serdes6g_write(base, addr);
+
+       /* set pll_fsm_ena = 1 */
+       writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
+              HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
+              HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
+              base + HSIO_ANA_SERDES6G_PLL_CFG);
+
+       serdes6g_write(base, addr);
+
+       /* wait 20ms for pll bringup */
+       mdelay(20);
+
+       /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
+       writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
+              HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
+              HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+              HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+              HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+              HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+              base + HSIO_ANA_SERDES6G_IB_CFG);
+       writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
+
+       serdes6g_write(base, addr);
+
+       /* wait 60 for calibration */
+       mdelay(60);
+
+       /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
+       writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
+              HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
+              HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+              HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+              HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+              HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+              HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+              base + HSIO_ANA_SERDES6G_IB_CFG);
+       writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
+              HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
+              HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
+              HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
+              HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
+              base + HSIO_ANA_SERDES6G_IB_CFG1);
+
+       serdes6g_write(base, addr);
+}
+
+static void serdes1g_write(void __iomem *base, u32 addr)
+{
+       u32 data;
+
+       writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
+              HSIO_MCB_SERDES1G_CFG_ADDR(addr),
+              base + HSIO_MCB_SERDES1G_CFG);
+
+       do {
+               data = readl(base + HSIO_MCB_SERDES1G_CFG);
+       } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
+}
+
+static void serdes1g_setup(void __iomem *base, uint32_t addr,
+                          phy_interface_t interface)
+{
+       writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
+       writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
+       writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
+       writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
+              HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
+              HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
+              HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
+              HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
+              base + HSIO_ANA_SERDES1G_OB_CFG);
+       writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
+              HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
+              HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
+              HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
+              base + HSIO_ANA_SERDES1G_IB_CFG);
+       writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
+              HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
+              HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
+              HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
+              base + HSIO_ANA_SERDES1G_DES_CFG);
+       writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
+              base + HSIO_DIG_SERDES1G_MISC_CFG);
+       writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
+              HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
+              HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
+              base + HSIO_ANA_SERDES1G_PLL_CFG);
+       writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
+              HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
+              HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
+              base + HSIO_ANA_SERDES1G_COMMON_CFG);
+
+       serdes1g_write(base, addr);
+
+       setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
+                    HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
+
+       serdes1g_write(base, addr);
+
+       clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
+                    HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
+
+       serdes1g_write(base, addr);
+}
+
+static int ram_init(u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+
+       if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
+               printf("Timeout in memory reset, reg = 0x%08x\n", val);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int jr2_switch_init(struct jr2_private *priv)
+{
+       /* Initialize memories */
+       ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
+       ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
+       ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
+       ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
+
+       /* Reset counters */
+       writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
+       writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
+
+       /* Enable switch-core and queue system */
+       writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
+
+       return 0;
+}
+
+static void jr2_switch_config(struct jr2_private *priv)
+{
+       writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
+       writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
+       writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
+       writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
+
+       writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
+              QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
+              priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
+}
+
+static int jr2_initialize(struct jr2_private *priv)
+{
+       int ret, i;
+
+       /* Initialize switch memories, enable core */
+       ret = jr2_switch_init(priv);
+       if (ret)
+               return ret;
+
+       jr2_switch_config(priv);
+
+       for (i = 0; i < MAX_PORT; i++)
+               jr2_port_init(priv, i);
+
+       jr2_cpu_capture_setup(priv);
+
+       return 0;
+}
+
+static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
+{
+       if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
+                             LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+                             false, 2000, false))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int jr2_mac_table_add(struct jr2_private *priv,
+                            const unsigned char mac[ETH_ALEN], int pgid)
+{
+       u32 macl = 0, mach = 0;
+
+       /*
+        * Set the MAC address to handle and the vlan associated in a format
+        * understood by the hardware.
+        */
+       mach |= MAC_VID << 16;
+       mach |= ((u32)mac[0]) << 8;
+       mach |= ((u32)mac[1]) << 0;
+       macl |= ((u32)mac[2]) << 24;
+       macl |= ((u32)mac[3]) << 16;
+       macl |= ((u32)mac[4]) << 8;
+       macl |= ((u32)mac[5]) << 0;
+
+       writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
+       writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
+
+       writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
+              priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
+
+       writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+              priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
+
+       return jr2_vlant_wait_for_completion(priv);
+}
+
+static int jr2_write_hwaddr(struct udevice *dev)
+{
+       struct jr2_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+
+       return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+}
+
+static void serdes_setup(struct jr2_private *priv)
+{
+       size_t mask;
+       int i = 0;
+
+       for (i = 0; i < MAX_PORT; ++i) {
+               if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
+                       continue;
+
+               mask = BIT(priv->ports[i].serdes_index);
+               if (priv->ports[i].serdes_index < SERDES1G_MAX) {
+                       serdes1g_setup(priv->regs[HSIO], mask,
+                                      priv->ports[i].phy_mode);
+               } else {
+                       mask >>= SERDES6G(0);
+                       serdes6g_setup(priv->regs[HSIO], mask,
+                                      priv->ports[i].phy_mode);
+               }
+       }
+}
+
+static int jr2_start(struct udevice *dev)
+{
+       struct jr2_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff };
+       int ret;
+
+       ret = jr2_initialize(priv);
+       if (ret)
+               return ret;
+
+       /* Set MAC address tables entries for CPU redirection */
+       ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
+       if (ret)
+               return ret;
+
+       ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+       if (ret)
+               return ret;
+
+       serdes_setup(priv);
+
+       return 0;
+}
+
+static void jr2_stop(struct udevice *dev)
+{
+}
+
+static int jr2_send(struct udevice *dev, void *packet, int length)
+{
+       struct jr2_private *priv = dev_get_priv(dev);
+       u32 ifh[IFH_LEN];
+       u32 *buf = packet;
+
+       memset(ifh, '\0', IFH_LEN);
+
+       /* Set DST PORT_MASK */
+       ifh[0] = htonl(0);
+       ifh[1] = htonl(0x1FFFFF);
+       ifh[2] = htonl(~0);
+       /* Set DST_MODE to INJECT and UPDATE_FCS */
+       ifh[5] = htonl(0x4c0);
+
+       return mscc_send(priv->regs[QS], jr2_regs_qs,
+                        ifh, IFH_LEN, buf, length);
+}
+
+static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct jr2_private *priv = dev_get_priv(dev);
+       u32 *rxbuf = (u32 *)net_rx_packets[0];
+       int byte_cnt = 0;
+
+       byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
+                            false);
+
+       *packetp = net_rx_packets[0];
+
+       return byte_cnt;
+}
+
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
+{
+       int i = 0;
+
+       for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
+               if (miim[i].miim_base == base && miim[i].miim_size == size)
+                       return miim[i].bus;
+
+       return NULL;
+}
+
+static void add_port_entry(struct jr2_private *priv, size_t index,
+                          size_t phy_addr, struct mii_dev *bus,
+                          u8 serdes_index, u8 phy_mode)
+{
+       priv->ports[index].phy_addr = phy_addr;
+       priv->ports[index].bus = bus;
+       priv->ports[index].serdes_index = serdes_index;
+       priv->ports[index].phy_mode = phy_mode;
+}
+
+static int jr2_probe(struct udevice *dev)
+{
+       struct jr2_private *priv = dev_get_priv(dev);
+       int i;
+       int ret;
+       struct resource res;
+       fdt32_t faddr;
+       phys_addr_t addr_base;
+       unsigned long addr_size;
+       ofnode eth_node, node, mdio_node;
+       size_t phy_addr;
+       struct mii_dev *bus;
+       struct ofnode_phandle_args phandle;
+       struct phy_device *phy;
+
+       if (!priv)
+               return -EINVAL;
+
+       /* Get registers and map them to the private structure */
+       for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
+               priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
+               if (!priv->regs[i]) {
+                       debug
+                           ("Error can't get regs base addresses for %s\n",
+                            regs_names[i]);
+                       return -ENOMEM;
+               }
+       }
+
+       /* Initialize miim buses */
+       memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
+
+       /* iterate all the ports and find out on which bus they are */
+       i = 0;
+       eth_node = dev_read_first_subnode(dev);
+       for (node = ofnode_first_subnode(eth_node);
+            ofnode_valid(node);
+            node = ofnode_next_subnode(node)) {
+               if (ofnode_read_resource(node, 0, &res))
+                       return -ENOMEM;
+               i = res.start;
+
+               ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
+                                                    0, 0, &phandle);
+               if (ret)
+                       continue;
+
+               /* Get phy address on mdio bus */
+               if (ofnode_read_resource(phandle.node, 0, &res))
+                       return -ENOMEM;
+               phy_addr = res.start;
+
+               /* Get mdio node */
+               mdio_node = ofnode_get_parent(phandle.node);
+
+               if (ofnode_read_resource(mdio_node, 0, &res))
+                       return -ENOMEM;
+               faddr = cpu_to_fdt32(res.start);
+
+               addr_base = ofnode_translate_address(mdio_node, &faddr);
+               addr_size = res.end - res.start;
+
+               /* If the bus is new then create a new bus */
+               if (!get_mdiobus(addr_base, addr_size))
+                       priv->bus[miim_count] =
+                               jr2_mdiobus_init(addr_base, addr_size);
+
+               /* Connect mdio bus with the port */
+               bus = get_mdiobus(addr_base, addr_size);
+
+               /* Get serdes info */
+               ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
+                                                    3, 0, &phandle);
+               if (ret)
+                       return -ENOMEM;
+
+               add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
+                              phandle.args[2]);
+       }
+
+       for (i = 0; i < MAX_PORT; i++) {
+               if (!priv->ports[i].bus)
+                       continue;
+
+               phy = phy_connect(priv->ports[i].bus,
+                                 priv->ports[i].phy_addr, dev,
+                                 PHY_INTERFACE_MODE_NONE);
+               if (phy)
+                       board_phy_config(phy);
+       }
+
+       return 0;
+}
+
+static int jr2_remove(struct udevice *dev)
+{
+       struct jr2_private *priv = dev_get_priv(dev);
+       int i;
+
+       for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
+               mdio_unregister(priv->bus[i]);
+               mdio_free(priv->bus[i]);
+       }
+
+       return 0;
+}
+
+static const struct eth_ops jr2_ops = {
+       .start        = jr2_start,
+       .stop         = jr2_stop,
+       .send         = jr2_send,
+       .recv         = jr2_recv,
+       .write_hwaddr = jr2_write_hwaddr,
+};
+
+static const struct udevice_id mscc_jr2_ids[] = {
+       {.compatible = "mscc,vsc7454-switch" },
+       { /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(jr2) = {
+       .name                           = "jr2-switch",
+       .id                             = UCLASS_ETH,
+       .of_match                       = mscc_jr2_ids,
+       .probe                          = jr2_probe,
+       .remove                         = jr2_remove,
+       .ops                            = &jr2_ops,
+       .priv_auto_alloc_size           = sizeof(struct jr2_private),
+       .platdata_auto_alloc_size       = sizeof(struct eth_pdata),
+};
index bf08c35ba04ffc8297926c1acd55755ee6c72f54..815c2da26469c54ff26388316b8ad7081bf19e5c 100644 (file)
@@ -142,18 +142,16 @@ static const unsigned long ocelot_regs_ana_table[] = {
 
 static struct mscc_miim_dev miim[NUM_PHY];
 
-static int mscc_miim_reset(struct mii_dev *bus)
+static void mscc_phy_reset(void)
 {
-       struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
-
-       if (miim->phy_regs) {
-               writel(0, miim->phy_regs + PHY_CFG);
-               writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
-                      | PHY_CFG_ENA, miim->phy_regs + PHY_CFG);
-               mdelay(500);
+       writel(0, miim[INTERNAL].phy_regs + PHY_CFG);
+       writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
+              | PHY_CFG_ENA, miim[INTERNAL].phy_regs + PHY_CFG);
+       if (wait_for_bit_le32(miim[INTERNAL].phy_regs + PHY_STAT,
+                             PHY_STAT_SUPERVISOR_COMPLETE,
+                             true, 2000, false)) {
+               pr_err("Timeout in phy reset\n");
        }
-
-       return 0;
 }
 
 /* For now only setup the internal mdio bus */
@@ -194,7 +192,6 @@ static struct mii_dev *ocelot_mdiobus_init(struct udevice *dev)
        miim[INTERNAL].phy_regs = ioremap(phy_base[PHY], phy_size[PHY]);
        miim[INTERNAL].regs = ioremap(phy_base[MIIM], phy_size[MIIM]);
        bus->priv = &miim[INTERNAL];
-       bus->reset = mscc_miim_reset;
        bus->read = mscc_miim_read;
        bus->write = mscc_miim_write;
 
@@ -210,13 +207,8 @@ __weak void mscc_switch_reset(void)
 
 static void ocelot_stop(struct udevice *dev)
 {
-       struct ocelot_private *priv = dev_get_priv(dev);
-       int i;
-
        mscc_switch_reset();
-       for (i = 0; i < NUM_PHY; i++)
-               if (priv->bus[i])
-                       mscc_miim_reset(priv->bus[i]);
+       mscc_phy_reset();
 }
 
 static void ocelot_cpu_capture_setup(struct ocelot_private *priv)
@@ -473,6 +465,7 @@ static int ocelot_probe(struct udevice *dev)
        }
 
        priv->bus[INTERNAL] = ocelot_mdiobus_init(dev);
+       mscc_phy_reset();
 
        for (i = 0; i < 4; i++) {
                phy_connect(priv->bus[INTERNAL], i, dev,
diff --git a/drivers/net/mscc_eswitch/servalt_switch.c b/drivers/net/mscc_eswitch/servalt_switch.c
new file mode 100644 (file)
index 0000000..995c623
--- /dev/null
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <dm/of_addr.h>
+#include <fdt_support.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <miiphy.h>
+#include <net.h>
+#include <wait_bit.h>
+
+#include "mscc_xfer.h"
+
+#define GCB_MIIM_MII_STATUS            0x0
+#define                GCB_MIIM_STAT_BUSY              BIT(3)
+#define GCB_MIIM_MII_CMD               0x8
+#define                GCB_MIIM_MII_CMD_OPR_WRITE      BIT(1)
+#define                GCB_MIIM_MII_CMD_OPR_READ       BIT(2)
+#define                GCB_MIIM_MII_CMD_WRDATA(x)      ((x) << 4)
+#define                GCB_MIIM_MII_CMD_REGAD(x)       ((x) << 20)
+#define                GCB_MIIM_MII_CMD_PHYAD(x)       ((x) << 25)
+#define                GCB_MIIM_MII_CMD_VLD            BIT(31)
+#define GCB_MIIM_DATA                  0xC
+#define                GCB_MIIM_DATA_ERROR             (0x3 << 16)
+
+#define PHY_CFG                                0x0
+#define PHY_CFG_ENA                            0x3
+#define PHY_CFG_COMMON_RST                     BIT(2)
+#define PHY_CFG_RST                            (0x3 << 3)
+#define PHY_STAT                       0x4
+#define PHY_STAT_SUPERVISOR_COMPLETE           BIT(0)
+
+#define ANA_AC_RAM_CTRL_RAM_INIT               0x14fdc
+#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET      0x15474
+
+#define ANA_CL_PORT_VLAN_CFG(x)                        (0xa018 + 0xc8 * (x))
+#define                ANA_CL_PORT_VLAN_CFG_AWARE_ENA                  BIT(19)
+#define                ANA_CL_PORT_VLAN_CFG_POP_CNT(x)                 ((x) << 17)
+
+#define ANA_L2_COMMON_FWD_CFG                  0x18498
+#define                ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
+
+#define ASM_CFG_STAT_CFG                       0xb08
+#define ASM_CFG_PORT(x)                                (0xb74 + 0x4 * (x))
+#define                ASM_CFG_PORT_NO_PREAMBLE_ENA            BIT(8)
+#define                ASM_CFG_PORT_INJ_FORMAT_CFG(x)          ((x) << 1)
+#define ASM_RAM_CTRL_RAM_INIT                  0xbfc
+
+#define DEV_DEV_CFG_DEV_RST_CTRL       0x0
+#define                DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x)   ((x) << 20)
+#define DEV_MAC_CFG_MAC_ENA            0x24
+#define                DEV_MAC_CFG_MAC_ENA_RX_ENA              BIT(4)
+#define                DEV_MAC_CFG_MAC_ENA_TX_ENA              BIT(0)
+#define DEV_MAC_CFG_MAC_IFG            0x3c
+#define                DEV_MAC_CFG_MAC_IFG_TX_IFG(x)           ((x) << 8)
+#define                DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)          ((x) << 4)
+#define                DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)          (x)
+#define DEV_PCS1G_CFG_PCS1G_CFG                0x48
+#define                DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA         BIT(0)
+#define DEV_PCS1G_CFG_PCS1G_MODE       0x4c
+#define DEV_PCS1G_CFG_PCS1G_SD         0x50
+#define DEV_PCS1G_CFG_PCS1G_ANEG       0x54
+#define                DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
+
+#define LRN_COMMON_ACCESS_CTRL                 0x0
+#define                LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT    BIT(0)
+#define LRN_COMMON_MAC_ACCESS_CFG0             0x4
+#define LRN_COMMON_MAC_ACCESS_CFG1             0x8
+#define LRN_COMMON_MAC_ACCESS_CFG2             0xc
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x)    (x)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x)    ((x) << 12)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD        BIT(15)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED     BIT(16)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY   BIT(23)
+#define                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x)  ((x) << 24)
+
+#define QFWD_SYSTEM_SWITCH_PORT_MODE(x)                (0x4400 + 0x4 * (x))
+#define                QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA           BIT(17)
+
+#define QS_XTR_GRP_CFG(x)              (4 * (x))
+#define QS_INJ_GRP_CFG(x)              (0x24 + (x) * 4)
+
+#define QSYS_SYSTEM_RESET_CFG                  0x1048
+#define QSYS_CALCFG_CAL_AUTO                   0x1134
+#define QSYS_CALCFG_CAL_CTRL                   0x113c
+#define                QSYS_CALCFG_CAL_CTRL_CAL_MODE(x)                ((x) << 11)
+#define QSYS_RAM_CTRL_RAM_INIT                 0x1140
+
+#define REW_RAM_CTRL_RAM_INIT                  0xFFF4
+
+#define MAC_VID                        0
+#define CPU_PORT               11
+#define IFH_LEN                        7
+#define ETH_ALEN               6
+#define PGID_BROADCAST         50
+#define PGID_UNICAST           51
+
+static const char * const regs_names[] = {
+       "port0", "port1",
+       "ana_ac", "ana_cl", "ana_l2", "asm", "lrn", "qfwd", "qs", "qsys", "rew",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 2
+
+enum servalt_ctrl_regs {
+       ANA_AC = MAX_PORT,
+       ANA_CL,
+       ANA_L2,
+       ASM,
+       LRN,
+       QFWD,
+       QS,
+       QSYS,
+       REW,
+};
+
+#define SERVALT_MIIM_BUS_COUNT 2
+
+struct servalt_phy_port_t {
+       size_t phy_addr;
+       struct mii_dev *bus;
+};
+
+struct servalt_private {
+       void __iomem *regs[REGS_NAMES_COUNT];
+       struct mii_dev *bus[SERVALT_MIIM_BUS_COUNT];
+       struct servalt_phy_port_t ports[MAX_PORT];
+};
+
+struct mscc_miim_dev {
+       void __iomem *regs;
+       phys_addr_t miim_base;
+       unsigned long miim_size;
+       struct mii_dev *bus;
+};
+
+static const unsigned long servalt_regs_qs[] = {
+       [MSCC_QS_XTR_RD] = 0x8,
+       [MSCC_QS_XTR_FLUSH] = 0x18,
+       [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
+       [MSCC_QS_INJ_WR] = 0x2c,
+       [MSCC_QS_INJ_CTRL] = 0x34,
+};
+
+static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
+static int miim_count = -1;
+
+static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
+{
+       return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
+                                GCB_MIIM_STAT_BUSY, false, 250, false);
+}
+
+static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+       struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
+       u32 val;
+       int ret;
+
+       ret = mscc_miim_wait_ready(miim);
+       if (ret)
+               goto out;
+
+       writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+              GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
+              miim->regs + GCB_MIIM_MII_CMD);
+
+       ret = mscc_miim_wait_ready(miim);
+       if (ret)
+               goto out;
+
+       val = readl(miim->regs + GCB_MIIM_DATA);
+       if (val & GCB_MIIM_DATA_ERROR) {
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = val & 0xFFFF;
+out:
+       return ret;
+}
+
+static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
+                          u16 val)
+{
+       struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
+       int ret;
+
+       ret = mscc_miim_wait_ready(miim);
+       if (ret < 0)
+               goto out;
+
+       writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+              GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
+              GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
+
+out:
+       return ret;
+}
+
+static struct mii_dev *servalt_mdiobus_init(phys_addr_t miim_base,
+                                           unsigned long miim_size)
+{
+       struct mii_dev *bus;
+
+       bus = mdio_alloc();
+       if (!bus)
+               return NULL;
+
+       ++miim_count;
+       sprintf(bus->name, "miim-bus%d", miim_count);
+
+       miim[miim_count].regs = ioremap(miim_base, miim_size);
+       miim[miim_count].miim_base = miim_base;
+       miim[miim_count].miim_size = miim_size;
+       bus->priv = &miim[miim_count];
+       bus->read = mscc_miim_read;
+       bus->write = mscc_miim_write;
+
+       if (mdio_register(bus))
+               return NULL;
+
+       miim[miim_count].bus = bus;
+       return bus;
+}
+
+static void mscc_phy_reset(void)
+{
+       writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
+       writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
+              | PHY_CFG_ENA, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
+       if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + GCB_PHY_CFG) +
+                             PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
+                             true, 2000, false)) {
+               pr_err("Timeout in phy reset\n");
+       }
+}
+
+static void servalt_cpu_capture_setup(struct servalt_private *priv)
+{
+       /* ASM: No preamble and IFH prefix on CPU injected frames */
+       writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
+              ASM_CFG_PORT_INJ_FORMAT_CFG(1),
+              priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
+
+       /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
+       writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
+
+       /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
+       writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
+
+       /* Enable CPU port for any frame transfer */
+       setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
+                    QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+
+       /* Send a copy to CPU when found as forwarding entry */
+       setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
+                    ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
+}
+
+static void servalt_port_init(struct servalt_private *priv, int port)
+{
+       void __iomem *regs = priv->regs[port];
+
+       /* Enable PCS */
+       writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
+              regs + DEV_PCS1G_CFG_PCS1G_CFG);
+
+       /* Disable Signal Detect */
+       writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
+
+       /* Enable MAC RX and TX */
+       writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
+              DEV_MAC_CFG_MAC_ENA_TX_ENA,
+              regs + DEV_MAC_CFG_MAC_ENA);
+
+       /* Clear sgmii_mode_ena */
+       writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
+
+       /*
+        * Clear sw_resolve_ena(bit 0) and set adv_ability to
+        * something meaningful just in case
+        */
+       writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
+              regs + DEV_PCS1G_CFG_PCS1G_ANEG);
+
+       /* Set MAC IFG Gaps */
+       writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
+              DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
+              DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
+              regs + DEV_MAC_CFG_MAC_IFG);
+
+       /* Set link speed and release all resets */
+       writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
+              regs + DEV_DEV_CFG_DEV_RST_CTRL);
+
+       /* Make VLAN aware for CPU traffic */
+       writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
+              ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
+              MAC_VID,
+              priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
+
+       /* Enable CPU port for any frame transfer */
+       setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
+                    QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+}
+
+static int ram_init(u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+
+       if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
+               printf("Timeout in memory reset, reg = 0x%08x\n", val);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int servalt_switch_init(struct servalt_private *priv)
+{
+       /* Initialize memories */
+       ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
+       ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
+       ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
+       ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
+
+       /* Reset counters */
+       writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
+       writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
+
+       /* Enable switch-core and queue system */
+       writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
+
+       return 0;
+}
+
+static void servalt_switch_config(struct servalt_private *priv)
+{
+       writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO);
+
+       writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
+              QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
+              priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
+}
+
+static int servalt_initialize(struct servalt_private *priv)
+{
+       int ret, i;
+
+       /* Initialize switch memories, enable core */
+       ret = servalt_switch_init(priv);
+       if (ret)
+               return ret;
+
+       servalt_switch_config(priv);
+
+       for (i = 0; i < MAX_PORT; i++)
+               servalt_port_init(priv, i);
+
+       servalt_cpu_capture_setup(priv);
+
+       return 0;
+}
+
+static inline
+int servalt_vlant_wait_for_completion(struct servalt_private *priv)
+{
+       if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
+                             LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+                             false, 2000, false))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int servalt_mac_table_add(struct servalt_private *priv,
+                                const unsigned char mac[ETH_ALEN], int pgid)
+{
+       u32 macl = 0, mach = 0;
+
+       /*
+        * Set the MAC address to handle and the vlan associated in a format
+        * understood by the hardware.
+        */
+       mach |= MAC_VID << 16;
+       mach |= ((u32)mac[0]) << 8;
+       mach |= ((u32)mac[1]) << 0;
+       macl |= ((u32)mac[2]) << 24;
+       macl |= ((u32)mac[3]) << 16;
+       macl |= ((u32)mac[4]) << 8;
+       macl |= ((u32)mac[5]) << 0;
+
+       writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
+       writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
+
+       writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
+              LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
+              priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
+
+       writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+              priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
+
+       return servalt_vlant_wait_for_completion(priv);
+}
+
+static int servalt_write_hwaddr(struct udevice *dev)
+{
+       struct servalt_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+
+       return servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+}
+
+static int servalt_start(struct udevice *dev)
+{
+       struct servalt_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff };
+       int ret;
+
+       ret = servalt_initialize(priv);
+       if (ret)
+               return ret;
+
+       /* Set MAC address tables entries for CPU redirection */
+       ret = servalt_mac_table_add(priv, mac, PGID_BROADCAST);
+       if (ret)
+               return ret;
+
+       ret = servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void servalt_stop(struct udevice *dev)
+{
+}
+
+static int servalt_send(struct udevice *dev, void *packet, int length)
+{
+       struct servalt_private *priv = dev_get_priv(dev);
+       u32 ifh[IFH_LEN];
+       u32 *buf = packet;
+
+       memset(ifh, '\0', IFH_LEN * 4);
+
+       /* Set DST PORT_MASK */
+       ifh[0] = htonl(0);
+       ifh[1] = htonl(0x1FFFFF);
+       ifh[2] = htonl(~0);
+       /* Set DST_MODE to INJECT and UPDATE_FCS */
+       ifh[5] = htonl(0x4c0);
+
+       return mscc_send(priv->regs[QS], servalt_regs_qs,
+                        ifh, IFH_LEN, buf, length);
+}
+
+static int servalt_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct servalt_private *priv = dev_get_priv(dev);
+       u32 *rxbuf = (u32 *)net_rx_packets[0];
+       int byte_cnt = 0;
+
+       byte_cnt = mscc_recv(priv->regs[QS], servalt_regs_qs, rxbuf, IFH_LEN,
+                            false);
+
+       *packetp = net_rx_packets[0];
+
+       return byte_cnt;
+}
+
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
+{
+       int i = 0;
+
+       for (i = 0; i < SERVALT_MIIM_BUS_COUNT; ++i)
+               if (miim[i].miim_base == base && miim[i].miim_size == size)
+                       return miim[i].bus;
+
+       return NULL;
+}
+
+static void add_port_entry(struct servalt_private *priv, size_t index,
+                          size_t phy_addr, struct mii_dev *bus)
+{
+       priv->ports[index].phy_addr = phy_addr;
+       priv->ports[index].bus = bus;
+}
+
+static int servalt_probe(struct udevice *dev)
+{
+       struct servalt_private *priv = dev_get_priv(dev);
+       int i;
+       struct resource res;
+       fdt32_t faddr;
+       phys_addr_t addr_base;
+       unsigned long addr_size;
+       ofnode eth_node, node, mdio_node;
+       size_t phy_addr;
+       struct mii_dev *bus;
+       struct ofnode_phandle_args phandle;
+
+       if (!priv)
+               return -EINVAL;
+
+       /* Get registers and map them to the private structure */
+       for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
+               priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
+               if (!priv->regs[i]) {
+                       debug
+                           ("Error can't get regs base addresses for %s\n",
+                            regs_names[i]);
+                       return -ENOMEM;
+               }
+       }
+
+       /* Initialize miim buses */
+       memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
+              SERVALT_MIIM_BUS_COUNT);
+
+       /* iterate all the ports and find out on which bus they are */
+       i = 0;
+       eth_node = dev_read_first_subnode(dev);
+       for (node = ofnode_first_subnode(eth_node);
+            ofnode_valid(node);
+            node = ofnode_next_subnode(node)) {
+               if (ofnode_read_resource(node, 0, &res))
+                       return -ENOMEM;
+               i = res.start;
+
+               ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
+                                              &phandle);
+
+               /* Get phy address on mdio bus */
+               if (ofnode_read_resource(phandle.node, 0, &res))
+                       return -ENOMEM;
+               phy_addr = res.start;
+
+               /* Get mdio node */
+               mdio_node = ofnode_get_parent(phandle.node);
+
+               if (ofnode_read_resource(mdio_node, 0, &res))
+                       return -ENOMEM;
+               faddr = cpu_to_fdt32(res.start);
+
+               addr_base = ofnode_translate_address(mdio_node, &faddr);
+               addr_size = res.end - res.start;
+
+               /* If the bus is new then create a new bus */
+               if (!get_mdiobus(addr_base, addr_size))
+                       priv->bus[miim_count] =
+                               servalt_mdiobus_init(addr_base, addr_size);
+
+               /* Connect mdio bus with the port */
+               bus = get_mdiobus(addr_base, addr_size);
+               add_port_entry(priv, i, phy_addr, bus);
+       }
+
+       mscc_phy_reset();
+
+       for (i = 0; i < MAX_PORT; i++) {
+               if (!priv->ports[i].bus)
+                       continue;
+
+               phy_connect(priv->ports[i].bus, priv->ports[i].phy_addr, dev,
+                           PHY_INTERFACE_MODE_NONE);
+       }
+
+       return 0;
+}
+
+static int servalt_remove(struct udevice *dev)
+{
+       struct servalt_private *priv = dev_get_priv(dev);
+       int i;
+
+       for (i = 0; i < SERVALT_MIIM_BUS_COUNT; i++) {
+               mdio_unregister(priv->bus[i]);
+               mdio_free(priv->bus[i]);
+       }
+
+       return 0;
+}
+
+static const struct eth_ops servalt_ops = {
+       .start        = servalt_start,
+       .stop         = servalt_stop,
+       .send         = servalt_send,
+       .recv         = servalt_recv,
+       .write_hwaddr = servalt_write_hwaddr,
+};
+
+static const struct udevice_id mscc_servalt_ids[] = {
+       {.compatible = "mscc,vsc7437-switch" },
+       { /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(servalt) = {
+       .name                           = "servalt-switch",
+       .id                             = UCLASS_ETH,
+       .of_match                       = mscc_servalt_ids,
+       .probe                          = servalt_probe,
+       .remove                         = servalt_remove,
+       .ops                            = &servalt_ops,
+       .priv_auto_alloc_size           = sizeof(struct servalt_private),
+       .platdata_auto_alloc_size       = sizeof(struct eth_pdata),
+};
index 32bbf41dd1f5972e6aaa8c25d36d151e14f92f3a..102fb91fffd07cc0f65a8aef150247dae6459a15 100644 (file)
@@ -174,4 +174,12 @@ config KEYSTONE_USB_PHY
 
          This PHY is found on some Keystone (K2) devices supporting USB.
 
+config MT76X8_USB_PHY
+       bool "MediaTek MT76x8 (7628/88) USB PHY support"
+       depends on PHY
+       help
+          Support the USB PHY in MT76x8 SoCs
+
+         This PHY is found on MT76x8 devices supporting USB.
+
 endmenu
index 099551d693082596878f52bbc592962e70429fb3..b55917bce1ae62353fb4ace629c74e790fedf808 100644 (file)
@@ -19,3 +19,4 @@ obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
+obj-$(CONFIG_MT76X8_USB_PHY) += mt76x8-usb-phy.o
diff --git a/drivers/phy/mt76x8-usb-phy.c b/drivers/phy/mt76x8-usb-phy.c
new file mode 100644 (file)
index 0000000..268da8e
--- /dev/null
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Stefan Roese <sr@denx.de>
+ *
+ * Derived from linux/drivers/phy/ralink/phy-ralink-usb.c
+ *     Copyright (C) 2017 John Crispin <john@phrozen.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+#include <asm/io.h>
+
+#define RT_SYSC_REG_SYSCFG1            0x014
+#define RT_SYSC_REG_CLKCFG1            0x030
+#define RT_SYSC_REG_USB_PHY_CFG                0x05c
+
+#define OFS_U2_PHY_AC0                 0x800
+#define OFS_U2_PHY_AC1                 0x804
+#define OFS_U2_PHY_AC2                 0x808
+#define OFS_U2_PHY_ACR0                        0x810
+#define OFS_U2_PHY_ACR1                        0x814
+#define OFS_U2_PHY_ACR2                        0x818
+#define OFS_U2_PHY_ACR3                        0x81C
+#define OFS_U2_PHY_ACR4                        0x820
+#define OFS_U2_PHY_AMON0               0x824
+#define OFS_U2_PHY_DCR0                        0x860
+#define OFS_U2_PHY_DCR1                        0x864
+#define OFS_U2_PHY_DTM0                        0x868
+#define OFS_U2_PHY_DTM1                        0x86C
+
+#define RT_RSTCTRL_UDEV                        BIT(25)
+#define RT_RSTCTRL_UHST                        BIT(22)
+#define RT_SYSCFG1_USB0_HOST_MODE      BIT(10)
+
+#define MT7620_CLKCFG1_UPHY0_CLK_EN    BIT(25)
+#define MT7620_CLKCFG1_UPHY1_CLK_EN    BIT(22)
+#define RT_CLKCFG1_UPHY1_CLK_EN                BIT(20)
+#define RT_CLKCFG1_UPHY0_CLK_EN                BIT(18)
+
+#define USB_PHY_UTMI_8B60M             BIT(1)
+#define UDEV_WAKEUP                    BIT(0)
+
+struct mt76x8_usb_phy {
+       u32                     clk;
+       void __iomem            *base;
+       struct regmap           *sysctl;
+};
+
+static void u2_phy_w32(struct mt76x8_usb_phy *phy, u32 val, u32 reg)
+{
+       writel(val, phy->base + reg);
+}
+
+static u32 u2_phy_r32(struct mt76x8_usb_phy *phy, u32 reg)
+{
+       return readl(phy->base + reg);
+}
+
+static void mt76x8_usb_phy_init(struct mt76x8_usb_phy *phy)
+{
+       u2_phy_r32(phy, OFS_U2_PHY_AC2);
+       u2_phy_r32(phy, OFS_U2_PHY_ACR0);
+       u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+
+       u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
+       u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+       u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
+       u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+       u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
+       u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+       u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
+       u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+       u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
+       u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
+       u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
+       u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
+}
+
+static int mt76x8_usb_phy_power_on(struct phy *_phy)
+{
+       struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
+       u32 t;
+
+       /* enable the phy */
+       regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
+                          phy->clk, phy->clk);
+
+       /* setup host mode */
+       regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,
+                          RT_SYSCFG1_USB0_HOST_MODE,
+                          RT_SYSCFG1_USB0_HOST_MODE);
+
+       /*
+        * The SDK kernel had a delay of 100ms. however on device
+        * testing showed that 10ms is enough
+        */
+       mdelay(10);
+
+       if (phy->base)
+               mt76x8_usb_phy_init(phy);
+
+       /* print some status info */
+       regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);
+       printf("remote usb device wakeup %s\n",
+              (t & UDEV_WAKEUP) ? "enabled" : "disabled");
+       if (t & USB_PHY_UTMI_8B60M)
+               printf("UTMI 8bit 60MHz\n");
+       else
+               printf("UTMI 16bit 30MHz\n");
+
+       return 0;
+}
+
+static int mt76x8_usb_phy_power_off(struct phy *_phy)
+{
+       struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
+
+       /* disable the phy */
+       regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
+                          phy->clk, 0);
+
+       return 0;
+}
+
+static int mt76x8_usb_phy_probe(struct udevice *dev)
+{
+       struct mt76x8_usb_phy *phy = dev_get_priv(dev);
+
+       phy->sysctl = syscon_regmap_lookup_by_phandle(dev, "ralink,sysctl");
+       if (IS_ERR(phy->sysctl))
+               return PTR_ERR(phy->sysctl);
+
+       phy->base = dev_read_addr_ptr(dev);
+       if (!phy->base)
+               return -EINVAL;
+
+       return 0;
+}
+
+static struct phy_ops mt76x8_usb_phy_ops = {
+       .power_on = mt76x8_usb_phy_power_on,
+       .power_off = mt76x8_usb_phy_power_off,
+};
+
+static const struct udevice_id mt76x8_usb_phy_ids[] = {
+       { .compatible = "mediatek,mt7628-usbphy" },
+       { }
+};
+
+U_BOOT_DRIVER(mt76x8_usb_phy) = {
+       .name           = "mt76x8_usb_phy",
+       .id             = UCLASS_PHY,
+       .of_match       = mt76x8_usb_phy_ids,
+       .ops            = &mt76x8_usb_phy_ops,
+       .probe          = mt76x8_usb_phy_probe,
+       .priv_auto_alloc_size = sizeof(struct mt76x8_usb_phy),
+};
index 1daa2123a149e65084827ad41e7b6b243e889c8e..c7d1e44882e8438c6373c5a45ce61c43e3dc0bda 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 obj-$(CONFIG_PINCTRL_AR933X) += pinctrl_ar933x.o
-obj-$(CONFIG_PINCTRL_QCA953x) += pinctrl_qca953x.o
+obj-$(CONFIG_PINCTRL_QCA953X) += pinctrl_qca953x.o
diff --git a/include/configs/ap152.h b/include/configs/ap152.h
new file mode 100644 (file)
index 0000000..c948a44
--- /dev/null
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_SYS_HZ                   1000
+#define CONFIG_SYS_MHZ                  375
+#define CONFIG_SYS_MIPS_TIMER_FREQ      (CONFIG_SYS_MHZ * 1000000)
+
+#define CONFIG_SYS_MONITOR_BASE         CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_MALLOC_LEN           0x40000
+#define CONFIG_SYS_BOOTPARAMS_LEN       0x20000
+
+#define CONFIG_SYS_SDRAM_BASE           0x80000000
+#define CONFIG_SYS_LOAD_ADDR            0x81000000
+
+#define CONFIG_SYS_INIT_RAM_ADDR        0xbd000000
+#define CONFIG_SYS_INIT_RAM_SIZE        0x2000
+#define CONFIG_SYS_INIT_SP_ADDR \
+       (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1)
+
+/*
+ * Serial Port
+ */
+#define CONFIG_SYS_NS16550_CLK          25000000
+#define CONFIG_SYS_BAUDRATE_TABLE \
+       {9600, 19200, 38400, 57600, 115200}
+
+#define CONFIG_BOOTCOMMAND              "sf probe;" \
+                                       "mtdparts default;" \
+                                       "bootm 0x9f060000"
+
+#define CONFIG_ENV_SPI_MAX_HZ           25000000
+#define CONFIG_ENV_OFFSET               0x40000
+#define CONFIG_ENV_SECT_SIZE            0x10000
+#define CONFIG_ENV_SIZE                 0x10000
+
+/* Miscellaneous configurable options */
+
+/*
+ * Diagnostics
+ */
+#define CONFIG_SYS_MEMTEST_START        0x80100000
+#define CONFIG_SYS_MEMTEST_END          0x83f00000
+
+#endif  /* __CONFIG_H */
index 2840c7b815b53275afeea6392fca53fda683e7e4..8c68372026e9f089df5062bb9430ab5fc1751105 100644 (file)
@@ -10,7 +10,7 @@
 
 /* Onboard devices */
 
-#define CONFIG_SYS_MALLOC_LEN          0x100000
+#define CONFIG_SYS_MALLOC_LEN          0x1F0000
 #define CONFIG_SYS_LOAD_ADDR           0x00100000
 #define CONFIG_SYS_INIT_SP_OFFSET       0x400000
 
@@ -27,7 +27,7 @@
 
 #if defined(CONFIG_ENV_IS_IN_SPI_FLASH) && !defined(CONFIG_ENV_OFFSET)
 #define CONFIG_ENV_OFFSET              (1024 * 1024)
-#define CONFIG_ENV_SIZE                        (256 * 1024)
+#define CONFIG_ENV_SIZE                        (8 * 1024)
 #define CONFIG_ENV_SECT_SIZE           (256 * 1024)
 
 #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
diff --git a/include/dt-bindings/mscc/jr2_data.h b/include/dt-bindings/mscc/jr2_data.h
new file mode 100644 (file)
index 0000000..2f06fc5
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _JR2_DATA_H_
+#define _JR2_DATA_H_
+
+#define SERDES1G(x)     (x)
+#define SERDES1G_MAX    SERDES1G(10)
+#define SERDES6G(x)     (SERDES1G_MAX + 1 + (x))
+#define SERDES6G_MAX    SERDES6G(17)
+#define SERDES_MAX      (SERDES6G_MAX + 1)
+
+/* similar with phy_interface_t */
+#define PHY_MODE_SGMII  2
+#define PHY_MODE_QSGMII 4
+
+#endif