Merge tag 'mips-pull-2019-05-03' of git://git.denx.de/u-boot-mips
authorTom Rini <trini@konsulko.com>
Sun, 5 May 2019 00:02:31 +0000 (20:02 -0400)
committerTom Rini <trini@konsulko.com>
Sun, 5 May 2019 00:02:42 +0000 (20:02 -0400)
- mscc: small fixes, enhance network support for Serval, Luton and Ocelot
- mt7620: rename arch to more generic name mtmips
- mips: pass initrd addresses via DT as physical addresses

50 files changed:
MAINTAINERS
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/dts/Makefile
arch/mips/dts/luton_pcb090.dts
arch/mips/dts/luton_pcb091.dts
arch/mips/dts/mscc,luton.dtsi
arch/mips/dts/mscc,ocelot.dtsi
arch/mips/dts/mscc,serval.dtsi
arch/mips/dts/ocelot_pcb120.dts
arch/mips/dts/ocelot_pcb123.dts
arch/mips/dts/serval_pcb105.dts
arch/mips/dts/serval_pcb106.dts
arch/mips/lib/bootm.c
arch/mips/mach-mscc/Kconfig
arch/mips/mach-mscc/include/mach/ddr.h
arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h
arch/mips/mach-mscc/reset.c
arch/mips/mach-mt7620/Kconfig [deleted file]
arch/mips/mach-mt7620/Makefile [deleted file]
arch/mips/mach-mt7620/cpu.c [deleted file]
arch/mips/mach-mt7620/ddr_calibrate.c [deleted file]
arch/mips/mach-mt7620/lowlevel_init.S [deleted file]
arch/mips/mach-mt7620/mt76xx.h [deleted file]
arch/mips/mach-mtmips/Kconfig [new file with mode: 0644]
arch/mips/mach-mtmips/Makefile [new file with mode: 0644]
arch/mips/mach-mtmips/cpu.c [new file with mode: 0644]
arch/mips/mach-mtmips/ddr_calibrate.c [new file with mode: 0644]
arch/mips/mach-mtmips/lowlevel_init.S [new file with mode: 0644]
arch/mips/mach-mtmips/mt76xx.h [new file with mode: 0644]
board/mscc/luton/luton.c
board/mscc/ocelot/ocelot.c
board/mscc/serval/serval.c
configs/gardena-smart-gateway-mt7688-ram_defconfig
configs/gardena-smart-gateway-mt7688_defconfig
configs/linkit-smart-7688-ram_defconfig
configs/linkit-smart-7688_defconfig
configs/mscc_serval_defconfig
drivers/gpio/Kconfig
drivers/net/Kconfig
drivers/net/mscc_eswitch/Kconfig
drivers/net/mscc_eswitch/Makefile
drivers/net/mscc_eswitch/luton_switch.c
drivers/net/mscc_eswitch/ocelot_switch.c
drivers/net/mscc_eswitch/serval_switch.c [new file with mode: 0644]
drivers/spi/Kconfig
drivers/watchdog/Kconfig
include/dt-bindings/mscc/luton_data.h [new file with mode: 0644]
include/dt-bindings/mscc/ocelot_data.h [new file with mode: 0644]
include/dt-bindings/mscc/serval_data.h [new file with mode: 0644]

index 5891fd08b6a700c967f74dc441089dcfbffb037f..33fd4652a42554599e6ced49d26613546b902ab2 100644 (file)
@@ -578,6 +578,7 @@ F:  configs/mscc*
 F:     drivers/gpio/mscc_sgpio.c
 F:     drivers/spi/mscc_bb_spi.c
 F:     include/configs/vcoreiii.h
+F:     include/dt-bindings/mscc/
 F:     drivers/pinctrl/mscc/
 F:     drivers/net/mscc_eswitch/
 
index 194f4f349ed5bbb14f08c6ceee5ae4d2116f9f25..9cf8e9800d8305361c54dc70dd2d8bd43e072084 100644 (file)
@@ -74,8 +74,8 @@ config ARCH_BMIPS
        select SYSRESET
        imply CMD_DM
 
-config ARCH_MT7620
-       bool "Support MT7620/7688 SoCs"
+config ARCH_MTMIPS
+       bool "Support MediaTek MIPS platforms"
        imply CMD_DM
        select DISPLAY_CPUINFO
        select DM
@@ -153,7 +153,7 @@ source "arch/mips/mach-mscc/Kconfig"
 source "arch/mips/mach-bmips/Kconfig"
 source "arch/mips/mach-jz47xx/Kconfig"
 source "arch/mips/mach-pic32/Kconfig"
-source "arch/mips/mach-mt7620/Kconfig"
+source "arch/mips/mach-mtmips/Kconfig"
 
 if MIPS
 
index 029d290f1e06665869b80efdfe64c3e64047f73a..af3f227436ee3b80440c5c7e08ead4ddf506efbe 100644 (file)
@@ -15,7 +15,7 @@ machine-$(CONFIG_ARCH_ATH79) += ath79
 machine-$(CONFIG_ARCH_BMIPS) += bmips
 machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
 machine-$(CONFIG_MACH_PIC32) += pic32
-machine-$(CONFIG_ARCH_MT7620) += mt7620
+machine-$(CONFIG_ARCH_MTMIPS) += mtmips
 machine-$(CONFIG_ARCH_MSCC) += mscc
 
 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
index 3522e6cdc82e5662424569a471d3202a11ce082f..e2de1da147e45c10b90e0d894b37aa9690e20cd6 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
-dtb-$(CONFIG_ARCH_MT7620) += \
+dtb-$(CONFIG_ARCH_MTMIPS) += \
        gardena-smart-gateway-mt7688.dtb \
        linkit-smart-7688.dtb
 dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
index fe457bae9d56e6ab49b2b051d0cf8de85c5c59d8..ea3e3b7fbd83ccda37f207e99c2885b552141757 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,luton.dtsi"
+#include <dt-bindings/mscc/luton_data.h>
 
 / {
        model = "Luton26 PCB090 Reference Board";
 
 &mdio0 {
        status = "okay";
-};
-
-&port0 {
-       phy-handle = <&phy0>;
-};
-
-&port1 {
-       phy-handle = <&phy1>;
-};
-
-&port2 {
-       phy-handle = <&phy2>;
-};
-
-&port3 {
-       phy-handle = <&phy3>;
-};
-
-&port4 {
-       phy-handle = <&phy4>;
-};
-
-&port5 {
-       phy-handle = <&phy5>;
-};
-
-&port6 {
-       phy-handle = <&phy6>;
-};
-
-&port7 {
-       phy-handle = <&phy7>;
-};
 
-&port8 {
-       phy-handle = <&phy8>;
+       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>;
+       };
 };
 
-&port9 {
-       phy-handle = <&phy9>;
-};
+&mdio1 {
+       status = "okay";
 
-&port10 {
-       phy-handle = <&phy10>;
+       phy12: ethernet-phy@12 {
+               reg = <0>;
+       };
+       phy13: ethernet-phy@13 {
+               reg = <1>;
+       };
+       phy14: ethernet-phy@14 {
+               reg = <2>;
+       };
+       phy15: ethernet-phy@15 {
+               reg = <3>;
+       };
+       phy16: ethernet-phy@16 {
+               reg = <4>;
+       };
+       phy17: ethernet-phy@17 {
+               reg = <5>;
+       };
+       phy18: ethernet-phy@18 {
+               reg = <6>;
+       };
+       phy19: ethernet-phy@19 {
+               reg = <7>;
+       };
+       phy20: ethernet-phy@20 {
+               reg = <8>;
+       };
+       phy21: ethernet-phy@21 {
+               reg = <9>;
+       };
+       phy22: ethernet-phy@22 {
+               reg = <10>;
+       };
+       phy23: ethernet-phy@23 {
+               reg = <11>;
+       };
 };
 
-&port11 {
-       phy-handle = <&phy11>;
+&switch {
+       ethernet-ports {
+               port0: port@0 {
+                       reg = <0>;
+                       phy-handle = <&phy0>;
+               };
+               port1: port@1 {
+                       reg = <1>;
+                       phy-handle = <&phy1>;
+               };
+               port2: port@2 {
+                       reg = <2>;
+                       phy-handle = <&phy2>;
+               };
+               port3: port@3 {
+                       reg = <3>;
+                       phy-handle = <&phy3>;
+               };
+               port4: port@4 {
+                       reg = <4>;
+                       phy-handle = <&phy4>;
+               };
+               port5: port@5 {
+                       reg = <5>;
+                       phy-handle = <&phy5>;
+               };
+               port6: port@6 {
+                       reg = <6>;
+                       phy-handle = <&phy6>;
+               };
+               port7: port@7 {
+                       reg = <7>;
+                       phy-handle = <&phy7>;
+               };
+               port8: port@8 {
+                       reg = <8>;
+                       phy-handle = <&phy8>;
+               };
+               port9: port@9 {
+                       reg = <9>;
+                       phy-handle = <&phy9>;
+               };
+               port10: port@10 {
+                       reg = <10>;
+                       phy-handle = <&phy10>;
+               };
+               port11: port@11 {
+                       reg = <11>;
+                       phy-handle = <&phy11>;
+               };
+               port12: port@12 {
+                       reg = <12>;
+                       phy-handle = <&phy12>;
+                       phys = <&serdes_hsio 12 SERDES6G(1) 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(2) 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(3) 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>;
+               };
+       };
 };
index f684cc8dd6332eb0c584030342ad04da1fdc932e..cb78c5751bb5bbcc8bc2cd1774e9a3e8d9eea466 100644 (file)
 
 &mdio0 {
        status = "okay";
-};
-
-&port0 {
-       phy-handle = <&phy0>;
-};
-
-&port1 {
-       phy-handle = <&phy1>;
-};
-
-&port2 {
-       phy-handle = <&phy2>;
-};
-
-&port3 {
-       phy-handle = <&phy3>;
-};
 
-&port4 {
-       phy-handle = <&phy4>;
-};
-
-&port5 {
-       phy-handle = <&phy5>;
-};
-
-&port6 {
-       phy-handle = <&phy6>;
-};
-
-&port7 {
-       phy-handle = <&phy7>;
-};
-
-&port8 {
-       phy-handle = <&phy8>;
-};
-
-&port9 {
-       phy-handle = <&phy9>;
-};
-
-&port10 {
-       phy-handle = <&phy10>;
+       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>;
+       };
 };
 
-&port11 {
-       phy-handle = <&phy11>;
+&switch {
+       ethernet-ports {
+               port0: port@0 {
+                       reg = <0>;
+                       phy-handle = <&phy0>;
+               };
+               port1: port@1 {
+                       reg = <1>;
+                       phy-handle = <&phy1>;
+               };
+               port2: port@2 {
+                       reg = <2>;
+                       phy-handle = <&phy2>;
+               };
+               port3: port@3 {
+                       reg = <3>;
+                       phy-handle = <&phy3>;
+               };
+               port4: port@4 {
+                       reg = <4>;
+                       phy-handle = <&phy4>;
+               };
+               port5: port@5 {
+                       reg = <5>;
+                       phy-handle = <&phy5>;
+               };
+               port6: port@6 {
+                       reg = <6>;
+                       phy-handle = <&phy6>;
+               };
+               port7: port@7 {
+                       reg = <7>;
+                       phy-handle = <&phy7>;
+               };
+               port8: port@8 {
+                       reg = <8>;
+                       phy-handle = <&phy8>;
+               };
+               port9: port@9 {
+                       reg = <9>;
+                       phy-handle = <&phy9>;
+               };
+               port10: port@10 {
+                       reg = <10>;
+                       phy-handle = <&phy10>;
+               };
+               port11: port@11 {
+                       reg = <11>;
+                       phy-handle = <&phy11>;
+               };
+       };
 };
index de354fe2ce26173903fff8c844937d4febadc2cb..c8231018f1029e9bc415f751505fa7053858d687 100644 (file)
                              <0x030000 0x1000>, // VTSS_TO_REW
                              <0x070000 0x1000>, // VTSS_TO_DEVCPU_GCB
                              <0x080000 0x0100>, // VTSS_TO_DEVCPU_QS
-                             <0x0a0000 0x0100>; // VTSS_TO_HSIO
+                             <0x0a0000 0x10000>; // VTSS_TO_HSIO
                        reg-names = "port0", "port1", "port2", "port3",
                                    "port4", "port5", "port6", "port7",
                                    "port8", "port9", "port10", "port11",
                        ethernet-ports {
                                #address-cells = <1>;
                                #size-cells = <0>;
-
-                               port0: port@0 {
-                                       reg = <0>;
-                               };
-                               port1: port@1 {
-                                       reg = <1>;
-                               };
-                               port2: port@2 {
-                                       reg = <2>;
-                               };
-                               port3: port@3 {
-                                       reg = <3>;
-                               };
-                               port4: port@4 {
-                                       reg = <4>;
-                               };
-                               port5: port@5 {
-                                       reg = <5>;
-                               };
-                               port6: port@6 {
-                                       reg = <6>;
-                               };
-                               port7: port@7 {
-                                       reg = <7>;
-                               };
-                               port8: port@8 {
-                                       reg = <8>;
-                               };
-                               port9: port@9 {
-                                       reg = <9>;
-                               };
-                               port10: port@10 {
-                                       reg = <10>;
-                               };
-                               port11: port@11 {
-                                       reg = <11>;
-                               };
-                               port12: port@12 {
-                                       reg = <12>;
-                               };
-                               port13: port@13 {
-                                       reg = <13>;
-                               };
-                               port14: port@14 {
-                                       reg = <14>;
-                               };
-                               port15: port@15 {
-                                       reg = <15>;
-                               };
-                               port16: port@16 {
-                                       reg = <16>;
-                               };
-                               port17: port@17 {
-                                       reg = <17>;
-                               };
-                               port18: port@18 {
-                                       reg = <18>;
-                               };
-                               port19: port@19 {
-                                       reg = <19>;
-                               };
-                               port20: port@20 {
-                                       reg = <20>;
-                               };
-                               port21: port@21 {
-                                       reg = <21>;
-                               };
-                               port22: port@22 {
-                                       reg = <22>;
-                               };
-                               port23: port@23 {
-                                       reg = <23>;
-                               };
                        };
                };
 
                        compatible = "mscc,luton-miim";
                        reg = <0x700a0 0x24>;
                        status = "disabled";
+               };
 
-                       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>;
+               mdio1: mdio@700c4 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,luton-miim";
+                       reg = <0x700c4 0x24>;
+                       status = "disabled";
+               };
+
+               hsio: syscon@10d0000 {
+                       compatible = "mscc,luton-hsio", "syscon", "simple-mfd";
+                       reg = <0xa0000 0x10000>;
+
+                       serdes_hsio: serdes_hsio {
+                               compatible = "mscc,vsc7527-serdes";
+                               #phy-cells = <3>;
                        };
                };
        };
index 4f3fe356c45654fd9cda9fd5f8cc882649e44bd7..9a187b6e5880a9975010d19cefc1c8a42a768449 100644 (file)
                        status = "disabled";
                };
 
-               switch@1010000 {
+               switch: switch@1010000 {
                        pinctrl-0 = <&miim1_pins>;
                        pinctrl-names = "default";
 
                        compatible = "mscc,vsc7514-switch";
-                       reg = <0x1010000 0x10000>, /* VTSS_TO_SYS */
-                             <0x1030000 0x10000>, /* VTSS_TO_REW */
-                             <0x1080000 0x100>, /* VTSS_TO_DEVCPU_QS */
-                             <0x10d0000 0x10000>, /* VTSS_TO_HSIO */
-                             <0x11e0000 0x100>, /* VTSS_TO_DEV_0 */
-                             <0x11f0000 0x100>, /* VTSS_TO_DEV_1 */
-                             <0x1200000 0x100>, /* VTSS_TO_DEV_2 */
-                             <0x1210000 0x100>, /* VTSS_TO_DEV_3 */
-                             <0x1220000 0x100>, /* VTSS_TO_DEV_4 */
-                             <0x1230000 0x100>, /* VTSS_TO_DEV_5 */
-                             <0x1240000 0x100>, /* VTSS_TO_DEV_6 */
-                             <0x1250000 0x100>, /* VTSS_TO_DEV_7 */
-                             <0x1260000 0x100>, /* VTSS_TO_DEV_8 */
-                             <0x1270000 0x100>, /* NA */
-                             <0x1280000 0x100>, /* NA */
-                             <0x1800000 0x80000>, /* VTSS_TO_QSYS */
-                             <0x1880000 0x10000>; /* VTSS_TO_ANA */
-                       reg-names = "sys", "rew", "qs", "hsio", "port0",
-                                   "port1", "port2", "port3", "port4", "port5",
-                                   "port6", "port7", "port8", "port9",
-                                   "port10", "qsys", "ana";
+
+                       reg = <0x11e0000 0x100>, // VTSS_TO_DEV_0
+                             <0x11f0000 0x100>, // VTSS_TO_DEV_1
+                             <0x1200000 0x100>, // VTSS_TO_DEV_2
+                             <0x1210000 0x100>, // VTSS_TO_DEV_3
+                             <0x1220000 0x100>, // VTSS_TO_DEV_4
+                             <0x1230000 0x100>, // VTSS_TO_DEV_5
+                             <0x1240000 0x100>, // VTSS_TO_DEV_6
+                             <0x1250000 0x100>, // VTSS_TO_DEV_7
+                             <0x1260000 0x100>, // VTSS_TO_DEV_8
+                             <0x1270000 0x100>, // VTSS_TO_DEV_9
+                             <0x1280000 0x100>, // VTSS_TO_DEV_10
+                             <0x1010000 0x10000>, // VTSS_TO_SYS
+                             <0x1030000 0x10000>, // VTSS_TO_REW
+                             <0x1080000 0x100>, // VTSS_TO_DEVCPU_QS
+                             <0x10d0000 0x10000>, // VTSS_TO_HSIO
+                             <0x1800000 0x80000>,// VTSS_TO_QSYS
+                             <0x1880000 0x10000>;// VTSS_TO_ANA
+                       reg-names = "port0", "port1", "port2", "port3", "port4",
+                                   "port5", "port6", "port7", "port8", "port9",
+                                   "port10",
+                                   "sys", "rew", "qs", "hsio", "qsys", "ana";
                        interrupts = <21 22>;
                        interrupt-names = "xtr", "inj";
                        status = "okay";
                        ethernet-ports {
                                #address-cells = <1>;
                                #size-cells = <0>;
-
-                               port0: port@0 {
-                                       reg = <0>;
-                               };
-                               port1: port@1 {
-                                       reg = <1>;
-                               };
-                               port2: port@2 {
-                                       reg = <2>;
-                               };
-                               port3: port@3 {
-                                       reg = <3>;
-                               };
-                               port4: port@4 {
-                                       reg = <4>;
-                               };
-                               port5: port@5 {
-                                       reg = <5>;
-                               };
-                               port6: port@6 {
-                                       reg = <6>;
-                               };
-                               port7: port@7 {
-                                       reg = <7>;
-                               };
-                               port8: port@8 {
-                                       reg = <8>;
-                               };
-                               port9: port@9 {
-                                       reg = <9>;
-                               };
-                               port10: port@10 {
-                                       reg = <10>;
-                               };
                        };
                };
 
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "mscc,ocelot-miim";
-                       reg = <0x107009c 0x24>, <0x10700f0 0x8>;
+                       reg = <0x107009c 0x24>;
                        interrupts = <14>;
                        status = "disabled";
+               };
 
-                       phy0: ethernet-phy@0 {
-                               reg = <0>;
-                       };
-                       phy1: ethernet-phy@1 {
-                               reg = <1>;
-                       };
-                       phy2: ethernet-phy@2 {
-                               reg = <2>;
-                       };
-                       phy3: ethernet-phy@3 {
-                               reg = <3>;
+               mdio1: mdio@10700f0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,ocelot-miim";
+                       reg = <0x10700c0 0x24>;
+                       interrupts = <14>;
+                       status = "disabled";
+               };
+
+               hsio: syscon@10d0000 {
+                       compatible = "mscc,ocelot-hsio", "syscon", "simple-mfd";
+                       reg = <0x10d0000 0x10000>;
+
+                       serdes_hsio: serdes_hsio {
+                               compatible = "mscc,vsc7514-serdes";
+                               #phy-cells = <3>;
                        };
                };
 
index bd60051719bde65271ee2dee86ecd4b75a61e2f4..90eeebd3a4ea8586820c63ead8a9feaf3dac74be 100644 (file)
                        #gpio-cells = <2>;
                        gpio-ranges = <&sgpio 0 0 64>;
                };
+
+               switch: switch@011e0000 {
+                       compatible = "mscc,vsc7418-switch";
+                       reg = <0x011e0000 0x0100>,   // VTSS_TO_DEV0
+                             <0x011f0000 0x0100>,   // VTSS_TO_DEV1
+                             <0x01200000 0x0100>,   // VTSS_TO_DEV2
+                             <0x01210000 0x0100>,   // VTSS_TO_DEV3
+                             <0x01220000 0x0100>,   // VTSS_TO_DEV4
+                             <0x01230000 0x0100>,   // VTSS_TO_DEV5
+                             <0x01240000 0x0100>,   // VTSS_TO_DEV6
+                             <0x01250000 0x0100>,   // VTSS_TO_DEV7
+                             <0x01260000 0x0100>,   // VTSS_TO_DEV8
+                             <0x01270000 0x0100>,   // VTSS_TO_DEV9
+                             <0x01280000 0x0100>,   // VTSS_TO_DEV10
+                             <0x01900000 0x100000>, // ANA
+                             <0x01080000 0x20000>,  // QS
+                             <0x01800000 0x100000>, // QSYS
+                             <0x01030000 0x10000>,  // REW
+                             <0x01010000 0x20000>,  // SYS
+                             <0x010a0000 0x10000>;  // HSIO
+                       reg-names = "port0", "port1", "port2", "port3",
+                                   "port4", "port5", "port6", "port7",
+                                   "port8", "port9", "port10",
+                                   "ana", "qs", "qsys", "rew", "sys",
+                                   "hsio";
+                       status = "okay";
+
+                       ethernet-ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+
+               mdio0: mdio@0107005c {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,serval-miim";
+                       reg = <0x0107005c 0x24>;
+                       status = "disabled";
+               };
+
+               mdio1: mdio@01070080 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "mscc,serval-miim";
+                       reg = <0x01070080 0x24>;
+                       status = "disabled";
+               };
+
+               hsio: syscon@10d0000 {
+                       compatible = "mscc,serval-hsio", "syscon", "simple-mfd";
+                       reg = <0x10a0000 0x10000>;
+
+                       serdes_hsio: serdes_hsio {
+                               compatible = "mscc,vsc7418-serdes";
+                               #phy-cells = <3>;
+                       };
+               };
        };
 };
index 658719e684f84e3fc4376107401fa546dfcb989e..e608029a3f8217248763c622ed8afe14adda18ce 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,ocelot_pcb.dtsi"
+#include <dt-bindings/mscc/ocelot_data.h>
 
 / {
        model = "Ocelot PCB120 Reference Board";
        mscc,sgpio-ports = <0x000FFFFF>;
 };
 
+&mdio0 {
+       status = "okay";
+
+       phy4: ethernet-phy@4 {
+               reg = <3>;
+       };
+       phy5: ethernet-phy@5 {
+               reg = <2>;
+       };
+       phy6: ethernet-phy@6 {
+               reg = <1>;
+       };
+       phy7: ethernet-phy@7 {
+               reg = <0>;
+       };
+};
+
+&mdio1 {
+       status = "okay";
+
+       phy0: ethernet-phy@0 {
+               reg = <3>;
+       };
+       phy1: ethernet-phy@1 {
+               reg = <2>;
+       };
+       phy2: ethernet-phy@2 {
+               reg = <1>;
+       };
+       phy3: ethernet-phy@3 {
+               reg = <0>;
+       };
+};
+
+&switch {
+       ethernet-ports {
+               port0: port@0 {
+                       reg = <5>;
+                       phy-handle = <&phy0>;
+                       phys = <&serdes_hsio 5 SERDES1G(2) PHY_MODE_SGMII>;
+               };
+               port1: port@1 {
+                       reg = <9>;
+                       phy-handle = <&phy1>;
+                       phys = <&serdes_hsio 9 SERDES1G(3) PHY_MODE_SGMII>;
+               };
+               port2: port@2 {
+                       reg = <6>;
+                       phy-handle = <&phy2>;
+                       phys = <&serdes_hsio 6 SERDES1G(4) PHY_MODE_SGMII>;
+               };
+               port3: port@3 {
+                       reg = <4>;
+                       phy-handle = <&phy3>;
+                       phys = <&serdes_hsio 4 SERDES1G(5) PHY_MODE_SGMII>;
+               };
+               port4: port@4 {
+                       reg = <3>;
+                       phy-handle = <&phy4>;
+               };
+               port5: port@5 {
+                       reg = <2>;
+                       phy-handle = <&phy5>;
+               };
+               port6: port@6 {
+                       reg = <1>;
+                       phy-handle = <&phy6>;
+               };
+               port7: port@7 {
+                       reg = <0>;
+                       phy-handle = <&phy7>;
+               };
+       };
+};
index a4fa37001f2400cc36c8262ab0992aae1bc9f849..1b0156e503c943801783129aeee4f48a7dd6b949 100644 (file)
 
 &mdio0 {
        status = "okay";
-};
-
-&port0 {
-       phy-handle = <&phy0>;
-};
 
-&port1 {
-       phy-handle = <&phy1>;
-};
-
-&port2 {
-       phy-handle = <&phy2>;
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+       phy2: ethernet-phy@2 {
+               reg = <2>;
+       };
+       phy3: ethernet-phy@3 {
+               reg = <3>;
+       };
 };
 
-&port3 {
-       phy-handle = <&phy3>;
+&switch {
+       ethernet-ports {
+               port0: port@0 {
+                       reg = <2>;
+                       phy-handle = <&phy2>;
+               };
+               port1: port@1 {
+                       reg = <3>;
+                       phy-handle = <&phy3>;
+               };
+               port2: port@2 {
+                       reg = <0>;
+                       phy-handle = <&phy0>;
+               };
+               port3: port@3 {
+                       reg = <1>;
+                       phy-handle = <&phy1>;
+               };
+       };
 };
index 1598669447fdd0a9cbe04674ac3fea3762122cdf..667277080f2da5ad1d1643829bcd698506f625c1 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,serval.dtsi"
+#include <dt-bindings/mscc/serval_data.h>
 
 / {
        model = "Serval PCB105 Reference Board";
        status = "okay";
        sgpio-ports = <0x00FFFFFF>;
 };
+
+&mdio1 {
+       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 = <7>;
+                       phy-handle = <&phy16>;
+                       phys = <&serdes_hsio 7 SERDES1G(7) PHY_MODE_SGMII>;
+               };
+               port1: port@1 {
+                       reg = <6>;
+                       phy-handle = <&phy17>;
+                       phys = <&serdes_hsio 6 SERDES1G(6) PHY_MODE_SGMII>;
+               };
+               port2: port@2 {
+                       reg = <5>;
+                       phy-handle = <&phy18>;
+                       phys = <&serdes_hsio 5 SERDES1G(5) PHY_MODE_SGMII>;
+               };
+               port3: port@3 {
+                       reg = <4>;
+                       phy-handle = <&phy19>;
+                       phys = <&serdes_hsio 4 SERDES1G(4) PHY_MODE_SGMII>;
+               };
+       };
+};
index fb3524bb31e0cab2aab8ea9a028ab34acc38bd04..e77c357868b82348a8938bba94d162cf9d7b13a3 100644 (file)
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,serval.dtsi"
+#include <dt-bindings/mscc/serval_data.h>
 
 / {
        model = "Serval PCB106 Reference Board";
        status = "okay";
        sgpio-ports = <0x00FFFFFF>;
 };
+
+&mdio1 {
+       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 = <7>;
+                       phy-handle = <&phy16>;
+                       phys = <&serdes_hsio 7 SERDES1G(7) PHY_MODE_SGMII>;
+               };
+               port1: port@1 {
+                       reg = <6>;
+                       phy-handle = <&phy17>;
+                       phys = <&serdes_hsio 6 SERDES1G(6) PHY_MODE_SGMII>;
+               };
+               port2: port@2 {
+                       reg = <5>;
+                       phy-handle = <&phy18>;
+                       phys = <&serdes_hsio 5 SERDES1G(5) PHY_MODE_SGMII>;
+               };
+               port3: port@3 {
+                       reg = <4>;
+                       phy-handle = <&phy19>;
+                       phys = <&serdes_hsio 4 SERDES1G(4) PHY_MODE_SGMII>;
+               };
+       };
+};
index 35152cb3f64afe122c1defb58b40fa006fe38d8a..6a462f3e5a5edf45ecb9f704d85d5bae6897a80a 100644 (file)
@@ -247,6 +247,8 @@ int arch_fixup_fdt(void *blob)
 
 static int boot_setup_fdt(bootm_headers_t *images)
 {
+       images->initrd_start = virt_to_phys((void *)images->initrd_start);
+       images->initrd_end = virt_to_phys((void *)images->initrd_end);
        return image_setup_libfdt(images, images->ft_addr, images->ft_len,
                &images->lmb);
 }
index 34584a1909905365ed82f9b43b320c336008d423..affc4721f82ea8379f1eb43022d5a091017e52d9 100644 (file)
@@ -29,7 +29,6 @@ config SOC_OCELOT
 config SOC_LUTON
        bool "Luton SOC Family"
        select SOC_VCOREIII
-       select MSCC_BITBANG_SPI_GPIO
        help
          This supports MSCC Luton family of SOCs.
 
index 84ecfbdd9206da3766dd645a466a95bb17ff66ba..d1f4287f654661727bba043984843c5c697002f8 100644 (file)
@@ -401,23 +401,7 @@ static inline void sleep_100ns(u32 val)
                ;
 }
 
-#if defined(CONFIG_SOC_OCELOT)
-static inline void hal_vcoreiii_ddr_reset_assert(void)
-{
-       /* DDR has reset pin on GPIO 19 toggle Low-High to release */
-       setbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
-       writel(BIT(19), BASE_DEVCPU_GCB + PERF_GPIO_OUT_CLR);
-       sleep_100ns(10000);
-}
-
-static inline void hal_vcoreiii_ddr_reset_release(void)
-{
-       /* DDR has reset pin on GPIO 19 toggle Low-High to release */
-       setbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
-       writel(BIT(19), BASE_DEVCPU_GCB + PERF_GPIO_OUT_SET);
-       sleep_100ns(10000);
-}
-
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_SERVAL)
 /*
  * DDR memory sanity checking failed, tally and do hard reset
  *
@@ -427,9 +411,11 @@ static inline void hal_vcoreiii_ddr_failed(void)
 {
        register u32 reset;
 
+#if defined(CONFIG_SOC_OCELOT)
        writel(readl(BASE_CFG + ICPU_GPR(6)) + 1, BASE_CFG + ICPU_GPR(6));
 
        clrbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
+#endif
 
        /* We have to execute the reset function from cache. Indeed,
         * the reboot workaround in _machine_restart() will change the
@@ -452,6 +438,33 @@ static inline void hal_vcoreiii_ddr_failed(void)
 
        panic("DDR init failed\n");
 }
+#else                          /* JR2 || ServalT */
+static inline void hal_vcoreiii_ddr_failed(void)
+{
+       writel(0, BASE_CFG + ICPU_RESET);
+       writel(PERF_SOFT_RST_SOFT_CHIP_RST, BASE_CFG + PERF_SOFT_RST);
+
+       panic("DDR init failed\n");
+}
+#endif
+
+#if defined(CONFIG_SOC_OCELOT)
+static inline void hal_vcoreiii_ddr_reset_assert(void)
+{
+       /* DDR has reset pin on GPIO 19 toggle Low-High to release */
+       setbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
+       writel(BIT(19), BASE_DEVCPU_GCB + PERF_GPIO_OUT_CLR);
+       sleep_100ns(10000);
+}
+
+static inline void hal_vcoreiii_ddr_reset_release(void)
+{
+       /* DDR has reset pin on GPIO 19 toggle Low-High to release */
+       setbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
+       writel(BIT(19), BASE_DEVCPU_GCB + PERF_GPIO_OUT_SET);
+       sleep_100ns(10000);
+}
+
 #else                          /* JR2 || ServalT || Serval */
 static inline void hal_vcoreiii_ddr_reset_assert(void)
 {
@@ -463,14 +476,6 @@ static inline void hal_vcoreiii_ddr_reset_assert(void)
        writel(readl(BASE_CFG + ICPU_RESET) |
               ICPU_RESET_MEM_RST_FORCE, BASE_CFG + ICPU_RESET);
 }
-
-static inline void hal_vcoreiii_ddr_failed(void)
-{
-       writel(0, BASE_CFG + ICPU_RESET);
-       writel(PERF_SOFT_RST_SOFT_CHIP_RST, BASE_CFG + PERF_SOFT_RST);
-
-       panic("DDR init failed\n");
-}
 #endif                         /* JR2 || ServalT || Serval */
 
 /*
index d3a76412e2e66c5b894abb7768651d5cc3f95722..b2a4203644aa7c8c88ee44f4ef6c388750c3686b 100644 (file)
@@ -20,4 +20,5 @@
 
 #define GPIO_ALT(x)                            (0x54 + 4 * (x))
 
+#define PERF_PHY_CFG                                      0xf0
 #endif
index a555fc9d9a9ffd3647b1c6ab149fb78feded17b1..a1214573b51aa5d1d0bff5c1194f37cf3ab39a6e 100644 (file)
@@ -36,7 +36,7 @@ void _machine_restart(void)
        /* Do global reset */
        writel(PERF_SOFT_RST_SOFT_CHIP_RST, BASE_DEVCPU_GCB + PERF_SOFT_RST);
 
-       for (i = 0; i < 1000; i++)
+       for (i = 0; i < 2000; i++)
                ;
 
        /* Power down DDR for clean DDR re-training */
diff --git a/arch/mips/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig
deleted file mode 100644 (file)
index a983443..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-menu "MediaTek MIPS platforms"
-       depends on ARCH_MT7620
-
-config SYS_MALLOC_F_LEN
-       default 0x1000
-
-config SYS_SOC
-       default "mt7620" if SOC_MT7620
-
-choice
-       prompt "MediaTek MIPS SoC select"
-
-config SOC_MT7620
-       bool "MT7620/8"
-       select MIPS_L1_CACHE_SHIFT_5
-       help
-         This supports MediaTek MIPS MT7620 family.
-
-endchoice
-
-choice
-       prompt "Board select"
-
-config BOARD_GARDENA_SMART_GATEWAY_MT7688
-       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
-         and 8 MiB of flash (SPI NOR) and additional SPI NAND storage.
-
-config BOARD_LINKIT_SMART_7688
-       bool "LinkIt Smart 7688"
-       depends on SOC_MT7620
-       select SUPPORTS_BOOT_RAM
-       help
-         Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
-         and 32 MiB of flash (SPI).
-         Between its different peripherals there's an integrated switch with 4
-         ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
-         a MT7688 (PCIe).
-
-endchoice
-
-choice
-       prompt "Boot mode"
-
-config BOOT_RAM
-       bool "RAM boot"
-       depends on SUPPORTS_BOOT_RAM
-       help
-         This builds an image that is linked to a RAM address. It can be used
-         for booting from CFE via TFTP using an ELF image, but it can also be
-         booted from RAM by other bootloaders using a BIN image.
-
-config BOOT_ROM
-       bool "ROM boot"
-       depends on SUPPORTS_BOOT_RAM
-       help
-         This builds an image that is linked to a ROM address. It can be
-         used as main bootloader image which is programmed onto the onboard
-         flash storage (SPI NOR).
-
-endchoice
-
-choice
-       prompt "DDR2 size"
-
-config ONBOARD_DDR2_SIZE_256MBIT
-       bool "256MBit (32MByte) total size"
-       depends on BOOT_ROM
-       help
-         Use 256MBit (32MByte) of DDR total size
-
-config ONBOARD_DDR2_SIZE_512MBIT
-       bool "512MBit (64MByte) total size"
-       depends on BOOT_ROM
-       help
-         Use 512MBit (64MByte) of DDR total size
-
-config ONBOARD_DDR2_SIZE_1024MBIT
-       bool "1024MBit (128MByte) total size"
-       depends on BOOT_ROM
-       help
-         Use 1024MBit (128MByte) of DDR total size
-
-config ONBOARD_DDR2_SIZE_2048MBIT
-       bool "2048MBit (256MByte) total size"
-       depends on BOOT_ROM
-       help
-         Use 2048MBit (256MByte) of DDR total size
-
-endchoice
-
-choice
-       prompt "DDR2 chip width"
-
-config ONBOARD_DDR2_CHIP_WIDTH_8BIT
-       bool "8bit DDR chip width"
-       depends on BOOT_ROM
-       help
-         Use DDR chips with 8bit width
-
-config ONBOARD_DDR2_CHIP_WIDTH_16BIT
-       bool "16bit DDR chip width"
-       depends on BOOT_ROM
-       help
-         Use DDR chips with 16bit width
-
-endchoice
-
-choice
-       prompt "DDR2 bus width"
-
-config ONBOARD_DDR2_BUS_WIDTH_16BIT
-       bool "16bit DDR bus width"
-       depends on BOOT_ROM
-       help
-         Use 16bit DDR bus width
-
-config ONBOARD_DDR2_BUS_WIDTH_32BIT
-       bool "32bit DDR bus width"
-       depends on BOOT_ROM
-       help
-         Use 32bit DDR bus width
-
-endchoice
-
-config SUPPORTS_BOOT_RAM
-       bool
-
-source "board/gardena/smart-gateway-mt7688/Kconfig"
-source "board/seeed/linkit-smart-7688/Kconfig"
-
-endmenu
diff --git a/arch/mips/mach-mt7620/Makefile b/arch/mips/mach-mt7620/Makefile
deleted file mode 100644 (file)
index 1f3e65e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-
-obj-y += cpu.o
-
-ifndef CONFIG_SKIP_LOWLEVEL_INIT
-obj-y += ddr_calibrate.o
-obj-y += lowlevel_init.o
-endif
diff --git a/arch/mips/mach-mt7620/cpu.c b/arch/mips/mach-mt7620/cpu.c
deleted file mode 100644 (file)
index fcd0484..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Stefan Roese <sr@denx.de>
- */
-
-#include <common.h>
-#include <dm.h>
-#include <ram.h>
-#include <wdt.h>
-#include <asm/io.h>
-#include <linux/io.h>
-#include <linux/sizes.h>
-#include "mt76xx.h"
-
-#define STR_LEN                        6
-
-#ifdef CONFIG_BOOT_ROM
-int mach_cpu_init(void)
-{
-       ddr_calibrate();
-
-       return 0;
-}
-#endif
-
-int dram_init(void)
-{
-       gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
-
-       return 0;
-}
-
-int print_cpuinfo(void)
-{
-       static const char * const boot_str[] = { "PLL (3-Byte SPI Addr)",
-                                                "PLL (4-Byte SPI Addr)",
-                                                "XTAL (3-Byte SPI Addr)",
-                                                "XTAL (4-Byte SPI Addr)" };
-       const void *blob = gd->fdt_blob;
-       void __iomem *sysc_base;
-       char buf[STR_LEN + 1];
-       fdt_addr_t base;
-       fdt_size_t size;
-       char *str;
-       int node;
-       u32 val;
-
-       /* Get system controller base address */
-       node = fdt_node_offset_by_compatible(blob, -1, "ralink,mt7620a-sysc");
-       if (node < 0)
-               return -FDT_ERR_NOTFOUND;
-
-       base = fdtdec_get_addr_size_auto_noparent(blob, node, "reg",
-                                                 0, &size, true);
-       if (base == FDT_ADDR_T_NONE)
-               return -EINVAL;
-
-       sysc_base = ioremap_nocache(base, size);
-
-       str = (char *)sysc_base + MT76XX_CHIPID_OFFS;
-       snprintf(buf, STR_LEN + 1, "%s", str);
-       val = readl(sysc_base + MT76XX_CHIP_REV_ID_OFFS);
-       printf("CPU:   %-*s Rev %ld.%ld - ", STR_LEN, buf,
-              (val & GENMASK(11, 8)) >> 8, val & GENMASK(3, 0));
-
-       val = (readl(sysc_base + MT76XX_SYSCFG0_OFFS) & GENMASK(3, 1)) >> 1;
-       printf("Boot from %s\n", boot_str[val]);
-
-       return 0;
-}
-
-int arch_misc_init(void)
-{
-       /*
-        * It has been noticed, that sometimes the d-cache is not in a
-        * "clean-state" when U-Boot is running on MT7688. This was
-        * detected when using the ethernet driver (which uses d-cache)
-        * and a TFTP command does not complete. Flushing the complete
-        * d-cache (again?) here seems to fix this issue.
-        */
-       flush_dcache_range(gd->bd->bi_memstart,
-                          gd->bd->bi_memstart + gd->ram_size - 1);
-
-       return 0;
-}
diff --git a/arch/mips/mach-mt7620/ddr_calibrate.c b/arch/mips/mach-mt7620/ddr_calibrate.c
deleted file mode 100644 (file)
index 75763c4..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Stefan Roese <sr@denx.de>
- *
- * This code is mostly based on the code extracted from this MediaTek
- * github repository:
- *
- * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
- *
- * I was not able to find a specific license or other developers
- * copyrights here, so I can't add them here.
- *
- * Most functions in this file are copied from the MediaTek U-Boot
- * repository. Without any documentation, it was impossible to really
- * implement this differently. So its mostly a cleaned-up version of
- * the original code, with only support for the MT7628 / MT7688 SoC.
- */
-
-#include <common.h>
-#include <linux/io.h>
-#include <asm/cacheops.h>
-#include <asm/io.h>
-#include "mt76xx.h"
-
-#define NUM_OF_CACHELINE       128
-#define MIN_START              6
-#define MIN_FINE_START         0xf
-#define MAX_START              7
-#define MAX_FINE_START         0x0
-
-#define CPU_FRAC_DIV           1
-
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
-#define DRAM_BUTTOM 0x02000000
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
-#define DRAM_BUTTOM 0x04000000
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
-#define DRAM_BUTTOM 0x08000000
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
-#define DRAM_BUTTOM 0x10000000
-#endif
-
-static inline void cal_memcpy(void *src, void *dst, u32 size)
-{
-       u8 *psrc = (u8 *)src;
-       u8 *pdst = (u8 *)dst;
-       int i;
-
-       for (i = 0; i < size; i++, psrc++, pdst++)
-               *pdst = *psrc;
-}
-
-static inline void cal_memset(void *src, u8 pat, u32 size)
-{
-       u8 *psrc = (u8 *)src;
-       int i;
-
-       for (i = 0; i < size; i++, psrc++)
-               *psrc = pat;
-}
-
-#define pref_op(hint, addr)                                            \
-       __asm__ __volatile__(                                           \
-               ".set   push\n"                                         \
-               ".set   noreorder\n"                                    \
-               "pref   %0, %1\n"                                       \
-               ".set   pop\n"                                          \
-               :                                                       \
-               : "i" (hint), "R" (*(u8 *)(addr)))
-
-static inline void cal_patgen(u32 start_addr, u32 size, u32 bias)
-{
-       u32 *addr = (u32 *)start_addr;
-       int i;
-
-       for (i = 0; i < size; i++)
-               addr[i] = start_addr + i + bias;
-}
-
-static inline int test_loop(int k, int dqs, u32 test_dqs, u32 *coarse_dqs,
-                           u32 offs, u32 pat, u32 val)
-{
-       u32 nc_addr;
-       u32 *c_addr;
-       int i;
-
-       for (nc_addr = 0xa0000000;
-            nc_addr < (0xa0000000 + DRAM_BUTTOM - NUM_OF_CACHELINE * 32);
-            nc_addr += (DRAM_BUTTOM >> 6) + offs) {
-               writel(0x00007474, (void *)MT76XX_MEMCTRL_BASE + 0x64);
-               wmb();          /* Make sure store if finished */
-
-               c_addr = (u32 *)(nc_addr & 0xdfffffff);
-               cal_memset(((u8 *)c_addr), 0x1F, NUM_OF_CACHELINE * 32);
-               cal_patgen(nc_addr, NUM_OF_CACHELINE * 8, pat);
-
-               if (dqs > 0)
-                       writel(0x00000074 |
-                              (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 12) |
-                              (((k == 0) ? val : test_dqs) << 8),
-                              (void *)MT76XX_MEMCTRL_BASE + 0x64);
-               else
-                       writel(0x00007400 |
-                              (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 4) |
-                              (((k == 0) ? val : test_dqs) << 0),
-                              (void *)MT76XX_MEMCTRL_BASE + 0x64);
-               wmb();          /* Make sure store if finished */
-
-               invalidate_dcache_range((u32)c_addr,
-                                       (u32)c_addr +
-                                       NUM_OF_CACHELINE * 32);
-               wmb();          /* Make sure store if finished */
-
-               for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
-                       if (i % 8 == 0)
-                               pref_op(0, &c_addr[i]);
-               }
-
-               for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
-                       if (c_addr[i] != nc_addr + i + pat)
-                               return -1;
-               }
-       }
-
-       return 0;
-}
-
-void ddr_calibrate(void)
-{
-       u32 min_coarse_dqs[2];
-       u32 max_coarse_dqs[2];
-       u32 min_fine_dqs[2];
-       u32 max_fine_dqs[2];
-       u32 coarse_dqs[2];
-       u32 fine_dqs[2];
-       int reg = 0, ddr_cfg2_reg;
-       int flag;
-       int i, k;
-       int dqs = 0;
-       u32 min_coarse_dqs_bnd, min_fine_dqs_bnd, coarse_dqs_dll, fine_dqs_dll;
-       u32 val;
-       u32 fdiv = 0, frac = 0;
-
-       /* Setup clock to run at full speed */
-       val = readl((void *)MT76XX_DYN_CFG0_REG);
-       fdiv = (u32)((val >> 8) & 0x0F);
-       if (CPU_FRAC_DIV < 1 || CPU_FRAC_DIV > 10)
-               frac = val & 0x0f;
-       else
-               frac = CPU_FRAC_DIV;
-
-       while (frac < fdiv) {
-               val = readl((void *)MT76XX_DYN_CFG0_REG);
-               fdiv = (val >> 8) & 0x0f;
-               fdiv--;
-               val &= ~(0x0f << 8);
-               val |= (fdiv << 8);
-               writel(val, (void *)MT76XX_DYN_CFG0_REG);
-               udelay(500);
-               val = readl((void *)MT76XX_DYN_CFG0_REG);
-               fdiv = (val >> 8) & 0x0f;
-       }
-
-       clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
-       ddr_cfg2_reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x48);
-       clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x48,
-                    (0x3 << 28) | (0x3 << 26));
-
-       min_coarse_dqs[0] = MIN_START;
-       min_coarse_dqs[1] = MIN_START;
-       min_fine_dqs[0] = MIN_FINE_START;
-       min_fine_dqs[1] = MIN_FINE_START;
-       max_coarse_dqs[0] = MAX_START;
-       max_coarse_dqs[1] = MAX_START;
-       max_fine_dqs[0] = MAX_FINE_START;
-       max_fine_dqs[1] = MAX_FINE_START;
-       dqs = 0;
-
-       /* Add by KP, DQS MIN boundary */
-       reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x20);
-       coarse_dqs_dll = (reg & 0xf00) >> 8;
-       fine_dqs_dll = (reg & 0xf0) >> 4;
-       if (coarse_dqs_dll <= 8)
-               min_coarse_dqs_bnd = 8 - coarse_dqs_dll;
-       else
-               min_coarse_dqs_bnd = 0;
-
-       if (fine_dqs_dll <= 8)
-               min_fine_dqs_bnd = 8 - fine_dqs_dll;
-       else
-               min_fine_dqs_bnd = 0;
-       /* DQS MIN boundary */
-
-DQS_CAL:
-
-       for (k = 0; k < 2; k++) {
-               u32 test_dqs;
-
-               if (k == 0)
-                       test_dqs = MAX_START;
-               else
-                       test_dqs = MAX_FINE_START;
-
-               do {
-                       flag = test_loop(k, dqs, test_dqs, max_coarse_dqs,
-                                        0x400, 0x3, 0xf);
-                       if (flag == -1)
-                               break;
-
-                       test_dqs++;
-               } while (test_dqs <= 0xf);
-
-               if (k == 0) {
-                       max_coarse_dqs[dqs] = test_dqs;
-               } else {
-                       test_dqs--;
-
-                       if (test_dqs == MAX_FINE_START - 1) {
-                               max_coarse_dqs[dqs]--;
-                               max_fine_dqs[dqs] = 0xf;
-                       } else {
-                               max_fine_dqs[dqs] = test_dqs;
-                       }
-               }
-       }
-
-       for (k = 0; k < 2; k++) {
-               u32 test_dqs;
-
-               if (k == 0)
-                       test_dqs = MIN_START;
-               else
-                       test_dqs = MIN_FINE_START;
-
-               do {
-                       flag = test_loop(k, dqs, test_dqs, min_coarse_dqs,
-                                        0x480, 0x1, 0x0);
-                       if (k == 0) {
-                               if (flag == -1 ||
-                                   test_dqs == min_coarse_dqs_bnd)
-                                       break;
-
-                               test_dqs--;
-
-                               if (test_dqs < min_coarse_dqs_bnd)
-                                       break;
-                       } else {
-                               if (flag == -1) {
-                                       test_dqs++;
-                                       break;
-                               } else if (test_dqs == min_fine_dqs_bnd) {
-                                       break;
-                               }
-
-                               test_dqs--;
-
-                               if (test_dqs < min_fine_dqs_bnd)
-                                       break;
-                       }
-               } while (test_dqs >= 0);
-
-               if (k == 0) {
-                       min_coarse_dqs[dqs] = test_dqs;
-               } else {
-                       if (test_dqs == MIN_FINE_START + 1) {
-                               min_coarse_dqs[dqs]++;
-                               min_fine_dqs[dqs] = 0x0;
-                       } else {
-                               min_fine_dqs[dqs] = test_dqs;
-                       }
-               }
-       }
-
-       if (dqs == 0) {
-               dqs = 1;
-               goto DQS_CAL;
-       }
-
-       for (i = 0; i < 2; i++) {
-               u32 temp;
-
-               coarse_dqs[i] = (max_coarse_dqs[i] + min_coarse_dqs[i]) >> 1;
-               temp =
-                   (((max_coarse_dqs[i] + min_coarse_dqs[i]) % 2) * 4) +
-                   ((max_fine_dqs[i] + min_fine_dqs[i]) >> 1);
-               if (temp >= 0x10) {
-                       coarse_dqs[i]++;
-                       fine_dqs[i] = (temp - 0x10) + 0x8;
-               } else {
-                       fine_dqs[i] = temp;
-               }
-       }
-       reg = (coarse_dqs[1] << 12) | (fine_dqs[1] << 8) |
-               (coarse_dqs[0] << 4) | fine_dqs[0];
-
-       clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
-       writel(reg, (void *)MT76XX_MEMCTRL_BASE + 0x64);
-       writel(ddr_cfg2_reg, (void *)MT76XX_MEMCTRL_BASE + 0x48);
-       setbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
-
-       for (i = 0; i < 2; i++)
-               debug("[%02X%02X%02X%02X]", min_coarse_dqs[i],
-                     min_fine_dqs[i], max_coarse_dqs[i], max_fine_dqs[i]);
-       debug("\nDDR Calibration DQS reg = %08X\n", reg);
-}
diff --git a/arch/mips/mach-mt7620/lowlevel_init.S b/arch/mips/mach-mt7620/lowlevel_init.S
deleted file mode 100644 (file)
index aa707e0..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (c) 2018 Stefan Roese <sr@denx.de>
- *
- * This code is mostly based on the code extracted from this MediaTek
- * github repository:
- *
- * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
- *
- * I was not able to find a specific license or other developers
- * copyrights here, so I can't add them here.
- */
-
-#include <config.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include "mt76xx.h"
-
-#ifndef BIT
-#define BIT(nr)                        (1 << (nr))
-#endif
-
-#define DELAY_USEC(us)         ((us) / 100)
-
-#define DDR_CFG1_CHIP_WIDTH_MASK (0x3 << 16)
-#define DDR_CFG1_BUS_WIDTH_MASK        (0x3 << 12)
-
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
-#define DDR_CFG1_SIZE_VAL      0x222e2323
-#define DDR_CFG4_SIZE_VAL      7
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
-#define DDR_CFG1_SIZE_VAL      0x22322323
-#define DDR_CFG4_SIZE_VAL      9
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
-#define DDR_CFG1_SIZE_VAL      0x22362323
-#define DDR_CFG4_SIZE_VAL      9
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
-#define DDR_CFG1_SIZE_VAL      0x223a2323
-#define DDR_CFG4_SIZE_VAL      9
-#endif
-
-#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_8BIT)
-#define DDR_CFG1_CHIP_WIDTH_VAL        (0x1 << 16)
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_16BIT)
-#define DDR_CFG1_CHIP_WIDTH_VAL        (0x2 << 16)
-#endif
-
-#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_16BIT)
-#define DDR_CFG1_BUS_WIDTH_VAL (0x2 << 12)
-#endif
-#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_32BIT)
-#define DDR_CFG1_BUS_WIDTH_VAL (0x3 << 12)
-#endif
-
-       .set noreorder
-
-LEAF(lowlevel_init)
-
-       /* Load base addresses as physical addresses for later usage */
-       li      s0, CKSEG1ADDR(MT76XX_SYSCTL_BASE)
-       li      s1, CKSEG1ADDR(MT76XX_MEMCTRL_BASE)
-       li      s2, CKSEG1ADDR(MT76XX_RGCTRL_BASE)
-
-       /* polling CPLL is ready */
-       li      t1, DELAY_USEC(1000000)
-       la      t5, MT76XX_ROM_STATUS_REG
-1:
-       lw      t2, 0(t5)
-       andi    t2, t2, 0x1
-       bnez    t2, CPLL_READY
-       subu    t1, t1, 1
-       bgtz    t1, 1b
-       nop
-       la      t0, MT76XX_CLKCFG0_REG
-       lw      t3, 0(t0)
-       ori     t3, t3, 0x1
-       sw      t3, 0(t0)
-       b       CPLL_DONE
-       nop
-CPLL_READY:
-       la      t0, MT76XX_CLKCFG0_REG
-       lw      t1, 0(t0)
-       li      t2, ~0x0c
-       and     t1, t1, t2
-       ori     t1, t1, 0xc
-       sw      t1, 0(t0)
-       la      t0, MT76XX_DYN_CFG0_REG
-       lw      t3, 0(t0)
-       li      t5, ~((0x0f << 8) | (0x0f << 0))
-       and     t3, t3, t5
-       li      t5, (10 << 8) | (1 << 0)
-       or      t3, t3, t5
-       sw      t3, 0(t0)
-       la      t0, MT76XX_CLKCFG0_REG
-       lw      t3, 0(t0)
-       li      t4, ~0x0F
-       and     t3, t3, t4
-       ori     t3, t3, 0xc
-       sw      t3, 0(t0)
-       lw      t3, 0(t0)
-       ori     t3, t3, 0x08
-       sw      t3, 0(t0)
-
-CPLL_DONE:
-       /* Reset MC */
-       lw      t2, 0x34(s0)
-       ori     t2, BIT(10)
-       sw      t2, 0x34(s0)
-       nop
-
-       /*
-        * SDR and DDR initialization: delay 200us
-        */
-       li      t0, DELAY_USEC(200 + 40)
-       li      t1, 0x1
-1:
-       sub     t0, t0, t1
-       bnez    t0, 1b
-       nop
-
-       /* set DRAM IO PAD for MT7628IC */
-       /* DDR LDO Enable  */
-       lw      t4, 0x100(s2)
-       li      t2, BIT(31)
-       or      t4, t4, t2
-       sw      t4, 0x100(s2)
-       lw      t4, 0x10c(s2)
-       j       LDO_1P8V
-       nop
-LDO_1P8V:
-       li      t2, ~BIT(6)
-       and     t4, t4, t2
-       sw      t4, 0x10c(s2)
-       j       DDRLDO_SOFT_START
-LDO_2P5V:
-       /* suppose external DDR1 LDO 2.5V */
-       li      t2, BIT(6)
-       or      t4, t4, t2
-       sw      t4, 0x10c(s2)
-
-DDRLDO_SOFT_START:
-       lw      t2, 0x10c(s2)
-       li      t3, BIT(16)
-       or      t2, t2, t3
-       sw      t2, 0x10c(s2)
-       li      t3, DELAY_USEC(250*50)
-LDO_DELAY:
-       subu    t3, t3, 1
-       bnez    t3, LDO_DELAY
-       nop
-
-       lw      t2, 0x10c(s2)
-       li      t3, BIT(18)
-       or      t2, t2, t3
-       sw      t2, 0x10c(s2)
-
-SET_RG_BUCK_FPWM:
-       lw      t2, 0x104(s2)
-       ori     t2, t2, BIT(10)
-       sw      t2, 0x104(s2)
-
-DDR_PAD_CFG:
-       /* clean CLK PAD */
-       lw      t2, 0x704(s2)
-       li      t8, 0xfffff0f0
-       and     t2, t2, t8
-       /* clean CMD PAD */
-       lw      t3, 0x70c(s2)
-       li      t8, 0xfffff0f0
-       and     t3, t3, t8
-       /* clean DQ IPAD */
-       lw      t4, 0x710(s2)
-       li      t8, 0xfffff8ff
-       and     t4, t4, t8
-       /* clean DQ OPAD */
-       lw      t5, 0x714(s2)
-       li      t8, 0xfffff0f0
-       and     t5, t5, t8
-       /* clean DQS IPAD */
-       lw      t6, 0x718(s2)
-       li      t8, 0xfffff8ff
-       and     t6, t6, t8
-       /* clean DQS OPAD */
-       lw      t7, 0x71c(s2)
-       li      t8, 0xfffff0f0
-       and     t7, t7, t8
-
-       lw      t9, 0xc(s0)
-       srl     t9, t9, 16
-       andi    t9, t9, 0x1
-       bnez    t9, MT7628_AN_DDR1_PAD
-MT7628_KN_PAD:
-       li      t8, 0x00000303
-       or      t2, t2, t8
-       or      t3, t3, t8
-       or      t5, t5, t8
-       or      t7, t7, t8
-       li      t8, 0x00000000
-       or      t4, t4, t8
-       or      t6, t6, t8
-       j       SET_PAD_CFG
-MT7628_AN_DDR1_PAD:
-       lw      t1, 0x10(s0)
-       andi    t1, t1, 0x1
-       beqz    t1, MT7628_AN_DDR2_PAD
-       li      t8, 0x00000c0c
-       or      t2, t2, t8
-       li      t8, 0x00000202
-       or      t3, t3, t8
-       li      t8, 0x00000707
-       or      t5, t5, t8
-       li      t8, 0x00000c0c
-       or      t7, t7, t8
-       li      t8, 0x00000000
-       or      t4, t4, t8
-       or      t6, t6, t8
-       j       SET_PAD_CFG
-MT7628_AN_DDR2_PAD:
-       li      t8, 0x00000c0c
-       or      t2, t2, t8
-       li      t8, 0x00000202
-       or      t3, t3, t8
-       li      t8, 0x00000404
-       or      t5, t5, t8
-       li      t8, 0x00000c0c
-       or      t7, t7, t8
-       li      t8, 0x00000000          /* ODT off */
-       or      t4, t4, t8
-       or      t6, t6, t8
-
-SET_PAD_CFG:
-       sw      t2, 0x704(s2)
-       sw      t3, 0x70c(s2)
-       sw      t4, 0x710(s2)
-       sw      t5, 0x714(s2)
-       sw      t6, 0x718(s2)
-       sw      t7, 0x71c(s2)
-
-       /*
-        * DDR initialization: reset pin to 0
-        */
-       lw      t2, 0x34(s0)
-       and     t2, ~BIT(10)
-       sw      t2, 0x34(s0)
-       nop
-
-       /*
-        * DDR initialization: wait til reg DDR_CFG1 bit 21 equal to 1 (ready)
-        */
-DDR_READY:
-       li      t1, DDR_CFG1_REG
-       lw      t0, 0(t1)
-       nop
-       and     t2, t0, BIT(21)
-       beqz    t2, DDR_READY
-       nop
-
-       /*
-        * DDR initialization
-        *
-        * Only DDR2 supported right now. DDR2 support can be added, once
-        * boards using it will get added to mainline U-Boot.
-        */
-       li      t1, DDR_CFG2_REG
-       lw      t0, 0(t1)
-       nop
-       and     t0, ~BIT(30)
-       and     t0, ~(7 << 4)
-       or      t0, (4 << 4)
-       or      t0, BIT(30)
-       or      t0, BIT(11)
-       sw      t0, 0(t1)
-       nop
-
-       li      t1, DDR_CFG3_REG
-       lw      t2, 0(t1)
-       /* Disable ODT; reference board ok, ev board fail */
-       and     t2, ~BIT(6)
-       or      t2, BIT(2)
-       li      t0, DDR_CFG4_REG
-       lw      t1, 0(t0)
-       li      t2, ~(0x01f | 0x0f0)
-       and     t1, t1, t2
-       ori     t1, t1, DDR_CFG4_SIZE_VAL
-       sw      t1, 0(t0)
-       nop
-
-       /*
-        * DDR initialization: config size and width on reg DDR_CFG1
-        */
-       li      t6, DDR_CFG1_SIZE_VAL
-
-       and     t6, ~DDR_CFG1_CHIP_WIDTH_MASK
-       or      t6, DDR_CFG1_CHIP_WIDTH_VAL
-
-       /* CONFIG DDR_CFG1[13:12] about TOTAL WIDTH */
-       and     t6, ~DDR_CFG1_BUS_WIDTH_MASK
-       or      t6, DDR_CFG1_BUS_WIDTH_VAL
-
-       li      t5, DDR_CFG1_REG
-       sw      t6, 0(t5)
-       nop
-
-       /*
-        * DDR: enable self auto refresh for power saving
-        * enable it by default for both RAM and ROM version (for CoC)
-        */
-       lw      t1, 0x14(s1)
-       nop
-       and     t1, 0xff000000
-       or      t1, 0x01
-       sw      t1, 0x14(s1)
-       nop
-       lw      t1, 0x10(s1)
-       nop
-       or      t1, 0x10
-       sw      t1, 0x10(s1)
-       nop
-
-       jr      ra
-       nop
-       END(lowlevel_init)
diff --git a/arch/mips/mach-mt7620/mt76xx.h b/arch/mips/mach-mt7620/mt76xx.h
deleted file mode 100644 (file)
index 17473ea..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2018 Stefan Roese <sr@denx.de>
- */
-
-#ifndef __MT76XX_H
-#define __MT76XX_H
-
-#define MT76XX_SYSCTL_BASE     0x10000000
-
-#define MT76XX_CHIPID_OFFS     0x00
-#define MT76XX_CHIP_REV_ID_OFFS        0x0c
-#define MT76XX_SYSCFG0_OFFS    0x10
-
-#define MT76XX_MEMCTRL_BASE    (MT76XX_SYSCTL_BASE + 0x0300)
-#define MT76XX_RGCTRL_BASE     (MT76XX_SYSCTL_BASE + 0x1000)
-
-#define MT76XX_ROM_STATUS_REG  (MT76XX_SYSCTL_BASE + 0x0028)
-#define MT76XX_CLKCFG0_REG     (MT76XX_SYSCTL_BASE + 0x002c)
-#define MT76XX_DYN_CFG0_REG    (MT76XX_SYSCTL_BASE + 0x0440)
-
-#define DDR_CFG1_REG           (MT76XX_MEMCTRL_BASE + 0x44)
-#define DDR_CFG2_REG           (MT76XX_MEMCTRL_BASE + 0x48)
-#define DDR_CFG3_REG           (MT76XX_MEMCTRL_BASE + 0x4c)
-#define DDR_CFG4_REG           (MT76XX_MEMCTRL_BASE + 0x50)
-
-#ifndef __ASSEMBLY__
-/* Prototypes */
-void ddr_calibrate(void);
-#endif
-
-#endif
diff --git a/arch/mips/mach-mtmips/Kconfig b/arch/mips/mach-mtmips/Kconfig
new file mode 100644 (file)
index 0000000..4af2d54
--- /dev/null
@@ -0,0 +1,136 @@
+menu "MediaTek MIPS platforms"
+       depends on ARCH_MTMIPS
+
+config SYS_MALLOC_F_LEN
+       default 0x1000
+
+config SYS_SOC
+       default "mt7628" if SOC_MT7628
+
+choice
+       prompt "MediaTek MIPS SoC select"
+
+config SOC_MT7628
+       bool "MT7628"
+       select MIPS_L1_CACHE_SHIFT_5
+       help
+         This supports MediaTek MT7628/MT7688.
+
+endchoice
+
+choice
+       prompt "Board select"
+
+config BOARD_GARDENA_SMART_GATEWAY_MT7688
+       bool "GARDENA smart Gateway"
+       depends on SOC_MT7628
+       select BOARD_LATE_INIT
+       select SUPPORTS_BOOT_RAM
+       help
+         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
+       bool "LinkIt Smart 7688"
+       depends on SOC_MT7628
+       select SUPPORTS_BOOT_RAM
+       help
+         Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
+         and 32 MiB of flash (SPI).
+         Between its different peripherals there's an integrated switch with 4
+         ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
+         a MT7688 (PCIe).
+
+endchoice
+
+choice
+       prompt "Boot mode"
+
+config BOOT_RAM
+       bool "RAM boot"
+       depends on SUPPORTS_BOOT_RAM
+       help
+         This builds an image that is linked to a RAM address. It can be used
+         for booting from CFE via TFTP using an ELF image, but it can also be
+         booted from RAM by other bootloaders using a BIN image.
+
+config BOOT_ROM
+       bool "ROM boot"
+       depends on SUPPORTS_BOOT_RAM
+       help
+         This builds an image that is linked to a ROM address. It can be
+         used as main bootloader image which is programmed onto the onboard
+         flash storage (SPI NOR).
+
+endchoice
+
+choice
+       prompt "DDR2 size"
+
+config ONBOARD_DDR2_SIZE_256MBIT
+       bool "256MBit (32MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 256MBit (32MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_512MBIT
+       bool "512MBit (64MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 512MBit (64MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_1024MBIT
+       bool "1024MBit (128MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 1024MBit (128MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_2048MBIT
+       bool "2048MBit (256MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 2048MBit (256MByte) of DDR total size
+
+endchoice
+
+choice
+       prompt "DDR2 chip width"
+
+config ONBOARD_DDR2_CHIP_WIDTH_8BIT
+       bool "8bit DDR chip width"
+       depends on BOOT_ROM
+       help
+         Use DDR chips with 8bit width
+
+config ONBOARD_DDR2_CHIP_WIDTH_16BIT
+       bool "16bit DDR chip width"
+       depends on BOOT_ROM
+       help
+         Use DDR chips with 16bit width
+
+endchoice
+
+choice
+       prompt "DDR2 bus width"
+
+config ONBOARD_DDR2_BUS_WIDTH_16BIT
+       bool "16bit DDR bus width"
+       depends on BOOT_ROM
+       help
+         Use 16bit DDR bus width
+
+config ONBOARD_DDR2_BUS_WIDTH_32BIT
+       bool "32bit DDR bus width"
+       depends on BOOT_ROM
+       help
+         Use 32bit DDR bus width
+
+endchoice
+
+config SUPPORTS_BOOT_RAM
+       bool
+
+source "board/gardena/smart-gateway-mt7688/Kconfig"
+source "board/seeed/linkit-smart-7688/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-mtmips/Makefile b/arch/mips/mach-mtmips/Makefile
new file mode 100644 (file)
index 0000000..1f3e65e
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+
+ifndef CONFIG_SKIP_LOWLEVEL_INIT
+obj-y += ddr_calibrate.o
+obj-y += lowlevel_init.o
+endif
diff --git a/arch/mips/mach-mtmips/cpu.c b/arch/mips/mach-mtmips/cpu.c
new file mode 100644 (file)
index 0000000..fcd0484
--- /dev/null
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include "mt76xx.h"
+
+#define STR_LEN                        6
+
+#ifdef CONFIG_BOOT_ROM
+int mach_cpu_init(void)
+{
+       ddr_calibrate();
+
+       return 0;
+}
+#endif
+
+int dram_init(void)
+{
+       gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
+
+       return 0;
+}
+
+int print_cpuinfo(void)
+{
+       static const char * const boot_str[] = { "PLL (3-Byte SPI Addr)",
+                                                "PLL (4-Byte SPI Addr)",
+                                                "XTAL (3-Byte SPI Addr)",
+                                                "XTAL (4-Byte SPI Addr)" };
+       const void *blob = gd->fdt_blob;
+       void __iomem *sysc_base;
+       char buf[STR_LEN + 1];
+       fdt_addr_t base;
+       fdt_size_t size;
+       char *str;
+       int node;
+       u32 val;
+
+       /* Get system controller base address */
+       node = fdt_node_offset_by_compatible(blob, -1, "ralink,mt7620a-sysc");
+       if (node < 0)
+               return -FDT_ERR_NOTFOUND;
+
+       base = fdtdec_get_addr_size_auto_noparent(blob, node, "reg",
+                                                 0, &size, true);
+       if (base == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       sysc_base = ioremap_nocache(base, size);
+
+       str = (char *)sysc_base + MT76XX_CHIPID_OFFS;
+       snprintf(buf, STR_LEN + 1, "%s", str);
+       val = readl(sysc_base + MT76XX_CHIP_REV_ID_OFFS);
+       printf("CPU:   %-*s Rev %ld.%ld - ", STR_LEN, buf,
+              (val & GENMASK(11, 8)) >> 8, val & GENMASK(3, 0));
+
+       val = (readl(sysc_base + MT76XX_SYSCFG0_OFFS) & GENMASK(3, 1)) >> 1;
+       printf("Boot from %s\n", boot_str[val]);
+
+       return 0;
+}
+
+int arch_misc_init(void)
+{
+       /*
+        * It has been noticed, that sometimes the d-cache is not in a
+        * "clean-state" when U-Boot is running on MT7688. This was
+        * detected when using the ethernet driver (which uses d-cache)
+        * and a TFTP command does not complete. Flushing the complete
+        * d-cache (again?) here seems to fix this issue.
+        */
+       flush_dcache_range(gd->bd->bi_memstart,
+                          gd->bd->bi_memstart + gd->ram_size - 1);
+
+       return 0;
+}
diff --git a/arch/mips/mach-mtmips/ddr_calibrate.c b/arch/mips/mach-mtmips/ddr_calibrate.c
new file mode 100644 (file)
index 0000000..75763c4
--- /dev/null
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ *
+ * This code is mostly based on the code extracted from this MediaTek
+ * github repository:
+ *
+ * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
+ *
+ * I was not able to find a specific license or other developers
+ * copyrights here, so I can't add them here.
+ *
+ * Most functions in this file are copied from the MediaTek U-Boot
+ * repository. Without any documentation, it was impossible to really
+ * implement this differently. So its mostly a cleaned-up version of
+ * the original code, with only support for the MT7628 / MT7688 SoC.
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <asm/cacheops.h>
+#include <asm/io.h>
+#include "mt76xx.h"
+
+#define NUM_OF_CACHELINE       128
+#define MIN_START              6
+#define MIN_FINE_START         0xf
+#define MAX_START              7
+#define MAX_FINE_START         0x0
+
+#define CPU_FRAC_DIV           1
+
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
+#define DRAM_BUTTOM 0x02000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
+#define DRAM_BUTTOM 0x04000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
+#define DRAM_BUTTOM 0x08000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
+#define DRAM_BUTTOM 0x10000000
+#endif
+
+static inline void cal_memcpy(void *src, void *dst, u32 size)
+{
+       u8 *psrc = (u8 *)src;
+       u8 *pdst = (u8 *)dst;
+       int i;
+
+       for (i = 0; i < size; i++, psrc++, pdst++)
+               *pdst = *psrc;
+}
+
+static inline void cal_memset(void *src, u8 pat, u32 size)
+{
+       u8 *psrc = (u8 *)src;
+       int i;
+
+       for (i = 0; i < size; i++, psrc++)
+               *psrc = pat;
+}
+
+#define pref_op(hint, addr)                                            \
+       __asm__ __volatile__(                                           \
+               ".set   push\n"                                         \
+               ".set   noreorder\n"                                    \
+               "pref   %0, %1\n"                                       \
+               ".set   pop\n"                                          \
+               :                                                       \
+               : "i" (hint), "R" (*(u8 *)(addr)))
+
+static inline void cal_patgen(u32 start_addr, u32 size, u32 bias)
+{
+       u32 *addr = (u32 *)start_addr;
+       int i;
+
+       for (i = 0; i < size; i++)
+               addr[i] = start_addr + i + bias;
+}
+
+static inline int test_loop(int k, int dqs, u32 test_dqs, u32 *coarse_dqs,
+                           u32 offs, u32 pat, u32 val)
+{
+       u32 nc_addr;
+       u32 *c_addr;
+       int i;
+
+       for (nc_addr = 0xa0000000;
+            nc_addr < (0xa0000000 + DRAM_BUTTOM - NUM_OF_CACHELINE * 32);
+            nc_addr += (DRAM_BUTTOM >> 6) + offs) {
+               writel(0x00007474, (void *)MT76XX_MEMCTRL_BASE + 0x64);
+               wmb();          /* Make sure store if finished */
+
+               c_addr = (u32 *)(nc_addr & 0xdfffffff);
+               cal_memset(((u8 *)c_addr), 0x1F, NUM_OF_CACHELINE * 32);
+               cal_patgen(nc_addr, NUM_OF_CACHELINE * 8, pat);
+
+               if (dqs > 0)
+                       writel(0x00000074 |
+                              (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 12) |
+                              (((k == 0) ? val : test_dqs) << 8),
+                              (void *)MT76XX_MEMCTRL_BASE + 0x64);
+               else
+                       writel(0x00007400 |
+                              (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 4) |
+                              (((k == 0) ? val : test_dqs) << 0),
+                              (void *)MT76XX_MEMCTRL_BASE + 0x64);
+               wmb();          /* Make sure store if finished */
+
+               invalidate_dcache_range((u32)c_addr,
+                                       (u32)c_addr +
+                                       NUM_OF_CACHELINE * 32);
+               wmb();          /* Make sure store if finished */
+
+               for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
+                       if (i % 8 == 0)
+                               pref_op(0, &c_addr[i]);
+               }
+
+               for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
+                       if (c_addr[i] != nc_addr + i + pat)
+                               return -1;
+               }
+       }
+
+       return 0;
+}
+
+void ddr_calibrate(void)
+{
+       u32 min_coarse_dqs[2];
+       u32 max_coarse_dqs[2];
+       u32 min_fine_dqs[2];
+       u32 max_fine_dqs[2];
+       u32 coarse_dqs[2];
+       u32 fine_dqs[2];
+       int reg = 0, ddr_cfg2_reg;
+       int flag;
+       int i, k;
+       int dqs = 0;
+       u32 min_coarse_dqs_bnd, min_fine_dqs_bnd, coarse_dqs_dll, fine_dqs_dll;
+       u32 val;
+       u32 fdiv = 0, frac = 0;
+
+       /* Setup clock to run at full speed */
+       val = readl((void *)MT76XX_DYN_CFG0_REG);
+       fdiv = (u32)((val >> 8) & 0x0F);
+       if (CPU_FRAC_DIV < 1 || CPU_FRAC_DIV > 10)
+               frac = val & 0x0f;
+       else
+               frac = CPU_FRAC_DIV;
+
+       while (frac < fdiv) {
+               val = readl((void *)MT76XX_DYN_CFG0_REG);
+               fdiv = (val >> 8) & 0x0f;
+               fdiv--;
+               val &= ~(0x0f << 8);
+               val |= (fdiv << 8);
+               writel(val, (void *)MT76XX_DYN_CFG0_REG);
+               udelay(500);
+               val = readl((void *)MT76XX_DYN_CFG0_REG);
+               fdiv = (val >> 8) & 0x0f;
+       }
+
+       clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
+       ddr_cfg2_reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x48);
+       clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x48,
+                    (0x3 << 28) | (0x3 << 26));
+
+       min_coarse_dqs[0] = MIN_START;
+       min_coarse_dqs[1] = MIN_START;
+       min_fine_dqs[0] = MIN_FINE_START;
+       min_fine_dqs[1] = MIN_FINE_START;
+       max_coarse_dqs[0] = MAX_START;
+       max_coarse_dqs[1] = MAX_START;
+       max_fine_dqs[0] = MAX_FINE_START;
+       max_fine_dqs[1] = MAX_FINE_START;
+       dqs = 0;
+
+       /* Add by KP, DQS MIN boundary */
+       reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x20);
+       coarse_dqs_dll = (reg & 0xf00) >> 8;
+       fine_dqs_dll = (reg & 0xf0) >> 4;
+       if (coarse_dqs_dll <= 8)
+               min_coarse_dqs_bnd = 8 - coarse_dqs_dll;
+       else
+               min_coarse_dqs_bnd = 0;
+
+       if (fine_dqs_dll <= 8)
+               min_fine_dqs_bnd = 8 - fine_dqs_dll;
+       else
+               min_fine_dqs_bnd = 0;
+       /* DQS MIN boundary */
+
+DQS_CAL:
+
+       for (k = 0; k < 2; k++) {
+               u32 test_dqs;
+
+               if (k == 0)
+                       test_dqs = MAX_START;
+               else
+                       test_dqs = MAX_FINE_START;
+
+               do {
+                       flag = test_loop(k, dqs, test_dqs, max_coarse_dqs,
+                                        0x400, 0x3, 0xf);
+                       if (flag == -1)
+                               break;
+
+                       test_dqs++;
+               } while (test_dqs <= 0xf);
+
+               if (k == 0) {
+                       max_coarse_dqs[dqs] = test_dqs;
+               } else {
+                       test_dqs--;
+
+                       if (test_dqs == MAX_FINE_START - 1) {
+                               max_coarse_dqs[dqs]--;
+                               max_fine_dqs[dqs] = 0xf;
+                       } else {
+                               max_fine_dqs[dqs] = test_dqs;
+                       }
+               }
+       }
+
+       for (k = 0; k < 2; k++) {
+               u32 test_dqs;
+
+               if (k == 0)
+                       test_dqs = MIN_START;
+               else
+                       test_dqs = MIN_FINE_START;
+
+               do {
+                       flag = test_loop(k, dqs, test_dqs, min_coarse_dqs,
+                                        0x480, 0x1, 0x0);
+                       if (k == 0) {
+                               if (flag == -1 ||
+                                   test_dqs == min_coarse_dqs_bnd)
+                                       break;
+
+                               test_dqs--;
+
+                               if (test_dqs < min_coarse_dqs_bnd)
+                                       break;
+                       } else {
+                               if (flag == -1) {
+                                       test_dqs++;
+                                       break;
+                               } else if (test_dqs == min_fine_dqs_bnd) {
+                                       break;
+                               }
+
+                               test_dqs--;
+
+                               if (test_dqs < min_fine_dqs_bnd)
+                                       break;
+                       }
+               } while (test_dqs >= 0);
+
+               if (k == 0) {
+                       min_coarse_dqs[dqs] = test_dqs;
+               } else {
+                       if (test_dqs == MIN_FINE_START + 1) {
+                               min_coarse_dqs[dqs]++;
+                               min_fine_dqs[dqs] = 0x0;
+                       } else {
+                               min_fine_dqs[dqs] = test_dqs;
+                       }
+               }
+       }
+
+       if (dqs == 0) {
+               dqs = 1;
+               goto DQS_CAL;
+       }
+
+       for (i = 0; i < 2; i++) {
+               u32 temp;
+
+               coarse_dqs[i] = (max_coarse_dqs[i] + min_coarse_dqs[i]) >> 1;
+               temp =
+                   (((max_coarse_dqs[i] + min_coarse_dqs[i]) % 2) * 4) +
+                   ((max_fine_dqs[i] + min_fine_dqs[i]) >> 1);
+               if (temp >= 0x10) {
+                       coarse_dqs[i]++;
+                       fine_dqs[i] = (temp - 0x10) + 0x8;
+               } else {
+                       fine_dqs[i] = temp;
+               }
+       }
+       reg = (coarse_dqs[1] << 12) | (fine_dqs[1] << 8) |
+               (coarse_dqs[0] << 4) | fine_dqs[0];
+
+       clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
+       writel(reg, (void *)MT76XX_MEMCTRL_BASE + 0x64);
+       writel(ddr_cfg2_reg, (void *)MT76XX_MEMCTRL_BASE + 0x48);
+       setbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
+
+       for (i = 0; i < 2; i++)
+               debug("[%02X%02X%02X%02X]", min_coarse_dqs[i],
+                     min_fine_dqs[i], max_coarse_dqs[i], max_fine_dqs[i]);
+       debug("\nDDR Calibration DQS reg = %08X\n", reg);
+}
diff --git a/arch/mips/mach-mtmips/lowlevel_init.S b/arch/mips/mach-mtmips/lowlevel_init.S
new file mode 100644 (file)
index 0000000..aa707e0
--- /dev/null
@@ -0,0 +1,328 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (c) 2018 Stefan Roese <sr@denx.de>
+ *
+ * This code is mostly based on the code extracted from this MediaTek
+ * github repository:
+ *
+ * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
+ *
+ * I was not able to find a specific license or other developers
+ * copyrights here, so I can't add them here.
+ */
+
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include "mt76xx.h"
+
+#ifndef BIT
+#define BIT(nr)                        (1 << (nr))
+#endif
+
+#define DELAY_USEC(us)         ((us) / 100)
+
+#define DDR_CFG1_CHIP_WIDTH_MASK (0x3 << 16)
+#define DDR_CFG1_BUS_WIDTH_MASK        (0x3 << 12)
+
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
+#define DDR_CFG1_SIZE_VAL      0x222e2323
+#define DDR_CFG4_SIZE_VAL      7
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
+#define DDR_CFG1_SIZE_VAL      0x22322323
+#define DDR_CFG4_SIZE_VAL      9
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
+#define DDR_CFG1_SIZE_VAL      0x22362323
+#define DDR_CFG4_SIZE_VAL      9
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
+#define DDR_CFG1_SIZE_VAL      0x223a2323
+#define DDR_CFG4_SIZE_VAL      9
+#endif
+
+#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_8BIT)
+#define DDR_CFG1_CHIP_WIDTH_VAL        (0x1 << 16)
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_16BIT)
+#define DDR_CFG1_CHIP_WIDTH_VAL        (0x2 << 16)
+#endif
+
+#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_16BIT)
+#define DDR_CFG1_BUS_WIDTH_VAL (0x2 << 12)
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_32BIT)
+#define DDR_CFG1_BUS_WIDTH_VAL (0x3 << 12)
+#endif
+
+       .set noreorder
+
+LEAF(lowlevel_init)
+
+       /* Load base addresses as physical addresses for later usage */
+       li      s0, CKSEG1ADDR(MT76XX_SYSCTL_BASE)
+       li      s1, CKSEG1ADDR(MT76XX_MEMCTRL_BASE)
+       li      s2, CKSEG1ADDR(MT76XX_RGCTRL_BASE)
+
+       /* polling CPLL is ready */
+       li      t1, DELAY_USEC(1000000)
+       la      t5, MT76XX_ROM_STATUS_REG
+1:
+       lw      t2, 0(t5)
+       andi    t2, t2, 0x1
+       bnez    t2, CPLL_READY
+       subu    t1, t1, 1
+       bgtz    t1, 1b
+       nop
+       la      t0, MT76XX_CLKCFG0_REG
+       lw      t3, 0(t0)
+       ori     t3, t3, 0x1
+       sw      t3, 0(t0)
+       b       CPLL_DONE
+       nop
+CPLL_READY:
+       la      t0, MT76XX_CLKCFG0_REG
+       lw      t1, 0(t0)
+       li      t2, ~0x0c
+       and     t1, t1, t2
+       ori     t1, t1, 0xc
+       sw      t1, 0(t0)
+       la      t0, MT76XX_DYN_CFG0_REG
+       lw      t3, 0(t0)
+       li      t5, ~((0x0f << 8) | (0x0f << 0))
+       and     t3, t3, t5
+       li      t5, (10 << 8) | (1 << 0)
+       or      t3, t3, t5
+       sw      t3, 0(t0)
+       la      t0, MT76XX_CLKCFG0_REG
+       lw      t3, 0(t0)
+       li      t4, ~0x0F
+       and     t3, t3, t4
+       ori     t3, t3, 0xc
+       sw      t3, 0(t0)
+       lw      t3, 0(t0)
+       ori     t3, t3, 0x08
+       sw      t3, 0(t0)
+
+CPLL_DONE:
+       /* Reset MC */
+       lw      t2, 0x34(s0)
+       ori     t2, BIT(10)
+       sw      t2, 0x34(s0)
+       nop
+
+       /*
+        * SDR and DDR initialization: delay 200us
+        */
+       li      t0, DELAY_USEC(200 + 40)
+       li      t1, 0x1
+1:
+       sub     t0, t0, t1
+       bnez    t0, 1b
+       nop
+
+       /* set DRAM IO PAD for MT7628IC */
+       /* DDR LDO Enable  */
+       lw      t4, 0x100(s2)
+       li      t2, BIT(31)
+       or      t4, t4, t2
+       sw      t4, 0x100(s2)
+       lw      t4, 0x10c(s2)
+       j       LDO_1P8V
+       nop
+LDO_1P8V:
+       li      t2, ~BIT(6)
+       and     t4, t4, t2
+       sw      t4, 0x10c(s2)
+       j       DDRLDO_SOFT_START
+LDO_2P5V:
+       /* suppose external DDR1 LDO 2.5V */
+       li      t2, BIT(6)
+       or      t4, t4, t2
+       sw      t4, 0x10c(s2)
+
+DDRLDO_SOFT_START:
+       lw      t2, 0x10c(s2)
+       li      t3, BIT(16)
+       or      t2, t2, t3
+       sw      t2, 0x10c(s2)
+       li      t3, DELAY_USEC(250*50)
+LDO_DELAY:
+       subu    t3, t3, 1
+       bnez    t3, LDO_DELAY
+       nop
+
+       lw      t2, 0x10c(s2)
+       li      t3, BIT(18)
+       or      t2, t2, t3
+       sw      t2, 0x10c(s2)
+
+SET_RG_BUCK_FPWM:
+       lw      t2, 0x104(s2)
+       ori     t2, t2, BIT(10)
+       sw      t2, 0x104(s2)
+
+DDR_PAD_CFG:
+       /* clean CLK PAD */
+       lw      t2, 0x704(s2)
+       li      t8, 0xfffff0f0
+       and     t2, t2, t8
+       /* clean CMD PAD */
+       lw      t3, 0x70c(s2)
+       li      t8, 0xfffff0f0
+       and     t3, t3, t8
+       /* clean DQ IPAD */
+       lw      t4, 0x710(s2)
+       li      t8, 0xfffff8ff
+       and     t4, t4, t8
+       /* clean DQ OPAD */
+       lw      t5, 0x714(s2)
+       li      t8, 0xfffff0f0
+       and     t5, t5, t8
+       /* clean DQS IPAD */
+       lw      t6, 0x718(s2)
+       li      t8, 0xfffff8ff
+       and     t6, t6, t8
+       /* clean DQS OPAD */
+       lw      t7, 0x71c(s2)
+       li      t8, 0xfffff0f0
+       and     t7, t7, t8
+
+       lw      t9, 0xc(s0)
+       srl     t9, t9, 16
+       andi    t9, t9, 0x1
+       bnez    t9, MT7628_AN_DDR1_PAD
+MT7628_KN_PAD:
+       li      t8, 0x00000303
+       or      t2, t2, t8
+       or      t3, t3, t8
+       or      t5, t5, t8
+       or      t7, t7, t8
+       li      t8, 0x00000000
+       or      t4, t4, t8
+       or      t6, t6, t8
+       j       SET_PAD_CFG
+MT7628_AN_DDR1_PAD:
+       lw      t1, 0x10(s0)
+       andi    t1, t1, 0x1
+       beqz    t1, MT7628_AN_DDR2_PAD
+       li      t8, 0x00000c0c
+       or      t2, t2, t8
+       li      t8, 0x00000202
+       or      t3, t3, t8
+       li      t8, 0x00000707
+       or      t5, t5, t8
+       li      t8, 0x00000c0c
+       or      t7, t7, t8
+       li      t8, 0x00000000
+       or      t4, t4, t8
+       or      t6, t6, t8
+       j       SET_PAD_CFG
+MT7628_AN_DDR2_PAD:
+       li      t8, 0x00000c0c
+       or      t2, t2, t8
+       li      t8, 0x00000202
+       or      t3, t3, t8
+       li      t8, 0x00000404
+       or      t5, t5, t8
+       li      t8, 0x00000c0c
+       or      t7, t7, t8
+       li      t8, 0x00000000          /* ODT off */
+       or      t4, t4, t8
+       or      t6, t6, t8
+
+SET_PAD_CFG:
+       sw      t2, 0x704(s2)
+       sw      t3, 0x70c(s2)
+       sw      t4, 0x710(s2)
+       sw      t5, 0x714(s2)
+       sw      t6, 0x718(s2)
+       sw      t7, 0x71c(s2)
+
+       /*
+        * DDR initialization: reset pin to 0
+        */
+       lw      t2, 0x34(s0)
+       and     t2, ~BIT(10)
+       sw      t2, 0x34(s0)
+       nop
+
+       /*
+        * DDR initialization: wait til reg DDR_CFG1 bit 21 equal to 1 (ready)
+        */
+DDR_READY:
+       li      t1, DDR_CFG1_REG
+       lw      t0, 0(t1)
+       nop
+       and     t2, t0, BIT(21)
+       beqz    t2, DDR_READY
+       nop
+
+       /*
+        * DDR initialization
+        *
+        * Only DDR2 supported right now. DDR2 support can be added, once
+        * boards using it will get added to mainline U-Boot.
+        */
+       li      t1, DDR_CFG2_REG
+       lw      t0, 0(t1)
+       nop
+       and     t0, ~BIT(30)
+       and     t0, ~(7 << 4)
+       or      t0, (4 << 4)
+       or      t0, BIT(30)
+       or      t0, BIT(11)
+       sw      t0, 0(t1)
+       nop
+
+       li      t1, DDR_CFG3_REG
+       lw      t2, 0(t1)
+       /* Disable ODT; reference board ok, ev board fail */
+       and     t2, ~BIT(6)
+       or      t2, BIT(2)
+       li      t0, DDR_CFG4_REG
+       lw      t1, 0(t0)
+       li      t2, ~(0x01f | 0x0f0)
+       and     t1, t1, t2
+       ori     t1, t1, DDR_CFG4_SIZE_VAL
+       sw      t1, 0(t0)
+       nop
+
+       /*
+        * DDR initialization: config size and width on reg DDR_CFG1
+        */
+       li      t6, DDR_CFG1_SIZE_VAL
+
+       and     t6, ~DDR_CFG1_CHIP_WIDTH_MASK
+       or      t6, DDR_CFG1_CHIP_WIDTH_VAL
+
+       /* CONFIG DDR_CFG1[13:12] about TOTAL WIDTH */
+       and     t6, ~DDR_CFG1_BUS_WIDTH_MASK
+       or      t6, DDR_CFG1_BUS_WIDTH_VAL
+
+       li      t5, DDR_CFG1_REG
+       sw      t6, 0(t5)
+       nop
+
+       /*
+        * DDR: enable self auto refresh for power saving
+        * enable it by default for both RAM and ROM version (for CoC)
+        */
+       lw      t1, 0x14(s1)
+       nop
+       and     t1, 0xff000000
+       or      t1, 0x01
+       sw      t1, 0x14(s1)
+       nop
+       lw      t1, 0x10(s1)
+       nop
+       or      t1, 0x10
+       sw      t1, 0x10(s1)
+       nop
+
+       jr      ra
+       nop
+       END(lowlevel_init)
diff --git a/arch/mips/mach-mtmips/mt76xx.h b/arch/mips/mach-mtmips/mt76xx.h
new file mode 100644 (file)
index 0000000..17473ea
--- /dev/null
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ */
+
+#ifndef __MT76XX_H
+#define __MT76XX_H
+
+#define MT76XX_SYSCTL_BASE     0x10000000
+
+#define MT76XX_CHIPID_OFFS     0x00
+#define MT76XX_CHIP_REV_ID_OFFS        0x0c
+#define MT76XX_SYSCFG0_OFFS    0x10
+
+#define MT76XX_MEMCTRL_BASE    (MT76XX_SYSCTL_BASE + 0x0300)
+#define MT76XX_RGCTRL_BASE     (MT76XX_SYSCTL_BASE + 0x1000)
+
+#define MT76XX_ROM_STATUS_REG  (MT76XX_SYSCTL_BASE + 0x0028)
+#define MT76XX_CLKCFG0_REG     (MT76XX_SYSCTL_BASE + 0x002c)
+#define MT76XX_DYN_CFG0_REG    (MT76XX_SYSCTL_BASE + 0x0440)
+
+#define DDR_CFG1_REG           (MT76XX_MEMCTRL_BASE + 0x44)
+#define DDR_CFG2_REG           (MT76XX_MEMCTRL_BASE + 0x48)
+#define DDR_CFG3_REG           (MT76XX_MEMCTRL_BASE + 0x4c)
+#define DDR_CFG4_REG           (MT76XX_MEMCTRL_BASE + 0x50)
+
+#ifndef __ASSEMBLY__
+/* Prototypes */
+void ddr_calibrate(void);
+#endif
+
+#endif
index 807c717e33a470ba5d55f11123ceae5682ce03cf..114f7fd9d9b25a4df1206630195f9fed8dd277e4 100644 (file)
@@ -6,8 +6,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <led.h>
-
-DECLARE_GLOBAL_DATA_PTR;
+#include <miiphy.h>
 
 enum {
        BOARD_TYPE_PCB090 = 0xAABBCD00,
@@ -36,6 +35,16 @@ int board_early_init_r(void)
        return 0;
 }
 
+int board_phy_config(struct phy_device *phydev)
+{
+       phy_write(phydev, 0, 31, 0x10);
+       phy_write(phydev, 0, 18, 0x80A0);
+       while (phy_read(phydev, 0, 18) & 0x8000)
+               ;
+       phy_write(phydev, 0, 31, 0);
+       return 0;
+}
+
 static void do_board_detect(void)
 {
        u32 chipid = (readl(BASE_DEVCPU_GCB + CHIP_ID) >> 12) & 0xFFFF;
index 532d06f00031fc15177d12db4305b3bb91f7639e..bcae8fa50ca2b5bce19621af0e6fc095230a38d0 100644 (file)
@@ -11,6 +11,7 @@
 #include <spi.h>
 #include <led.h>
 #include <wait_bit.h>
+#include <miiphy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -42,6 +43,20 @@ void mscc_switch_reset(bool enter)
        mscc_gpio_set_alternate(19, 0);
 }
 
+int board_phy_config(struct phy_device *phydev)
+{
+       if (gd->board_type == BOARD_TYPE_PCB123)
+               return 0;
+
+       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);
+
+       return 0;
+}
+
 void board_debug_uart_init(void)
 {
        /* too early for the pinctrl driver, so configure the UART pins here */
index 24ee5e528d9f9de85da837ba799e6e3cc552b168..da7f55620debec24178a77bd12829cdfb9af01cc 100644 (file)
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <led.h>
+#include <miiphy.h>
 
 enum {
        BOARD_TYPE_PCB106 = 0xAABBCD00,
@@ -27,6 +28,17 @@ int board_early_init_r(void)
        return 0;
 }
 
+int board_phy_config(struct phy_device *phydev)
+{
+       phy_write(phydev, 0, 31, 0x10);
+       phy_write(phydev, 0, 18, 0x80F0);
+       while (phy_read(phydev, 0, 18) & 0x8000)
+               ;
+       phy_write(phydev, 0, 14, 0x800);
+       phy_write(phydev, 0, 31, 0);
+       return 0;
+}
+
 static void do_board_detect(void)
 {
        u16 gpio_in_reg;
@@ -42,10 +54,10 @@ static void do_board_detect(void)
                        gd->board_type = BOARD_TYPE_PCB106;
                else
                        gd->board_type = BOARD_TYPE_PCB105;
-               mscc_phy_wr(1, 16, 15, 0);
        } else {
                gd->board_type = BOARD_TYPE_PCB105;
        }
+       mscc_phy_wr(1, 16, 31, 0x0);
 }
 
 #if defined(CONFIG_MULTI_DTB_FIT)
index 7c8ae0f6474e4c3458ae4f7e0f17371f2ce10748..e09950637ff9ee38e587656840415da1e0a7b872 100644 (file)
@@ -1,7 +1,7 @@
 CONFIG_MIPS=y
 CONFIG_SYS_TEXT_BASE=0x80010000
 CONFIG_NR_DRAM_BANKS=1
-CONFIG_ARCH_MT7620=y
+CONFIG_ARCH_MTMIPS=y
 # CONFIG_MIPS_BOOT_ENV_LEGACY is not set
 CONFIG_MIPS_BOOT_FDT=y
 CONFIG_ENV_VARS_UBOOT_CONFIG=y
index 8fd676025aadc03341d0c42030f5293184b3895b..ad0db2e7235d122214309aeef0fc7f0f726afded 100644 (file)
@@ -1,7 +1,7 @@
 CONFIG_MIPS=y
 CONFIG_SYS_TEXT_BASE=0x9c000000
 CONFIG_NR_DRAM_BANKS=1
-CONFIG_ARCH_MT7620=y
+CONFIG_ARCH_MTMIPS=y
 CONFIG_BOOT_ROM=y
 CONFIG_ONBOARD_DDR2_SIZE_1024MBIT=y
 CONFIG_ONBOARD_DDR2_CHIP_WIDTH_16BIT=y
index 6e9aa7adefcd19d8b0ec6bdc9dd98853612f03c9..c2502b27139dacf05acbe3cde97e6b77052d76c5 100644 (file)
@@ -1,7 +1,7 @@
 CONFIG_MIPS=y
 CONFIG_SYS_TEXT_BASE=0x80010000
 CONFIG_NR_DRAM_BANKS=1
-CONFIG_ARCH_MT7620=y
+CONFIG_ARCH_MTMIPS=y
 CONFIG_BOARD_LINKIT_SMART_7688=y
 # CONFIG_MIPS_BOOT_ENV_LEGACY is not set
 CONFIG_MIPS_BOOT_FDT=y
index 5660f41e8e348488ef345c786873bcc85c2b6ec9..fba1bfd653cbdbb361032d7a670c1269baf4dd22 100644 (file)
@@ -1,7 +1,7 @@
 CONFIG_MIPS=y
 CONFIG_SYS_TEXT_BASE=0x9c000000
 CONFIG_NR_DRAM_BANKS=1
-CONFIG_ARCH_MT7620=y
+CONFIG_ARCH_MTMIPS=y
 CONFIG_BOARD_LINKIT_SMART_7688=y
 CONFIG_BOOT_ROM=y
 CONFIG_ONBOARD_DDR2_SIZE_1024MBIT=y
index 146188bb0c90f73af7188e573681e3b1573165cf..753a11aa122bd38514775e7ea42fbfd14479378a 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NFS 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)"
@@ -58,3 +57,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_SERVAL_SWITCH=y
index b3e4ecc50e1e23b5a66e152b5e6acd2359645f74..684ca9d868fc4233cfa5602337489f0824e69c08 100644 (file)
@@ -351,7 +351,7 @@ config MPC8XXX_GPIO
 
 config MT7621_GPIO
        bool "MediaTek MT7621 GPIO driver"
-       depends on DM_GPIO && ARCH_MT7620
+       depends on DM_GPIO && SOC_MT7628
        default y
        help
          Say yes here to support MediaTek MT7621 compatible GPIOs.
index 6e436b56abf064e40a639b7c198d5d8f0c574513..64cdc58f92c318fe4b5048d12b809f712793c28a 100644 (file)
@@ -269,7 +269,7 @@ config MACB_ZYNQ
 
 config MT7628_ETH
        bool "MediaTek MT7628 Ethernet Interface"
-       depends on ARCH_MT7620
+       depends on SOC_MT7628
        help
          The MediaTek MT7628 ethernet interface is used on MT7628 and
          MT7688 based boards.
index 6359d0b61015915b7a0f63cdff9bd056e77fed3f..80dd22f98b7f591768c28a67b66e3a2b5dd095f9 100644 (file)
@@ -29,3 +29,10 @@ config MSCC_SERVALT_SWITCH
        select PHYLIB
        help
          This driver supports the Servalt network switch device.
+
+config MSCC_SERVAL_SWITCH
+       bool "Serval switch driver"
+       depends on DM_ETH && ARCH_MSCC
+       select PHYLIB
+       help
+         This driver supports the Serval network switch device.
index bffd8ec77b0f6a11f00c12db1df91ac9b3f6be24..02f39a76bb0fa13eb070f59b36cc2c6e9e6909d9 100644 (file)
@@ -1,5 +1,6 @@
 
-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_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o
+obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.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
+obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o
index 6667614966daf38b77edb5be3b27891f8be10984..94852b06e745995d1867660f871444f47df7da63 100644 (file)
 #include <net.h>
 #include <wait_bit.h>
 
-#include "mscc_miim.h"
 #include "mscc_xfer.h"
 #include "mscc_mac_table.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                     (0x2 << 16)
+
 #define ANA_PORT_VLAN_CFG(x)           (0x00 + 0x80 * (x))
 #define                ANA_PORT_VLAN_CFG_AWARE_ENA     BIT(20)
 #define                ANA_PORT_VLAN_CFG_POP_CNT(x)    ((x) << 18)
 #define PGID_UNICAST           29
 #define PGID_SRC               80
 
-enum luton_target {
-       PORT0,
-       PORT1,
-       PORT2,
-       PORT3,
-       PORT4,
-       PORT5,
-       PORT6,
-       PORT7,
-       PORT8,
-       PORT9,
-       PORT10,
-       PORT11,
-       PORT12,
-       PORT13,
-       PORT14,
-       PORT15,
-       PORT16,
-       PORT17,
-       PORT18,
-       PORT19,
-       PORT20,
-       PORT21,
-       PORT22,
-       PORT23,
-       SYS,
+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",
+       "sys", "ana", "rew", "gcb", "qs", "hsio",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 24
+
+enum luton_ctrl_regs {
+       SYS = MAX_PORT,
        ANA,
        REW,
        GCB,
        QS,
-       HSIO,
-       TARGET_MAX,
+       HSIO
 };
 
-#define MAX_PORT (PORT23 - PORT0 + 1)
+#define MIN_INT_PORT   0
+#define PORT10         10
+#define PORT11         11
+#define MAX_INT_PORT   12
+#define MIN_EXT_PORT   MAX_INT_PORT
+#define MAX_EXT_PORT   MAX_PORT
 
-#define MIN_INT_PORT PORT0
-#define MAX_INT_PORT (PORT11 - PORT0  + 1)
-#define MIN_EXT_PORT PORT12
-#define MAX_EXT_PORT MAX_PORT
+#define LUTON_MIIM_BUS_COUNT 2
 
-enum luton_mdio_target {
-       MIIM,
-       TARGET_MDIO_MAX,
+struct luton_phy_port_t {
+       size_t phy_addr;
+       struct mii_dev *bus;
+       u8 serdes_index;
+       u8 phy_mode;
 };
 
-enum luton_phy_id {
-       INTERNAL,
-       EXTERNAL,
-       NUM_PHY,
+struct luton_private {
+       void __iomem *regs[REGS_NAMES_COUNT];
+       struct mii_dev *bus[LUTON_MIIM_BUS_COUNT];
+       struct luton_phy_port_t ports[MAX_PORT];
 };
 
-struct luton_private {
-       void __iomem *regs[TARGET_MAX];
-       struct mii_dev *bus[NUM_PHY];
+struct mscc_miim_dev {
+       void __iomem *regs;
+       phys_addr_t miim_base;
+       unsigned long miim_size;
+       struct mii_dev *bus;
 };
 
 static const unsigned long luton_regs_qs[] = {
@@ -207,53 +210,85 @@ static const unsigned long luton_regs_ana_table[] = {
        [MSCC_ANA_TABLES_MACACCESS] = 0x11b8,
 };
 
-static struct mscc_miim_dev miim[NUM_PHY];
+static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
+static int miim_count = -1;
 
-static struct mii_dev *luton_mdiobus_init(struct udevice *dev,
-                                         int mdiobus_id)
+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 *serval_mdiobus_init(phys_addr_t miim_base,
+                                          unsigned long miim_size)
 {
-       unsigned long phy_size[NUM_PHY];
-       phys_addr_t phy_base[NUM_PHY];
-       struct ofnode_phandle_args phandle;
-       ofnode eth_node, node, mdio_node;
-       struct resource res;
        struct mii_dev *bus;
-       fdt32_t faddr;
-       int i;
 
        bus = mdio_alloc();
        if (!bus)
                return NULL;
 
-       /* gather only the first mdio bus */
-       eth_node = dev_read_first_subnode(dev);
-       node = ofnode_first_subnode(eth_node);
-       ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
-                                      &phandle);
-       mdio_node = ofnode_get_parent(phandle.node);
-
-       for (i = 0; i < TARGET_MDIO_MAX; i++) {
-               if (ofnode_read_resource(mdio_node, i, &res)) {
-                       pr_err("%s: get OF resource failed\n", __func__);
-                       return NULL;
-               }
-
-               faddr = cpu_to_fdt32(res.start);
-               phy_base[i] = ofnode_translate_address(mdio_node, &faddr);
-               phy_size[i] = res.end - res.start;
-       }
+       ++miim_count;
+       sprintf(bus->name, "miim-bus%d", miim_count);
 
-       strcpy(bus->name, "miim-internal");
-       miim[mdiobus_id].regs = ioremap(phy_base[mdiobus_id],
-                                       phy_size[mdiobus_id]);
-       bus->priv = &miim[mdiobus_id];
+       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;
-       else
-               return bus;
+
+       miim[miim_count].bus = bus;
+       return bus;
 }
 
 static void luton_stop(struct udevice *dev)
@@ -324,10 +359,10 @@ static void luton_gmii_port_init(struct luton_private *priv, int port)
        writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
               ANA_PORT_VLAN_CFG_POP_CNT(1) |
               MAC_VID,
-              priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
+              priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
 
        /* Enable switching to/from port */
-       setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port - PORT0),
+       setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
                     SYS_SWITCH_PORT_MODE_PORT_ENA);
 }
 
@@ -346,10 +381,10 @@ static void luton_port_init(struct luton_private *priv, int port)
        writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
               ANA_PORT_VLAN_CFG_POP_CNT(1) |
               MAC_VID,
-              priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
+              priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
 
        /* Enable switching to/from port */
-       setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port - PORT0),
+       setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
                     SYS_SWITCH_PORT_MODE_PORT_ENA);
 }
 
@@ -393,35 +428,34 @@ static void luton_ext_port_init(struct luton_private *priv, int port)
        writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
               ANA_PORT_VLAN_CFG_POP_CNT(1) |
               MAC_VID,
-              priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
+              priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
 
        /* Enable switching to/from port */
-       setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port - PORT0),
+       setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
                     SYS_SWITCH_PORT_MODE_PORT_ENA);
 }
 
-static void serdes6g_write(struct luton_private *priv, u32 addr)
+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),
-              priv->regs[HSIO] + HSIO_MCB_SERDES6G_CFG);
+              base + HSIO_MCB_SERDES6G_CFG);
 
        do {
-               data = readl(priv->regs[HSIO] + HSIO_MCB_SERDES6G_CFG);
+               data = readl(base + HSIO_MCB_SERDES6G_CFG);
        } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
-
-       mdelay(100);
 }
 
-static void serdes6g_cfg(struct luton_private *priv)
+static void serdes6g_setup(void __iomem *base, uint32_t addr,
+                          phy_interface_t interface)
 {
        writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
               HSIO_RCOMP_CFG_CFG0_RUN_CAL,
-              priv->regs[HSIO] + HSIO_RCOMP_CFG_CFG0);
+              base + HSIO_RCOMP_CFG_CFG0);
 
-       while (readl(priv->regs[HSIO] + HSIO_RCOMP_STATUS) &
+       while (readl(base + HSIO_RCOMP_STATUS) &
               HSIO_RCOMP_STATUS_BUSY)
                ;
 
@@ -430,50 +464,64 @@ static void serdes6g_cfg(struct luton_private *priv)
               HSIO_SERDES6G_ANA_CFG_OB_CFG_POST0(0x10) |
               HSIO_SERDES6G_ANA_CFG_OB_CFG_POL |
               HSIO_SERDES6G_ANA_CFG_OB_CFG_ENA1V_MODE,
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_OB_CFG);
+              base + HSIO_SERDES6G_ANA_CFG_OB_CFG);
        writel(HSIO_SERDES6G_ANA_CFG_OB_CFG1_LEV(0x18) |
               HSIO_SERDES6G_ANA_CFG_OB_CFG1_ENA_CAS(0x1),
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_OB_CFG1);
+              base + HSIO_SERDES6G_ANA_CFG_OB_CFG1);
        writel(HSIO_SERDES6G_ANA_CFG_IB_CFG_RESISTOR_CTRL(0xc) |
               HSIO_SERDES6G_ANA_CFG_IB_CFG_VBCOM(0x4) |
               HSIO_SERDES6G_ANA_CFG_IB_CFG_VBAC(0x5) |
               HSIO_SERDES6G_ANA_CFG_IB_CFG_RT(0xf) |
               HSIO_SERDES6G_ANA_CFG_IB_CFG_RF(0x4),
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_IB_CFG);
+              base + HSIO_SERDES6G_ANA_CFG_IB_CFG);
        writel(HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST |
               HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSDC |
               HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSAC |
               HSIO_SERDES6G_ANA_CFG_IB_CFG1_ANEG_MODE |
               HSIO_SERDES6G_ANA_CFG_IB_CFG1_CHF |
               HSIO_SERDES6G_ANA_CFG_IB_CFG1_C(0x4),
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_IB_CFG1);
+              base + HSIO_SERDES6G_ANA_CFG_IB_CFG1);
        writel(HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_ANA(0x5) |
               HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_HYST(0x5) |
               HSIO_SERDES6G_ANA_CFG_DES_CFG_MBTR_CTRL(0x2) |
               HSIO_SERDES6G_ANA_CFG_DES_CFG_PHS_CTRL(0x6),
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_DES_CFG);
+              base + HSIO_SERDES6G_ANA_CFG_DES_CFG);
        writel(HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_ENA |
               HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_CTRL_DATA(0x78),
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_PLL_CFG);
+              base + HSIO_SERDES6G_ANA_CFG_PLL_CFG);
        writel(HSIO_SERDES6G_ANA_CFG_COMMON_CFG_IF_MODE(0x30) |
               HSIO_SERDES6G_ANA_CFG_COMMON_CFG_ENA_LANE,
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
+              base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
        /*
         * There are 4 serdes6g, configure all except serdes6g0, therefore
         * the address is b1110
         */
-       serdes6g_write(priv, 0xe);
+       serdes6g_write(base, addr);
 
-       writel(readl(priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_COMMON_CFG) |
+       writel(readl(base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG) |
               HSIO_SERDES6G_ANA_CFG_COMMON_CFG_SYS_RST,
-              priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
-       serdes6g_write(priv, 0xe);
+              base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
+       serdes6g_write(base, addr);
 
-       clrbits_le32(priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_IB_CFG1,
+       clrbits_le32(base + HSIO_SERDES6G_ANA_CFG_IB_CFG1,
                     HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST);
        writel(HSIO_SERDES6G_DIG_CFG_MISC_CFG_LANE_RST,
-              priv->regs[HSIO] + HSIO_SERDES6G_DIG_CFG_MISC_CFG);
-       serdes6g_write(priv, 0xe);
+              base + HSIO_SERDES6G_DIG_CFG_MISC_CFG);
+       serdes6g_write(base, addr);
+}
+
+static void serdes_setup(struct luton_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);
+               serdes6g_setup(priv->regs[HSIO], mask, priv->ports[i].phy_mode);
+       }
 }
 
 static int luton_switch_init(struct luton_private *priv)
@@ -495,8 +543,8 @@ static int luton_switch_init(struct luton_private *priv)
        setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
                     SYS_SYSTEM_RST_CORE_ENA);
 
-       /* Setup the Serdes6g macros */
-       serdes6g_cfg(priv);
+       /* Setup the Serdes macros */
+       serdes_setup(priv);
 
        return 0;
 }
@@ -525,7 +573,7 @@ static int luton_initialize(struct luton_private *priv)
        writel(2000000000 / 4,
               priv->regs[SYS] + SYS_FRM_AGING);
 
-       for (i = PORT0; i < MAX_PORT; i++) {
+       for (i = 0; i < MAX_PORT; i++) {
                if (i < PORT10)
                        luton_gmii_port_init(priv, i);
                else
@@ -608,56 +656,51 @@ static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
        return byte_cnt;
 }
 
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
+{
+       int i = 0;
+
+       for (i = 0; i < LUTON_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 luton_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 luton_probe(struct udevice *dev)
 {
        struct luton_private *priv = dev_get_priv(dev);
-       int i;
-
-       struct {
-               enum luton_target id;
-               char *name;
-       } reg[] = {
-               { PORT0, "port0" },
-               { PORT1, "port1" },
-               { PORT2, "port2" },
-               { PORT3, "port3" },
-               { PORT4, "port4" },
-               { PORT5, "port5" },
-               { PORT6, "port6" },
-               { PORT7, "port7" },
-               { PORT8, "port8" },
-               { PORT9, "port9" },
-               { PORT10, "port10" },
-               { PORT11, "port11" },
-               { PORT12, "port12" },
-               { PORT13, "port13" },
-               { PORT14, "port14" },
-               { PORT15, "port15" },
-               { PORT16, "port16" },
-               { PORT17, "port17" },
-               { PORT18, "port18" },
-               { PORT19, "port19" },
-               { PORT20, "port20" },
-               { PORT21, "port21" },
-               { PORT22, "port22" },
-               { PORT23, "port23" },
-               { SYS, "sys" },
-               { ANA, "ana" },
-               { REW, "rew" },
-               { GCB, "gcb" },
-               { QS, "qs" },
-               { HSIO, "hsio" },
-       };
+       int i, 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;
 
-       for (i = 0; i < ARRAY_SIZE(reg); i++) {
-               priv->regs[reg[i].id] = dev_remap_addr_name(dev, reg[i].name);
-               if (!priv->regs[reg[i].id]) {
+       /* 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",
-                            reg[i].name);
+                            regs_names[i]);
                        return -ENOMEM;
                }
        }
@@ -666,7 +709,7 @@ static int luton_probe(struct udevice *dev)
        writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
 
        /* Ports with ext phy don't need to reset clk */
-       for (i = PORT0; i < MAX_INT_PORT; i++) {
+       for (i = 0; i < MAX_INT_PORT; i++) {
                if (i < PORT10)
                        clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
                                     DEV_GMII_PORT_MODE_CLK_PHY_RST);
@@ -680,20 +723,76 @@ static int luton_probe(struct udevice *dev)
                              GCB_MISC_STAT_PHY_READY, true, 500, false))
                return -EACCES;
 
-       priv->bus[INTERNAL] = luton_mdiobus_init(dev, INTERNAL);
 
-       for (i = 0; i < MAX_INT_PORT; i++) {
-               phy_connect(priv->bus[INTERNAL], i, dev,
-                           PHY_INTERFACE_MODE_NONE);
+       /* Initialize miim buses */
+       memset(&miim, 0x0, sizeof(miim) * LUTON_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] =
+                               serval_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)
+                       add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
+               else
+                       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 && i >= MAX_INT_PORT)
+                       board_phy_config(phy);
        }
 
        /*
         * coma_mode is need on only one phy, because all the other phys
         * will be affected.
         */
-       mscc_miim_write(priv->bus[INTERNAL], 0, 0, 31, 0x10);
-       mscc_miim_write(priv->bus[INTERNAL], 0, 0, 14, 0x800);
-       mscc_miim_write(priv->bus[INTERNAL], 0, 0, 31, 0);
+       mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0x10);
+       mscc_miim_write(priv->ports[0].bus, 0, 0, 14, 0x800);
+       mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0);
 
        return 0;
 }
@@ -703,7 +802,7 @@ static int luton_remove(struct udevice *dev)
        struct luton_private *priv = dev_get_priv(dev);
        int i;
 
-       for (i = 0; i < NUM_PHY; i++) {
+       for (i = 0; i < LUTON_MIIM_BUS_COUNT; i++) {
                mdio_unregister(priv->bus[i]);
                mdio_free(priv->bus[i]);
        }
index 815c2da26469c54ff26388316b8ad7081bf19e5c..5c7e6961be43668f655eba905a6ab82a6f5f6011 100644 (file)
@@ -15,7 +15,6 @@
 #include <net.h>
 #include <wait_bit.h>
 
-#include "mscc_miim.h"
 #include "mscc_xfer.h"
 #include "mscc_mac_table.h"
 
 #define PHY_STAT                       0x4
 #define PHY_STAT_SUPERVISOR_COMPLETE           BIT(0)
 
+#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_PORT_VLAN_CFG(x)           (0x7000 + 0x100 * (x))
 #define                ANA_PORT_VLAN_CFG_AWARE_ENA     BIT(20)
 #define                ANA_PORT_VLAN_CFG_POP_CNT(x)    ((x) << 18)
 #define                ANA_PORT_PORT_CFG_RECV_ENA      BIT(6)
 #define ANA_PGID(x)                    (0x8c00 + 4 * (x))
 
+#define HSIO_ANA_SERDES1G_DES_CFG              0x4c
+#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               0x50
+#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_ACJTAG_HYST(x)         ((x) << 24)
+#define HSIO_ANA_SERDES1G_OB_CFG               0x54
+#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              0x58
+#define HSIO_ANA_SERDES1G_COMMON_CFG           0x5c
+#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              0x60
+#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             0x68
+#define HSIO_DIG_SERDES1G_MISC_CFG             0x7c
+#define                HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST             BIT(0)
+#define HSIO_MCB_SERDES1G_CFG                  0x88
+#define                HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT               BIT(31)
+#define                HSIO_MCB_SERDES1G_CFG_ADDR(x)                   (x)
+#define HSIO_HW_CFGSTAT_HW_CFG                 0x10c
+
 #define SYS_FRM_AGING                  0x574
 #define                SYS_FRM_AGING_ENA               BIT(20)
 
 #define                QS_INJ_GRP_CFG_BYTE_SWAP        BIT(0)
 
 #define IFH_INJ_BYPASS         BIT(31)
-#define        IFH_TAG_TYPE_C          0
-#define        MAC_VID                 1
+#define IFH_TAG_TYPE_C         0
+#define MAC_VID                        1
 #define CPU_PORT               11
-#define INTERNAL_PORT_MSK      0xF
+#define INTERNAL_PORT_MSK      0x2FF
 #define IFH_LEN                        4
 #define ETH_ALEN               6
-#define        PGID_BROADCAST          13
-#define        PGID_UNICAST            14
-#define        PGID_SRC                80
+#define PGID_BROADCAST         13
+#define PGID_UNICAST           14
+#define PGID_SRC               80
 
-enum ocelot_target {
-       ANA,
-       QS,
-       QSYS,
+static const char * const regs_names[] = {
+       "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
+       "port8", "port9", "port10", "sys", "rew", "qs", "hsio", "qsys", "ana",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 11
+
+enum ocelot_ctrl_regs {
+       SYS = MAX_PORT,
        REW,
-       SYS,
+       QS,
        HSIO,
-       PORT0,
-       PORT1,
-       PORT2,
-       PORT3,
-       TARGET_MAX,
+       QSYS,
+       ANA,
 };
 
-#define MAX_PORT (PORT3 - PORT0)
+#define OCELOT_MIIM_BUS_COUNT 2
 
-enum ocelot_mdio_target {
-       MIIM,
-       PHY,
-       TARGET_MDIO_MAX,
+struct ocelot_phy_port_t {
+       size_t phy_addr;
+       struct mii_dev *bus;
+       u8 serdes_index;
+       u8 phy_mode;
 };
 
-enum ocelot_phy_id {
-       INTERNAL,
-       EXTERNAL,
-       NUM_PHY,
+struct ocelot_private {
+       void __iomem *regs[REGS_NAMES_COUNT];
+       struct mii_dev *bus[OCELOT_MIIM_BUS_COUNT];
+       struct ocelot_phy_port_t ports[MAX_PORT];
 };
 
-struct ocelot_private {
-       void __iomem *regs[TARGET_MAX];
-       struct mii_dev *bus[NUM_PHY];
+struct mscc_miim_dev {
+       void __iomem *regs;
+       phys_addr_t miim_base;
+       unsigned long miim_size;
+       struct mii_dev *bus;
 };
 
+static struct mscc_miim_dev miim[OCELOT_MIIM_BUS_COUNT];
+static int miim_count = -1;
+
 static const unsigned long ocelot_regs_qs[] = {
        [MSCC_QS_XTR_RD] = 0x8,
        [MSCC_QS_XTR_FLUSH] = 0x18,
@@ -140,65 +197,95 @@ static const unsigned long ocelot_regs_ana_table[] = {
        [MSCC_ANA_TABLES_MACACCESS] = 0x8b3c,
 };
 
-static struct mscc_miim_dev miim[NUM_PHY];
-
 static void mscc_phy_reset(void)
 {
-       writel(0, miim[INTERNAL].phy_regs + PHY_CFG);
+       writel(0, BASE_DEVCPU_GCB + PERF_PHY_CFG + 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,
+              | PHY_CFG_ENA, BASE_DEVCPU_GCB + PERF_PHY_CFG + PHY_CFG);
+       if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + PERF_PHY_CFG) +
+                             PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
                              true, 2000, false)) {
                pr_err("Timeout in phy reset\n");
        }
 }
 
-/* For now only setup the internal mdio bus */
-static struct mii_dev *ocelot_mdiobus_init(struct udevice *dev)
+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 *ocelot_mdiobus_init(phys_addr_t miim_base,
+                                          unsigned long miim_size)
 {
-       unsigned long phy_size[TARGET_MAX];
-       phys_addr_t phy_base[TARGET_MAX];
-       struct ofnode_phandle_args phandle;
-       ofnode eth_node, node, mdio_node;
-       struct resource res;
        struct mii_dev *bus;
-       fdt32_t faddr;
-       int i;
 
        bus = mdio_alloc();
 
        if (!bus)
                return NULL;
 
-       /* gathered only the first mdio bus */
-       eth_node = dev_read_first_subnode(dev);
-       node = ofnode_first_subnode(eth_node);
-       ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
-                                      &phandle);
-       mdio_node = ofnode_get_parent(phandle.node);
-
-       for (i = 0; i < TARGET_MDIO_MAX; i++) {
-               if (ofnode_read_resource(mdio_node, i, &res)) {
-                       pr_err("%s: get OF resource failed\n", __func__);
-                       return NULL;
-               }
-               faddr = cpu_to_fdt32(res.start);
-               phy_base[i] = ofnode_translate_address(mdio_node, &faddr);
-               phy_size[i] = res.end - res.start;
-       }
+       ++miim_count;
+       sprintf(bus->name, "miim-bus%d", miim_count);
 
-       strcpy(bus->name, "miim-internal");
-       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];
+       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;
-       else
-               return bus;
+
+       miim[miim_count].bus = bus;
+       return bus;
 }
 
 __weak void mscc_switch_reset(void)
@@ -291,13 +378,87 @@ static void ocelot_port_init(struct ocelot_private *priv, int port)
 
        /* Make VLAN aware for CPU traffic */
        writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
-              MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
+              MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
 
        /* Enable the port in the core */
-       setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port - PORT0),
+       setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port),
                     QSYS_SWITCH_PORT_MODE_PORT_ENA);
 }
 
+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(0x34, base + HSIO_HW_CFGSTAT_HW_CFG);
+
+       writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
+       writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
+       writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(11) |
+              HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(0) |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
+              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_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_COMMON_CFG_IF_MODE |
+              HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE,
+              base + HSIO_ANA_SERDES1G_COMMON_CFG);
+       writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
+              HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(200) |
+              HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
+              base + HSIO_ANA_SERDES1G_PLL_CFG);
+       writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
+              base + HSIO_DIG_SERDES1G_MISC_CFG);
+
+       serdes1g_write(base, addr);
+
+       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);
+
+       writel(0x0, base + HSIO_DIG_SERDES1G_MISC_CFG);
+       serdes1g_write(base, addr);
+}
+
+static void serdes_setup(struct ocelot_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);
+               serdes1g_setup(priv->regs[HSIO], mask,
+                              priv->ports[i].phy_mode);
+       }
+}
+
 static int ocelot_switch_init(struct ocelot_private *priv)
 {
        /* Reset switch & memories */
@@ -315,6 +476,7 @@ static int ocelot_switch_init(struct ocelot_private *priv)
        setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
                     SYS_SYSTEM_RST_CORE_ENA);
 
+       serdes_setup(priv);
        return 0;
 }
 
@@ -331,7 +493,7 @@ static int ocelot_initialize(struct ocelot_private *priv)
         * Put fron ports in "port isolation modes" - i.e. they cant send
         * to other ports - via the PGID sorce masks.
         */
-       for (i = 0; i <= MAX_PORT; i++)
+       for (i = 0; i < MAX_PORT; i++)
                writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
 
        /* Flush queues */
@@ -341,7 +503,7 @@ static int ocelot_initialize(struct ocelot_private *priv)
        writel(SYS_FRM_AGING_ENA | (20000000 / 65),
               priv->regs[SYS] + SYS_FRM_AGING);
 
-       for (i = PORT0; i <= PORT3; i++)
+       for (i = 0; i < MAX_PORT; i++)
                ocelot_port_init(priv, i);
 
        ocelot_cpu_capture_setup(priv);
@@ -433,43 +595,119 @@ static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp)
        return byte_cnt;
 }
 
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
+{
+       int i = 0;
+
+       for (i = 0; i < OCELOT_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 ocelot_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 external_bus(struct ocelot_private *priv, size_t port_index)
+{
+       return priv->ports[port_index].serdes_index != 0xff;
+}
+
 static int ocelot_probe(struct udevice *dev)
 {
        struct ocelot_private *priv = dev_get_priv(dev);
-       int ret, i;
+       int i, 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;
 
-       struct {
-               enum ocelot_target id;
-               char *name;
-       } reg[] = {
-               { SYS, "sys" },
-               { REW, "rew" },
-               { QSYS, "qsys" },
-               { ANA, "ana" },
-               { QS, "qs" },
-               { HSIO, "hsio" },
-               { PORT0, "port0" },
-               { PORT1, "port1" },
-               { PORT2, "port2" },
-               { PORT3, "port3" },
-       };
-
-       for (i = 0; i < ARRAY_SIZE(reg); i++) {
-               priv->regs[reg[i].id] = dev_remap_addr_name(dev, reg[i].name);
-               if (!priv->regs[reg[i].id]) {
-                       pr_err
-                           ("Error %d: can't get regs base addresses for %s\n",
-                            ret, reg[i].name);
+       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;
                }
        }
 
-       priv->bus[INTERNAL] = ocelot_mdiobus_init(dev);
+       /* Initialize miim buses */
+       memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
+              OCELOT_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] =
+                               ocelot_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)
+                       add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
+               else
+                       add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
+                                      phandle.args[2]);
+       }
+
        mscc_phy_reset();
 
-       for (i = 0; i < 4; i++) {
-               phy_connect(priv->bus[INTERNAL], i, dev,
-                           PHY_INTERFACE_MODE_NONE);
+       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 && external_bus(priv, i))
+                       board_phy_config(phy);
        }
 
        return 0;
@@ -480,7 +718,7 @@ static int ocelot_remove(struct udevice *dev)
        struct ocelot_private *priv = dev_get_priv(dev);
        int i;
 
-       for (i = 0; i < NUM_PHY; i++) {
+       for (i = 0; i < OCELOT_MIIM_BUS_COUNT; i++) {
                mdio_unregister(priv->bus[i]);
                mdio_free(priv->bus[i]);
        }
diff --git a/drivers/net/mscc_eswitch/serval_switch.c b/drivers/net/mscc_eswitch/serval_switch.c
new file mode 100644 (file)
index 0000000..2559f5d
--- /dev/null
@@ -0,0 +1,703 @@
+// 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"
+#include "mscc_mac_table.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                     (0x2 << 16)
+
+#define ANA_PORT_VLAN_CFG(x)                   (0xc000 + 0x100 * (x))
+#define                ANA_PORT_VLAN_CFG_AWARE_ENA             BIT(20)
+#define                ANA_PORT_VLAN_CFG_POP_CNT(x)            ((x) << 18)
+#define ANA_PORT_PORT_CFG(x)                   (0xc070 + 0x100 * (x))
+#define                ANA_PORT_PORT_CFG_RECV_ENA              BIT(6)
+#define ANA_PGID(x)                            (0x9c00 + 4 * (x))
+
+#define HSIO_ANA_SERDES1G_DES_CFG              0x3c
+#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               0x40
+#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               0x44
+#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              0x48
+#define HSIO_ANA_SERDES1G_COMMON_CFG           0x4c
+#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              0x50
+#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             0x58
+#define HSIO_DIG_SERDES1G_MISC_CFG             0x6c
+#define                HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST             BIT(0)
+#define HSIO_MCB_SERDES1G_CFG                  0x74
+#define                HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT       BIT(31)
+#define                HSIO_MCB_SERDES1G_CFG_ADDR(x)           (x)
+
+#define SYS_FRM_AGING                          0x584
+#define                SYS_FRM_AGING_ENA                       BIT(20)
+#define SYS_SYSTEM_RST_CFG                     0x518
+#define                SYS_SYSTEM_RST_MEM_INIT                 BIT(5)
+#define                SYS_SYSTEM_RST_MEM_ENA                  BIT(6)
+#define                SYS_SYSTEM_RST_CORE_ENA                 BIT(7)
+#define SYS_PORT_MODE(x)                       (0x524 + 0x4 * (x))
+#define                SYS_PORT_MODE_INCL_INJ_HDR(x)           ((x) << 4)
+#define                SYS_PORT_MODE_INCL_XTR_HDR(x)           ((x) << 2)
+#define SYS_PAUSE_CFG(x)                       (0x65c + 0x4 * (x))
+#define                SYS_PAUSE_CFG_PAUSE_ENA                 BIT(0)
+
+#define QSYS_SWITCH_PORT_MODE(x)               (0x15a34 + 0x4 * (x))
+#define                QSYS_SWITCH_PORT_MODE_PORT_ENA          BIT(13)
+#define QSYS_EGR_NO_SHARING                    0x15a9c
+#define QSYS_QMAP                              0x15adc
+
+/* Port registers */
+#define DEV_CLOCK_CFG                          0x0
+#define DEV_CLOCK_CFG_LINK_SPEED_1000                  1
+#define DEV_MAC_ENA_CFG                                0x10
+#define                DEV_MAC_ENA_CFG_RX_ENA                  BIT(4)
+#define                DEV_MAC_ENA_CFG_TX_ENA                  BIT(0)
+#define DEV_MAC_IFG_CFG                                0x24
+#define                DEV_MAC_IFG_CFG_TX_IFG(x)               ((x) << 8)
+#define                DEV_MAC_IFG_CFG_RX_IFG2(x)              ((x) << 4)
+#define                DEV_MAC_IFG_CFG_RX_IFG1(x)              (x)
+#define PCS1G_CFG                              0x3c
+#define                PCS1G_MODE_CFG_SGMII_MODE_ENA           BIT(0)
+#define PCS1G_MODE_CFG                         0x40
+#define PCS1G_SD_CFG                           0x44
+#define PCS1G_ANEG_CFG                         0x48
+#define                PCS1G_ANEG_CFG_ADV_ABILITY(x)           ((x) << 16)
+
+#define QS_XTR_GRP_CFG(x)                      (4 * (x))
+#define                QS_XTR_GRP_CFG_MODE(x)                  ((x) << 2)
+#define                QS_XTR_GRP_CFG_BYTE_SWAP                BIT(0)
+#define QS_INJ_GRP_CFG(x)                      (0x24 + (x) * 4)
+#define                QS_INJ_GRP_CFG_MODE(x)                  ((x) << 2)
+#define                QS_INJ_GRP_CFG_BYTE_SWAP                BIT(0)
+
+#define IFH_INJ_BYPASS         BIT(31)
+#define IFH_TAG_TYPE_C         0
+#define MAC_VID                        1
+#define CPU_PORT               11
+#define INTERNAL_PORT_MSK      0xFF
+#define IFH_LEN                        4
+#define ETH_ALEN               6
+#define PGID_BROADCAST         13
+#define PGID_UNICAST           14
+
+static const char *const regs_names[] = {
+       "port0", "port1", "port2", "port3", "port4", "port5", "port6",
+       "port7", "port8", "port9", "port10",
+       "ana", "qs", "qsys", "rew", "sys", "hsio",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 11
+
+enum serval_ctrl_regs {
+       ANA = MAX_PORT,
+       QS,
+       QSYS,
+       REW,
+       SYS,
+       HSIO,
+};
+
+#define SERVAL_MIIM_BUS_COUNT 2
+
+struct serval_phy_port_t {
+       size_t phy_addr;
+       struct mii_dev *bus;
+       u8 serdes_index;
+       u8 phy_mode;
+};
+
+struct serval_private {
+       void __iomem *regs[REGS_NAMES_COUNT];
+       struct mii_dev *bus[SERVAL_MIIM_BUS_COUNT];
+       struct serval_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 serval_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 const unsigned long serval_regs_ana_table[] = {
+       [MSCC_ANA_TABLES_MACHDATA] = 0x9b34,
+       [MSCC_ANA_TABLES_MACLDATA] = 0x9b38,
+       [MSCC_ANA_TABLES_MACACCESS] = 0x9b3c,
+};
+
+static struct mscc_miim_dev miim[SERVAL_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 *serval_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 serval_cpu_capture_setup(struct serval_private *priv)
+{
+       int i;
+
+       /* map the 8 CPU extraction queues to CPU port 11 */
+       writel(0, priv->regs[QSYS] + QSYS_QMAP);
+
+       for (i = 0; i <= 1; i++) {
+               /*
+                * Do byte-swap and expect status after last data word
+                * Extraction: Mode: manual extraction) | Byte_swap
+                */
+               writel(QS_XTR_GRP_CFG_MODE(1) | QS_XTR_GRP_CFG_BYTE_SWAP,
+                      priv->regs[QS] + QS_XTR_GRP_CFG(i));
+               /*
+                * Injection: Mode: manual extraction | Byte_swap
+                */
+               writel(QS_INJ_GRP_CFG_MODE(1) | QS_INJ_GRP_CFG_BYTE_SWAP,
+                      priv->regs[QS] + QS_INJ_GRP_CFG(i));
+       }
+
+       for (i = 0; i <= 1; i++)
+               /* Enable IFH insertion/parsing on CPU ports */
+               writel(SYS_PORT_MODE_INCL_INJ_HDR(1) |
+                      SYS_PORT_MODE_INCL_XTR_HDR(1),
+                      priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i));
+       /*
+        * Setup the CPU port as VLAN aware to support switching frames
+        * based on tags
+        */
+       writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
+              MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
+
+       /* Disable learning (only RECV_ENA must be set) */
+       writel(ANA_PORT_PORT_CFG_RECV_ENA,
+              priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
+
+       /* Enable switching to/from cpu port */
+       setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(CPU_PORT),
+                    QSYS_SWITCH_PORT_MODE_PORT_ENA);
+
+       /* No pause on CPU port - not needed (off by default) */
+       clrbits_le32(priv->regs[SYS] + SYS_PAUSE_CFG(CPU_PORT),
+                    SYS_PAUSE_CFG_PAUSE_ENA);
+
+       setbits_le32(priv->regs[QSYS] + QSYS_EGR_NO_SHARING, BIT(CPU_PORT));
+}
+
+static void serval_port_init(struct serval_private *priv, int port)
+{
+       void __iomem *regs = priv->regs[port];
+
+       /* Enable PCS */
+       writel(PCS1G_MODE_CFG_SGMII_MODE_ENA, regs + PCS1G_CFG);
+
+       /* Disable Signal Detect */
+       writel(0, regs + PCS1G_SD_CFG);
+
+       /* Enable MAC RX and TX */
+       writel(DEV_MAC_ENA_CFG_RX_ENA | DEV_MAC_ENA_CFG_TX_ENA,
+              regs + DEV_MAC_ENA_CFG);
+
+       /* Clear sgmii_mode_ena */
+       writel(0, regs + PCS1G_MODE_CFG);
+
+       /*
+        * Clear sw_resolve_ena(bit 0) and set adv_ability to
+        * something meaningful just in case
+        */
+       writel(PCS1G_ANEG_CFG_ADV_ABILITY(0x20), regs + PCS1G_ANEG_CFG);
+
+       /* Set MAC IFG Gaps */
+       writel(DEV_MAC_IFG_CFG_TX_IFG(5) | DEV_MAC_IFG_CFG_RX_IFG1(5) |
+              DEV_MAC_IFG_CFG_RX_IFG2(1), regs + DEV_MAC_IFG_CFG);
+
+       /* Set link speed and release all resets */
+       writel(DEV_CLOCK_CFG_LINK_SPEED_1000, regs + DEV_CLOCK_CFG);
+
+       /* Make VLAN aware for CPU traffic */
+       writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
+              MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
+
+       /* Enable the port in the core */
+       setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port),
+                    QSYS_SWITCH_PORT_MODE_PORT_ENA);
+}
+
+static void serdes_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);
+
+       mdelay(100);
+}
+
+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_DFT_CFG0);
+       writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(11) |
+              HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(0) |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
+              HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
+              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_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_COMMON_CFG_IF_MODE |
+              HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE,
+              base + HSIO_ANA_SERDES1G_COMMON_CFG);
+       writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
+              HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(200) |
+              HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
+              base + HSIO_ANA_SERDES1G_PLL_CFG);
+       writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
+              base + HSIO_DIG_SERDES1G_MISC_CFG);
+       serdes_write(base, addr);
+
+       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);
+       serdes_write(base, addr);
+
+       writel(0x0, base + HSIO_DIG_SERDES1G_MISC_CFG);
+       serdes_write(base, addr);
+}
+
+static void serdes_setup(struct serval_private *priv)
+{
+       size_t mask;
+       int i = 0;
+
+       for (i = 0; i < MAX_PORT; ++i) {
+               if (!priv->ports[i].bus)
+                       continue;
+
+               mask = BIT(priv->ports[i].serdes_index);
+               serdes1g_setup(priv->regs[HSIO], mask,
+                              priv->ports[i].phy_mode);
+       }
+}
+
+static int serval_switch_init(struct serval_private *priv)
+{
+       /* Reset switch & memories */
+       writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
+              priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
+
+       if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
+                             SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
+               pr_err("Timeout in memory reset\n");
+               return -EIO;
+       }
+
+       /* Enable switch core */
+       setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
+                    SYS_SYSTEM_RST_CORE_ENA);
+
+       serdes_setup(priv);
+
+       return 0;
+}
+
+static int serval_initialize(struct serval_private *priv)
+{
+       int ret, i;
+
+       /* Initialize switch memories, enable core */
+       ret = serval_switch_init(priv);
+       if (ret)
+               return ret;
+
+       /* Flush queues */
+       mscc_flush(priv->regs[QS], serval_regs_qs);
+
+       /* Setup frame ageing - "2 sec" - The unit is 6.5us on serval */
+       writel(SYS_FRM_AGING_ENA | (20000000 / 65),
+              priv->regs[SYS] + SYS_FRM_AGING);
+
+       for (i = 0; i < MAX_PORT; i++)
+               serval_port_init(priv, i);
+
+       serval_cpu_capture_setup(priv);
+
+       debug("Ports enabled\n");
+
+       return 0;
+}
+
+static int serval_write_hwaddr(struct udevice *dev)
+{
+       struct serval_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+
+       mscc_mac_table_add(priv->regs[ANA], serval_regs_ana_table,
+                          pdata->enetaddr, PGID_UNICAST);
+
+       writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
+
+       return 0;
+}
+
+static int serval_start(struct udevice *dev)
+{
+       struct serval_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 = serval_initialize(priv);
+       if (ret)
+               return ret;
+
+       /* Set MAC address tables entries for CPU redirection */
+       mscc_mac_table_add(priv->regs[ANA], serval_regs_ana_table, mac,
+                          PGID_BROADCAST);
+
+       writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
+              priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
+
+       /* It should be setup latter in serval_write_hwaddr */
+       mscc_mac_table_add(priv->regs[ANA], serval_regs_ana_table,
+                          pdata->enetaddr, PGID_UNICAST);
+
+       writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
+       return 0;
+}
+
+static void serval_stop(struct udevice *dev)
+{
+       writel(ICPU_RESET_CORE_RST_PROTECT, BASE_CFG + ICPU_RESET);
+       writel(PERF_SOFT_RST_SOFT_CHIP_RST, BASE_DEVCPU_GCB + PERF_SOFT_RST);
+}
+
+static int serval_send(struct udevice *dev, void *packet, int length)
+{
+       struct serval_private *priv = dev_get_priv(dev);
+       u32 ifh[IFH_LEN];
+       u32 *buf = packet;
+
+       /*
+        * Generate the IFH for frame injection
+        *
+        * The IFH is a 128bit-value
+        * bit 127: bypass the analyzer processing
+        * bit 57-67: destination mask
+        * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
+        * bit 20-27: cpu extraction queue mask
+        * bit 16: tag type 0: C-tag, 1: S-tag
+        * bit 0-11: VID
+        */
+       ifh[0] = IFH_INJ_BYPASS;
+       ifh[1] = (0x07);
+       ifh[2] = (0x7f) << 25;
+       ifh[3] = (IFH_TAG_TYPE_C << 16);
+
+       return mscc_send(priv->regs[QS], serval_regs_qs,
+                        ifh, IFH_LEN, buf, length);
+}
+
+static int serval_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct serval_private *priv = dev_get_priv(dev);
+       u32 *rxbuf = (u32 *)net_rx_packets[0];
+       int byte_cnt = 0;
+
+       byte_cnt = mscc_recv(priv->regs[QS], serval_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 < SERVAL_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 serval_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 serval_probe(struct udevice *dev)
+{
+       struct serval_private *priv = dev_get_priv(dev);
+       int i, 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(miim) * SERVAL_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] =
+                               serval_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 serval_remove(struct udevice *dev)
+{
+       struct serval_private *priv = dev_get_priv(dev);
+       int i;
+
+       for (i = 0; i < SERVAL_MIIM_BUS_COUNT; i++) {
+               mdio_unregister(priv->bus[i]);
+               mdio_free(priv->bus[i]);
+       }
+
+       return 0;
+}
+
+static const struct eth_ops serval_ops = {
+       .start        = serval_start,
+       .stop         = serval_stop,
+       .send         = serval_send,
+       .recv         = serval_recv,
+       .write_hwaddr = serval_write_hwaddr,
+};
+
+static const struct udevice_id mscc_serval_ids[] = {
+       {.compatible = "mscc,vsc7418-switch"},
+       { /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(serval) = {
+       .name                           = "serval-switch",
+       .id                             = UCLASS_ETH,
+       .of_match                       = mscc_serval_ids,
+       .probe                          = serval_probe,
+       .remove                         = serval_remove,
+       .ops                            = &serval_ops,
+       .priv_auto_alloc_size           = sizeof(struct serval_private),
+       .platdata_auto_alloc_size       = sizeof(struct eth_pdata),
+};
index fb794adae725d8e1736dedd2ed5c35d31a39b610..2830f765877bbc9ca49f330923f051528178fffc 100644 (file)
@@ -133,7 +133,7 @@ config MPC8XX_SPI
 
 config MT7621_SPI
        bool "MediaTek MT7621 SPI driver"
-       depends on ARCH_MT7620
+       depends on SOC_MT7628
        help
          Enable the MT7621 SPI driver. This driver can be used to access
          the SPI NOR flash on platforms embedding this Ralink / MediaTek
index 16d47b88858ed2ac31b316ef7e2ad22ee655a509..f909d40f45588e27af74f626770268458fafc165 100644 (file)
@@ -143,7 +143,7 @@ config WDT_AT91
 
 config WDT_MT7621
        bool "MediaTek MT7621 watchdog timer support"
-       depends on WDT && ARCH_MT7620
+       depends on WDT && SOC_MT7628
        help
           Select this to enable Ralink / Mediatek watchdog timer,
           which can be found on some MediaTek chips.
diff --git a/include/dt-bindings/mscc/luton_data.h b/include/dt-bindings/mscc/luton_data.h
new file mode 100644 (file)
index 0000000..e488567
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Microsemi Corporation
+ */
+
+#ifndef _LUTON_DATA_H_
+#define _LUTON_DATA_H_
+
+#define SERDES6G(x)     (x)
+#define SERDES6G_MAX    SERDES6G(5)
+#define SERDES_MAX      (SERDES6G_MAX)
+
+/* similar with phy_interface_t */
+#define PHY_MODE_SGMII  2
+#define PHY_MODE_QSGMII 4
+
+#endif
diff --git a/include/dt-bindings/mscc/ocelot_data.h b/include/dt-bindings/mscc/ocelot_data.h
new file mode 100644 (file)
index 0000000..7a5a1bf
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Microsemi Corporation
+ */
+
+#ifndef _OCELOT_DATA_H_
+#define _OCELOT_DATA_H_
+
+#define SERDES1G(x)     (x)
+#define SERDES1G_MAX    SERDES1G(7)
+#define SERDES6G(x)     (SERDES1G_MAX + 1 + (x))
+#define SERDES6G_MAX    SERDES6G(11)
+#define SERDES_MAX      (SERDES6G_MAX + 1)
+
+/* similar with phy_interface_t */
+#define PHY_MODE_SGMII  2
+#define PHY_MODE_QSGMII 4
+
+#endif
diff --git a/include/dt-bindings/mscc/serval_data.h b/include/dt-bindings/mscc/serval_data.h
new file mode 100644 (file)
index 0000000..b374fda
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _SERVAL_DATA_H_
+#define _SERVAL_DATA_H_
+
+#define SERDES1G(x)     (x)
+#define SERDES1G_MAX    SERDES1G(9)
+#define SERDES6G(x)     (SERDES1G_MAX + 1 + (x))
+#define SERDES6G_MAX    SERDES6G(11)
+#define SERDES_MAX      (SERDES6G_MAX + 1)
+
+/* similar with phy_interface_t */
+#define PHY_MODE_SGMII  2
+#define PHY_MODE_QSGMII 4
+
+#endif