]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
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

44 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-mtmips/Kconfig [moved from arch/mips/mach-mt7620/Kconfig with 93% similarity]
arch/mips/mach-mtmips/Makefile [moved from arch/mips/mach-mt7620/Makefile with 100% similarity]
arch/mips/mach-mtmips/cpu.c [moved from arch/mips/mach-mt7620/cpu.c with 100% similarity]
arch/mips/mach-mtmips/ddr_calibrate.c [moved from arch/mips/mach-mt7620/ddr_calibrate.c with 100% similarity]
arch/mips/mach-mtmips/lowlevel_init.S [moved from arch/mips/mach-mt7620/lowlevel_init.S with 100% similarity]
arch/mips/mach-mtmips/mt76xx.h [moved from arch/mips/mach-mt7620/mt76xx.h with 100% similarity]
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 */
similarity index 93%
rename from arch/mips/mach-mt7620/Kconfig
rename to arch/mips/mach-mtmips/Kconfig
index a9834439993de448bd132a8edade956fe0ea9885..4af2d545288aed64da2ef0f0d3d403e52e479eab 100644 (file)
@@ -1,20 +1,20 @@
 menu "MediaTek MIPS platforms"
-       depends on ARCH_MT7620
+       depends on ARCH_MTMIPS
 
 config SYS_MALLOC_F_LEN
        default 0x1000
 
 config SYS_SOC
-       default "mt7620" if SOC_MT7620
+       default "mt7628" if SOC_MT7628
 
 choice
        prompt "MediaTek MIPS SoC select"
 
-config SOC_MT7620
-       bool "MT7620/8"
+config SOC_MT7628
+       bool "MT7628"
        select MIPS_L1_CACHE_SHIFT_5
        help
-         This supports MediaTek MIPS MT7620 family.
+         This supports MediaTek MT7628/MT7688.
 
 endchoice
 
@@ -23,7 +23,7 @@ choice
 
 config BOARD_GARDENA_SMART_GATEWAY_MT7688
        bool "GARDENA smart Gateway"
-       depends on SOC_MT7620
+       depends on SOC_MT7628
        select BOARD_LATE_INIT
        select SUPPORTS_BOOT_RAM
        help
@@ -32,7 +32,7 @@ config BOARD_GARDENA_SMART_GATEWAY_MT7688
 
 config BOARD_LINKIT_SMART_7688
        bool "LinkIt Smart 7688"
-       depends on SOC_MT7620
+       depends on SOC_MT7628
        select SUPPORTS_BOOT_RAM
        help
          Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
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