mediatek: add v4.19 support
authorJohn Crispin <john@phrozen.org>
Fri, 2 Aug 2019 08:33:28 +0000 (10:33 +0200)
committerJohn Crispin <john@phrozen.org>
Fri, 2 Aug 2019 08:36:11 +0000 (10:36 +0200)
Bump the target to v4.19. Add a patch with additional eth driver
fixes/features that MTK provided aswell as the driver for the new mt7530
switch.

Signed-off-by: John Crispin <john@phrozen.org>
35 files changed:
target/linux/mediatek/base-files/etc/hotplug.d/iface/99-mtk-lro [new file with mode: 0755]
target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-lynx-rfb.dts [new file with mode: 0755]
target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-rfb.dts [new file with mode: 0755]
target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629.dtsi [new file with mode: 0755]
target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/a.patch [new file with mode: 0644]
target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts [new file with mode: 0644]
target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-lynx-rfb1.dts [new file with mode: 0755]
target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts [new file with mode: 0755]
target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622.dtsi [new file with mode: 0755]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h [new file with mode: 0644]
target/linux/mediatek/image/mt7622.mk
target/linux/mediatek/mt7622/config-4.19 [new file with mode: 0755]
target/linux/mediatek/patches-4.19/0001-arm-dts-mediatek-add-basic-support-for-MT7629-SoC.patch [new file with mode: 0755]
target/linux/mediatek/patches-4.19/0001-eth-sync-from-mtk-lede.patch [new file with mode: 0644]
target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch [new file with mode: 0644]
target/linux/mediatek/patches-4.19/0003-switch-add-mt7531.patch [new file with mode: 0644]
target/linux/mediatek/patches-4.19/0227-arm-dts-Add-Unielec-U7623-DTS.patch [new file with mode: 0644]
target/linux/mediatek/patches-4.19/0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch [new file with mode: 0755]
target/linux/mediatek/patches-4.19/0303-mtd-spinand-disable-on-die-ECC.patch [new file with mode: 0755]
target/linux/mediatek/patches-4.19/0304-dt-bindings-ARM-MediaTek-Document-devicetree-binding.patch [new file with mode: 0755]
target/linux/mediatek/patches-4.19/0306-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch [new file with mode: 0644]
target/linux/mediatek/patches-4.19/0900-bt-mtk-serial-fix.patch [new file with mode: 0755]

diff --git a/target/linux/mediatek/base-files/etc/hotplug.d/iface/99-mtk-lro b/target/linux/mediatek/base-files/etc/hotplug.d/iface/99-mtk-lro
new file mode 100755 (executable)
index 0000000..9a2ffae
--- /dev/null
@@ -0,0 +1,14 @@
+[ ifup = "$ACTION" ] && {
+       [ -n "$DEVICE" ] && {
+               if [ "$INTERFACE" == "lan" ]; then
+                       if [ -f /usr/sbin/ethtool ]; then
+                               ifname=eth0
+                               lan_ip=`uci -q get network.lan.ipaddr`
+                               ethdrv=`ethtool -i $ifname | grep mtk_soc_eth`
+                               [ -n "$ethdrv" ] && {
+                                       ethtool -N $ifname flow-type tcp4 dst-ip $lan_ip loc 0
+                               }
+                       fi
+               fi
+       }
+}
diff --git a/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-lynx-rfb.dts b/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-lynx-rfb.dts
new file mode 100755 (executable)
index 0000000..f3fadd3
--- /dev/null
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "mt7629.dtsi"
+
+/ {
+       model = "MediaTek MT7629 reference board";
+       compatible = "mediatek,mt7629-rfb", "mediatek,mt7629";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               reset {
+                       label = "factory";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&pio 60 GPIO_ACTIVE_LOW>;
+               };
+
+               wps {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&pio 58 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gsw: gsw@0 {
+               compatible = "mediatek,mt753x";
+               mediatek,ethsys = <&ethsys>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       memory@40000000 {
+               device_type = "memory";
+               reg = <0 0x40000000 0 0x10000000>;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_5v: regulator-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
+
+&eth {
+        pinctrl-names = "default";
+        pinctrl-0 = <&ephy_leds_pins>;
+        status = "okay";
+
+        gmac0: mac@0 {
+                compatible = "mediatek,eth-mac";
+                reg = <0>;
+                phy-mode = "sgmii";
+                fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                };
+        };
+
+        gmac1: mac@1 {
+                compatible = "mediatek,eth-mac";
+                reg = <1>;
+                phy-handle = <&phy0>;
+        };
+
+        mdio: mdio-bus {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                phy0: ethernet-phy@0 {
+                        reg = <0>;
+                        phy-mode = "gmii";
+                };
+        };
+};
+
+&gsw {
+       mediatek,mdio = <&mdio>;
+       mediatek,portmap = "llllw";
+       mediatek,mdio_master_pinmux = <0>;
+       reset-gpios = <&pio 28 0>;
+       interrupt-parent = <&pio>;
+       interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
+       status = "okay";
+
+       port6: port@6 {
+               compatible = "mediatek,mt753x-port";
+               reg = <6>;
+               phy-mode = "sgmii";
+               fixed-link {
+                       speed = <2500>;
+                       full-duplex;
+               };
+       };
+};
+
+&i2c {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c_pins>;
+       status = "okay";
+};
+
+&qspi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&qspi_pins>;
+       status = "okay";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0x00000 0x60000>;
+                               read-only;
+                       };
+
+                       partition@60000 {
+                               label = "u-boot-env";
+                               reg = <0x60000 0x10000>;
+                               read-only;
+                       };
+
+                       factory: partition@70000 {
+                               label = "Factory";
+                               reg = <0x70000 0x40000>;
+                               read-only;
+                       };
+
+                       partition@b0000 {
+                               label = "Kernel";
+                               reg = <0xb0000 0xb50000>;
+                       };
+               };
+       };
+};
+
+&pio {
+       eth_pins: eth-pins {
+               mux {
+                       function = "eth";
+                       groups = "mdc_mdio";
+               };
+       };
+
+       ephy_leds_pins: ephy-leds-pins {
+               mux {
+                       function = "led";
+                       groups = "gphy_leds_0", "ephy_leds";
+               };
+       };
+
+       i2c_pins: i2c-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c_0";
+               };
+
+               conf {
+                       pins = "I2C_SDA", "I2C_SCL";
+                       drive-strength = <4>;
+                       bias-disable;
+               };
+       };
+
+       pcie_pins: pcie-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie_clkreq",
+                                "pcie_pereset",
+                                "pcie_wake";
+               };
+       };
+
+       pwm_pins: pwm-pins {
+               mux {
+                       function = "pwm";
+                       groups = "pwm_0";
+               };
+       };
+
+       /* Serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       spi_pins: spi-pins {
+               mux {
+                       function = "spi";
+                       groups = "spi_0";
+               };
+       };
+
+       /* SPI-NOR is shared pin with serial NAND */
+       qspi_pins: qspi-pins {
+               mux {
+                       function = "flash";
+                       groups = "spi_nor";
+               };
+       };
+
+       uart0_pins: uart0-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart0_txd_rxd" ;
+               };
+       };
+
+       uart1_pins: uart1-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart1_0_tx_rx" ;
+               };
+       };
+
+       uart2_pins: uart2-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart2_0_txd_rxd" ;
+               };
+       };
+
+       watchdog_pins: watchdog-pins {
+               mux {
+                       function = "watchdog";
+                       groups = "watchdog";
+               };
+       };
+
+       wmac0_pins: wmac0-pins {
+               mux {
+                       function = "wifi";
+                       groups = "wf0_5g";
+                       drive-strength = <4>;
+               };
+       };
+
+       wmac1_pins: wmac0-pins {
+               mux {
+                       function = "wifi";
+                       groups = "wf0_2g";
+                       drive-strength = <4>;
+               };
+       };
+};
+
+&spi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_pins>;
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+       status = "okay";
+};
+
+&ssusb {
+       vusb33-supply = <&reg_3p3v>;
+       vbus-supply = <&reg_5v>;
+       status = "okay";
+};
+
+&u3phy1 {
+       status = "okay";
+};
+
+&watchdog {
+       pinctrl-names = "default";
+       pinctrl-0 = <&watchdog_pins>;
+       status = "okay";
+};
+
+&wmac {
+       pinctrl-names = "default";
+       pinctrl-0 = <&wmac0_pins>;
+       pinctrl-1 = <&wmac1_pins>;
+       status = "okay";
+};
diff --git a/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-rfb.dts b/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-rfb.dts
new file mode 100755 (executable)
index 0000000..8043238
--- /dev/null
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "mt7629.dtsi"
+
+/ {
+       model = "MediaTek MT7629 reference board";
+       compatible = "mediatek,mt7629-rfb", "mediatek,mt7629";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               reset {
+                       label = "factory";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&pio 60 GPIO_ACTIVE_LOW>;
+               };
+
+               wps {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&pio 58 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       memory@40000000 {
+               device_type = "memory";
+               reg = <0 0x40000000 0 0x10000000>;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_5v: regulator-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+        rtkgsw: rtkgsw@0 {
+                compatible = "mediatek,rtk-gsw";
+                mediatek,ethsys = <&ethsys>;
+               mediatek,mdio = <&mdio>;
+                status = "okay";
+        };
+};
+
+&eth {
+        pinctrl-names = "default";
+        pinctrl-0 = <&ephy_leds_pins>;
+        status = "okay";
+
+        gmac0: mac@0 {
+                compatible = "mediatek,eth-mac";
+                reg = <0>;
+                phy-mode = "sgmii";
+                fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                };
+        };
+
+        gmac1: mac@1 {
+                compatible = "mediatek,eth-mac";
+                reg = <1>;
+                phy-handle = <&phy0>;
+        };
+
+        mdio: mdio-bus {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                phy0: ethernet-phy@0 {
+                        reg = <0>;
+                        phy-mode = "gmii";
+                };
+        };
+};
+
+&i2c {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c_pins>;
+       status = "okay";
+};
+
+&qspi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&qspi_pins>;
+       status = "okay";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0x00000 0x60000>;
+                               read-only;
+                       };
+
+                       partition@60000 {
+                               label = "u-boot-env";
+                               reg = <0x60000 0x10000>;
+                               read-only;
+                       };
+
+                       factory: partition@70000 {
+                               label = "Factory";
+                               reg = <0x70000 0x40000>;
+                               read-only;
+                       };
+
+                       partition@b0000 {
+                               label = "Kernel";
+                               reg = <0xb0000 0xb50000>;
+                       };
+               };
+       };
+};
+
+&pio {
+       eth_pins: eth-pins {
+               mux {
+                       function = "eth";
+                       groups = "mdc_mdio";
+               };
+       };
+
+       ephy_leds_pins: ephy-leds-pins {
+               mux {
+                       function = "led";
+                       groups = "gphy_leds_0", "ephy_leds";
+               };
+       };
+
+       i2c_pins: i2c-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c_0";
+               };
+
+               conf {
+                       pins = "I2C_SDA", "I2C_SCL";
+                       drive-strength = <4>;
+                       bias-disable;
+               };
+       };
+
+       pcie_pins: pcie-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie_clkreq",
+                                "pcie_pereset",
+                                "pcie_wake";
+               };
+       };
+
+       pwm_pins: pwm-pins {
+               mux {
+                       function = "pwm";
+                       groups = "pwm_0";
+               };
+       };
+
+       /* Serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       spi_pins: spi-pins {
+               mux {
+                       function = "spi";
+                       groups = "spi_0";
+               };
+       };
+
+       /* SPI-NOR is shared pin with serial NAND */
+       qspi_pins: qspi-pins {
+               mux {
+                       function = "flash";
+                       groups = "spi_nor";
+               };
+       };
+
+       uart0_pins: uart0-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart0_txd_rxd" ;
+               };
+       };
+
+       uart1_pins: uart1-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart1_0_tx_rx" ;
+               };
+       };
+
+       uart2_pins: uart2-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart2_0_txd_rxd" ;
+               };
+       };
+
+       watchdog_pins: watchdog-pins {
+               mux {
+                       function = "watchdog";
+                       groups = "watchdog";
+               };
+       };
+
+       wmac0_pins: wmac0-pins {
+               mux {
+                       function = "wifi";
+                       groups = "wf0_5g";
+                       drive-strength = <4>;
+               };
+       };
+
+       wmac1_pins: wmac0-pins {
+               mux {
+                       function = "wifi";
+                       groups = "wf0_2g";
+                       drive-strength = <4>;
+               };
+       };
+};
+
+&spi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_pins>;
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+       status = "okay";
+};
+
+&ssusb {
+       vusb33-supply = <&reg_3p3v>;
+       vbus-supply = <&reg_5v>;
+       status = "okay";
+};
+
+&u3phy1 {
+       status = "okay";
+};
+
+&watchdog {
+       pinctrl-names = "default";
+       pinctrl-0 = <&watchdog_pins>;
+       status = "okay";
+};
+
+&wmac {
+       pinctrl-names = "default";
+       pinctrl-0 = <&wmac0_pins>;
+       pinctrl-1 = <&wmac1_pins>;
+       status = "okay";
+};
diff --git a/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629.dtsi b/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629.dtsi
new file mode 100755 (executable)
index 0000000..53f4779
--- /dev/null
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ *
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/mt7629-clk.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/reset/mt7629-resets.h>
+
+/ {
+       compatible = "mediatek,mt7629";
+       interrupt-parent = <&sysirq>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               enable-method = "mediatek,mt6589-smp";
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x0>;
+                       clock-frequency = <1250000000>;
+                       cci-control-port = <&cci_control2>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x1>;
+                       clock-frequency = <1250000000>;
+                       cci-control-port = <&cci_control2>;
+               };
+       };
+
+       pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 9 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-affinity = <&cpu0>, <&cpu1>;
+       };
+
+       clk20m: oscillator-0 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <20000000>;
+               clock-output-names = "clk20m";
+       };
+
+       clk40m: oscillator-1 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <40000000>;
+               clock-output-names = "clkxtal";
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clock-frequency = <20000000>;
+               arm,cpu-registers-not-fw-configured;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               infracfg: syscon@10000000 {
+                       compatible = "mediatek,mt7629-infracfg", "syscon";
+                       reg = <0x10000000 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               pericfg: syscon@10002000 {
+                       compatible = "mediatek,mt7629-pericfg", "syscon";
+                       reg = <0x10002000 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               scpsys: scpsys@10006000 {
+                       compatible = "mediatek,mt7629-scpsys",
+                                    "mediatek,mt7622-scpsys";
+                       #power-domain-cells = <1>;
+                       reg = <0x10006000 0x1000>;
+                       clocks = <&topckgen CLK_TOP_HIF_SEL>;
+                       clock-names = "hif_sel";
+                       assigned-clocks = <&topckgen CLK_TOP_HIF_SEL>;
+                       assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>;
+                       infracfg = <&infracfg>;
+               };
+
+               timer: timer@10009000 {
+                       compatible = "mediatek,mt7629-timer",
+                                    "mediatek,mt6765-timer";
+                       reg = <0x10009000 0x60>;
+                       interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk20m>;
+                       clock-names = "clk20m";
+               };
+
+               sysirq: interrupt-controller@10200a80 {
+                       compatible = "mediatek,mt7629-sysirq",
+                                    "mediatek,mt6577-sysirq";
+                       reg = <0x10200a80 0x20>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       interrupt-parent = <&gic>;
+               };
+
+               apmixedsys: syscon@10209000 {
+                       compatible = "mediatek,mt7629-apmixedsys", "syscon";
+                       reg = <0x10209000 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               rng: rng@1020f000 {
+                       compatible = "mediatek,mt7629-rng",
+                                    "mediatek,mt7623-rng";
+                       reg = <0x1020f000 0x100>;
+                       clocks = <&infracfg CLK_INFRA_TRNG_PD>;
+                       clock-names = "rng";
+               };
+
+               topckgen: syscon@10210000 {
+                       compatible = "mediatek,mt7629-topckgen", "syscon";
+                       reg = <0x10210000 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               watchdog: watchdog@10212000 {
+                       compatible = "mediatek,mt7629-wdt",
+                                    "mediatek,mt6589-wdt";
+                       reg = <0x10212000 0x100>;
+               };
+
+               pio: pinctrl@10217000 {
+                       compatible = "mediatek,mt7629-pinctrl";
+                       reg = <0x10217000 0x8000>,
+                             <0x10005000 0x1000>;
+                       reg-names = "base", "eint";
+                       gpio-controller;
+                       gpio-ranges = <&pio 0 0 79>;
+                       #gpio-cells = <2>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-parent = <&gic>;
+               };
+
+               gic: interrupt-controller@10300000 {
+                       compatible = "arm,gic-400";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       interrupt-parent = <&gic>;
+                       reg = <0x10310000 0x1000>,
+                             <0x10320000 0x1000>,
+                             <0x10340000 0x2000>,
+                             <0x10360000 0x2000>;
+               };
+
+               cci: cci@10390000 {
+                       compatible = "arm,cci-400";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x10390000 0x1000>;
+                       ranges = <0 0x10390000 0x10000>;
+
+                       cci_control0: slave-if@1000 {
+                               compatible = "arm,cci-400-ctrl-if";
+                               interface-type = "ace-lite";
+                               reg = <0x1000 0x1000>;
+                       };
+
+                       cci_control1: slave-if@4000 {
+                               compatible = "arm,cci-400-ctrl-if";
+                               interface-type = "ace";
+                               reg = <0x4000 0x1000>;
+                       };
+
+                       cci_control2: slave-if@5000 {
+                               compatible = "arm,cci-400-ctrl-if";
+                               interface-type = "ace";
+                               reg = <0x5000 0x1000>;
+                       };
+
+                       pmu@9000 {
+                               compatible = "arm,cci-400-pmu,r1";
+                               reg = <0x9000 0x5000>;
+                               interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               uart0: serial@11002000 {
+                       compatible = "mediatek,mt7629-uart",
+                                    "mediatek,mt6577-uart";
+                       reg = <0x11002000 0x400>;
+                       interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&topckgen CLK_TOP_UART_SEL>,
+                                <&pericfg CLK_PERI_UART0_PD>;
+                       clock-names = "baud", "bus";
+                       status = "disabled";
+               };
+
+               uart1: serial@11003000 {
+                       compatible = "mediatek,mt7629-uart",
+                                    "mediatek,mt6577-uart";
+                       reg = <0x11003000 0x400>;
+                       interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&topckgen CLK_TOP_UART_SEL>,
+                                <&pericfg CLK_PERI_UART1_PD>;
+                       clock-names = "baud", "bus";
+                       status = "disabled";
+               };
+
+               uart2: serial@11004000 {
+                       compatible = "mediatek,mt7629-uart",
+                                    "mediatek,mt6577-uart";
+                       reg = <0x11004000 0x400>;
+                       interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&topckgen CLK_TOP_UART_SEL>,
+                                <&pericfg CLK_PERI_UART2_PD>;
+                       clock-names = "baud", "bus";
+                       status = "disabled";
+               };
+
+               i2c: i2c@11007000 {
+                       compatible = "mediatek,mt7629-i2c",
+                                    "mediatek,mt2712-i2c";
+                       reg = <0x11007000 0x90>,
+                             <0x11000100 0x80>;
+                       interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>;
+                       clock-div = <4>;
+                       clocks = <&pericfg CLK_PERI_I2C0_PD>,
+                                <&pericfg CLK_PERI_AP_DMA_PD>;
+                       clock-names = "main", "dma";
+                       assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
+                       assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               spi: spi@1100a000 {
+                       compatible = "mediatek,mt7629-spi",
+                                    "mediatek,mt7622-spi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x1100a000 0x100>;
+                       interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+                                <&topckgen CLK_TOP_SPI0_SEL>,
+                                <&pericfg CLK_PERI_SPI0_PD>;
+                       clock-names = "parent-clk", "sel-clk", "spi-clk";
+                       status = "disabled";
+               };
+
+               qspi: spi@11014000 {
+                       compatible = "mediatek,mt7629-nor",
+                                    "mediatek,mt8173-nor";
+                       reg = <0x11014000 0xe0>;
+                       clocks = <&pericfg CLK_PERI_FLASH_PD>,
+                                <&topckgen CLK_TOP_FLASH_SEL>;
+                       clock-names = "spi", "sf";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               wmac: wmac@18000000 {
+                       compatible = "mediatek,mt7629-wmac";
+                       reg = <0x18000000 0x100000>;
+                       interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>,
+                                    <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>;
+                       mediatek,mtd-eeprom = <&factory 0x0000>;
+                       status = "disabled";
+               };
+
+               ssusbsys: syscon@1a000000 {
+                       compatible = "mediatek,mt7629-ssusbsys", "syscon";
+                       reg = <0x1a000000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               ssusb: usb@1a0c0000 {
+                       compatible = "mediatek,mt7629-xhci",
+                                    "mediatek,mtk-xhci";
+                       reg = <0x1a0c0000 0x01000>,
+                             <0x1a0c3e00 0x0100>;
+                       reg-names = "mac", "ippc";
+                       interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&ssusbsys CLK_SSUSB_SYS_EN>,
+                                <&ssusbsys CLK_SSUSB_REF_EN>,
+                                <&ssusbsys CLK_SSUSB_MCU_EN>,
+                                <&ssusbsys CLK_SSUSB_DMA_EN>;
+                       clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck";
+                       assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>,
+                                         <&topckgen CLK_TOP_SATA_SEL>,
+                                         <&topckgen CLK_TOP_HIF_SEL>;
+                       assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>,
+                                                <&topckgen CLK_TOP_UNIVPLL2_D4>,
+                                                <&topckgen CLK_TOP_UNIVPLL1_D2>;
+                       power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>;
+                       phys = <&u2port0 PHY_TYPE_USB2>,
+                              <&u3port0 PHY_TYPE_USB3>;
+                       status = "disabled";
+               };
+
+               u3phy1: usb-phy@1a0c4000 {
+                       compatible = "mediatek,generic-tphy-v2";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+                       status = "disabled";
+
+                       u2port0: usb-phy@1a0c4000 {
+                               reg = <0x1a0c4000 0x700>;
+                               clocks = <&ssusbsys CLK_SSUSB_U2_PHY_EN>;
+                               clock-names = "ref";
+                               #phy-cells = <1>;
+                               status = "okay";
+                       };
+
+                       u3port0: usb-phy@1a1c4700 {
+                               reg = <0x1a1c4700 0x700>;
+                               clocks = <&clk20m>;
+                               clock-names = "ref";
+                               #phy-cells = <1>;
+                               status = "okay";
+                       };
+               };
+
+               pciesys: syscon@1a100800 {
+                       compatible = "mediatek,mt7629-pciesys", "syscon";
+                       reg = <0x1a100800 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               ethsys: syscon@1b000000 {
+                       compatible = "mediatek,mt7629-ethsys", "syscon";
+                       reg = <0x1b000000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               eth: ethernet@1b100000 {
+                compatible = "mediatek,mt7629-eth",
+                                "syscon";
+                reg = <0x1b100000 0x20000>;
+                interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
+                             <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
+                             <GIC_SPI 225 IRQ_TYPE_LEVEL_LOW>;
+                clocks = <&topckgen CLK_TOP_ETH_SEL>,
+                         <&topckgen CLK_TOP_F10M_REF_SEL>,
+                         <&ethsys CLK_ETH_ESW_EN>,
+                         <&ethsys CLK_ETH_GP0_EN>,
+                         <&ethsys CLK_ETH_GP1_EN>,
+                         <&ethsys CLK_ETH_GP2_EN>,
+                         <&ethsys CLK_ETH_FE_EN>,
+                         <&sgmiisys0 CLK_SGMII_TX_EN>,
+                         <&sgmiisys0 CLK_SGMII_RX_EN>,
+                         <&sgmiisys0 CLK_SGMII_CDR_REF>,
+                         <&sgmiisys0 CLK_SGMII_CDR_FB>,
+                         <&sgmiisys1 CLK_SGMII_TX_EN>,
+                         <&sgmiisys1 CLK_SGMII_RX_EN>,
+                         <&sgmiisys1 CLK_SGMII_CDR_REF>,
+                         <&sgmiisys1 CLK_SGMII_CDR_FB>,
+                         <&apmixedsys CLK_APMIXED_SGMIPLL>,
+                         <&apmixedsys CLK_APMIXED_ETH2PLL>;
+                clock-names = "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2",
+                              "fe", "sgmii_tx250m", "sgmii_rx250m",
+                              "sgmii_cdr_ref", "sgmii_cdr_fb",
+                              "sgmii2_tx250m", "sgmii2_rx250m",
+                              "sgmii2_cdr_ref", "sgmii2_cdr_fb",
+                              "sgmii_ck", "eth2pll";
+                assigned-clocks = <&topckgen CLK_TOP_ETH_SEL>,
+                                  <&topckgen CLK_TOP_F10M_REF_SEL>;
+                assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>,
+                                         <&topckgen CLK_TOP_SGMIIPLL_D2>;
+                power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+                mediatek,ethsys = <&ethsys>;
+                mediatek,sgmiisys = <&sgmiisys0>,<&sgmiisys1>;
+                mediatek,infracfg = <&infracfg>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+                status = "disabled";
+               };
+
+               sgmiisys0: syscon@1b128000 {
+                       compatible = "mediatek,mt7629-sgmiisys", "syscon";
+                       reg = <0x1b128000 0x3000>;
+                       #clock-cells = <1>;
+                       mediatek,physpeed = "2500";
+               };
+
+               sgmiisys1: syscon@1b130000 {
+                       compatible = "mediatek,mt7629-sgmiisys", "syscon";
+                       reg = <0x1b130000 0x3000>;
+                       #clock-cells = <1>;
+                       mediatek,physpeed = "2500";
+               };
+       };
+};
diff --git a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/a.patch b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/a.patch
new file mode 100644 (file)
index 0000000..7312b47
--- /dev/null
@@ -0,0 +1,19 @@
+\e[?25l\e[J\e[J\e[J\e[J\e[J\e[J\e[?2004h\e[?25h\e[?1049h\e[22;0;0t\e[?1h\e=\e[?2004h\e[1;76r\e[?12h\e[?12l\e[22;2t\e[22;1t\e[27m\e[23m\e[29m\e[m\e[H\e[2J\e[?25l\e[76;1H"mt7622-lynx-rfb1.dts" 605L, 11203C\e[1;1H/*\r
+ * Copyright (c) 2017 MediaTek Inc.\r
+ * Author: Ming Huang <ming.huang@mediatek.com>\r
+ *\e[9CSean Wang <sean.wang@mediatek.com>\r
+ *\r
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)\r
+ */\r
+\r
+/dts-v1/;\r
+#include <dt-bindings/input/input.h>\r
+#include <dt-bindings/gpio/gpio.h>\r
+\r
+#include "mt7622.dtsi"\r
+#include "mt6380.dtsi"\r
+\r
+/ {\e[17;9Hmodel = "MediaTek MT7622 RFB1 board";\e[18;9Hcompatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";\e[20;9Haliases {\e[21;17Hserial0 = &uart0;\e[22;9H};\e[24;9Hchosen {\e[25;17Hstdout-path = "serial0:115200n8";\e[26;17Hbootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";\e[27;9H};\e[29;9Hcpus {\e[30;17Hcpu@0 {\e[31;25Hproc-supply = <&mt6380_vcpu_reg>;\e[32;25Hsram-supply = <&mt6380_vm_reg>;\e[33;17H};\e[35;17Hcpu@1 {\e[36;25Hproc-supply = <&mt6380_vcpu_reg>;\e[37;25Hsram-supply = <&mt6380_vm_reg>;\e[38;17H};\e[39;9H};\e[41;9Hgpio-keys {\e[42;17Hcompatible = "gpio-keys";\e[43;17Hpoll-interval = <100>;\e[45;17Hfactory {\e[46;25Hlabel = "factory";\e[47;25Hlinux,code = <BTN_0>;\e[48;25Hgpios = <&pio 0 0>;\e[49;17H};\e[51;17Hwps {\e[52;25Hlabel = "wps";\e[53;25Hlinux,code = <KEY_WPS_BUTTON>;\e[54;25Hgpios = <&pio 102 0>;\e[55;17H};\e[56;9H};\e[58;9Hgsw: gsw@0 {\e[59;17Hcompatible = "mediatek,mt753x";\e[60;17Hmediatek,ethsys = <&ethsys>;\e[61;17H#address-cells = <1>;\e[62;17H#size-cells = <0>;\e[63;9H};\e[65;9Hmemory {\e[66;17Hreg = <0 0x40000000 0 0x3F000000>;\e[67;9H};\e[69;9Hreg_1p8v: regulator-1p8v {\e[70;17Hcompatible = "regulator-fixed";\e[71;17Hregulator-name = "fixed-1.8V";\e[72;17Hregulator-min-microvolt = <1800000>;\e[73;17Hregulator-max-microvolt = <1800000>;\e[74;17Hregulator-always-on;\e[75;9H};\e[1;1H\e[?25h\a\r
\e[?25l\e[76;1HType  :qa!  and press <Enter> to abandon all changes and exit Vim\a\e[2;2H\e[?25h\e[76;1H\e[?2004l\e[?1l\e>\e[?1049l\e[23;0;0tVim: Caught deadly signal TERM\r
+Vim: Finished.\r
+\e[76;1H\e[23;2t\e[23;1t\e[22;2t\e[22;1t\e[23;2t\e[23;1t
\ No newline at end of file
diff --git a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
new file mode 100644 (file)
index 0000000..62a876c
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+       model = "Bananapi BPI-R64";
+       compatible = "bananapi,bpi-r64", "mediatek,mt7622";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
+       };
+
+       cpus {
+               cpu@0 {
+                       proc-supply = <&mt6380_vcpu_reg>;
+                       sram-supply = <&mt6380_vm_reg>;
+               };
+
+               cpu@1 {
+                       proc-supply = <&mt6380_vcpu_reg>;
+                       sram-supply = <&mt6380_vm_reg>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               factory {
+                       label = "factory";
+                       linux,code = <BTN_0>;
+                       gpios = <&pio 0 GPIO_ACTIVE_HIGH>;
+               };
+
+               wps {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               green {
+                       label = "bpi-r64:pio:green";
+                       gpios = <&pio 89 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               red {
+                       label = "bpi-r64:pio:red";
+                       gpios = <&pio 88 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+       };
+
+       gsw: gsw@0 {
+               compatible = "mediatek,mt753x";
+               mediatek,ethsys = <&ethsys>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       memory {
+               reg = <0 0x40000000 0 0x40000000>;
+       };
+
+       reg_1p8v: regulator-1p8v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-1.8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_5v: regulator-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
+
+&bch {
+       status = "disabled";
+};
+
+&btif {
+       status = "okay";
+};
+
+&cir {
+       pinctrl-names = "default";
+       pinctrl-0 = <&irrx_pins>;
+       status = "okay";
+};
+
+&eth {
+       pinctrl-names = "default";
+       pinctrl-0 = <&eth_pins>;
+       status = "okay";
+
+       gmac1: mac@1 {
+               compatible = "mediatek,eth-mac";
+               reg = <1>;
+               phy-handle = <&phy5>;
+       };
+
+       mdio: mdio-bus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               phy5: ethernet-phy@5 {
+                       reg = <5>;
+                       phy-mode = "sgmii";
+               };
+       };
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+       status = "okay";
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
+       status = "okay";
+};
+
+&mmc0 {
+       pinctrl-names = "default", "state_uhs";
+       pinctrl-0 = <&emmc_pins_default>;
+       pinctrl-1 = <&emmc_pins_uhs>;
+       status = "okay";
+       bus-width = <8>;
+       max-frequency = <50000000>;
+       cap-mmc-highspeed;
+       mmc-hs200-1_8v;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_1p8v>;
+       assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+       assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+       non-removable;
+};
+
+&mmc1 {
+       pinctrl-names = "default", "state_uhs";
+       pinctrl-0 = <&sd0_pins_default>;
+       pinctrl-1 = <&sd0_pins_uhs>;
+       status = "okay";
+       bus-width = <4>;
+       max-frequency = <50000000>;
+       cap-sd-highspeed;
+       r_smpl = <1>;
+       cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_3p3v>;
+       assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+       assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nandc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&parallel_nand_pins>;
+       status = "disabled";
+};
+
+&nor_flash {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_nor_pins>;
+       status = "disabled";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+       };
+};
+
+&pcie {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>;
+       status = "okay";
+
+       pcie@0,0 {
+               status = "okay";
+       };
+
+       pcie@1,0 {
+               status = "okay";
+       };
+};
+
+&pio {
+       /* Attention: GPIO 90 is used to switch between PCIe@1,0 and
+        * SATA functions. i.e. output-high: PCIe, output-low: SATA
+        */
+       asm_sel {
+               gpio-hog;
+               gpios = <90 GPIO_ACTIVE_HIGH>;
+               output-high;
+       };
+
+       /* eMMC is shared pin with parallel NAND */
+       emmc_pins_default: emmc-pins-default {
+               mux {
+                       function = "emmc", "emmc_rst";
+                       groups = "emmc";
+               };
+
+               /* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
+                * "NRB","NCLE" pins are used as DAT0,DAT1,DAT2,DAT3,DAT4,
+                * DAT5,DAT6,DAT7,CMD,CLK for eMMC respectively
+                */
+               conf-cmd-dat {
+                       pins = "NDL0", "NDL1", "NDL2",
+                              "NDL3", "NDL4", "NDL5",
+                              "NDL6", "NDL7", "NRB";
+                       input-enable;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "NCLE";
+                       bias-pull-down;
+               };
+       };
+
+       emmc_pins_uhs: emmc-pins-uhs {
+               mux {
+                       function = "emmc";
+                       groups = "emmc";
+               };
+
+               conf-cmd-dat {
+                       pins = "NDL0", "NDL1", "NDL2",
+                              "NDL3", "NDL4", "NDL5",
+                              "NDL6", "NDL7", "NRB";
+                       input-enable;
+                       drive-strength = <4>;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "NCLE";
+                       drive-strength = <4>;
+                       bias-pull-down;
+               };
+       };
+
+       eth_pins: eth-pins {
+               mux {
+                       function = "eth";
+                       groups = "mdc_mdio", "rgmii_via_gmac2";
+               };
+       };
+
+       i2c1_pins: i2c1-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c1_0";
+               };
+       };
+
+       i2c2_pins: i2c2-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c2_0";
+               };
+       };
+
+       i2s1_pins: i2s1-pins {
+               mux {
+                       function = "i2s";
+                       groups =  "i2s_out_mclk_bclk_ws",
+                                 "i2s1_in_data",
+                                 "i2s1_out_data";
+               };
+
+               conf {
+                       pins = "I2S1_IN", "I2S1_OUT", "I2S_BCLK",
+                              "I2S_WS", "I2S_MCLK";
+                       drive-strength = <12>;
+                       bias-pull-down;
+               };
+       };
+
+       irrx_pins: irrx-pins {
+               mux {
+                       function = "ir";
+                       groups =  "ir_1_rx";
+               };
+       };
+
+       irtx_pins: irtx-pins {
+               mux {
+                       function = "ir";
+                       groups =  "ir_1_tx";
+               };
+       };
+
+       /* Parallel nand is shared pin with eMMC */
+       parallel_nand_pins: parallel-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "par_nand";
+               };
+       };
+
+       pcie0_pins: pcie0-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie0_pad_perst",
+                                "pcie0_1_waken",
+                                "pcie0_1_clkreq";
+               };
+       };
+
+       pcie1_pins: pcie1-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie1_pad_perst",
+                                "pcie1_0_waken",
+                                "pcie1_0_clkreq";
+               };
+       };
+
+       pmic_bus_pins: pmic-bus-pins {
+               mux {
+                       function = "pmic";
+                       groups = "pmic_bus";
+               };
+       };
+
+       pwm7_pins: pwm1-2-pins {
+               mux {
+                       function = "pwm";
+                       groups = "pwm_ch7_2";
+               };
+       };
+
+       wled_pins: wled-pins {
+               mux {
+                       function = "led";
+                       groups = "wled";
+               };
+       };
+
+       sd0_pins_default: sd0-pins-default {
+               mux {
+                       function = "sd";
+                       groups = "sd_0";
+               };
+
+               /* "I2S2_OUT, "I2S4_IN"", "I2S3_IN", "I2S2_IN",
+                *  "I2S4_OUT", "I2S3_OUT" are used as DAT0, DAT1,
+                *  DAT2, DAT3, CMD, CLK for SD respectively.
+                */
+               conf-cmd-data {
+                       pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN",
+                              "I2S2_IN","I2S4_OUT";
+                       input-enable;
+                       drive-strength = <8>;
+                       bias-pull-up;
+               };
+               conf-clk {
+                       pins = "I2S3_OUT";
+                       drive-strength = <12>;
+                       bias-pull-down;
+               };
+               conf-cd {
+                       pins = "TXD3";
+                       bias-pull-up;
+               };
+       };
+
+       sd0_pins_uhs: sd0-pins-uhs {
+               mux {
+                       function = "sd";
+                       groups = "sd_0";
+               };
+
+               conf-cmd-data {
+                       pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN",
+                              "I2S2_IN","I2S4_OUT";
+                       input-enable;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "I2S3_OUT";
+                       bias-pull-down;
+               };
+       };
+
+       /* Serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       spic0_pins: spic0-pins {
+               mux {
+                       function = "spi";
+                       groups = "spic0_0";
+               };
+       };
+
+       spic1_pins: spic1-pins {
+               mux {
+                       function = "spi";
+                       groups = "spic1_0";
+               };
+       };
+
+       /* SPI-NOR is shared pin with serial NAND */
+       spi_nor_pins: spi-nor-pins {
+               mux {
+                       function = "flash";
+                       groups = "spi_nor";
+               };
+       };
+
+       /* serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       uart0_pins: uart0-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart0_0_tx_rx" ;
+               };
+       };
+
+       uart2_pins: uart2-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart2_1_tx_rx" ;
+               };
+       };
+
+       watchdog_pins: watchdog-pins {
+               mux {
+                       function = "watchdog";
+                       groups = "watchdog";
+               };
+       };
+};
+
+&pwm {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pwm7_pins>;
+       status = "okay";
+};
+
+&pwrap {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pmic_bus_pins>;
+
+       status = "okay";
+};
+
+&sata {
+       status = "disable";
+};
+
+&sata_phy {
+       status = "disable";
+};
+
+&spi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spic0_pins>;
+       status = "okay";
+};
+
+&spi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spic1_pins>;
+       status = "okay";
+};
+
+&ssusb {
+       vusb33-supply = <&reg_3p3v>;
+       vbus-supply = <&reg_5v>;
+       status = "okay";
+};
+
+&u3phy {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+       status = "okay";
+};
+
+&watchdog {
+       pinctrl-names = "default";
+       pinctrl-0 = <&watchdog_pins>;
+       status = "okay";
+};
+
+&gsw {
+       mediatek,mdio = <&mdio>;
+       mediatek,portmap = "llllw";
+       mediatek,mdio_master_pinmux = <0>;
+       reset-gpios = <&pio 54 0>;
+       interrupt-parent = <&pio>;
+       interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
+       status = "okay";
+
+       port5: port@5 {
+               compatible = "mediatek,mt753x-port";
+               reg = <5>;
+               phy-mode = "rgmii";
+               fixed-link {
+                       speed = <1000>;
+                       full-duplex;
+               };
+       };
+
+       port6: port@6 {
+               compatible = "mediatek,mt753x-port";
+               reg = <6>;
+               phy-mode = "sgmii";
+               fixed-link {
+                       speed = <2500>;
+                       full-duplex;
+               };
+       };
+};
+
+
diff --git a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-lynx-rfb1.dts b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-lynx-rfb1.dts
new file mode 100755 (executable)
index 0000000..1045851
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *        Sean Wang <sean.wang@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+       model = "MediaTek MT7622 RFB1 board";
+       compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
+       };
+
+       cpus {
+               cpu@0 {
+                       proc-supply = <&mt6380_vcpu_reg>;
+                       sram-supply = <&mt6380_vm_reg>;
+               };
+
+               cpu@1 {
+                       proc-supply = <&mt6380_vcpu_reg>;
+                       sram-supply = <&mt6380_vm_reg>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               poll-interval = <100>;
+
+               factory {
+                       label = "factory";
+                       linux,code = <BTN_0>;
+                       gpios = <&pio 0 0>;
+               };
+
+               wps {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&pio 102 0>;
+               };
+       };
+
+       gsw: gsw@0 {
+               compatible = "mediatek,mt753x";
+               mediatek,ethsys = <&ethsys>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       memory {
+               reg = <0 0x40000000 0 0x3F000000>;
+       };
+
+       reg_1p8v: regulator-1p8v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-1.8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_5v: regulator-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
+
+&pcie {
+       pinctrl-names = "default", "pcie1_pins";
+       pinctrl-0 = <&pcie0_pins>;
+       pinctrl-1 = <&pcie1_pins>;
+       status = "okay";
+
+       pcie@0,0 {
+               status = "okay";
+       };
+
+       pcie@1,0 {
+               status = "okay";
+       };
+
+};
+
+&pio {
+       /* eMMC is shared pin with parallel NAND */
+       emmc_pins_default: emmc-pins-default {
+               mux {
+                       function = "emmc", "emmc_rst";
+                       groups = "emmc";
+               };
+
+               /* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
+                * "NRB","NCLE" pins are used as DAT0,DAT1,DAT2,DAT3,DAT4,
+                * DAT5,DAT6,DAT7,CMD,CLK for eMMC respectively
+                */
+               conf-cmd-dat {
+                       pins = "NDL0", "NDL1", "NDL2",
+                              "NDL3", "NDL4", "NDL5",
+                              "NDL6", "NDL7", "NRB";
+                       input-enable;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "NCLE";
+                       bias-pull-down;
+               };
+       };
+
+       emmc_pins_uhs: emmc-pins-uhs {
+               mux {
+                       function = "emmc";
+                       groups = "emmc";
+               };
+
+               conf-cmd-dat {
+                       pins = "NDL0", "NDL1", "NDL2",
+                              "NDL3", "NDL4", "NDL5",
+                              "NDL6", "NDL7", "NRB";
+                       input-enable;
+                       drive-strength = <4>;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "NCLE";
+                       drive-strength = <4>;
+                       bias-pull-down;
+               };
+       };
+
+       eth_pins: eth-pins {
+               mux {
+                       function = "eth";
+                       groups = "mdc_mdio", "rgmii_via_gmac2";
+               };
+       };
+
+       i2c1_pins: i2c1-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c1_0";
+               };
+       };
+
+       i2c2_pins: i2c2-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c2_0";
+               };
+       };
+
+       i2s1_pins: i2s1-pins {
+               mux {
+                       function = "i2s";
+                       groups =  "i2s_out_mclk_bclk_ws",
+                                 "i2s1_in_data",
+                                 "i2s1_out_data";
+               };
+
+               conf {
+                       pins = "I2S1_IN", "I2S1_OUT", "I2S_BCLK",
+                              "I2S_WS", "I2S_MCLK";
+                       drive-strength = <12>;
+                       bias-pull-down;
+               };
+       };
+
+       irrx_pins: irrx-pins {
+               mux {
+                       function = "ir";
+                       groups =  "ir_1_rx";
+               };
+       };
+
+       irtx_pins: irtx-pins {
+               mux {
+                       function = "ir";
+                       groups =  "ir_1_tx";
+               };
+       };
+
+       /* Parallel nand is shared pin with eMMC */
+       parallel_nand_pins: parallel-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "par_nand";
+               };
+       };
+
+       pcie0_pins: pcie0-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie0_pad_perst",
+                                "pcie0_1_waken",
+                                "pcie0_1_clkreq";
+               };
+       };
+
+       pcie1_pins: pcie1-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie1_pad_perst",
+                                "pcie1_0_waken",
+                                "pcie1_0_clkreq";
+               };
+       };
+
+       pmic_bus_pins: pmic-bus-pins {
+               mux {
+                       function = "pmic";
+                       groups = "pmic_bus";
+               };
+       };
+
+       pwm7_pins: pwm1-2-pins {
+               mux {
+                       function = "pwm";
+                       groups = "pwm_ch7_2";
+               };
+       };
+
+       wled_pins: wled-pins {
+               mux {
+                       function = "led";
+                       groups = "wled";
+               };
+       };
+
+       sd0_pins_default: sd0-pins-default {
+               mux {
+                       function = "sd";
+                       groups = "sd_0";
+               };
+
+               /* "I2S2_OUT, "I2S4_IN"", "I2S3_IN", "I2S2_IN",
+                *  "I2S4_OUT", "I2S3_OUT" are used as DAT0, DAT1,
+                *  DAT2, DAT3, CMD, CLK for SD respectively.
+                */
+               conf-cmd-data {
+                       pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN",
+                              "I2S2_IN","I2S4_OUT";
+                       input-enable;
+                       drive-strength = <8>;
+                       bias-pull-up;
+               };
+               conf-clk {
+                       pins = "I2S3_OUT";
+                       drive-strength = <12>;
+                       bias-pull-down;
+               };
+               conf-cd {
+                       pins = "TXD3";
+                       bias-pull-up;
+               };
+       };
+
+       sd0_pins_uhs: sd0-pins-uhs {
+               mux {
+                       function = "sd";
+                       groups = "sd_0";
+               };
+
+               conf-cmd-data {
+                       pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN",
+                              "I2S2_IN","I2S4_OUT";
+                       input-enable;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "I2S3_OUT";
+                       bias-pull-down;
+               };
+       };
+
+       /* Serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       spic0_pins: spic0-pins {
+               mux {
+                       function = "spi";
+                       groups = "spic0_0";
+               };
+       };
+
+       spic1_pins: spic1-pins {
+               mux {
+                       function = "spi";
+                       groups = "spic1_0";
+               };
+       };
+
+       /* SPI-NOR is shared pin with serial NAND */
+       spi_nor_pins: spi-nor-pins {
+               mux {
+                       function = "flash";
+                       groups = "spi_nor";
+               };
+       };
+
+       /* serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       uart0_pins: uart0-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart0_0_tx_rx" ;
+               };
+       };
+
+       uart2_pins: uart2-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart2_1_tx_rx" ;
+               };
+       };
+
+       watchdog_pins: watchdog-pins {
+               mux {
+                       function = "watchdog";
+                       groups = "watchdog";
+               };
+       };
+};
+
+&bch {
+       status = "okay";
+};
+
+&btif {
+       status = "okay";
+};
+
+&cir {
+       pinctrl-names = "default";
+       pinctrl-0 = <&irrx_pins>;
+       status = "okay";
+};
+
+&eth {
+       status = "okay";
+       gmac0: mac@0 {
+                compatible = "mediatek,eth-mac";
+                reg = <0>;
+                phy-mode = "sgmii";
+                fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                };
+        };
+        gmac1: mac@1 {
+                compatible = "mediatek,eth-mac";
+                reg = <1>;
+                phy-mode = "rgmii";
+                fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                };
+        };
+        mdio: mdio-bus {
+                #address-cells = <1>;
+                #size-cells = <0>;
+        };
+};
+
+&gsw {
+       mediatek,mdio = <&mdio>;
+       mediatek,portmap = "llllw";
+       mediatek,mdio_master_pinmux = <0>;
+       reset-gpios = <&pio 54 0>;
+       interrupt-parent = <&pio>;
+       interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
+       status = "okay";
+
+       port5: port@5 {
+               compatible = "mediatek,mt753x-port";
+               reg = <5>;
+               phy-mode = "rgmii";
+               fixed-link {
+                       speed = <1000>;
+                       full-duplex;
+               };
+       };
+
+       port6: port@6 {
+               compatible = "mediatek,mt753x-port";
+               reg = <6>;
+               phy-mode = "sgmii";
+               fixed-link {
+                       speed = <2500>;
+                       full-duplex;
+               };
+       };
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+       status = "okay";
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
+       status = "okay";
+};
+
+&mmc0 {
+       pinctrl-names = "default", "state_uhs";
+       pinctrl-0 = <&emmc_pins_default>;
+       pinctrl-1 = <&emmc_pins_uhs>;
+       status = "okay";
+       bus-width = <8>;
+       max-frequency = <50000000>;
+       cap-mmc-highspeed;
+       mmc-hs200-1_8v;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_1p8v>;
+       assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+       assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+       non-removable;
+};
+
+&mmc1 {
+       pinctrl-names = "default", "state_uhs";
+       pinctrl-0 = <&sd0_pins_default>;
+       pinctrl-1 = <&sd0_pins_uhs>;
+       status = "okay";
+       bus-width = <4>;
+       max-frequency = <50000000>;
+       cap-sd-highspeed;
+       r_smpl = <1>;
+       cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_3p3v>;
+       assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+       assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nandc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&parallel_nand_pins>;
+       status = "disabled";
+};
+
+&nor_flash {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_nor_pins>;
+       status = "disabled";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+       };
+};
+
+&pwm {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pwm7_pins>;
+       status = "okay";
+};
+
+&pwrap {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pmic_bus_pins>;
+
+       status = "okay";
+};
+
+&snfi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&serial_nand_pins>;
+       status = "okay";
+
+       spi_nand@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spi-nand";
+               spi-max-frequency = <104000000>;
+               reg = <0>;
+
+               partitions {
+                        compatible = "fixed-partitions";
+                        #address-cells = <1>;
+                        #size-cells = <1>;
+
+                        partition@0 {
+                                label = "Preloader";
+                                reg = <0x00000 0x0080000>;
+                                read-only;
+                        };
+
+                        partition@80000 {
+                                label = "ATF";
+                                reg = <0x80000 0x0040000>;
+                        };
+
+                        partition@c0000 {
+                                label = "Bootloader";
+                                reg = <0xc0000 0x0080000>;
+                        };
+
+                        partition@140000 {
+                                label = "Config";
+                                reg = <0x140000 0x0080000>;
+                        };
+
+                        partition@1c0000 {
+                                label = "Factory";
+                                reg = <0x1c0000 0x0040000>;
+                        };
+
+                        partition@200000 {
+                                label = "Kernel";
+                                reg = <0x200000 0x2000000>;
+                        };
+
+                        partition@2200000 {
+                                label = "User_data";
+                                reg = <0x2200000 0x4000000>;
+                        };
+                };
+       };
+};
+
+&spi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spic0_pins>;
+       status = "okay";
+};
+
+&spi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spic1_pins>;
+       status = "okay";
+};
+
+&ssusb {
+       vusb33-supply = <&reg_3p3v>;
+       vbus-supply = <&reg_5v>;
+       status = "okay";
+};
+
+&u3phy {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+       status = "okay";
+};
+
+&watchdog {
+       pinctrl-names = "default";
+       pinctrl-0 = <&watchdog_pins>;
+       status = "okay";
+};
diff --git a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
new file mode 100755 (executable)
index 0000000..3805c5c
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *        Sean Wang <sean.wang@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+       model = "MediaTek MT7622 RFB1 board";
+       compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
+       };
+
+       cpus {
+               cpu@0 {
+                       proc-supply = <&mt6380_vcpu_reg>;
+                       sram-supply = <&mt6380_vm_reg>;
+               };
+
+               cpu@1 {
+                       proc-supply = <&mt6380_vcpu_reg>;
+                       sram-supply = <&mt6380_vm_reg>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               poll-interval = <100>;
+
+               factory {
+                       label = "factory";
+                       linux,code = <BTN_0>;
+                       gpios = <&pio 0 0>;
+               };
+
+               wps {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&pio 102 0>;
+               };
+       };
+
+       memory {
+               reg = <0 0x40000000 0 0x3F000000>;
+       };
+
+       reg_1p8v: regulator-1p8v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-1.8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_5v: regulator-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+        rtkgsw: rtkgsw@0 {
+                compatible = "mediatek,rtk-gsw";
+                mediatek,ethsys = <&ethsys>;
+                mediatek,mdio = <&mdio>;
+                mediatek,reset-pin = <&pio 54 0>;
+                status = "okay";
+        };
+};
+
+&pcie {
+       pinctrl-names = "default", "pcie1_pins";
+       pinctrl-0 = <&pcie0_pins>;
+       pinctrl-1 = <&pcie1_pins>;
+       status = "okay";
+
+       pcie@0,0 {
+               status = "okay";
+       };
+
+       pcie@1,0 {
+               status = "okay";
+       };
+
+};
+
+&pio {
+       /* eMMC is shared pin with parallel NAND */
+       emmc_pins_default: emmc-pins-default {
+               mux {
+                       function = "emmc", "emmc_rst";
+                       groups = "emmc";
+               };
+
+               /* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
+                * "NRB","NCLE" pins are used as DAT0,DAT1,DAT2,DAT3,DAT4,
+                * DAT5,DAT6,DAT7,CMD,CLK for eMMC respectively
+                */
+               conf-cmd-dat {
+                       pins = "NDL0", "NDL1", "NDL2",
+                              "NDL3", "NDL4", "NDL5",
+                              "NDL6", "NDL7", "NRB";
+                       input-enable;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "NCLE";
+                       bias-pull-down;
+               };
+       };
+
+       emmc_pins_uhs: emmc-pins-uhs {
+               mux {
+                       function = "emmc";
+                       groups = "emmc";
+               };
+
+               conf-cmd-dat {
+                       pins = "NDL0", "NDL1", "NDL2",
+                              "NDL3", "NDL4", "NDL5",
+                              "NDL6", "NDL7", "NRB";
+                       input-enable;
+                       drive-strength = <4>;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "NCLE";
+                       drive-strength = <4>;
+                       bias-pull-down;
+               };
+       };
+
+       eth_pins: eth-pins {
+               mux {
+                       function = "eth";
+                       groups = "mdc_mdio", "rgmii_via_gmac2";
+               };
+       };
+
+       i2c1_pins: i2c1-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c1_0";
+               };
+       };
+
+       i2c2_pins: i2c2-pins {
+               mux {
+                       function = "i2c";
+                       groups =  "i2c2_0";
+               };
+       };
+
+       i2s1_pins: i2s1-pins {
+               mux {
+                       function = "i2s";
+                       groups =  "i2s_out_mclk_bclk_ws",
+                                 "i2s1_in_data",
+                                 "i2s1_out_data";
+               };
+
+               conf {
+                       pins = "I2S1_IN", "I2S1_OUT", "I2S_BCLK",
+                              "I2S_WS", "I2S_MCLK";
+                       drive-strength = <12>;
+                       bias-pull-down;
+               };
+       };
+
+       irrx_pins: irrx-pins {
+               mux {
+                       function = "ir";
+                       groups =  "ir_1_rx";
+               };
+       };
+
+       irtx_pins: irtx-pins {
+               mux {
+                       function = "ir";
+                       groups =  "ir_1_tx";
+               };
+       };
+
+       /* Parallel nand is shared pin with eMMC */
+       parallel_nand_pins: parallel-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "par_nand";
+               };
+       };
+
+       pcie0_pins: pcie0-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie0_pad_perst",
+                                "pcie0_1_waken",
+                                "pcie0_1_clkreq";
+               };
+       };
+
+       pcie1_pins: pcie1-pins {
+               mux {
+                       function = "pcie";
+                       groups = "pcie1_pad_perst",
+                                "pcie1_0_waken",
+                                "pcie1_0_clkreq";
+               };
+       };
+
+       pmic_bus_pins: pmic-bus-pins {
+               mux {
+                       function = "pmic";
+                       groups = "pmic_bus";
+               };
+       };
+
+       pwm7_pins: pwm1-2-pins {
+               mux {
+                       function = "pwm";
+                       groups = "pwm_ch7_2";
+               };
+       };
+
+       wled_pins: wled-pins {
+               mux {
+                       function = "led";
+                       groups = "wled";
+               };
+       };
+
+       sd0_pins_default: sd0-pins-default {
+               mux {
+                       function = "sd";
+                       groups = "sd_0";
+               };
+
+               /* "I2S2_OUT, "I2S4_IN"", "I2S3_IN", "I2S2_IN",
+                *  "I2S4_OUT", "I2S3_OUT" are used as DAT0, DAT1,
+                *  DAT2, DAT3, CMD, CLK for SD respectively.
+                */
+               conf-cmd-data {
+                       pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN",
+                              "I2S2_IN","I2S4_OUT";
+                       input-enable;
+                       drive-strength = <8>;
+                       bias-pull-up;
+               };
+               conf-clk {
+                       pins = "I2S3_OUT";
+                       drive-strength = <12>;
+                       bias-pull-down;
+               };
+               conf-cd {
+                       pins = "TXD3";
+                       bias-pull-up;
+               };
+       };
+
+       sd0_pins_uhs: sd0-pins-uhs {
+               mux {
+                       function = "sd";
+                       groups = "sd_0";
+               };
+
+               conf-cmd-data {
+                       pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN",
+                              "I2S2_IN","I2S4_OUT";
+                       input-enable;
+                       bias-pull-up;
+               };
+
+               conf-clk {
+                       pins = "I2S3_OUT";
+                       bias-pull-down;
+               };
+       };
+
+       /* Serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       spic0_pins: spic0-pins {
+               mux {
+                       function = "spi";
+                       groups = "spic0_0";
+               };
+       };
+
+       spic1_pins: spic1-pins {
+               mux {
+                       function = "spi";
+                       groups = "spic1_0";
+               };
+       };
+
+       /* SPI-NOR is shared pin with serial NAND */
+       spi_nor_pins: spi-nor-pins {
+               mux {
+                       function = "flash";
+                       groups = "spi_nor";
+               };
+       };
+
+       /* serial NAND is shared pin with SPI-NOR */
+       serial_nand_pins: serial-nand-pins {
+               mux {
+                       function = "flash";
+                       groups = "snfi";
+               };
+       };
+
+       uart0_pins: uart0-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart0_0_tx_rx" ;
+               };
+       };
+
+       uart2_pins: uart2-pins {
+               mux {
+                       function = "uart";
+                       groups = "uart2_1_tx_rx" ;
+               };
+       };
+
+       watchdog_pins: watchdog-pins {
+               mux {
+                       function = "watchdog";
+                       groups = "watchdog";
+               };
+       };
+};
+
+&bch {
+       status = "okay";
+};
+
+&btif {
+       status = "okay";
+};
+
+&cir {
+       pinctrl-names = "default";
+       pinctrl-0 = <&irrx_pins>;
+       status = "okay";
+};
+
+&eth {
+       status = "okay";
+       gmac0: mac@0 {
+                compatible = "mediatek,eth-mac";
+                reg = <0>;
+                phy-mode = "sgmii";
+                fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                };
+        };
+        gmac1: mac@1 {
+                compatible = "mediatek,eth-mac";
+                reg = <1>;
+                phy-mode = "rgmii";
+                fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                };
+        };
+        mdio: mdio-bus {
+                #address-cells = <1>;
+                #size-cells = <0>;
+        };
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+       status = "okay";
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
+       status = "okay";
+};
+
+&mmc0 {
+       pinctrl-names = "default", "state_uhs";
+       pinctrl-0 = <&emmc_pins_default>;
+       pinctrl-1 = <&emmc_pins_uhs>;
+       status = "okay";
+       bus-width = <8>;
+       max-frequency = <50000000>;
+       cap-mmc-highspeed;
+       mmc-hs200-1_8v;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_1p8v>;
+       assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+       assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+       non-removable;
+};
+
+&mmc1 {
+       pinctrl-names = "default", "state_uhs";
+       pinctrl-0 = <&sd0_pins_default>;
+       pinctrl-1 = <&sd0_pins_uhs>;
+       status = "okay";
+       bus-width = <4>;
+       max-frequency = <50000000>;
+       cap-sd-highspeed;
+       r_smpl = <1>;
+       cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_3p3v>;
+       assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+       assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nandc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&parallel_nand_pins>;
+       status = "disabled";
+};
+
+&nor_flash {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_nor_pins>;
+       status = "disabled";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+       };
+};
+
+&pwm {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pwm7_pins>;
+       status = "okay";
+};
+
+&pwrap {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pmic_bus_pins>;
+
+       status = "okay";
+};
+
+&snfi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&serial_nand_pins>;
+       status = "okay";
+
+       spi_nand@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spi-nand";
+               spi-max-frequency = <104000000>;
+               reg = <0>;
+
+               partitions {
+                        compatible = "fixed-partitions";
+                        #address-cells = <1>;
+                        #size-cells = <1>;
+
+                        partition@0 {
+                                label = "Preloader";
+                                reg = <0x00000 0x0080000>;
+                                read-only;
+                        };
+
+                        partition@80000 {
+                                label = "ATF";
+                                reg = <0x80000 0x0040000>;
+                        };
+
+                        partition@c0000 {
+                                label = "Bootloader";
+                                reg = <0xc0000 0x0080000>;
+                        };
+
+                        partition@140000 {
+                                label = "Config";
+                                reg = <0x140000 0x0080000>;
+                        };
+
+                        partition@1c0000 {
+                                label = "Factory";
+                                reg = <0x1c0000 0x0040000>;
+                        };
+
+                        partition@200000 {
+                                label = "Kernel";
+                                reg = <0x200000 0x2000000>;
+                        };
+
+                        partition@2200000 {
+                                label = "User_data";
+                                reg = <0x2200000 0x4000000>;
+                        };
+                };
+       };
+};
+
+&spi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spic0_pins>;
+       status = "okay";
+};
+
+&spi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spic1_pins>;
+       status = "okay";
+};
+
+&ssusb {
+       vusb33-supply = <&reg_3p3v>;
+       vbus-supply = <&reg_5v>;
+       status = "okay";
+};
+
+&u3phy {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+       status = "okay";
+};
+
+&watchdog {
+       pinctrl-names = "default";
+       pinctrl-0 = <&watchdog_pins>;
+       status = "okay";
+};
diff --git a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622.dtsi
new file mode 100755 (executable)
index 0000000..3fdd06a
--- /dev/null
@@ -0,0 +1,903 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *        Sean Wang <sean.wang@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <dt-bindings/reset/mt7622-reset.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+       compatible = "mediatek,mt7622";
+       interrupt-parent = <&sysirq>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpu_opp_table: opp-table {
+               compatible = "operating-points-v2";
+               opp-shared;
+               opp-300000000 {
+                       opp-hz = /bits/ 64 <30000000>;
+                       opp-microvolt = <950000>;
+               };
+
+               opp-437500000 {
+                       opp-hz = /bits/ 64 <437500000>;
+                       opp-microvolt = <1000000>;
+               };
+
+               opp-600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <1050000>;
+               };
+
+               opp-812500000 {
+                       opp-hz = /bits/ 64 <812500000>;
+                       opp-microvolt = <1100000>;
+               };
+
+               opp-1025000000 {
+                       opp-hz = /bits/ 64 <1025000000>;
+                       opp-microvolt = <1150000>;
+               };
+
+               opp-1137500000 {
+                       opp-hz = /bits/ 64 <1137500000>;
+                       opp-microvolt = <1200000>;
+               };
+
+               opp-1262500000 {
+                       opp-hz = /bits/ 64 <1262500000>;
+                       opp-microvolt = <1250000>;
+               };
+
+               opp-1350000000 {
+                       opp-hz = /bits/ 64 <1350000000>;
+                       opp-microvolt = <1310000>;
+               };
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x0>;
+                       clocks = <&infracfg CLK_INFRA_MUX1_SEL>,
+                                <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>;
+                       clock-names = "cpu", "intermediate";
+                       operating-points-v2 = <&cpu_opp_table>;
+                       #cooling-cells = <2>;
+                       enable-method = "psci";
+                       clock-frequency = <1300000000>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x1>;
+                       clocks = <&infracfg CLK_INFRA_MUX1_SEL>,
+                                <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>;
+                       clock-names = "cpu", "intermediate";
+                       operating-points-v2 = <&cpu_opp_table>;
+                       #cooling-cells = <2>;
+                       enable-method = "psci";
+                       clock-frequency = <1300000000>;
+               };
+       };
+
+       pwrap_clk: dummy40m {
+               compatible = "fixed-clock";
+               clock-frequency = <40000000>;
+               #clock-cells = <0>;
+       };
+
+       clk25m: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <25000000>;
+               clock-output-names = "clkxtal";
+       };
+
+       psci {
+               compatible  = "arm,psci-0.2";
+               method      = "smc";
+       };
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+               secmon_reserved: secmon@43000000 {
+                       reg = <0 0x43000000 0 0x30000>;
+                       no-map;
+               };
+       };
+
+       thermal-zones {
+               cpu_thermal: cpu-thermal {
+                       polling-delay-passive = <1000>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&thermal 0>;
+
+                       trips {
+                               cpu_passive: cpu-passive {
+                                       temperature = <47000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_active: cpu-active {
+                                       temperature = <67000>;
+                                       hysteresis = <2000>;
+                                       type = "active";
+                               };
+
+                               cpu_hot: cpu-hot {
+                                       temperature = <87000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+
+                               cpu-crit {
+                                       temperature = <107000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+
+                       cooling-maps {
+                               map0 {
+                                       trip = <&cpu_passive>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+
+                               map1 {
+                                       trip = <&cpu_active>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+
+                               map2 {
+                                       trip = <&cpu_hot>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+                       };
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+                             IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
+                             IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) |
+                             IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) |
+                             IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       infracfg: infracfg@10000000 {
+               compatible = "mediatek,mt7622-infracfg",
+                            "syscon";
+               reg = <0 0x10000000 0 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+       pwrap: pwrap@10001000 {
+               compatible = "mediatek,mt7622-pwrap";
+               reg = <0 0x10001000 0 0x250>;
+               reg-names = "pwrap";
+               clocks = <&infracfg CLK_INFRA_PMIC_PD>, <&pwrap_clk>;
+               clock-names = "spi", "wrap";
+               resets = <&infracfg MT7622_INFRA_PMIC_WRAP_RST>;
+               reset-names = "pwrap";
+               interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       pericfg: pericfg@10002000 {
+               compatible = "mediatek,mt7622-pericfg",
+                            "syscon";
+               reg = <0 0x10002000 0 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+       scpsys: scpsys@10006000 {
+               compatible = "mediatek,mt7622-scpsys",
+                            "syscon";
+               #power-domain-cells = <1>;
+               reg = <0 0x10006000 0 0x1000>;
+               interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 166 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 167 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 168 IRQ_TYPE_LEVEL_LOW>;
+               infracfg = <&infracfg>;
+               clocks = <&topckgen CLK_TOP_HIF_SEL>;
+               clock-names = "hif_sel";
+       };
+
+       cir: cir@10009000 {
+               compatible = "mediatek,mt7622-cir";
+               reg = <0 0x10009000 0 0x1000>;
+               interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&infracfg CLK_INFRA_IRRX_PD>,
+                        <&topckgen CLK_TOP_AXI_SEL>;
+               clock-names = "clk", "bus";
+               status = "disabled";
+       };
+
+       sysirq: interrupt-controller@10200620 {
+               compatible = "mediatek,mt7622-sysirq",
+                            "mediatek,mt6577-sysirq";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
+               reg = <0 0x10200620 0 0x20>;
+       };
+
+       efuse: efuse@10206000 {
+               compatible = "mediatek,mt7622-efuse",
+                            "mediatek,efuse";
+               reg = <0 0x10206000 0 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               thermal_calibration: calib@198 {
+                       reg = <0x198 0xc>;
+               };
+       };
+
+       apmixedsys: apmixedsys@10209000 {
+               compatible = "mediatek,mt7622-apmixedsys",
+                            "syscon";
+               reg = <0 0x10209000 0 0x1000>;
+               #clock-cells = <1>;
+       };
+
+       topckgen: topckgen@10210000 {
+               compatible = "mediatek,mt7622-topckgen",
+                            "syscon";
+               reg = <0 0x10210000 0 0x1000>;
+               #clock-cells = <1>;
+       };
+
+       rng: rng@1020f000 {
+               compatible = "mediatek,mt7622-rng",
+                            "mediatek,mt7623-rng";
+               reg = <0 0x1020f000 0 0x1000>;
+               clocks = <&infracfg CLK_INFRA_TRNG>;
+               clock-names = "rng";
+       };
+
+       pio: pinctrl@10211000 {
+               compatible = "mediatek,mt7622-pinctrl";
+               reg = <0 0x10211000 0 0x1000>,
+                     <0 0x10005000 0 0x1000>;
+               reg-names = "base", "eint";
+               gpio-controller;
+               #gpio-cells = <2>;
+               gpio-ranges = <&pio 0 0 103>;
+               interrupt-controller;
+               interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&gic>;
+               #interrupt-cells = <2>;
+       };
+
+       watchdog: watchdog@10212000 {
+               compatible = "mediatek,mt7622-wdt",
+                            "mediatek,mt6589-wdt";
+               reg = <0 0x10212000 0 0x800>;
+       };
+
+       rtc: rtc@10212800 {
+               compatible = "mediatek,mt7622-rtc",
+                            "mediatek,soc-rtc";
+               reg = <0 0x10212800 0 0x200>;
+               interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_RTC>;
+               clock-names = "rtc";
+       };
+
+       gic: interrupt-controller@10300000 {
+               compatible = "arm,gic-400";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
+               reg = <0 0x10310000 0 0x1000>,
+                     <0 0x10320000 0 0x1000>,
+                     <0 0x10340000 0 0x2000>,
+                     <0 0x10360000 0 0x2000>;
+       };
+
+       auxadc: adc@11001000 {
+               compatible = "mediatek,mt7622-auxadc";
+               reg = <0 0x11001000 0 0x1000>;
+               clocks = <&pericfg CLK_PERI_AUXADC_PD>;
+               clock-names = "main";
+               #io-channel-cells = <1>;
+       };
+
+       uart0: serial@11002000 {
+               compatible = "mediatek,mt7622-uart",
+                            "mediatek,mt6577-uart";
+               reg = <0 0x11002000 0 0x400>;
+               interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_UART_SEL>,
+                        <&pericfg CLK_PERI_UART0_PD>;
+               clock-names = "baud", "bus";
+               status = "disabled";
+       };
+
+       uart1: serial@11003000 {
+               compatible = "mediatek,mt7622-uart",
+                            "mediatek,mt6577-uart";
+               reg = <0 0x11003000 0 0x400>;
+               interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_UART_SEL>,
+                        <&pericfg CLK_PERI_UART1_PD>;
+               clock-names = "baud", "bus";
+               status = "disabled";
+       };
+
+       uart2: serial@11004000 {
+               compatible = "mediatek,mt7622-uart",
+                            "mediatek,mt6577-uart";
+               reg = <0 0x11004000 0 0x400>;
+               interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_UART_SEL>,
+                        <&pericfg CLK_PERI_UART2_PD>;
+               clock-names = "baud", "bus";
+               status = "disabled";
+       };
+
+       uart3: serial@11005000 {
+               compatible = "mediatek,mt7622-uart",
+                            "mediatek,mt6577-uart";
+               reg = <0 0x11005000 0 0x400>;
+               interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_UART_SEL>,
+                        <&pericfg CLK_PERI_UART3_PD>;
+               clock-names = "baud", "bus";
+               status = "disabled";
+       };
+
+       pwm: pwm@11006000 {
+               compatible = "mediatek,mt7622-pwm";
+               reg = <0 0x11006000 0 0x1000>;
+               interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_PWM_SEL>,
+                        <&pericfg CLK_PERI_PWM_PD>,
+                        <&pericfg CLK_PERI_PWM1_PD>,
+                        <&pericfg CLK_PERI_PWM2_PD>,
+                        <&pericfg CLK_PERI_PWM3_PD>,
+                        <&pericfg CLK_PERI_PWM4_PD>,
+                        <&pericfg CLK_PERI_PWM5_PD>,
+                        <&pericfg CLK_PERI_PWM6_PD>;
+               clock-names = "top", "main", "pwm1", "pwm2", "pwm3", "pwm4",
+                             "pwm5", "pwm6";
+               status = "disabled";
+       };
+
+       i2c0: i2c@11007000 {
+               compatible = "mediatek,mt7622-i2c";
+               reg = <0 0x11007000 0 0x90>,
+                     <0 0x11000100 0 0x80>;
+               interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>;
+               clock-div = <16>;
+               clocks = <&pericfg CLK_PERI_I2C0_PD>,
+                        <&pericfg CLK_PERI_AP_DMA_PD>;
+               clock-names = "main", "dma";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@11008000 {
+               compatible = "mediatek,mt7622-i2c";
+               reg = <0 0x11008000 0 0x90>,
+                     <0 0x11000180 0 0x80>;
+               interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_LOW>;
+               clock-div = <16>;
+               clocks = <&pericfg CLK_PERI_I2C1_PD>,
+                        <&pericfg CLK_PERI_AP_DMA_PD>;
+               clock-names = "main", "dma";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@11009000 {
+               compatible = "mediatek,mt7622-i2c";
+               reg = <0 0x11009000 0 0x90>,
+                     <0 0x11000200 0 0x80>;
+               interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_LOW>;
+               clock-div = <16>;
+               clocks = <&pericfg CLK_PERI_I2C2_PD>,
+                        <&pericfg CLK_PERI_AP_DMA_PD>;
+               clock-names = "main", "dma";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       spi0: spi@1100a000 {
+               compatible = "mediatek,mt7622-spi";
+               reg = <0 0x1100a000 0 0x100>;
+               interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+                        <&topckgen CLK_TOP_SPI0_SEL>,
+                        <&pericfg CLK_PERI_SPI0_PD>;
+               clock-names = "parent-clk", "sel-clk", "spi-clk";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       thermal: thermal@1100b000 {
+               #thermal-sensor-cells = <1>;
+               compatible = "mediatek,mt7622-thermal";
+               reg = <0 0x1100b000 0 0x1000>;
+               interrupts = <0 78 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_THERM_PD>,
+                        <&pericfg CLK_PERI_AUXADC_PD>;
+               clock-names = "therm", "auxadc";
+               resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
+               reset-names = "therm";
+               mediatek,auxadc = <&auxadc>;
+               mediatek,apmixedsys = <&apmixedsys>;
+               nvmem-cells = <&thermal_calibration>;
+               nvmem-cell-names = "calibration-data";
+       };
+
+       btif: serial@1100c000 {
+               compatible = "mediatek,mt7622-btif",
+                            "mediatek,mtk-btif";
+               reg = <0 0x1100c000 0 0x1000>;
+               interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_BTIF_PD>;
+               clock-names = "main";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               status = "disabled";
+
+               bluetooth {
+                       compatible = "mediatek,mt7622-bluetooth";
+                       power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>;
+                       clocks = <&clk25m>;
+                       clock-names = "ref";
+               };
+       };
+
+       nandc: nfi@1100d000 {
+               compatible = "mediatek,mt7622-nfc";
+               reg = <0 0x1100D000 0 0x1000>;
+               interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_NFI_PD>,
+                        <&pericfg CLK_PERI_SNFI_PD>;
+               clock-names = "nfi_clk", "pad_clk";
+               ecc-engine = <&bch>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       bch: ecc@1100e000 {
+               compatible = "mediatek,mt7622-ecc";
+               reg = <0 0x1100e000 0 0x1000>;
+               interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_NFIECC_PD>;
+               clock-names = "nfiecc_clk";
+               status = "disabled";
+       };
+
+       nor_flash: spi@11014000 {
+               compatible = "mediatek,mt7622-nor",
+                            "mediatek,mt8173-nor";
+               reg = <0 0x11014000 0 0xe0>;
+               clocks = <&pericfg CLK_PERI_FLASH_PD>,
+                        <&topckgen CLK_TOP_FLASH_SEL>;
+               clock-names = "spi", "sf";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       snfi: spi@1100d000 {
+               compatible = "mediatek,mt7622-snfi";
+               reg = <0 0x1100d000 0 0x1000>;
+               interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_NFI_PD>,
+                        <&pericfg CLK_PERI_SNFI_PD>;
+               clock-names = "nfi_clk", "spi_clk";
+               ecc-engine = <&bch>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       spi1: spi@11016000 {
+               compatible = "mediatek,mt7622-spi";
+               reg = <0 0x11016000 0 0x100>;
+               interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+                        <&topckgen CLK_TOP_SPI1_SEL>,
+                        <&pericfg CLK_PERI_SPI1_PD>;
+               clock-names = "parent-clk", "sel-clk", "spi-clk";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       uart4: serial@11019000 {
+               compatible = "mediatek,mt7622-uart",
+                            "mediatek,mt6577-uart";
+               reg = <0 0x11019000 0 0x400>;
+               interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_UART_SEL>,
+                        <&pericfg CLK_PERI_UART4_PD>;
+               clock-names = "baud", "bus";
+               status = "disabled";
+       };
+
+       audsys: clock-controller@11220000 {
+               compatible = "mediatek,mt7622-audsys", "syscon";
+               reg = <0 0x11220000 0 0x2000>;
+               #clock-cells = <1>;
+
+               afe: audio-controller {
+                       compatible = "mediatek,mt7622-audio";
+                       interrupts =  <GIC_SPI 144 IRQ_TYPE_LEVEL_LOW>,
+                                     <GIC_SPI 145 IRQ_TYPE_LEVEL_LOW>;
+                       interrupt-names = "afe", "asys";
+
+                       clocks = <&infracfg CLK_INFRA_AUDIO_PD>,
+                                <&topckgen CLK_TOP_AUD1_SEL>,
+                                <&topckgen CLK_TOP_AUD2_SEL>,
+                                <&topckgen CLK_TOP_A1SYS_HP_DIV_PD>,
+                                <&topckgen CLK_TOP_A2SYS_HP_DIV_PD>,
+                                <&topckgen CLK_TOP_I2S0_MCK_SEL>,
+                                <&topckgen CLK_TOP_I2S1_MCK_SEL>,
+                                <&topckgen CLK_TOP_I2S2_MCK_SEL>,
+                                <&topckgen CLK_TOP_I2S3_MCK_SEL>,
+                                <&topckgen CLK_TOP_I2S0_MCK_DIV>,
+                                <&topckgen CLK_TOP_I2S1_MCK_DIV>,
+                                <&topckgen CLK_TOP_I2S2_MCK_DIV>,
+                                <&topckgen CLK_TOP_I2S3_MCK_DIV>,
+                                <&topckgen CLK_TOP_I2S0_MCK_DIV_PD>,
+                                <&topckgen CLK_TOP_I2S1_MCK_DIV_PD>,
+                                <&topckgen CLK_TOP_I2S2_MCK_DIV_PD>,
+                                <&topckgen CLK_TOP_I2S3_MCK_DIV_PD>,
+                                <&audsys CLK_AUDIO_I2SO1>,
+                                <&audsys CLK_AUDIO_I2SO2>,
+                                <&audsys CLK_AUDIO_I2SO3>,
+                                <&audsys CLK_AUDIO_I2SO4>,
+                                <&audsys CLK_AUDIO_I2SIN1>,
+                                <&audsys CLK_AUDIO_I2SIN2>,
+                                <&audsys CLK_AUDIO_I2SIN3>,
+                                <&audsys CLK_AUDIO_I2SIN4>,
+                                <&audsys CLK_AUDIO_ASRCO1>,
+                                <&audsys CLK_AUDIO_ASRCO2>,
+                                <&audsys CLK_AUDIO_ASRCO3>,
+                                <&audsys CLK_AUDIO_ASRCO4>,
+                                <&audsys CLK_AUDIO_AFE>,
+                                <&audsys CLK_AUDIO_AFE_CONN>,
+                                <&audsys CLK_AUDIO_A1SYS>,
+                                <&audsys CLK_AUDIO_A2SYS>;
+
+                       clock-names = "infra_sys_audio_clk",
+                                     "top_audio_mux1_sel",
+                                     "top_audio_mux2_sel",
+                                     "top_audio_a1sys_hp",
+                                     "top_audio_a2sys_hp",
+                                     "i2s0_src_sel",
+                                     "i2s1_src_sel",
+                                     "i2s2_src_sel",
+                                     "i2s3_src_sel",
+                                     "i2s0_src_div",
+                                     "i2s1_src_div",
+                                     "i2s2_src_div",
+                                     "i2s3_src_div",
+                                     "i2s0_mclk_en",
+                                     "i2s1_mclk_en",
+                                     "i2s2_mclk_en",
+                                     "i2s3_mclk_en",
+                                     "i2so0_hop_ck",
+                                     "i2so1_hop_ck",
+                                     "i2so2_hop_ck",
+                                     "i2so3_hop_ck",
+                                     "i2si0_hop_ck",
+                                     "i2si1_hop_ck",
+                                     "i2si2_hop_ck",
+                                     "i2si3_hop_ck",
+                                     "asrc0_out_ck",
+                                     "asrc1_out_ck",
+                                     "asrc2_out_ck",
+                                     "asrc3_out_ck",
+                                     "audio_afe_pd",
+                                     "audio_afe_conn_pd",
+                                     "audio_a1sys_pd",
+                                     "audio_a2sys_pd";
+
+                       assigned-clocks = <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+                                         <&topckgen CLK_TOP_A2SYS_HP_SEL>,
+                                         <&topckgen CLK_TOP_A1SYS_HP_DIV>,
+                                         <&topckgen CLK_TOP_A2SYS_HP_DIV>;
+                       assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL>,
+                                                <&topckgen CLK_TOP_AUD2PLL>;
+                       assigned-clock-rates = <0>, <0>, <49152000>, <45158400>;
+               };
+       };
+
+       mmc0: mmc@11230000 {
+               compatible = "mediatek,mt7622-mmc";
+               reg = <0 0x11230000 0 0x1000>;
+               interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_MSDC30_0_PD>,
+                        <&topckgen CLK_TOP_MSDC50_0_SEL>;
+               clock-names = "source", "hclk";
+               status = "disabled";
+       };
+
+       mmc1: mmc@11240000 {
+               compatible = "mediatek,mt7622-mmc";
+               reg = <0 0x11240000 0 0x1000>;
+               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pericfg CLK_PERI_MSDC30_1_PD>,
+                        <&topckgen CLK_TOP_AXI_SEL>;
+               clock-names = "source", "hclk";
+               status = "disabled";
+       };
+
+       ssusbsys: ssusbsys@1a000000 {
+               compatible = "mediatek,mt7622-ssusbsys",
+                            "syscon";
+               reg = <0 0x1a000000 0 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+       ssusb: usb@1a0c0000 {
+               compatible = "mediatek,mt7622-xhci",
+                            "mediatek,mtk-xhci";
+               reg = <0 0x1a0c0000 0 0x01000>,
+                     <0 0x1a0c4700 0 0x0100>;
+               reg-names = "mac", "ippc";
+               interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_LOW>;
+               power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>;
+               clocks = <&ssusbsys CLK_SSUSB_SYS_EN>,
+                        <&ssusbsys CLK_SSUSB_REF_EN>,
+                        <&ssusbsys CLK_SSUSB_MCU_EN>,
+                        <&ssusbsys CLK_SSUSB_DMA_EN>;
+               clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck";
+               phys = <&u2port0 PHY_TYPE_USB2>,
+                      <&u3port0 PHY_TYPE_USB3>,
+                      <&u2port1 PHY_TYPE_USB2>;
+
+               status = "disabled";
+       };
+
+       u3phy: usb-phy@1a0c4000 {
+               compatible = "mediatek,mt7622-u3phy",
+                            "mediatek,generic-tphy-v1";
+               reg = <0 0x1a0c4000 0 0x700>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               status = "disabled";
+
+               u2port0: usb-phy@1a0c4800 {
+                       reg = <0 0x1a0c4800 0 0x0100>;
+                       #phy-cells = <1>;
+                       clocks = <&ssusbsys CLK_SSUSB_U2_PHY_EN>;
+                       clock-names = "ref";
+               };
+
+               u3port0: usb-phy@1a0c4900 {
+                       reg = <0 0x1a0c4900 0 0x0700>;
+                       #phy-cells = <1>;
+                       clocks = <&clk25m>;
+                       clock-names = "ref";
+               };
+
+               u2port1: usb-phy@1a0c5000 {
+                       reg = <0 0x1a0c5000 0 0x0100>;
+                       #phy-cells = <1>;
+                       clocks = <&ssusbsys CLK_SSUSB_U2_PHY_1P_EN>;
+                       clock-names = "ref";
+               };
+       };
+
+       pciesys: pciesys@1a100800 {
+               compatible = "mediatek,mt7622-pciesys",
+                            "syscon";
+               reg = <0 0x1a100800 0 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+       pcie: pcie@1a140000 {
+               compatible = "mediatek,mt7622-pcie";
+               device_type = "pci";
+               reg = <0 0x1a140000 0 0x1000>,
+                     <0 0x1a143000 0 0x1000>,
+                     <0 0x1a145000 0 0x1000>;
+               reg-names = "subsys", "port0", "port1";
+               #address-cells = <3>;
+               #size-cells = <2>;
+               interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+                        <&pciesys CLK_PCIE_P1_MAC_EN>,
+                        <&pciesys CLK_PCIE_P0_AHB_EN>,
+                        <&pciesys CLK_PCIE_P0_AHB_EN>,
+                        <&pciesys CLK_PCIE_P0_AUX_EN>,
+                        <&pciesys CLK_PCIE_P1_AUX_EN>,
+                        <&pciesys CLK_PCIE_P0_AXI_EN>,
+                        <&pciesys CLK_PCIE_P1_AXI_EN>,
+                        <&pciesys CLK_PCIE_P0_OBFF_EN>,
+                        <&pciesys CLK_PCIE_P1_OBFF_EN>,
+                        <&pciesys CLK_PCIE_P0_PIPE_EN>,
+                        <&pciesys CLK_PCIE_P1_PIPE_EN>;
+               clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+                             "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+                             "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+               power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+               bus-range = <0x00 0xff>;
+               ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
+               status = "disabled";
+
+               pcie0: pcie@0,0 {
+                       reg = <0x0000 0 0 0 0>;
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       #interrupt-cells = <1>;
+                       ranges;
+                       status = "disabled";
+
+                       num-lanes = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+                                       <0 0 0 2 &pcie_intc0 1>,
+                                       <0 0 0 3 &pcie_intc0 2>,
+                                       <0 0 0 4 &pcie_intc0 3>;
+                       pcie_intc0: interrupt-controller {
+                               interrupt-controller;
+                               #address-cells = <0>;
+                               #interrupt-cells = <1>;
+                       };
+               };
+
+               pcie1: pcie@1,0 {
+                       reg = <0x0800 0 0 0 0>;
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       #interrupt-cells = <1>;
+                       ranges;
+                       status = "disabled";
+
+                       num-lanes = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+                                       <0 0 0 2 &pcie_intc1 1>,
+                                       <0 0 0 3 &pcie_intc1 2>,
+                                       <0 0 0 4 &pcie_intc1 3>;
+                       pcie_intc1: interrupt-controller {
+                               interrupt-controller;
+                               #address-cells = <0>;
+                               #interrupt-cells = <1>;
+                       };
+               };
+       };
+
+       sata: sata@1a200000 {
+               compatible = "mediatek,mt7622-ahci",
+                            "mediatek,mtk-ahci";
+               reg = <0 0x1a200000 0 0x1100>;
+               interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "hostc";
+               clocks = <&pciesys CLK_SATA_AHB_EN>,
+                        <&pciesys CLK_SATA_AXI_EN>,
+                        <&pciesys CLK_SATA_ASIC_EN>,
+                        <&pciesys CLK_SATA_RBC_EN>,
+                        <&pciesys CLK_SATA_PM_EN>;
+               clock-names = "ahb", "axi", "asic", "rbc", "pm";
+               phys = <&sata_port PHY_TYPE_SATA>;
+               phy-names = "sata-phy";
+               ports-implemented = <0x1>;
+               power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+               resets = <&pciesys MT7622_SATA_AXI_BUS_RST>,
+                        <&pciesys MT7622_SATA_PHY_SW_RST>,
+                        <&pciesys MT7622_SATA_PHY_REG_RST>;
+               reset-names = "axi", "sw", "reg";
+               mediatek,phy-mode = <&pciesys>;
+               status = "disabled";
+       };
+
+       sata_phy: sata-phy@1a243000 {
+               compatible = "mediatek,generic-tphy-v1";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               status = "disabled";
+
+               sata_port: sata-phy@1a243000 {
+                       reg = <0 0x1a243000 0 0x0100>;
+                       clocks = <&topckgen CLK_TOP_ETH_500M>;
+                       clock-names = "ref";
+                       #phy-cells = <1>;
+               };
+       };
+
+       ethsys: syscon@1b000000 {
+               compatible = "mediatek,mt7622-ethsys",
+                            "syscon";
+               reg = <0 0x1b000000 0 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+       hsdma: dma-controller@1b007000 {
+               compatible = "mediatek,mt7622-hsdma";
+               reg = <0 0x1b007000 0 0x1000>;
+               interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&ethsys CLK_ETH_HSDMA_EN>;
+               clock-names = "hsdma";
+               power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+               #dma-cells = <1>;
+       };
+
+       eth: ethernet@1b100000 {
+               compatible = "mediatek,mt7622-eth",
+                            "mediatek,mt2701-eth",
+                            "syscon";
+               reg = <0 0x1b100000 0 0x20000>;
+               interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 225 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&topckgen CLK_TOP_ETH_SEL>,
+                        <&ethsys CLK_ETH_ESW_EN>,
+                        <&ethsys CLK_ETH_GP0_EN>,
+                        <&ethsys CLK_ETH_GP1_EN>,
+                        <&ethsys CLK_ETH_GP2_EN>,
+                        <&sgmiisys CLK_SGMII_TX250M_EN>,
+                        <&sgmiisys CLK_SGMII_RX250M_EN>,
+                        <&sgmiisys CLK_SGMII_CDR_REF>,
+                        <&sgmiisys CLK_SGMII_CDR_FB>,
+                        <&topckgen CLK_TOP_SGMIIPLL>,
+                        <&apmixedsys CLK_APMIXED_ETH2PLL>;
+               clock-names = "ethif", "esw", "gp0", "gp1", "gp2",
+                             "sgmii_tx250m", "sgmii_rx250m",
+                             "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck",
+                             "eth2pll";
+               power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+               mediatek,ethsys = <&ethsys>;
+               mediatek,sgmiisys = <&sgmiisys>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       sgmiisys: sgmiisys@1b128000 {
+               compatible = "mediatek,mt7622-sgmiisys",
+                            "syscon";
+               reg = <0 0x1b128000 0 0x3000>;
+               #clock-cells = <1>;
+               mediatek,physpeed = "2500";
+       };
+};
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig
new file mode 100644 (file)
index 0000000..cf83c6a
--- /dev/null
@@ -0,0 +1,4 @@
+
+config MT753X_GSW
+       tristate "Driver for the MediaTek MT753x switch"
+
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile
new file mode 100644 (file)
index 0000000..3829bac
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for MediaTek MT753x gigabit switch
+#
+
+obj-$(CONFIG_MT753X_GSW)       += mt753x.o
+
+mt753x-$(CONFIG_SWCONFIG)      += mt753x_swconfig.o
+
+mt753x-y                       += mt753x_mdio.o mt7530.o mt7531.o \
+                                       mt753x_common.o mt753x_nl.o
+
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c
new file mode 100644 (file)
index 0000000..45d4984
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * Driver for MediaTek MT7530 gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "mt753x.h"
+#include "mt753x_regs.h"
+
+/* MT7530 registers */
+
+/* Unique fields of PMCR for MT7530 */
+#define FORCE_MODE                     BIT(15)
+
+/* Unique fields of GMACCR for MT7530 */
+#define VLAN_SUPT_NO_S                 14
+#define VLAN_SUPT_NO_M                 0x1c000
+#define LATE_COL_DROP                  BIT(13)
+
+/* Unique fields of (M)HWSTRAP for MT7530 */
+#define BOND_OPTION                    BIT(24)
+#define P5_PHY0_SEL                    BIT(20)
+#define CHG_TRAP                       BIT(16)
+#define LOOPDET_DIS                    BIT(14)
+#define P5_INTF_SEL_GMAC5              BIT(13)
+#define SMI_ADDR_S                     11
+#define SMI_ADDR_M                     0x1800
+#define XTAL_FSEL_S                    9
+#define XTAL_FSEL_M                    0x600
+#define P6_INTF_DIS                    BIT(8)
+#define P5_INTF_MODE_RGMII             BIT(7)
+#define P5_INTF_DIS_S                  BIT(6)
+#define C_MDIO_BPS_S                   BIT(5)
+#define EEPROM_EN_S                    BIT(4)
+
+/* PHY EEE Register bitmap of define */
+#define PHY_DEV07                      0x07
+#define PHY_DEV07_REG_03C              0x3c
+
+/* PHY Extend Register 0x14 bitmap of define */
+#define PHY_EXT_REG_14                 0x14
+
+/* Fields of PHY_EXT_REG_14 */
+#define PHY_EN_DOWN_SHFIT              BIT(4)
+
+/* PHY Token Ring Register 0x10 bitmap of define */
+#define PHY_TR_REG_10                  0x10
+
+/* PHY Token Ring Register 0x12 bitmap of define */
+#define PHY_TR_REG_12                  0x12
+
+/* PHY LPI PCS/DSP Control Register bitmap of define */
+#define PHY_LPI_REG_11                 0x11
+
+/* PHY DEV 0x1e Register bitmap of define */
+#define PHY_DEV1E                      0x1e
+#define PHY_DEV1E_REG_123              0x123
+#define PHY_DEV1E_REG_A6               0xa6
+
+/* Values of XTAL_FSEL */
+#define XTAL_20MHZ                     1
+#define XTAL_40MHZ                     2
+#define XTAL_25MHZ                     3
+
+#define P6ECR                          0x7830
+#define P6_INTF_MODE_TRGMII            BIT(0)
+
+#define TRGMII_TXCTRL                  0x7a40
+#define TRAIN_TXEN                     BIT(31)
+#define TXC_INV                                BIT(30)
+#define TX_DOEO                                BIT(29)
+#define TX_RST                         BIT(28)
+
+#define TRGMII_TD0_CTRL                        0x7a50
+#define TRGMII_TD1_CTRL                        0x7a58
+#define TRGMII_TD2_CTRL                        0x7a60
+#define TRGMII_TD3_CTRL                        0x7a68
+#define TRGMII_TXCTL_CTRL              0x7a70
+#define TRGMII_TCK_CTRL                        0x7a78
+#define TRGMII_TD_CTRL(n)              (0x7a50 + (n) * 8)
+#define NUM_TRGMII_CTRL                        6
+#define TX_DMPEDRV                     BIT(31)
+#define TX_DM_SR                       BIT(15)
+#define TX_DMERODT                     BIT(14)
+#define TX_DMOECTL                     BIT(13)
+#define TX_TAP_S                       8
+#define TX_TAP_M                       0xf00
+#define TX_TRAIN_WD_S                  0
+#define TX_TRAIN_WD_M                  0xff
+
+#define TRGMII_TD0_ODT                 0x7a54
+#define TRGMII_TD1_ODT                 0x7a5c
+#define TRGMII_TD2_ODT                 0x7a64
+#define TRGMII_TD3_ODT                 0x7a6c
+#define TRGMII_TXCTL_ODT               0x7574
+#define TRGMII_TCK_ODT                 0x757c
+#define TRGMII_TD_ODT(n)               (0x7a54 + (n) * 8)
+#define NUM_TRGMII_ODT                 6
+#define TX_DM_DRVN_PRE_S               30
+#define TX_DM_DRVN_PRE_M               0xc0000000
+#define TX_DM_DRVP_PRE_S               28
+#define TX_DM_DRVP_PRE_M               0x30000000
+#define TX_DM_TDSEL_S                  24
+#define TX_DM_TDSEL_M                  0xf000000
+#define TX_ODTEN                       BIT(23)
+#define TX_DME_PRE                     BIT(20)
+#define TX_DM_DRVNT0                   BIT(19)
+#define TX_DM_DRVPT0                   BIT(18)
+#define TX_DM_DRVNTE                   BIT(17)
+#define TX_DM_DRVPTE                   BIT(16)
+#define TX_DM_ODTN_S                   12
+#define TX_DM_ODTN_M                   0x7000
+#define TX_DM_ODTP_S                   8
+#define TX_DM_ODTP_M                   0x700
+#define TX_DM_DRVN_S                   4
+#define TX_DM_DRVN_M                   0xf0
+#define TX_DM_DRVP_S                   0
+#define TX_DM_DRVP_M                   0x0f
+
+#define P5RGMIIRXCR                    0x7b00
+#define CSR_RGMII_RCTL_CFG_S           24
+#define CSR_RGMII_RCTL_CFG_M           0x7000000
+#define CSR_RGMII_RXD_CFG_S            16
+#define CSR_RGMII_RXD_CFG_M            0x70000
+#define CSR_RGMII_EDGE_ALIGN           BIT(8)
+#define CSR_RGMII_RXC_90DEG_CFG_S      4
+#define CSR_RGMII_RXC_90DEG_CFG_M      0xf0
+#define CSR_RGMII_RXC_0DEG_CFG_S       0
+#define CSR_RGMII_RXC_0DEG_CFG_M       0x0f
+
+#define P5RGMIITXCR                    0x7b04
+#define CSR_RGMII_TXEN_CFG_S           16
+#define CSR_RGMII_TXEN_CFG_M           0x70000
+#define CSR_RGMII_TXD_CFG_S            8
+#define CSR_RGMII_TXD_CFG_M            0x700
+#define CSR_RGMII_TXC_CFG_S            0
+#define CSR_RGMII_TXC_CFG_M            0x1f
+
+#define CHIP_REV                       0x7ffc
+#define CHIP_NAME_S                    16
+#define CHIP_NAME_M                    0xffff0000
+#define CHIP_REV_S                     0
+#define CHIP_REV_M                     0x0f
+
+/* MMD registers */
+#define CORE_PLL_GROUP2                        0x401
+#define RG_SYSPLL_EN_NORMAL            BIT(15)
+#define RG_SYSPLL_VODEN                        BIT(14)
+#define RG_SYSPLL_POSDIV_S             5
+#define RG_SYSPLL_POSDIV_M             0x60
+
+#define CORE_PLL_GROUP4                        0x403
+#define RG_SYSPLL_DDSFBK_EN            BIT(12)
+#define RG_SYSPLL_BIAS_EN              BIT(11)
+#define RG_SYSPLL_BIAS_LPF_EN          BIT(10)
+
+#define CORE_PLL_GROUP5                        0x404
+#define RG_LCDDS_PCW_NCPO1_S           0
+#define RG_LCDDS_PCW_NCPO1_M           0xffff
+
+#define CORE_PLL_GROUP6                        0x405
+#define RG_LCDDS_PCW_NCPO0_S           0
+#define RG_LCDDS_PCW_NCPO0_M           0xffff
+
+#define CORE_PLL_GROUP7                        0x406
+#define RG_LCDDS_PWDB                  BIT(15)
+#define RG_LCDDS_ISO_EN                        BIT(13)
+#define RG_LCCDS_C_S                   4
+#define RG_LCCDS_C_M                   0x70
+#define RG_LCDDS_PCW_NCPO_CHG          BIT(3)
+
+#define CORE_PLL_GROUP10               0x409
+#define RG_LCDDS_SSC_DELTA_S           0
+#define RG_LCDDS_SSC_DELTA_M           0xfff
+
+#define CORE_PLL_GROUP11               0x40a
+#define RG_LCDDS_SSC_DELTA1_S          0
+#define RG_LCDDS_SSC_DELTA1_M          0xfff
+
+#define CORE_GSWPLL_GCR_1              0x040d
+#define GSWPLL_PREDIV_S                        14
+#define GSWPLL_PREDIV_M                        0xc000
+#define GSWPLL_POSTDIV_200M_S          12
+#define GSWPLL_POSTDIV_200M_M          0x3000
+#define GSWPLL_EN_PRE                  BIT(11)
+#define GSWPLL_FBKSEL                  BIT(10)
+#define GSWPLL_BP                      BIT(9)
+#define GSWPLL_BR                      BIT(8)
+#define GSWPLL_FBKDIV_200M_S           0
+#define GSWPLL_FBKDIV_200M_M           0xff
+
+#define CORE_GSWPLL_GCR_2              0x040e
+#define GSWPLL_POSTDIV_500M_S          8
+#define GSWPLL_POSTDIV_500M_M          0x300
+#define GSWPLL_FBKDIV_500M_S           0
+#define GSWPLL_FBKDIV_500M_M           0xff
+
+#define TRGMII_GSW_CLK_CG              0x0410
+#define TRGMIICK_EN                    BIT(1)
+#define GSWCK_EN                       BIT(0)
+
+static int mt7530_mii_read(struct gsw_mt753x *gsw, int phy, int reg)
+{
+       if (phy < MT753X_NUM_PHYS)
+               phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK;
+
+       return mdiobus_read(gsw->host_bus, phy, reg);
+}
+
+static void mt7530_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val)
+{
+       if (phy < MT753X_NUM_PHYS)
+               phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK;
+
+       mdiobus_write(gsw->host_bus, phy, reg, val);
+}
+
+static int mt7530_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg)
+{
+       u16 val;
+
+       if (addr < MT753X_NUM_PHYS)
+               addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->host_bus->mdio_lock);
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG,
+                            (MMD_ADDR << MMD_CMD_S) |
+                            ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG, reg);
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG,
+                            (MMD_DATA << MMD_CMD_S) |
+                            ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+
+       val = gsw->host_bus->read(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG);
+
+       mutex_unlock(&gsw->host_bus->mdio_lock);
+
+       return val;
+}
+
+static void mt7530_mmd_write(struct gsw_mt753x *gsw, int addr, int devad,
+                            u16 reg, u16 val)
+{
+       if (addr < MT753X_NUM_PHYS)
+               addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->host_bus->mdio_lock);
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG,
+                     (MMD_ADDR << MMD_CMD_S) |
+                     ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG, reg);
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG,
+                     (MMD_DATA << MMD_CMD_S) |
+                     ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+
+       gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG, val);
+
+       mutex_unlock(&gsw->host_bus->mdio_lock);
+}
+
+static void mt7530_core_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
+{
+       gsw->mmd_write(gsw, 0, 0x1f, reg, val);
+}
+
+static int mt7530_mac_port_setup(struct gsw_mt753x *gsw)
+{
+       u32 hwstrap, p6ecr = 0, p5mcr, p6mcr, phyad;
+
+       hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+       hwstrap &= ~(P6_INTF_DIS | P5_INTF_MODE_RGMII | P5_INTF_DIS_S);
+       hwstrap |= CHG_TRAP | P5_INTF_SEL_GMAC5;
+
+       if (gsw->direct_phy_access)
+               hwstrap &= ~C_MDIO_BPS_S;
+       else
+               hwstrap |= C_MDIO_BPS_S;
+
+       if (!gsw->port5_cfg.enabled) {
+               p5mcr = FORCE_MODE;
+               hwstrap |= P5_INTF_DIS_S;
+       } else {
+               p5mcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
+                       MAC_MODE | MAC_TX_EN | MAC_RX_EN |
+                       BKOFF_EN | BACKPR_EN;
+
+               if (gsw->port5_cfg.force_link) {
+                       p5mcr |= FORCE_MODE | FORCE_LINK | FORCE_RX_FC |
+                                FORCE_TX_FC;
+                       p5mcr |= gsw->port5_cfg.speed << FORCE_SPD_S;
+
+                       if (gsw->port5_cfg.duplex)
+                               p5mcr |= FORCE_DPX;
+               }
+
+               switch (gsw->port5_cfg.phy_mode) {
+               case PHY_INTERFACE_MODE_MII:
+               case PHY_INTERFACE_MODE_GMII:
+                       break;
+               case PHY_INTERFACE_MODE_RGMII:
+                       hwstrap |= P5_INTF_MODE_RGMII;
+                       break;
+               default:
+                       dev_info(gsw->dev, "%s is not supported by port5\n",
+                                phy_modes(gsw->port5_cfg.phy_mode));
+                       p5mcr = FORCE_MODE;
+                       hwstrap |= P5_INTF_DIS_S;
+               }
+
+               /* Port5 to PHY direct mode */
+               if (of_property_read_u32(gsw->port5_cfg.np, "phy-address",
+                                        &phyad))
+                       goto parse_p6;
+
+               if (phyad != 0 && phyad != 4) {
+                       dev_info(gsw->dev,
+                                "Only PHY 0/4 can be connected to Port 5\n");
+                       goto parse_p6;
+               }
+
+               hwstrap &= ~P5_INTF_SEL_GMAC5;
+               if (phyad == 0)
+                       hwstrap |= P5_PHY0_SEL;
+               else
+                       hwstrap &= ~P5_PHY0_SEL;
+       }
+
+parse_p6:
+       if (!gsw->port6_cfg.enabled) {
+               p6mcr = FORCE_MODE;
+               hwstrap |= P6_INTF_DIS;
+       } else {
+               p6mcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
+                       MAC_MODE | MAC_TX_EN | MAC_RX_EN |
+                       BKOFF_EN | BACKPR_EN;
+
+               if (gsw->port6_cfg.force_link) {
+                       p6mcr |= FORCE_MODE | FORCE_LINK | FORCE_RX_FC |
+                                FORCE_TX_FC;
+                       p6mcr |= gsw->port6_cfg.speed << FORCE_SPD_S;
+
+                       if (gsw->port6_cfg.duplex)
+                               p6mcr |= FORCE_DPX;
+               }
+
+               switch (gsw->port6_cfg.phy_mode) {
+               case PHY_INTERFACE_MODE_RGMII:
+                       break;
+               case PHY_INTERFACE_MODE_TRGMII:
+                       /* set MT7530 central align */
+                       p6ecr = BIT(1); /* TODO: confirm this */
+                       break;
+               default:
+                       dev_info(gsw->dev, "%s is not supported by port6\n",
+                                phy_modes(gsw->port6_cfg.phy_mode));
+                       p6mcr = FORCE_MODE;
+                       hwstrap |= P6_INTF_DIS;
+               }
+       }
+
+       mt753x_reg_write(gsw, MHWSTRAP, hwstrap);
+       mt753x_reg_write(gsw, P6ECR, p6ecr);
+
+       mt753x_reg_write(gsw, PMCR(5), p5mcr);
+       mt753x_reg_write(gsw, PMCR(6), p6mcr);
+
+       return 0;
+}
+
+static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
+{
+       u32 hwstrap, val, ncpo1, ssc_delta;
+       int i;
+
+       hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+
+       switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) {
+       case XTAL_40MHZ:
+               /* Disable MT7530 core clock */
+               mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, 0);
+
+               /* disable MT7530 PLL */
+               mt7530_core_reg_write(gsw, CORE_GSWPLL_GCR_1,
+                                     (2 << GSWPLL_POSTDIV_200M_S) |
+                                     (32 << GSWPLL_FBKDIV_200M_S));
+
+               /* For MT7530 core clock = 500Mhz */
+               mt7530_core_reg_write(gsw, CORE_GSWPLL_GCR_2,
+                                     (1 << GSWPLL_POSTDIV_500M_S) |
+                                     (25 << GSWPLL_FBKDIV_500M_S));
+
+               /* Enable MT7530 PLL */
+               mt7530_core_reg_write(gsw, CORE_GSWPLL_GCR_1,
+                                     (2 << GSWPLL_POSTDIV_200M_S) |
+                                     (32 << GSWPLL_FBKDIV_200M_S) |
+                                     GSWPLL_EN_PRE);
+
+               usleep_range(20, 40);
+
+               /* Enable MT7530 core clock */
+               mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN);
+               break;
+       default:
+               /* TODO: PLL settings for 20/25MHz */
+               break;
+       }
+
+       if (gsw->port6_cfg.enabled &&
+           gsw->port6_cfg.phy_mode == PHY_INTERFACE_MODE_TRGMII) {
+               ncpo1 = 0x1400;
+               ssc_delta = 0x57;
+       } else {
+               /* RGMII */
+               ncpo1 = 0x0c80;
+               ssc_delta = 0x87;
+       }
+
+       /* Setup the MT7530 TRGMII Tx Clock */
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, ncpo1);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, ssc_delta);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, ssc_delta);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
+                             RG_SYSPLL_DDSFBK_EN |
+                             RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
+
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP2,
+                             RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
+                             (1 << RG_SYSPLL_POSDIV_S));
+
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP7,
+                             RG_LCDDS_PCW_NCPO_CHG | (3 << RG_LCCDS_C_S) |
+                             RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
+
+       /* Enable MT7530 TRGMII clock */
+       mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN);
+
+       val = mt753x_reg_read(gsw, TRGMII_TXCTRL);
+       val &= ~TXC_INV;
+       mt753x_reg_write(gsw, TRGMII_TXCTRL, val);
+
+       /* lower Tx Driving */
+       for (i = 0 ; i < NUM_TRGMII_ODT; i++)
+               mt753x_reg_write(gsw, TRGMII_TD_ODT(i),
+                                (8 << TX_DM_DRVP_S) | (8 << TX_DM_DRVN_S));
+
+       mt753x_reg_write(gsw, TRGMII_TCK_CTRL,
+                        (8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S));
+
+       /* delay setting for 10/1000M */
+       mt753x_reg_write(gsw, P5RGMIIRXCR,
+                        CSR_RGMII_EDGE_ALIGN |
+                        (2 << CSR_RGMII_RXC_0DEG_CFG_S));
+       mt753x_reg_write(gsw, P5RGMIITXCR, 0x14 << CSR_RGMII_TXC_CFG_S);
+}
+
+static int mt7530_sw_detect(struct gsw_mt753x *gsw, struct chip_rev *crev)
+{
+       u32 rev;
+
+       rev = mt753x_reg_read(gsw, CHIP_REV);
+
+       if (((rev & CHIP_NAME_M) >> CHIP_NAME_S) == MT7530) {
+               if (crev) {
+                       crev->rev = rev & CHIP_REV_M;
+                       crev->name = "MT7530";
+               }
+
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static void mt7530_phy_setting(struct gsw_mt753x *gsw)
+{
+       int i;
+       u32 val;
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               /* Disable EEE */
+               gsw->mmd_write(gsw, i, PHY_DEV07, PHY_DEV07_REG_03C, 0);
+
+               /* Enable HW auto downshift */
+               gsw->mii_write(gsw, i, 0x1f, 0x1);
+               val = gsw->mii_read(gsw, i, PHY_EXT_REG_14);
+               val |= PHY_EN_DOWN_SHFIT;
+               gsw->mii_write(gsw, i, PHY_EXT_REG_14, val);
+
+               /* Increase SlvDPSready time */
+               gsw->mii_write(gsw, i, 0x1f, 0x52b5);
+               gsw->mii_write(gsw, i, PHY_TR_REG_10, 0xafae);
+               gsw->mii_write(gsw, i, PHY_TR_REG_12, 0x2f);
+               gsw->mii_write(gsw, i, PHY_TR_REG_10, 0x8fae);
+
+               /* Increase post_update_timer */
+               gsw->mii_write(gsw, i, 0x1f, 0x3);
+               gsw->mii_write(gsw, i, PHY_LPI_REG_11, 0x4b);
+               gsw->mii_write(gsw, i, 0x1f, 0);
+
+               /* Adjust 100_mse_threshold */
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_123, 0xffff);
+
+               /* Disable mcc */
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_A6, 0x300);
+       }
+}
+
+static int mt7530_sw_init(struct gsw_mt753x *gsw)
+{
+       int i;
+       u32 val;
+
+       gsw->direct_phy_access = of_property_read_bool(gsw->dev->of_node,
+                                               "mt7530,direct-phy-access");
+
+       /* Force MT7530 to use (in)direct PHY access */
+       val = mt753x_reg_read(gsw, HWSTRAP);
+       val |= CHG_TRAP;
+       if (gsw->direct_phy_access)
+               val &= ~C_MDIO_BPS_S;
+       else
+               val |= C_MDIO_BPS_S;
+       mt753x_reg_write(gsw, MHWSTRAP, val);
+
+       /* Read PHY address base from HWSTRAP */
+       gsw->phy_base  = (((val & SMI_ADDR_M) >> SMI_ADDR_S) << 3) + 8;
+       gsw->phy_base &= MT753X_SMI_ADDR_MASK;
+
+       if (gsw->direct_phy_access) {
+               gsw->mii_read = mt7530_mii_read;
+               gsw->mii_write = mt7530_mii_write;
+               gsw->mmd_read = mt7530_mmd_read;
+               gsw->mmd_write = mt7530_mmd_write;
+       } else {
+               gsw->mii_read = mt753x_mii_read;
+               gsw->mii_write = mt753x_mii_write;
+               gsw->mmd_read = mt753x_mmd_ind_read;
+               gsw->mmd_write = mt753x_mmd_ind_write;
+       }
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               val = gsw->mii_read(gsw, i, MII_BMCR);
+               val |= BMCR_PDOWN;
+               gsw->mii_write(gsw, i, MII_BMCR, val);
+       }
+
+       /* Force MAC link down before reset */
+       mt753x_reg_write(gsw, PMCR(5), FORCE_MODE);
+       mt753x_reg_write(gsw, PMCR(6), FORCE_MODE);
+
+       /* Switch soft reset */
+       /* BUG: sw reset causes gsw int flooding */
+       mt753x_reg_write(gsw, SYS_CTRL, SW_PHY_RST | SW_SYS_RST | SW_REG_RST);
+       usleep_range(10, 20);
+
+       /* global mac control settings configuration */
+       mt753x_reg_write(gsw, GMACCR,
+                        LATE_COL_DROP | (15 << MTCC_LMT_S) |
+                        (2 << MAX_RX_JUMBO_S) | RX_PKT_LEN_MAX_JUMBO);
+
+       mt7530_core_pll_setup(gsw);
+       mt7530_mac_port_setup(gsw);
+
+       return 0;
+}
+
+static int mt7530_sw_post_init(struct gsw_mt753x *gsw)
+{
+       int i;
+       u32 val;
+
+       mt7530_phy_setting(gsw);
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               val = gsw->mii_read(gsw, i, MII_BMCR);
+               val &= ~BMCR_PDOWN;
+               gsw->mii_write(gsw, i, MII_BMCR, val);
+       }
+
+       return 0;
+}
+
+struct mt753x_sw_id mt7530_id = {
+       .model = MT7530,
+       .detect = mt7530_sw_detect,
+       .init = mt7530_sw_init,
+       .post_init = mt7530_sw_post_init
+};
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h
new file mode 100644 (file)
index 0000000..b4c8a02
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MT7530_H_
+#define _MT7530_H_
+
+#include "mt753x.h"
+
+extern struct mt753x_sw_id mt7530_id;
+
+#endif /* _MT7530_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c
new file mode 100644 (file)
index 0000000..4d44141
--- /dev/null
@@ -0,0 +1,851 @@
+/*
+ * Driver for MediaTek MT7531 gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Zhanguo Ju <zhanguo.ju@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+
+#include "mt753x.h"
+#include "mt753x_regs.h"
+
+/* MT7531 registers */
+#define SGMII_REG_BASE                 0x5000
+#define SGMII_REG_PORT_BASE            0x1000
+#define SGMII_REG(p, r)                        (SGMII_REG_BASE + \
+                                       (p) * SGMII_REG_PORT_BASE + (r))
+#define PCS_CONTROL_1(p)               SGMII_REG(p, 0x00)
+#define SGMII_MODE(p)                  SGMII_REG(p, 0x20)
+#define QPHY_PWR_STATE_CTRL(p)         SGMII_REG(p, 0xe8)
+#define PHYA_CTRL_SIGNAL3(p)           SGMII_REG(p, 0x128)
+
+/* Fields of PCS_CONTROL_1 */
+#define SGMII_LINK_STATUS              BIT(18)
+#define SGMII_AN_ENABLE                        BIT(12)
+#define SGMII_AN_RESTART               BIT(9)
+
+/* Fields of SGMII_MODE */
+#define SGMII_REMOTE_FAULT_DIS         BIT(8)
+#define SGMII_IF_MODE_FORCE_DUPLEX     BIT(4)
+#define SGMII_IF_MODE_FORCE_SPEED_S    0x2
+#define SGMII_IF_MODE_FORCE_SPEED_M    0x0c
+#define SGMII_IF_MODE_ADVERT_AN                BIT(1)
+
+/* Values of SGMII_IF_MODE_FORCE_SPEED */
+#define SGMII_IF_MODE_FORCE_SPEED_10   0
+#define SGMII_IF_MODE_FORCE_SPEED_100  1
+#define SGMII_IF_MODE_FORCE_SPEED_1000 2
+
+/* Fields of QPHY_PWR_STATE_CTRL */
+#define PHYA_PWD                       BIT(4)
+
+/* Fields of PHYA_CTRL_SIGNAL3 */
+#define RG_TPHY_SPEED_S                        2
+#define RG_TPHY_SPEED_M                        0x0c
+
+/* Values of RG_TPHY_SPEED */
+#define RG_TPHY_SPEED_1000             0
+#define RG_TPHY_SPEED_2500             1
+
+/* Unique fields of (M)HWSTRAP for MT7531 */
+#define XTAL_FSEL_S                    7
+#define XTAL_FSEL_M                    BIT(7)
+#define PHY_EN                         BIT(6)
+#define CHG_STRAP                      BIT(8)
+
+/* Efuse Register Define */
+#define GBE_EFUSE                      0x7bc8
+#define GBE_SEL_EFUSE_EN               BIT(0)
+
+/* PHY ENABLE Register bitmap define */
+#define PHY_DEV1F                      0x1f
+#define PHY_DEV1F_REG_44               0x44
+#define PHY_DEV1F_REG_268              0x268
+#define PHY_DEV1F_REG_269              0x269
+#define PHY_DEV1F_REG_403              0x403
+
+/* Fields of PHY_DEV1F_REG_403 */
+#define GBE_EFUSE_SETTING              BIT(3)
+#define PHY_EN_BYPASS_MODE             BIT(4)
+#define POWER_ON_OFF                   BIT(5)
+
+/* PHY EEE Register bitmap of define */
+#define PHY_DEV07                      0x07
+#define PHY_DEV07_REG_03C              0x3c
+
+/* PHY Extend Register 0x14 bitmap of define */
+#define PHY_EXT_REG_14                 0x14
+
+/* Fields of PHY_EXT_REG_14 */
+#define PHY_EN_DOWN_SHFIT              BIT(4)
+
+/* PHY Extend Register 0x17 bitmap of define */
+#define PHY_EXT_REG_17                 0x17
+
+/* Fields of PHY_EXT_REG_17 */
+#define PHY_LINKDOWN_POWER_SAVING_EN   BIT(4)
+
+/* PHY Token Ring Register 0x10 bitmap of define */
+#define PHY_TR_REG_10                  0x10
+
+/* PHY Token Ring Register 0x12 bitmap of define */
+#define PHY_TR_REG_12                  0x12
+
+/* PHY DEV 0x1e Register bitmap of define */
+#define PHY_DEV1E                      0x1e
+#define PHY_DEV1E_REG_13               0x13
+#define PHY_DEV1E_REG_14               0x14
+#define PHY_DEV1E_REG_41               0x41
+#define PHY_DEV1E_REG_A6               0xa6
+#define PHY_DEV1E_REG_0C6              0x0c6
+#define PHY_DEV1E_REG_0FE              0x0fe
+#define PHY_DEV1E_REG_123              0x123
+#define PHY_DEV1E_REG_189              0x189
+
+/* Fields of PHY_DEV1E_REG_0C6 */
+#define PHY_POWER_SAVING_S             8
+#define PHY_POWER_SAVING_M             0x300
+#define PHY_POWER_SAVING_TX            0x0
+
+/* Fields of PHY_DEV1E_REG_189 */
+#define DESCRAMBLER_CLEAR_EN           0x1
+
+/* Values of XTAL_FSEL_S */
+#define XTAL_40MHZ                     0
+#define XTAL_25MHZ                     1
+
+#define PLLGP_EN                       0x7820
+#define EN_COREPLL                     BIT(2)
+#define SW_CLKSW                       BIT(1)
+#define SW_PLLGP                       BIT(0)
+
+#define PLLGP_CR0                      0x78a8
+#define RG_COREPLL_EN                  BIT(22)
+#define RG_COREPLL_POSDIV_S            23
+#define RG_COREPLL_POSDIV_M            0x3800000
+#define RG_COREPLL_SDM_PCW_S           1
+#define RG_COREPLL_SDM_PCW_M           0x3ffffe
+#define RG_COREPLL_SDM_PCW_CHG         BIT(0)
+
+/* TOP Signals Status Register */
+#define TOP_SIG_SR                     0x780c
+#define PAD_DUAL_SGMII_EN              BIT(1)
+
+/* RGMII and SGMII PLL clock */
+#define ANA_PLLGP_CR2                  0x78b0
+#define ANA_PLLGP_CR5                  0x78bc
+
+/* GPIO mode define */
+#define GPIO_MODE_REGS(x)              (0x7c0c + ((x / 8) * 4))
+#define GPIO_MODE_S                    4
+
+/* GPIO GROUP IOLB SMT0 Control */
+#define SMT0_IOLB                      0x7f04
+#define SMT_IOLB_5_SMI_MDC_EN          BIT(5)
+
+/* Unique fields of PMCR for MT7531 */
+#define FORCE_MODE_EEE1G               BIT(25)
+#define FORCE_MODE_EEE100              BIT(26)
+#define FORCE_MODE_TX_FC               BIT(27)
+#define FORCE_MODE_RX_FC               BIT(28)
+#define FORCE_MODE_DPX                 BIT(29)
+#define FORCE_MODE_SPD                 BIT(30)
+#define FORCE_MODE_LNK                 BIT(31)
+#define FORCE_MODE                     BIT(15)
+
+#define CHIP_REV                       0x781C
+#define CHIP_NAME_S                    16
+#define CHIP_NAME_M                    0xffff0000
+#define CHIP_REV_S                     0
+#define CHIP_REV_M                     0x0f
+#define CHIP_REV_E1                    0x0
+
+#define CLKGEN_CTRL                    0x7500
+#define CLK_SKEW_OUT_S                 8
+#define CLK_SKEW_OUT_M                 0x300
+#define CLK_SKEW_IN_S                  6
+#define CLK_SKEW_IN_M                  0xc0
+#define RXCLK_NO_DELAY                 BIT(5)
+#define TXCLK_NO_REVERSE               BIT(4)
+#define GP_MODE_S                      1
+#define GP_MODE_M                      0x06
+#define GP_CLK_EN                      BIT(0)
+
+/* Values of GP_MODE */
+#define GP_MODE_RGMII                  0
+#define GP_MODE_MII                    1
+#define GP_MODE_REV_MII                        2
+
+/* Values of CLK_SKEW_IN */
+#define CLK_SKEW_IN_NO_CHANGE          0
+#define CLK_SKEW_IN_DELAY_100PPS       1
+#define CLK_SKEW_IN_DELAY_200PPS       2
+#define CLK_SKEW_IN_REVERSE            3
+
+/* Values of CLK_SKEW_OUT */
+#define CLK_SKEW_OUT_NO_CHANGE         0
+#define CLK_SKEW_OUT_DELAY_100PPS      1
+#define CLK_SKEW_OUT_DELAY_200PPS      2
+#define CLK_SKEW_OUT_REVERSE           3
+
+/* Proprietory Control Register of Internal Phy device 0x1e */
+#define RXADC_CONTROL_3                        0xc2
+#define RXADC_LDO_CONTROL_2            0xd3
+
+/* Proprietory Control Register of Internal Phy device 0x1f */
+#define TXVLD_DA_271                   0x271
+#define TXVLD_DA_272                   0x272
+#define TXVLD_DA_273                   0x273
+
+/* DSP Channel and NOD_ADDR*/
+#define DSP_CH                         0x2
+#define DSP_NOD_ADDR                   0xD
+
+/* gpio pinmux pins and functions define */
+static int gpio_int_pins[] = {0};
+static int gpio_int_funcs[] = {1};
+static int gpio_mdc_pins[] = {11, 20};
+static int gpio_mdc_funcs[] = {2, 2};
+static int gpio_mdio_pins[] = {12, 21};
+static int gpio_mdio_funcs[] = {2, 2};
+
+static int mt7531_set_port_sgmii_force_mode(struct gsw_mt753x *gsw, u32 port,
+                                           struct mt753x_port_cfg *port_cfg)
+{
+       u32 speed, port_base, val;
+       ktime_t timeout;
+       u32 timeout_us;
+
+       if (port < 5 || port >= MT753X_NUM_PORTS) {
+               dev_info(gsw->dev, "port %d is not a SGMII port\n", port);
+               return -EINVAL;
+       }
+
+       port_base = port - 5;
+
+       switch (port_cfg->speed) {
+       case MAC_SPD_1000:
+               speed = RG_TPHY_SPEED_1000;
+               break;
+       case MAC_SPD_2500:
+               speed = RG_TPHY_SPEED_2500;
+               break;
+       default:
+               dev_info(gsw->dev, "invalid SGMII speed idx %d for port %d\n",
+                        port_cfg->speed, port);
+
+               speed = RG_TPHY_SPEED_1000;
+       }
+
+       /* Step 1: Speed select register setting */
+       val = mt753x_reg_read(gsw, PHYA_CTRL_SIGNAL3(port_base));
+       val &= ~RG_TPHY_SPEED_M;
+       val |= speed << RG_TPHY_SPEED_S;
+       mt753x_reg_write(gsw, PHYA_CTRL_SIGNAL3(port_base), val);
+
+       /* Step 2 : Disable AN */
+       val = mt753x_reg_read(gsw, PCS_CONTROL_1(port_base));
+       val &= ~SGMII_AN_ENABLE;
+       mt753x_reg_write(gsw, PCS_CONTROL_1(port_base), val);
+
+       /* Step 3: SGMII force mode setting */
+       val = mt753x_reg_read(gsw, SGMII_MODE(port_base));
+       val &= ~SGMII_IF_MODE_ADVERT_AN;
+       val &= ~SGMII_IF_MODE_FORCE_SPEED_M;
+       val |= SGMII_IF_MODE_FORCE_SPEED_1000 << SGMII_IF_MODE_FORCE_SPEED_S;
+       val |= SGMII_IF_MODE_FORCE_DUPLEX;
+       /* For sgmii force mode, 0 is full duplex and 1 is half duplex */
+       if (port_cfg->duplex)
+               val &= ~SGMII_IF_MODE_FORCE_DUPLEX;
+
+       mt753x_reg_write(gsw, SGMII_MODE(port_base), val);
+
+       /* Step 4: XXX: Disable Link partner's AN and set force mode */
+
+       /* Step 5: XXX: Special setting for PHYA ==> reserved for flexible */
+
+       /* Step 6 : Release PHYA power down state */
+       val = mt753x_reg_read(gsw, QPHY_PWR_STATE_CTRL(port_base));
+       val &= ~PHYA_PWD;
+       mt753x_reg_write(gsw, QPHY_PWR_STATE_CTRL(port_base), val);
+
+       /* Step 7 : Polling SGMII_LINK_STATUS */
+       timeout_us = 2000000;
+       timeout = ktime_add_us(ktime_get(), timeout_us);
+       while (1) {
+               val = mt753x_reg_read(gsw, PCS_CONTROL_1(port_base));
+               val &= SGMII_LINK_STATUS;
+
+               if (val)
+                       break;
+
+               if (ktime_compare(ktime_get(), timeout) > 0)
+                       return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int mt7531_set_port_sgmii_an_mode(struct gsw_mt753x *gsw, u32 port,
+                                        struct mt753x_port_cfg *port_cfg)
+{
+       u32 speed, port_base, val;
+       ktime_t timeout;
+       u32 timeout_us;
+
+       if (port < 5 || port >= MT753X_NUM_PORTS) {
+               dev_info(gsw->dev, "port %d is not a SGMII port\n", port);
+               return -EINVAL;
+       }
+
+       port_base = port - 5;
+
+       switch (port_cfg->speed) {
+       case MAC_SPD_1000:
+               speed = RG_TPHY_SPEED_1000;
+               break;
+       case MAC_SPD_2500:
+               speed = RG_TPHY_SPEED_2500;
+               break;
+       default:
+               dev_info(gsw->dev, "invalid SGMII speed idx %d for port %d\n",
+                        port_cfg->speed, port);
+
+               speed = RG_TPHY_SPEED_1000;
+       }
+
+       /* Step 1: Speed select register setting */
+       val = mt753x_reg_read(gsw, PHYA_CTRL_SIGNAL3(port_base));
+       val &= ~RG_TPHY_SPEED_M;
+       val |= speed << RG_TPHY_SPEED_S;
+       mt753x_reg_write(gsw, PHYA_CTRL_SIGNAL3(port_base), val);
+
+       /* Step 2: Remote fault disable */
+       val = mt753x_reg_read(gsw, SGMII_MODE(port));
+       val |= SGMII_REMOTE_FAULT_DIS;
+       mt753x_reg_write(gsw, SGMII_MODE(port), val);
+
+       /* Step 3: Setting Link partner's AN enable = 1 */
+
+       /* Step 4: Setting Link partner's device ability for speed/duplex */
+
+       /* Step 5: AN re-start */
+       val = mt753x_reg_read(gsw, PCS_CONTROL_1(port));
+       val |= SGMII_AN_RESTART;
+       mt753x_reg_write(gsw, PCS_CONTROL_1(port), val);
+
+       /* Step 6: Special setting for PHYA ==> reserved for flexible */
+
+       /* Step 7 : Polling SGMII_LINK_STATUS */
+       timeout_us = 2000000;
+       timeout = ktime_add_us(ktime_get(), timeout_us);
+       while (1) {
+               val = mt753x_reg_read(gsw, PCS_CONTROL_1(port_base));
+               val &= SGMII_LINK_STATUS;
+
+               if (val)
+                       break;
+
+               if (ktime_compare(ktime_get(), timeout) > 0)
+                       return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int mt7531_set_port_rgmii(struct gsw_mt753x *gsw, u32 port)
+{
+       u32 val;
+
+       if (port != 5) {
+               dev_info(gsw->dev, "RGMII mode is not available for port %d\n",
+                        port);
+               return -EINVAL;
+       }
+
+       val = mt753x_reg_read(gsw, CLKGEN_CTRL);
+       val |= GP_CLK_EN;
+       val &= ~GP_MODE_M;
+       val |= GP_MODE_RGMII << GP_MODE_S;
+       val |= TXCLK_NO_REVERSE;
+       val |= RXCLK_NO_DELAY;
+       val &= ~CLK_SKEW_IN_M;
+       val |= CLK_SKEW_IN_NO_CHANGE << CLK_SKEW_IN_S;
+       val &= ~CLK_SKEW_OUT_M;
+       val |= CLK_SKEW_OUT_NO_CHANGE << CLK_SKEW_OUT_S;
+       mt753x_reg_write(gsw, CLKGEN_CTRL, val);
+
+       return 0;
+}
+
+static int mt7531_mac_port_setup(struct gsw_mt753x *gsw, u32 port,
+                                struct mt753x_port_cfg *port_cfg)
+{
+       u32 pmcr;
+       u32 speed;
+
+       if (port < 5 || port >= MT753X_NUM_PORTS) {
+               dev_info(gsw->dev, "port %d is not a MAC port\n", port);
+               return -EINVAL;
+       }
+
+       if (port_cfg->enabled) {
+               pmcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
+                      MAC_MODE | MAC_TX_EN | MAC_RX_EN |
+                      BKOFF_EN | BACKPR_EN;
+
+               if (port_cfg->force_link) {
+                       /* PMCR's speed field 0x11 is reserved,
+                        * sw should set 0x10
+                        */
+                       speed = port_cfg->speed;
+                       if (port_cfg->speed == MAC_SPD_2500)
+                               speed = MAC_SPD_1000;
+
+                       pmcr |= FORCE_MODE_LNK | FORCE_LINK |
+                               FORCE_MODE_SPD | FORCE_MODE_DPX |
+                               FORCE_MODE_RX_FC | FORCE_MODE_TX_FC |
+                               FORCE_RX_FC | FORCE_TX_FC |
+                               (speed << FORCE_SPD_S);
+
+                       if (port_cfg->duplex)
+                               pmcr |= FORCE_DPX;
+               }
+       } else {
+               pmcr = FORCE_MODE_LNK;
+       }
+
+       switch (port_cfg->phy_mode) {
+       case PHY_INTERFACE_MODE_RGMII:
+               mt7531_set_port_rgmii(gsw, port);
+               break;
+       case PHY_INTERFACE_MODE_SGMII:
+               if (port_cfg->force_link)
+                       mt7531_set_port_sgmii_force_mode(gsw, port, port_cfg);
+               else
+                       mt7531_set_port_sgmii_an_mode(gsw, port, port_cfg);
+               break;
+       default:
+               if (port_cfg->enabled)
+                       dev_info(gsw->dev, "%s is not supported by port %d\n",
+                                phy_modes(port_cfg->phy_mode), port);
+
+               pmcr = FORCE_MODE_LNK;
+       }
+
+       mt753x_reg_write(gsw, PMCR(port), pmcr);
+
+       return 0;
+}
+
+static void mt7531_core_pll_setup(struct gsw_mt753x *gsw)
+{
+       u32 hwstrap;
+       u32 val;
+
+       val = mt753x_reg_read(gsw, TOP_SIG_SR);
+       if (val & PAD_DUAL_SGMII_EN)
+               return;
+
+       hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+
+       switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) {
+       case XTAL_25MHZ:
+               /* Step 1 : Disable MT7531 COREPLL */
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val &= ~EN_COREPLL;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+
+               /* Step 2: switch to XTAL output */
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val |= SW_CLKSW;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_EN;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               /* Step 3: disable PLLGP and enable program PLLGP */
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val |= SW_PLLGP;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+
+               /* Step 4: program COREPLL output frequency to 500MHz */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_POSDIV_M;
+               val |= 2 << RG_COREPLL_POSDIV_S;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+               usleep_range(25, 35);
+
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_SDM_PCW_M;
+               val |= 0x140000 << RG_COREPLL_SDM_PCW_S;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               /* Set feedback divide ratio update signal to high */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val |= RG_COREPLL_SDM_PCW_CHG;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+               /* Wait for at least 16 XTAL clocks */
+               usleep_range(10, 20);
+
+               /* Step 5: set feedback divide ratio update signal to low */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_SDM_PCW_CHG;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               /* Enable 325M clock for SGMII */
+               mt753x_reg_write(gsw, ANA_PLLGP_CR5, 0xad0000);
+
+               /* Enable 250SSC clock for RGMII */
+               mt753x_reg_write(gsw, ANA_PLLGP_CR2, 0x4f40000);
+
+               /* Step 6: Enable MT7531 PLL */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val |= RG_COREPLL_EN;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val |= EN_COREPLL;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+               usleep_range(25, 35);
+
+               break;
+       case XTAL_40MHZ:
+               /* Step 1 : Disable MT7531 COREPLL */
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val &= ~EN_COREPLL;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+
+               /* Step 2: switch to XTAL output */
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val |= SW_CLKSW;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_EN;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               /* Step 3: disable PLLGP and enable program PLLGP */
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val |= SW_PLLGP;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+
+               /* Step 4: program COREPLL output frequency to 500MHz */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_POSDIV_M;
+               val |= 2 << RG_COREPLL_POSDIV_S;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+               usleep_range(25, 35);
+
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_SDM_PCW_M;
+               val |= 0x190000 << RG_COREPLL_SDM_PCW_S;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               /* Set feedback divide ratio update signal to high */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val |= RG_COREPLL_SDM_PCW_CHG;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+               /* Wait for at least 16 XTAL clocks */
+               usleep_range(10, 20);
+
+               /* Step 5: set feedback divide ratio update signal to low */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val &= ~RG_COREPLL_SDM_PCW_CHG;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               /* Enable 325M clock for SGMII */
+               mt753x_reg_write(gsw, ANA_PLLGP_CR5, 0xad0000);
+
+               /* Enable 250SSC clock for RGMII */
+               mt753x_reg_write(gsw, ANA_PLLGP_CR2, 0x4f40000);
+
+               /* Step 6: Enable MT7531 PLL */
+               val = mt753x_reg_read(gsw, PLLGP_CR0);
+               val |= RG_COREPLL_EN;
+               mt753x_reg_write(gsw, PLLGP_CR0, val);
+
+               val = mt753x_reg_read(gsw, PLLGP_EN);
+               val |= EN_COREPLL;
+               mt753x_reg_write(gsw, PLLGP_EN, val);
+               usleep_range(25, 35);
+               break;
+       }
+}
+
+static int mt7531_internal_phy_calibration(struct gsw_mt753x *gsw)
+{
+       return 0;
+}
+
+static int mt7531_sw_detect(struct gsw_mt753x *gsw, struct chip_rev *crev)
+{
+       u32 rev, topsig;
+
+       rev = mt753x_reg_read(gsw, CHIP_REV);
+
+       if (((rev & CHIP_NAME_M) >> CHIP_NAME_S) == MT7531) {
+               if (crev) {
+                       topsig = mt753x_reg_read(gsw, TOP_SIG_SR);
+
+                       crev->rev = rev & CHIP_REV_M;
+                       crev->name = topsig & PAD_DUAL_SGMII_EN ?
+                                    "MT7531AE" : "MT7531BE";
+               }
+
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static void pinmux_set_mux_7531(struct gsw_mt753x *gsw, u32 pin, u32 mode)
+{
+       u32 val;
+
+       val = mt753x_reg_read(gsw, GPIO_MODE_REGS(pin));
+       val &= ~(0xf << (pin & 7) * GPIO_MODE_S);
+       val |= mode << (pin & 7) * GPIO_MODE_S;
+       mt753x_reg_write(gsw, GPIO_MODE_REGS(pin), val);
+}
+
+static int mt7531_set_gpio_pinmux(struct gsw_mt753x *gsw)
+{
+       u32 group = 0;
+       struct device_node *np = gsw->dev->of_node;
+
+       /* Set GPIO 0 interrupt mode */
+       pinmux_set_mux_7531(gsw, gpio_int_pins[0], gpio_int_funcs[0]);
+
+       of_property_read_u32(np, "mediatek,mdio_master_pinmux", &group);
+
+       /* group = 0: do nothing, 1: 1st group (AE), 2: 2nd group (BE) */
+       if (group > 0 && group <= 2) {
+               group--;
+               pinmux_set_mux_7531(gsw, gpio_mdc_pins[group],
+                                   gpio_mdc_funcs[group]);
+               pinmux_set_mux_7531(gsw, gpio_mdio_pins[group],
+                                   gpio_mdio_funcs[group]);
+       }
+
+       return 0;
+}
+
+static void mt7531_phy_setting(struct gsw_mt753x *gsw)
+{
+       int i;
+       u32 val;
+
+       /* Adjust DAC TX Delay */
+       gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_44, 0xc0);
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               /* Disable EEE */
+               gsw->mmd_write(gsw, i, PHY_DEV07, PHY_DEV07_REG_03C, 0);
+
+               /* Enable HW auto downshift */
+               gsw->mii_write(gsw, i, 0x1f, 0x1);
+               val = gsw->mii_read(gsw, i, PHY_EXT_REG_14);
+               val |= PHY_EN_DOWN_SHFIT;
+               gsw->mii_write(gsw, i, PHY_EXT_REG_14, val);
+
+               /* Increase SlvDPSready time */
+               gsw->mii_write(gsw, i, 0x1f, 0x52b5);
+               gsw->mii_write(gsw, i, PHY_TR_REG_10, 0xafae);
+               gsw->mii_write(gsw, i, PHY_TR_REG_12, 0x2f);
+               gsw->mii_write(gsw, i, PHY_TR_REG_10, 0x8fae);
+               gsw->mii_write(gsw, i, 0x1f, 0);
+
+               /* Adjust 100_mse_threshold */
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_123, 0xffff);
+
+               /* Disable mcc */
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_A6, 0x300);
+
+               /* PHY link down power saving enable */
+               val = gsw->mii_read(gsw, i, PHY_EXT_REG_17);
+               val |= PHY_LINKDOWN_POWER_SAVING_EN;
+               gsw->mii_write(gsw, i, PHY_EXT_REG_17, val);
+
+               val = gsw->mmd_read(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6);
+               val &= ~PHY_POWER_SAVING_M;
+               val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6, val);
+
+               /* Set TX Pair delay selection */
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_13, 0x404);
+               gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_14, 0x404);
+       }
+}
+
+static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
+{
+       /* For ADC timing margin window for LDO calibration */
+       gsw->mmd_write(gsw, port, PHY_DEV1E, RXADC_LDO_CONTROL_2, 0x2222);
+
+       /* Adjust AD sample timing */
+       gsw->mmd_write(gsw, port, PHY_DEV1E, RXADC_CONTROL_3, 0x4444);
+
+       /* Adjust Line driver current for different mode */
+       gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2c63);
+
+       /* Adjust Line driver current for different mode */
+       gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_272, 0xc6b);
+
+       /* Adjust Line driver amplitude for 10BT */
+       gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_273, 0x3000);
+
+       /* Adjust RX Echo path filter */
+       gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_0FE, 0x2);
+
+       /* Adjust RX HVGA bias current */
+       gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_41, 0x3333);
+
+       /* Adjust TX class AB driver 1 */
+       gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x3aa);
+
+       /* Adjust TX class AB driver 2 */
+       gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0xaaaa);
+}
+
+static void mt7531_eee_setting(struct gsw_mt753x *gsw, u32 port)
+{
+       u32 tr_reg_control;
+       u32 val;
+
+       /* Disable generate signal to clear the scramble_lock when lpi mode */
+       val = gsw->mmd_read(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_189);
+       val &= ~DESCRAMBLER_CLEAR_EN;
+       gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_189, val);
+
+       /* roll back CR*/
+       gsw->mii_write(gsw, port, 0x1f, 0x52b5);
+       gsw->mmd_write(gsw, port, 0x1e, 0x2d1, 0);
+       tr_reg_control = (1 << 15) | (0 << 13) | (DSP_CH << 11) |
+                        (DSP_NOD_ADDR << 7) | (0x8 << 1);
+       gsw->mii_write(gsw, port, 17, 0x1b);
+       gsw->mii_write(gsw, port, 18, 0);
+       gsw->mii_write(gsw, port, 16, tr_reg_control);
+       tr_reg_control = (1 << 15) | (0 << 13) | (DSP_CH << 11) |
+                        (DSP_NOD_ADDR << 7) | (0xf << 1);
+       gsw->mii_write(gsw, port, 17, 0);
+       gsw->mii_write(gsw, port, 18, 0);
+       gsw->mii_write(gsw, port, 16, tr_reg_control);
+
+       tr_reg_control = (1 << 15) | (0 << 13) | (DSP_CH << 11) |
+                        (DSP_NOD_ADDR << 7) | (0x10 << 1);
+       gsw->mii_write(gsw, port, 17, 0x500);
+       gsw->mii_write(gsw, port, 18, 0);
+       gsw->mii_write(gsw, port, 16, tr_reg_control);
+       gsw->mii_write(gsw, port, 0x1f, 0);
+}
+
+static int mt7531_sw_init(struct gsw_mt753x *gsw)
+{
+       int i;
+       u32 val;
+
+       gsw->phy_base = (gsw->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
+
+       gsw->mii_read = mt753x_mii_read;
+       gsw->mii_write = mt753x_mii_write;
+       gsw->mmd_read = mt753x_mmd_read;
+       gsw->mmd_write = mt753x_mmd_write;
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               val = gsw->mii_read(gsw, i, MII_BMCR);
+               val |= BMCR_ISOLATE;
+               gsw->mii_write(gsw, i, MII_BMCR, val);
+       }
+
+       /* Force MAC link down before reset */
+       mt753x_reg_write(gsw, PMCR(5), FORCE_MODE_LNK);
+       mt753x_reg_write(gsw, PMCR(6), FORCE_MODE_LNK);
+
+       /* Switch soft reset */
+       mt753x_reg_write(gsw, SYS_CTRL, SW_SYS_RST | SW_REG_RST);
+       usleep_range(10, 20);
+
+       /* Enable MDC input Schmitt Trigger */
+       val = mt753x_reg_read(gsw, SMT0_IOLB);
+       mt753x_reg_write(gsw, SMT0_IOLB, val | SMT_IOLB_5_SMI_MDC_EN);
+
+       /* Set 7531 gpio pinmux */
+       mt7531_set_gpio_pinmux(gsw);
+
+       /* Global mac control settings */
+       mt753x_reg_write(gsw, GMACCR,
+                        (15 << MTCC_LMT_S) | (11 << MAX_RX_JUMBO_S) |
+                        RX_PKT_LEN_MAX_JUMBO);
+
+       mt7531_core_pll_setup(gsw);
+       mt7531_mac_port_setup(gsw, 5, &gsw->port5_cfg);
+       mt7531_mac_port_setup(gsw, 6, &gsw->port6_cfg);
+
+       return 0;
+}
+
+static int mt7531_sw_post_init(struct gsw_mt753x *gsw)
+{
+       int i;
+       u32 val;
+
+       /* Internal PHYs are disabled by default. SW should enable them.
+        * Note that this may already be enabled in bootloader stage.
+        */
+       val = gsw->mmd_read(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403);
+       val |= PHY_EN_BYPASS_MODE;
+       val &= ~POWER_ON_OFF;
+       gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
+
+       mt7531_phy_setting(gsw);
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               val = gsw->mii_read(gsw, i, MII_BMCR);
+               val &= ~BMCR_ISOLATE;
+               gsw->mii_write(gsw, i, MII_BMCR, val);
+       }
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++)
+               mt7531_adjust_line_driving(gsw, i);
+
+       for (i = 0; i < MT753X_NUM_PHYS; i++)
+               mt7531_eee_setting(gsw, i);
+
+       val = mt753x_reg_read(gsw, CHIP_REV);
+       val &= CHIP_REV_M;
+       if (val == CHIP_REV_E1) {
+               mt7531_internal_phy_calibration(gsw);
+       } else {
+               val = mt753x_reg_read(gsw, GBE_EFUSE);
+               if (val & GBE_SEL_EFUSE_EN) {
+                       val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
+                                           PHY_DEV1F_REG_403);
+                       val &= ~GBE_EFUSE_SETTING;
+                       gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403,
+                                      val);
+               } else {
+                       mt7531_internal_phy_calibration(gsw);
+               }
+       }
+
+       return 0;
+}
+
+struct mt753x_sw_id mt7531_id = {
+       .model = MT7531,
+       .detect = mt7531_sw_detect,
+       .init = mt7531_sw_init,
+       .post_init = mt7531_sw_post_init
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Zhanguo Ju <zhanguo.ju@mediatek.com>");
+MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h
new file mode 100644 (file)
index 0000000..736cb0c
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MT7531_H_
+#define _MT7531_H_
+
+#include "mt753x.h"
+
+extern struct mt753x_sw_id mt7531_id;
+
+#endif /* _MT7531_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h
new file mode 100644 (file)
index 0000000..b9bca54
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Driver for MediaTek MT753x gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MT753X_H_
+#define _MT753X_H_
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/of_mdio.h>
+#include <linux/workqueue.h>
+#include <linux/gpio/consumer.h>
+
+#ifdef CONFIG_SWCONFIG
+#include <linux/switch.h>
+#endif
+
+#define MT753X_DFL_CPU_PORT    6
+#define MT753X_NUM_PORTS       7
+#define MT753X_NUM_PHYS                5
+#define MT753X_NUM_VLANS       4095
+
+#define MT753X_MAX_VID         4095
+#define MT753X_MIN_VID         0
+
+#define MT753X_DFL_SMI_ADDR    0x1f
+#define MT753X_SMI_ADDR_MASK   0x1f
+
+struct gsw_mt753x;
+
+enum mt753x_model {
+       MT7530 = 0x7530,
+       MT7531 = 0x7531
+};
+
+struct mt753x_port_entry {
+       u16     pvid;
+};
+
+struct mt753x_vlan_entry {
+       u16     vid;
+       u8      member;
+       u8      etags;
+};
+
+struct mt753x_port_cfg {
+       struct device_node *np;
+       int phy_mode;
+       u32 enabled: 1;
+       u32 force_link: 1;
+       u32 speed: 2;
+       u32 duplex: 1;
+};
+
+struct mt753x_phy {
+       struct gsw_mt753x *gsw;
+       struct net_device netdev;
+       struct phy_device *phydev;
+};
+
+struct gsw_mt753x {
+       u32 id;
+
+       struct device *dev;
+       struct mii_bus *host_bus;
+       struct mii_bus *gphy_bus;
+       struct mutex mii_lock;  /* MII access lock */
+       u32 smi_addr;
+       u32 phy_base;
+       int direct_phy_access;
+
+       enum mt753x_model model;
+       const char *name;
+
+       struct mt753x_port_cfg port5_cfg;
+       struct mt753x_port_cfg port6_cfg;
+
+       bool phy_status_poll;
+       struct mt753x_phy phys[MT753X_NUM_PHYS];
+
+       int phy_link_sts;
+
+       int irq;
+       int reset_pin;
+       struct work_struct irq_worker;
+
+#ifdef CONFIG_SWCONFIG
+       struct switch_dev swdev;
+
+       struct mt753x_vlan_entry vlan_entries[MT753X_NUM_VLANS];
+       struct mt753x_port_entry port_entries[MT753X_NUM_PORTS];
+
+       int global_vlan_enable;
+       u32 cpu_port;
+#endif
+
+       int (*mii_read)(struct gsw_mt753x *gsw, int phy, int reg);
+       void (*mii_write)(struct gsw_mt753x *gsw, int phy, int reg, u16 val);
+
+       int (*mmd_read)(struct gsw_mt753x *gsw, int addr, int devad, u16 reg);
+       void (*mmd_write)(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
+                         u16 val);
+
+       struct list_head list;
+};
+
+struct chip_rev {
+       const char *name;
+       u32 rev;
+};
+
+struct mt753x_sw_id {
+       enum mt753x_model model;
+       int (*detect)(struct gsw_mt753x *gsw, struct chip_rev *crev);
+       int (*init)(struct gsw_mt753x *gsw);
+       int (*post_init)(struct gsw_mt753x *gsw);
+};
+
+extern struct list_head mt753x_devs;
+
+struct gsw_mt753x *mt753x_get_gsw(u32 id);
+struct gsw_mt753x *mt753x_get_first_gsw(void);
+void mt753x_put_gsw(void);
+void mt753x_lock_gsw(void);
+
+u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg);
+void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val);
+
+int mt753x_mii_read(struct gsw_mt753x *gsw, int phy, int reg);
+void mt753x_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val);
+
+int mt753x_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg);
+void mt753x_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
+                     u16 val);
+
+int mt753x_mmd_ind_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg);
+void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
+                         u16 val);
+
+void mt753x_irq_worker(struct work_struct *work);
+void mt753x_irq_enable(struct gsw_mt753x *gsw);
+
+/* MDIO Indirect Access Registers */
+#define MII_MMD_ACC_CTL_REG            0x0d
+#define MMD_CMD_S                      14
+#define MMD_CMD_M                      0xc000
+#define MMD_DEVAD_S                    0
+#define MMD_DEVAD_M                    0x1f
+
+/* MMD_CMD: MMD commands */
+#define MMD_ADDR                       0
+#define MMD_DATA                       1
+
+#define MII_MMD_ADDR_DATA_REG          0x0e
+
+/* Procedure of MT753x Internal Register Access
+ *
+ * 1. Internal Register Address
+ *
+ *    The MT753x has a 16-bit register address and each register is 32-bit.
+ *    This means the lowest two bits are not used as the register address is
+ *    4-byte aligned.
+ *
+ *    Rest of the valid bits are divided into two parts:
+ *      Bit 15..6 is the Page address
+ *      Bit 5..2 is the low address
+ *
+ *    -------------------------------------------------------------------
+ *    | 15  14  13  12  11  10   9   8   7   6 | 5   4   3   2 | 1   0  |
+ *    |----------------------------------------|---------------|--------|
+ *    |              Page Address              |    Address    | Unused |
+ *    -------------------------------------------------------------------
+ *
+ * 2. MDIO access timing
+ *
+ *    The MT753x uses the following MDIO timing for a single register read
+ *
+ *      Phase 1: Write Page Address
+ *    -------------------------------------------------------------------
+ *    | ST | OP | PHY_ADDR | TYPE | RSVD | TA |  RSVD |    PAGE_ADDR    |
+ *    -------------------------------------------------------------------
+ *    | 01 | 01 |   11111  |   1  | 1111 | xx | 00000 | REG_ADDR[15..6] |
+ *    -------------------------------------------------------------------
+ *
+ *      Phase 2: Write low Address & Read low word
+ *    -------------------------------------------------------------------
+ *    | ST | OP | PHY_ADDR | TYPE |    LOW_ADDR    | TA |      DATA     |
+ *    -------------------------------------------------------------------
+ *    | 01 | 10 |   11111  |   0  | REG_ADDR[5..2] | xx |  DATA[15..0]  |
+ *    -------------------------------------------------------------------
+ *
+ *      Phase 3: Read high word
+ *    -------------------------------------------------------------------
+ *    | ST | OP | PHY_ADDR | TYPE | RSVD | TA |           DATA          |
+ *    -------------------------------------------------------------------
+ *    | 01 | 10 |   11111  |   1  | 0000 | xx |       DATA[31..16]      |
+ *    -------------------------------------------------------------------
+ *
+ *    The MT753x uses the following MDIO timing for a single register write
+ *
+ *      Phase 1: Write Page Address (The same as read)
+ *
+ *      Phase 2: Write low Address and low word
+ *    -------------------------------------------------------------------
+ *    | ST | OP | PHY_ADDR | TYPE |    LOW_ADDR    | TA |      DATA     |
+ *    -------------------------------------------------------------------
+ *    | 01 | 01 |   11111  |   0  | REG_ADDR[5..2] | xx |  DATA[15..0]  |
+ *    -------------------------------------------------------------------
+ *
+ *      Phase 3: write high word
+ *    -------------------------------------------------------------------
+ *    | ST | OP | PHY_ADDR | TYPE | RSVD | TA |           DATA          |
+ *    -------------------------------------------------------------------
+ *    | 01 | 01 |   11111  |   1  | 0000 | xx |       DATA[31..16]      |
+ *    -------------------------------------------------------------------
+ *
+ */
+
+/* Internal Register Address fields */
+#define MT753X_REG_PAGE_ADDR_S         6
+#define MT753X_REG_PAGE_ADDR_M         0xffc0
+#define MT753X_REG_ADDR_S              2
+#define MT753X_REG_ADDR_M              0x3c
+
+#endif /* _MT753X_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c
new file mode 100644 (file)
index 0000000..c836a63
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Common part for MediaTek MT753x gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "mt753x.h"
+#include "mt753x_regs.h"
+
+void mt753x_irq_enable(struct gsw_mt753x *gsw)
+{
+       u32 val;
+       int i;
+
+       /* Record initial PHY link status */
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               val = gsw->mii_read(gsw, i, MII_BMSR);
+               if (val & BMSR_LSTATUS)
+                       gsw->phy_link_sts |= BIT(i);
+       }
+
+       val = BIT(MT753X_NUM_PHYS) - 1;
+
+       mt753x_reg_write(gsw, SYS_INT_EN, val);
+}
+
+static void display_port_link_status(struct gsw_mt753x *gsw, u32 port)
+{
+       u32 pmsr, speed_bits;
+       const char *speed;
+
+       pmsr = mt753x_reg_read(gsw, PMSR(port));
+
+       speed_bits = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S;
+
+       switch (speed_bits) {
+       case MAC_SPD_10:
+               speed = "10Mbps";
+               break;
+       case MAC_SPD_100:
+               speed = "100Mbps";
+               break;
+       case MAC_SPD_1000:
+               speed = "1Gbps";
+               break;
+       case MAC_SPD_2500:
+               speed = "2.5Gbps";
+               break;
+       }
+
+       if (pmsr & MAC_LNK_STS) {
+       dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n",
+                port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half");
+       } else {
+               dev_info(gsw->dev, "Port %d Link is Down\n", port);
+       }
+}
+
+void mt753x_irq_worker(struct work_struct *work)
+{
+       struct gsw_mt753x *gsw;
+       u32 sts, physts, laststs;
+       int i;
+
+       gsw = container_of(work, struct gsw_mt753x, irq_worker);
+
+       sts = mt753x_reg_read(gsw, SYS_INT_STS);
+
+       /* Check for changed PHY link status */
+       for (i = 0; i < MT753X_NUM_PHYS; i++) {
+               if (!(sts & PHY_LC_INT(i)))
+                       continue;
+
+               laststs = gsw->phy_link_sts & BIT(i);
+               physts = !!(gsw->mii_read(gsw, i, MII_BMSR) & BMSR_LSTATUS);
+               physts <<= i;
+
+               if (physts ^ laststs) {
+                       gsw->phy_link_sts ^= BIT(i);
+                       display_port_link_status(gsw, i);
+               }
+       }
+
+       mt753x_reg_write(gsw, SYS_INT_STS, sts);
+
+       enable_irq(gsw->irq);
+}
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
new file mode 100644 (file)
index 0000000..695713e
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * Driver for MediaTek MT753x gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+#include <linux/hrtimer.h>
+#include <linux/mii.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
+#include <linux/of_irq.h>
+#include <linux/phy.h>
+
+#include "mt753x.h"
+#include "mt753x_swconfig.h"
+#include "mt753x_regs.h"
+#include "mt753x_nl.h"
+#include "mt7530.h"
+#include "mt7531.h"
+
+static u32 mt753x_id;
+struct list_head mt753x_devs;
+static DEFINE_MUTEX(mt753x_devs_lock);
+
+static struct mt753x_sw_id *mt753x_sw_ids[] = {
+       &mt7530_id,
+       &mt7531_id,
+};
+
+u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg)
+{
+       u32 high, low;
+
+       mutex_lock(&gsw->host_bus->mdio_lock);
+
+       gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
+               (reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S);
+
+       low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr,
+               (reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S);
+
+       high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x10);
+
+       mutex_unlock(&gsw->host_bus->mdio_lock);
+
+       return (high << 16) | (low & 0xffff);
+}
+
+void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
+{
+       mutex_lock(&gsw->host_bus->mdio_lock);
+
+       gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
+               (reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S);
+
+       gsw->host_bus->write(gsw->host_bus, gsw->smi_addr,
+               (reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S, val & 0xffff);
+
+       gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, val >> 16);
+
+       mutex_unlock(&gsw->host_bus->mdio_lock);
+}
+
+/* Indirect MDIO clause 22/45 access */
+static int mt753x_mii_rw(struct gsw_mt753x *gsw, int phy, int reg, u16 data,
+                        u32 cmd, u32 st)
+{
+       ktime_t timeout;
+       u32 val, timeout_us;
+       int ret = 0;
+
+       timeout_us = 100000;
+       timeout = ktime_add_us(ktime_get(), timeout_us);
+       while (1) {
+               val = mt753x_reg_read(gsw, PHY_IAC);
+
+               if ((val & PHY_ACS_ST) == 0)
+                       break;
+
+               if (ktime_compare(ktime_get(), timeout) > 0)
+                       return -ETIMEDOUT;
+       }
+
+       val = (st << MDIO_ST_S) |
+             ((cmd << MDIO_CMD_S) & MDIO_CMD_M) |
+             ((phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) |
+             ((reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M);
+
+       if (cmd == MDIO_CMD_WRITE || cmd == MDIO_CMD_ADDR)
+               val |= data & MDIO_RW_DATA_M;
+
+       mt753x_reg_write(gsw, PHY_IAC, val | PHY_ACS_ST);
+
+       timeout_us = 100000;
+       timeout = ktime_add_us(ktime_get(), timeout_us);
+       while (1) {
+               val = mt753x_reg_read(gsw, PHY_IAC);
+
+               if ((val & PHY_ACS_ST) == 0)
+                       break;
+
+               if (ktime_compare(ktime_get(), timeout) > 0)
+                       return -ETIMEDOUT;
+       }
+
+       if (cmd == MDIO_CMD_READ || cmd == MDIO_CMD_READ_C45) {
+               val = mt753x_reg_read(gsw, PHY_IAC);
+               ret = val & MDIO_RW_DATA_M;
+       }
+
+       return ret;
+}
+
+int mt753x_mii_read(struct gsw_mt753x *gsw, int phy, int reg)
+{
+       int val;
+
+       if (phy < MT753X_NUM_PHYS)
+               phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->mii_lock);
+       val = mt753x_mii_rw(gsw, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22);
+       mutex_unlock(&gsw->mii_lock);
+
+       return val;
+}
+
+void mt753x_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val)
+{
+       if (phy < MT753X_NUM_PHYS)
+               phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->mii_lock);
+       mt753x_mii_rw(gsw, phy, reg, val, MDIO_CMD_WRITE, MDIO_ST_C22);
+       mutex_unlock(&gsw->mii_lock);
+}
+
+int mt753x_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg)
+{
+       int val;
+
+       if (addr < MT753X_NUM_PHYS)
+               addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->mii_lock);
+       mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
+       val = mt753x_mii_rw(gsw, addr, devad, 0, MDIO_CMD_READ_C45,
+                           MDIO_ST_C45);
+       mutex_unlock(&gsw->mii_lock);
+
+       return val;
+}
+
+void mt753x_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
+                     u16 val)
+{
+       if (addr < MT753X_NUM_PHYS)
+               addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->mii_lock);
+       mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
+       mt753x_mii_rw(gsw, addr, devad, val, MDIO_CMD_WRITE, MDIO_ST_C45);
+       mutex_unlock(&gsw->mii_lock);
+}
+
+int mt753x_mmd_ind_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg)
+{
+       u16 val;
+
+       if (addr < MT753X_NUM_PHYS)
+               addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->mii_lock);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
+                     (MMD_ADDR << MMD_CMD_S) |
+                     ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg,
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
+                     (MMD_DATA << MMD_CMD_S) |
+                     ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       val = mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, 0,
+                           MDIO_CMD_READ, MDIO_ST_C22);
+
+       mutex_unlock(&gsw->mii_lock);
+
+       return val;
+}
+
+void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
+                         u16 val)
+{
+       if (addr < MT753X_NUM_PHYS)
+               addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
+
+       mutex_lock(&gsw->mii_lock);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
+                     (MMD_ADDR << MMD_CMD_S) |
+                     ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg,
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
+                     (MMD_DATA << MMD_CMD_S) |
+                     ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, val,
+                     MDIO_CMD_WRITE, MDIO_ST_C22);
+
+       mutex_unlock(&gsw->mii_lock);
+}
+
+static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
+{
+       struct device_node *port_np;
+       struct device_node *fixed_link_node;
+       struct mt753x_port_cfg *port_cfg;
+       u32 port;
+
+       for_each_child_of_node(gsw->dev->of_node, port_np) {
+               if (!of_device_is_compatible(port_np, "mediatek,mt753x-port"))
+                       continue;
+
+               if (!of_device_is_available(port_np))
+                       continue;
+
+               if (of_property_read_u32(port_np, "reg", &port))
+                       continue;
+
+               switch (port) {
+               case 5:
+                       port_cfg = &gsw->port5_cfg;
+                       break;
+               case 6:
+                       port_cfg = &gsw->port6_cfg;
+                       break;
+               default:
+                       continue;
+               }
+
+               if (port_cfg->enabled) {
+                       dev_info(gsw->dev, "duplicated node for port%d\n",
+                                port_cfg->phy_mode);
+                       continue;
+               }
+
+               port_cfg->np = port_np;
+
+               port_cfg->phy_mode = of_get_phy_mode(port_np);
+               if (port_cfg->phy_mode < 0) {
+                       dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
+                       continue;
+               }
+
+               fixed_link_node = of_get_child_by_name(port_np, "fixed-link");
+               if (fixed_link_node) {
+                       u32 speed;
+
+                       port_cfg->force_link = 1;
+                       port_cfg->duplex = of_property_read_bool(
+                                               fixed_link_node,
+                                               "full-duplex");
+
+                       if (of_property_read_u32(fixed_link_node, "speed",
+                                                &speed)) {
+                               speed = 0;
+                               continue;
+                       }
+
+                       of_node_put(fixed_link_node);
+
+                       switch (speed) {
+                       case 10:
+                               port_cfg->speed = MAC_SPD_10;
+                               break;
+                       case 100:
+                               port_cfg->speed = MAC_SPD_100;
+                               break;
+                       case 1000:
+                               port_cfg->speed = MAC_SPD_1000;
+                               break;
+                       case 2500:
+                               port_cfg->speed = MAC_SPD_2500;
+                               break;
+                       default:
+                               dev_info(gsw->dev, "incorrect speed %d\n",
+                                        speed);
+                               continue;
+                       }
+               }
+
+               port_cfg->enabled = 1;
+       }
+}
+
+static void mt753x_add_gsw(struct gsw_mt753x *gsw)
+{
+       mutex_lock(&mt753x_devs_lock);
+       gsw->id = mt753x_id++;
+       INIT_LIST_HEAD(&gsw->list);
+       list_add_tail(&gsw->list, &mt753x_devs);
+       mutex_unlock(&mt753x_devs_lock);
+}
+
+static void mt753x_remove_gsw(struct gsw_mt753x *gsw)
+{
+       mutex_lock(&mt753x_devs_lock);
+       list_del(&gsw->list);
+       mutex_unlock(&mt753x_devs_lock);
+}
+
+struct gsw_mt753x *mt753x_get_gsw(u32 id)
+{
+       struct gsw_mt753x *dev;
+
+       mutex_lock(&mt753x_devs_lock);
+
+       list_for_each_entry(dev, &mt753x_devs, list) {
+               if (dev->id == id)
+                       return dev;
+       }
+
+       mutex_unlock(&mt753x_devs_lock);
+
+       return NULL;
+}
+
+struct gsw_mt753x *mt753x_get_first_gsw(void)
+{
+       struct gsw_mt753x *dev;
+
+       mutex_lock(&mt753x_devs_lock);
+
+       list_for_each_entry(dev, &mt753x_devs, list)
+               return dev;
+
+       mutex_unlock(&mt753x_devs_lock);
+
+       return NULL;
+}
+
+void mt753x_put_gsw(void)
+{
+       mutex_unlock(&mt753x_devs_lock);
+}
+
+void mt753x_lock_gsw(void)
+{
+       mutex_lock(&mt753x_devs_lock);
+}
+
+static int mt753x_hw_reset(struct gsw_mt753x *gsw)
+{
+       struct device_node *np = gsw->dev->of_node;
+       struct reset_control *rstc;
+       int mcm;
+       int ret = -EINVAL;
+
+       mcm = of_property_read_bool(np, "mediatek,mcm");
+       if (mcm) {
+               rstc = devm_reset_control_get(gsw->dev, "mcm");
+               ret = IS_ERR(rstc);
+               if (IS_ERR(rstc)) {
+                       dev_err(gsw->dev, "Missing reset ctrl of switch\n");
+                       return ret;
+               }
+
+               reset_control_assert(rstc);
+               msleep(30);
+               reset_control_deassert(rstc);
+
+               gsw->reset_pin = -1;
+               return 0;
+       }
+
+       gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
+       if (gsw->reset_pin < 0) {
+               dev_err(gsw->dev, "Missing reset pin of switch\n");
+               return ret;
+       }
+
+       ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "mt753x-reset");
+       if (ret) {
+               dev_info(gsw->dev, "Failed to request gpio %d\n",
+                        gsw->reset_pin);
+               return ret;
+       }
+
+       gpio_direction_output(gsw->reset_pin, 0);
+       msleep(30);
+       gpio_set_value(gsw->reset_pin, 1);
+       msleep(500);
+
+       return 0;
+}
+
+static int mt753x_mdio_read(struct mii_bus *bus, int addr, int reg)
+{
+       struct gsw_mt753x *gsw = bus->priv;
+
+       return gsw->mii_read(gsw, addr, reg);
+}
+
+static int mt753x_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
+{
+       struct gsw_mt753x *gsw = bus->priv;
+
+       gsw->mii_write(gsw, addr, reg, val);
+
+       return 0;
+}
+
+static const struct net_device_ops mt753x_dummy_netdev_ops = {
+};
+
+static void mt753x_phy_link_handler(struct net_device *dev)
+{
+       struct mt753x_phy *phy = container_of(dev, struct mt753x_phy, netdev);
+       struct phy_device *phydev = phy->phydev;
+       struct gsw_mt753x *gsw = phy->gsw;
+       u32 port = phy - gsw->phys;
+
+       if (phydev->link) {
+               dev_info(gsw->dev,
+                        "Port %d Link is Up - %s/%s - flow control %s\n",
+                        port, phy_speed_to_str(phydev->speed),
+                        (phydev->duplex == DUPLEX_FULL) ? "Full" : "Half",
+                        phydev->pause ? "rx/tx" : "off");
+       } else {
+               dev_info(gsw->dev, "Port %d Link is Down\n", port);
+       }
+}
+
+static void mt753x_connect_internal_phys(struct gsw_mt753x *gsw,
+                                        struct device_node *mii_np)
+{
+       struct device_node *phy_np;
+       struct mt753x_phy *phy;
+       int phy_mode;
+       u32 phyad;
+
+       if (!mii_np)
+               return;
+
+       for_each_child_of_node(mii_np, phy_np) {
+               if (of_property_read_u32(phy_np, "reg", &phyad))
+                       continue;
+
+               if (phyad >= MT753X_NUM_PHYS)
+                       continue;
+
+               phy_mode = of_get_phy_mode(phy_np);
+               if (phy_mode < 0) {
+                       dev_info(gsw->dev, "incorrect phy-mode %d for PHY %d\n",
+                                phy_mode, phyad);
+                       continue;
+               }
+
+               phy = &gsw->phys[phyad];
+               phy->gsw = gsw;
+
+               init_dummy_netdev(&phy->netdev);
+               phy->netdev.netdev_ops = &mt753x_dummy_netdev_ops;
+
+               phy->phydev = of_phy_connect(&phy->netdev, phy_np,
+                                       mt753x_phy_link_handler, 0, phy_mode);
+               if (!phy->phydev) {
+                       dev_info(gsw->dev, "could not connect to PHY %d\n",
+                                phyad);
+                       continue;
+               }
+
+               phy_start(phy->phydev);
+       }
+}
+
+static void mt753x_disconnect_internal_phys(struct gsw_mt753x *gsw)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(gsw->phys); i++) {
+               if (gsw->phys[i].phydev) {
+                       phy_stop(gsw->phys[i].phydev);
+                       phy_disconnect(gsw->phys[i].phydev);
+                       gsw->phys[i].phydev = NULL;
+               }
+       }
+}
+
+static int mt753x_mdio_register(struct gsw_mt753x *gsw)
+{
+       struct device_node *mii_np;
+       int i, ret;
+
+       mii_np = of_get_child_by_name(gsw->dev->of_node, "mdio-bus");
+       if (mii_np && !of_device_is_available(mii_np)) {
+               ret = -ENODEV;
+               goto err_put_node;
+       }
+
+       gsw->gphy_bus = devm_mdiobus_alloc(gsw->dev);
+       if (!gsw->gphy_bus) {
+               ret = -ENOMEM;
+               goto err_put_node;
+       }
+
+       gsw->gphy_bus->name = "mt753x_mdio";
+       gsw->gphy_bus->read = mt753x_mdio_read;
+       gsw->gphy_bus->write = mt753x_mdio_write;
+       gsw->gphy_bus->priv = gsw;
+       gsw->gphy_bus->parent = gsw->dev;
+       gsw->gphy_bus->phy_mask = BIT(MT753X_NUM_PHYS) - 1;
+
+       for (i = 0; i < PHY_MAX_ADDR; i++)
+               gsw->gphy_bus->irq[i] = PHY_POLL;
+
+       if (mii_np)
+               snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "%s@%s",
+                        mii_np->name, gsw->dev->of_node->name);
+       else
+               snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "mdio@%s",
+                        gsw->dev->of_node->name);
+
+       ret = of_mdiobus_register(gsw->gphy_bus, mii_np);
+
+       if (ret) {
+               devm_mdiobus_free(gsw->dev, gsw->gphy_bus);
+               gsw->gphy_bus = NULL;
+       } else {
+               if (gsw->phy_status_poll)
+                       mt753x_connect_internal_phys(gsw, mii_np);
+       }
+
+err_put_node:
+       if (mii_np)
+               of_node_put(mii_np);
+
+       return ret;
+}
+
+static irqreturn_t mt753x_irq_handler(int irq, void *dev)
+{
+       struct gsw_mt753x *gsw = dev;
+
+       disable_irq_nosync(gsw->irq);
+
+       schedule_work(&gsw->irq_worker);
+
+       return IRQ_HANDLED;
+}
+
+static int mt753x_probe(struct platform_device *pdev)
+{
+       struct gsw_mt753x *gsw;
+       struct mt753x_sw_id *sw;
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *mdio;
+       struct mii_bus *mdio_bus;
+       int ret = -EINVAL;
+       struct chip_rev rev;
+       int i;
+
+       mdio = of_parse_phandle(np, "mediatek,mdio", 0);
+       if (!mdio)
+               return -EINVAL;
+
+       mdio_bus = of_mdio_find_bus(mdio);
+       if (!mdio_bus)
+               return -EPROBE_DEFER;
+
+       gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_mt753x), GFP_KERNEL);
+       if (!gsw)
+               return -ENOMEM;
+
+       gsw->host_bus = mdio_bus;
+       gsw->dev = &pdev->dev;
+       mutex_init(&gsw->mii_lock);
+
+       /* Switch hard reset */
+       mt753x_hw_reset(gsw);
+
+       /* Fetch the SMI address dirst */
+       if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
+               gsw->smi_addr = MT753X_DFL_SMI_ADDR;
+
+       /* Load MAC port configurations */
+       mt753x_load_port_cfg(gsw);
+
+       /* Check for valid switch and then initialize */
+       for (i = 0; i < ARRAY_SIZE(mt753x_sw_ids); i++) {
+               if (!mt753x_sw_ids[i]->detect(gsw, &rev)) {
+                       sw = mt753x_sw_ids[i];
+
+                       gsw->name = rev.name;
+                       gsw->model = sw->model;
+
+                       dev_info(gsw->dev, "Switch is MediaTek %s rev %d",
+                                gsw->name, rev.rev);
+
+                       /* Initialize the switch */
+                       ret = sw->init(gsw);
+                       if (ret)
+                               goto fail;
+
+                       break;
+               }
+       }
+
+       if (i >= ARRAY_SIZE(mt753x_sw_ids)) {
+               dev_err(gsw->dev, "No mt753x switch found\n");
+               goto fail;
+       }
+
+       gsw->irq = platform_get_irq(pdev, 0);
+       if (gsw->irq >= 0) {
+               ret = devm_request_irq(gsw->dev, gsw->irq, mt753x_irq_handler,
+                                      0, dev_name(gsw->dev), gsw);
+               if (ret) {
+                       dev_err(gsw->dev, "Failed to request irq %d\n",
+                               gsw->irq);
+                       goto fail;
+               }
+
+               INIT_WORK(&gsw->irq_worker, mt753x_irq_worker);
+       }
+
+       platform_set_drvdata(pdev, gsw);
+
+       gsw->phy_status_poll = of_property_read_bool(gsw->dev->of_node,
+                                                    "mediatek,phy-poll");
+
+       mt753x_add_gsw(gsw);
+
+       mt753x_mdio_register(gsw);
+
+#ifdef CONFIG_SWCONFIG
+       mt753x_swconfig_init(gsw);
+#endif
+
+       if (sw->post_init)
+               sw->post_init(gsw);
+
+       if (gsw->irq >= 0)
+               mt753x_irq_enable(gsw);
+
+       return 0;
+
+fail:
+       devm_kfree(&pdev->dev, gsw);
+
+       return ret;
+}
+
+static int mt753x_remove(struct platform_device *pdev)
+{
+       struct gsw_mt753x *gsw = platform_get_drvdata(pdev);
+
+       if (gsw->irq >= 0)
+               cancel_work_sync(&gsw->irq_worker);
+
+       if (gsw->reset_pin >= 0)
+               devm_gpio_free(&pdev->dev, gsw->reset_pin);
+
+#ifdef CONFIG_SWCONFIG
+       mt753x_swconfig_destroy(gsw);
+#endif
+
+       mt753x_disconnect_internal_phys(gsw);
+
+       mdiobus_unregister(gsw->gphy_bus);
+
+       mt753x_remove_gsw(gsw);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static const struct of_device_id mt753x_ids[] = {
+       { .compatible = "mediatek,mt753x" },
+       { },
+};
+
+MODULE_DEVICE_TABLE(of, mt753x_ids);
+
+static struct platform_driver mt753x_driver = {
+       .probe = mt753x_probe,
+       .remove = mt753x_remove,
+       .driver = {
+               .name = "mt753x",
+               .of_match_table = mt753x_ids,
+       },
+};
+
+static int __init mt753x_init(void)
+{
+       int ret;
+
+       INIT_LIST_HEAD(&mt753x_devs);
+       ret = platform_driver_register(&mt753x_driver);
+
+       mt753x_nl_init();
+
+       return ret;
+}
+module_init(mt753x_init);
+
+static void __exit mt753x_exit(void)
+{
+       mt753x_nl_exit();
+
+       platform_driver_unregister(&mt753x_driver);
+}
+module_exit(mt753x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Weijie Gao <weijie.gao@mediatek.com>");
+MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c
new file mode 100644 (file)
index 0000000..756df4e
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Configuration layer for MediaTek MT753x gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <net/genetlink.h>
+
+#include "mt753x.h"
+#include "mt753x_nl.h"
+
+#define MT753X_NL_CMD_REQ_ATTRS(attr)          \
+       .required_attrs = attr,                 \
+       .nr_required_attrs = ARRAY_SIZE(attr),
+
+struct mt753x_nl_cmd_item {
+       enum mt753x_cmd cmd;
+       bool require_dev;
+       int (*process)(struct genl_info *info, struct gsw_mt753x *gsw);
+       u32 nr_required_attrs;
+       const enum mt753x_attr *required_attrs;
+};
+
+static int mt753x_nl_response(struct sk_buff *skb, struct genl_info *info);
+
+static const struct nla_policy mt753x_nl_cmd_policy[] = {
+       [MT753X_ATTR_TYPE_MESG] = { .type = NLA_STRING },
+       [MT753X_ATTR_TYPE_PHY] = { .type = NLA_S32 },
+       [MT753X_ATTR_TYPE_REG] = { .type = NLA_S32 },
+       [MT753X_ATTR_TYPE_VAL] = { .type = NLA_S32 },
+       [MT753X_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },
+       [MT753X_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },
+       [MT753X_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },
+};
+
+static const struct genl_ops mt753x_nl_ops[] = {
+       {
+               .cmd = MT753X_CMD_REQUEST,
+               .doit = mt753x_nl_response,
+               .policy = mt753x_nl_cmd_policy,
+               .flags = GENL_ADMIN_PERM,
+       }, {
+               .cmd = MT753X_CMD_READ,
+               .doit = mt753x_nl_response,
+               .policy = mt753x_nl_cmd_policy,
+               .flags = GENL_ADMIN_PERM,
+       }, {
+               .cmd = MT753X_CMD_WRITE,
+               .doit = mt753x_nl_response,
+               .policy = mt753x_nl_cmd_policy,
+               .flags = GENL_ADMIN_PERM,
+       },
+};
+
+static struct genl_family mt753x_nl_family = {
+//     .id =           GENL_ID_GENERATE,
+       .name =         MT753X_GENL_NAME,
+       .version =      MT753X_GENL_VERSION,
+       .maxattr =      MT753X_NR_ATTR_TYPE,
+       .ops =          mt753x_nl_ops,
+       .n_ops =        ARRAY_SIZE(mt753x_nl_ops),
+};
+
+static int mt753x_nl_list_devs(char *buff, int size)
+{
+       struct gsw_mt753x *gsw;
+       int len, total = 0;
+       char buf[80];
+
+       memset(buff, 0, size);
+
+       mt753x_lock_gsw();
+
+       list_for_each_entry(gsw, &mt753x_devs, list) {
+               len = snprintf(buf, sizeof(buf),
+                              "id: %d, model: %s, node: %s\n",
+                              gsw->id, gsw->name, gsw->dev->of_node->name);
+               strncat(buff, buf, size - total);
+               total += len;
+       }
+
+       mt753x_put_gsw();
+
+       return total;
+}
+
+static int mt753x_nl_prepare_reply(struct genl_info *info, u8 cmd,
+                                  struct sk_buff **skbp)
+{
+       struct sk_buff *msg;
+       void *reply;
+
+       if (!info)
+               return -EINVAL;
+
+       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       /* Construct send-back message header */
+       reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+                           &mt753x_nl_family, 0, cmd);
+       if (!reply) {
+               nlmsg_free(msg);
+               return -EINVAL;
+       }
+
+       *skbp = msg;
+       return 0;
+}
+
+static int mt753x_nl_send_reply(struct sk_buff *skb, struct genl_info *info)
+{
+       struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
+       void *reply = genlmsg_data(genlhdr);
+
+       /* Finalize a generic netlink message (update message header) */
+       genlmsg_end(skb, reply);
+
+       /* reply to a request */
+       return genlmsg_reply(skb, info);
+}
+
+static s32 mt753x_nl_get_s32(struct genl_info *info, enum mt753x_attr attr,
+                            s32 defval)
+{
+       struct nlattr *na;
+
+       na = info->attrs[attr];
+       if (na)
+               return nla_get_s32(na);
+
+       return defval;
+}
+
+static int mt753x_nl_get_u32(struct genl_info *info, enum mt753x_attr attr,
+                            u32 *val)
+{
+       struct nlattr *na;
+
+       na = info->attrs[attr];
+       if (na) {
+               *val = nla_get_u32(na);
+               return 0;
+       }
+
+       return -1;
+}
+
+static struct gsw_mt753x *mt753x_nl_parse_find_gsw(struct genl_info *info)
+{
+       struct gsw_mt753x *gsw;
+       struct nlattr *na;
+       int gsw_id;
+
+       na = info->attrs[MT753X_ATTR_TYPE_DEV_ID];
+       if (na) {
+               gsw_id = nla_get_s32(na);
+               if (gsw_id >= 0)
+                       gsw = mt753x_get_gsw(gsw_id);
+               else
+                       gsw = mt753x_get_first_gsw();
+       } else {
+               gsw = mt753x_get_first_gsw();
+       }
+
+       return gsw;
+}
+
+static int mt753x_nl_get_swdevs(struct genl_info *info, struct gsw_mt753x *gsw)
+{
+       struct sk_buff *rep_skb = NULL;
+       char dev_info[512];
+       int ret;
+
+       ret = mt753x_nl_list_devs(dev_info, sizeof(dev_info));
+       if (!ret) {
+               pr_info("No switch registered\n");
+               return -EINVAL;
+       }
+
+       ret = mt753x_nl_prepare_reply(info, MT753X_CMD_REPLY, &rep_skb);
+       if (ret < 0)
+               goto err;
+
+       ret = nla_put_string(rep_skb, MT753X_ATTR_TYPE_MESG, dev_info);
+       if (ret < 0)
+               goto err;
+
+       return mt753x_nl_send_reply(rep_skb, info);
+
+err:
+       if (rep_skb)
+               nlmsg_free(rep_skb);
+
+       return ret;
+}
+
+static int mt753x_nl_reply_read(struct genl_info *info, struct gsw_mt753x *gsw)
+{
+       struct sk_buff *rep_skb = NULL;
+       s32 phy, devad, reg;
+       int ret, value;
+
+       phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
+       devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
+       reg = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_REG, -1);
+
+       if (reg < 0)
+               goto err;
+
+       ret = mt753x_nl_prepare_reply(info, MT753X_CMD_READ, &rep_skb);
+       if (ret < 0)
+               goto err;
+
+       if (phy >= 0) {
+               if (devad < 0)
+                       value = gsw->mii_read(gsw, phy, reg);
+               else
+                       value = gsw->mmd_read(gsw, phy, devad, reg);
+       } else {
+               value = mt753x_reg_read(gsw, reg);
+       }
+
+       ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_REG, reg);
+       if (ret < 0)
+               goto err;
+
+       ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_VAL, value);
+       if (ret < 0)
+               goto err;
+
+       return mt753x_nl_send_reply(rep_skb, info);
+
+err:
+       if (rep_skb)
+               nlmsg_free(rep_skb);
+
+       return ret;
+}
+
+static int mt753x_nl_reply_write(struct genl_info *info, struct gsw_mt753x *gsw)
+{
+       struct sk_buff *rep_skb = NULL;
+       s32 phy, devad, reg;
+       u32 value;
+       int ret;
+
+       phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
+       devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
+       reg = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_REG, -1);
+
+       if (mt753x_nl_get_u32(info, MT753X_ATTR_TYPE_VAL, &value))
+               goto err;
+
+       if (reg < 0)
+               goto err;
+
+       ret = mt753x_nl_prepare_reply(info, MT753X_CMD_WRITE, &rep_skb);
+       if (ret < 0)
+               goto err;
+
+       if (phy >= 0) {
+               if (devad < 0)
+                       gsw->mii_write(gsw, phy, reg, value);
+               else
+                       gsw->mmd_write(gsw, phy, devad, reg, value);
+       } else {
+               mt753x_reg_write(gsw, reg, value);
+       }
+
+       ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_REG, reg);
+       if (ret < 0)
+               goto err;
+
+       ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_VAL, value);
+       if (ret < 0)
+               goto err;
+
+       return mt753x_nl_send_reply(rep_skb, info);
+
+err:
+       if (rep_skb)
+               nlmsg_free(rep_skb);
+
+       return ret;
+}
+
+static const enum mt753x_attr mt753x_nl_cmd_read_attrs[] = {
+       MT753X_ATTR_TYPE_REG
+};
+
+static const enum mt753x_attr mt753x_nl_cmd_write_attrs[] = {
+       MT753X_ATTR_TYPE_REG,
+       MT753X_ATTR_TYPE_VAL
+};
+
+static const struct mt753x_nl_cmd_item mt753x_nl_cmds[] = {
+       {
+               .cmd = MT753X_CMD_REQUEST,
+               .require_dev = false,
+               .process = mt753x_nl_get_swdevs
+       }, {
+               .cmd = MT753X_CMD_READ,
+               .require_dev = true,
+               .process = mt753x_nl_reply_read,
+               MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_read_attrs)
+       }, {
+               .cmd = MT753X_CMD_WRITE,
+               .require_dev = true,
+               .process = mt753x_nl_reply_write,
+               MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_write_attrs)
+       }
+};
+
+static int mt753x_nl_response(struct sk_buff *skb, struct genl_info *info)
+{
+       struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
+       const struct mt753x_nl_cmd_item *cmditem = NULL;
+       struct gsw_mt753x *gsw = NULL;
+       u32 sat_req_attrs = 0;
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(mt753x_nl_cmds); i++) {
+               if (hdr->cmd == mt753x_nl_cmds[i].cmd) {
+                       cmditem = &mt753x_nl_cmds[i];
+                       break;
+               }
+       }
+
+       if (!cmditem) {
+               pr_info("mt753x-nl: unknown cmd %u\n", hdr->cmd);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < cmditem->nr_required_attrs; i++) {
+               if (info->attrs[cmditem->required_attrs[i]])
+                       sat_req_attrs++;
+       }
+
+       if (sat_req_attrs != cmditem->nr_required_attrs) {
+               pr_info("mt753x-nl: missing required attr(s) for cmd %u\n",
+                       hdr->cmd);
+               return -EINVAL;
+       }
+
+       if (cmditem->require_dev) {
+               gsw = mt753x_nl_parse_find_gsw(info);
+               if (!gsw) {
+                       pr_info("mt753x-nl: failed to find switch dev\n");
+                       return -EINVAL;
+               }
+       }
+
+       ret = cmditem->process(info, gsw);
+
+       mt753x_put_gsw();
+
+       return ret;
+}
+
+int __init mt753x_nl_init(void)
+{
+       int ret;
+
+       ret = genl_register_family(&mt753x_nl_family);
+       if (ret) {
+               pr_info("mt753x-nl: genl_register_family_with_ops failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+void __exit mt753x_nl_exit(void)
+{
+       genl_unregister_family(&mt753x_nl_family);
+}
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h
new file mode 100644 (file)
index 0000000..f6a1df3
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Driver for MediaTek MT753x gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MT753X_NL_H_
+#define _MT753X_NL_H_
+
+#define MT753X_GENL_NAME               "mt753x"
+#define MT753X_GENL_VERSION            0x1
+
+enum mt753x_cmd {
+       MT753X_CMD_UNSPEC = 0,
+       MT753X_CMD_REQUEST,
+       MT753X_CMD_REPLY,
+       MT753X_CMD_READ,
+       MT753X_CMD_WRITE,
+
+       __MT753X_CMD_MAX,
+};
+
+enum mt753x_attr {
+       MT753X_ATTR_TYPE_UNSPEC = 0,
+       MT753X_ATTR_TYPE_MESG,
+       MT753X_ATTR_TYPE_PHY,
+       MT753X_ATTR_TYPE_DEVAD,
+       MT753X_ATTR_TYPE_REG,
+       MT753X_ATTR_TYPE_VAL,
+       MT753X_ATTR_TYPE_DEV_NAME,
+       MT753X_ATTR_TYPE_DEV_ID,
+
+       __MT753X_ATTR_TYPE_MAX,
+};
+
+#define MT753X_NR_ATTR_TYPE            (__MT753X_ATTR_TYPE_MAX - 1)
+
+#ifdef __KERNEL__
+int __init mt753x_nl_init(void);
+void __exit mt753x_nl_exit(void);
+#endif /* __KERNEL__ */
+
+#endif /* _MT753X_NL_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h
new file mode 100644 (file)
index 0000000..1525527
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Register definitions for MediaTek MT753x Gigabit switches
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MT753X_REGS_H_
+#define _MT753X_REGS_H_
+
+#include <linux/bitops.h>
+
+/* Values of Egress TAG Control */
+#define ETAG_CTRL_UNTAG                        0
+#define ETAG_CTRL_TAG                  2
+#define ETAG_CTRL_SWAP                 1
+#define ETAG_CTRL_STACK                        3
+
+#define VTCR                           0x90
+#define VAWD1                          0x94
+#define VAWD2                          0x98
+
+/* Fields of VTCR */
+#define VTCR_BUSY                      BIT(31)
+#define IDX_INVLD                      BIT(16)
+#define VTCR_FUNC_S                    12
+#define VTCR_FUNC_M                    0xf000
+#define VTCR_VID_S                     0
+#define VTCR_VID_M                     0xfff
+
+/* Values of VTCR_FUNC */
+#define VTCR_READ_VLAN_ENTRY           0
+#define VTCR_WRITE_VLAN_ENTRY          1
+#define VTCR_INVD_VLAN_ENTRY           2
+#define VTCR_ENABLE_VLAN_ENTRY         3
+#define VTCR_READ_ACL_ENTRY            4
+#define VTCR_WRITE_ACL_ENTRY           5
+#define VTCR_READ_TRTCM_TABLE          6
+#define VTCR_WRITE_TRTCM_TABLE         7
+#define VTCR_READ_ACL_MASK_ENTRY       8
+#define VTCR_WRITE_ACL_MASK_ENTRY      9
+#define VTCR_READ_ACL_RULE_ENTRY       10
+#define VTCR_WRITE_ACL_RULE_ENTRY      11
+#define VTCR_READ_ACL_RATE_ENTRY       12
+#define VTCR_WRITE_ACL_RATE_ENTRY      13
+
+/* VLAN entry fields */
+/* VAWD1 */
+#define PORT_STAG                      BIT(31)
+#define IVL_MAC                                BIT(30)
+#define EG_CON                         BIT(29)
+#define VTAG_EN                                BIT(28)
+#define COPY_PRI                       BIT(27)
+#define USER_PRI_S                     24
+#define USER_PRI_M                     0x7000000
+#define PORT_MEM_S                     16
+#define PORT_MEM_M                     0xff0000
+#define S_TAG1_S                       4
+#define S_TAG1_M                       0xfff0
+#define FID_S                          1
+#define FID_M                          0x0e
+#define VENTRY_VALID                   BIT(0)
+
+/* VAWD2 */
+#define S_TAG2_S                       16
+#define S_TAG2_M                       0xffff0000
+#define PORT_ETAG_S(p)                 ((p) * 2)
+#define PORT_ETAG_M                    0x03
+
+#define PORT_CTRL_BASE                 0x2000
+#define PORT_CTRL_PORT_OFFSET          0x100
+#define PORT_CTRL_REG(p, r)            (PORT_CTRL_BASE + \
+                                       (p) * PORT_CTRL_PORT_OFFSET +  (r))
+#define CKGCR(p)                       PORT_CTRL_REG(p, 0x00)
+#define PCR(p)                         PORT_CTRL_REG(p, 0x04)
+#define PIC(p)                         PORT_CTRL_REG(p, 0x08)
+#define PSC(p)                         PORT_CTRL_REG(p, 0x0c)
+#define PVC(p)                         PORT_CTRL_REG(p, 0x10)
+#define PPBV1(p)                       PORT_CTRL_REG(p, 0x14)
+#define PPBV2(p)                       PORT_CTRL_REG(p, 0x18)
+#define BSR(p)                         PORT_CTRL_REG(p, 0x1c)
+#define STAG01                         PORT_CTRL_REG(p, 0x20)
+#define STAG23                         PORT_CTRL_REG(p, 0x24)
+#define STAG45                         PORT_CTRL_REG(p, 0x28)
+#define STAG67                         PORT_CTRL_REG(p, 0x2c)
+
+#define PPBV(p, g)                     (PPBV1(p) + ((g) / 2) * 4)
+
+/* Fields of PCR */
+#define MLDV2_EN                       BIT(30)
+#define EG_TAG_S                       28
+#define EG_TAG_M                       0x30000000
+#define PORT_PRI_S                     24
+#define PORT_PRI_M                     0x7000000
+#define PORT_MATRIX_S                  16
+#define PORT_MATRIX_M                  0xff0000
+#define UP2DSCP_EN                     BIT(12)
+#define UP2TAG_EN                      BIT(11)
+#define ACL_EN                         BIT(10)
+#define PORT_TX_MIR                    BIT(9)
+#define PORT_RX_MIR                    BIT(8)
+#define ACL_MIR                                BIT(7)
+#define MIS_PORT_FW_S                  4
+#define MIS_PORT_FW_M                  0x70
+#define VLAN_MIS                       BIT(2)
+#define PORT_VLAN_S                    0
+#define PORT_VLAN_M                    0x03
+
+/* Values of PORT_VLAN */
+#define PORT_MATRIX_MODE               0
+#define FALLBACK_MODE                  1
+#define CHECK_MODE                     2
+#define SECURITY_MODE                  3
+
+/* Fields of PVC */
+#define STAG_VPID_S                    16
+#define STAG_VPID_M                    0xffff0000
+#define DIS_PVID                       BIT(15)
+#define FORCE_PVID                     BIT(14)
+#define PT_VPM                         BIT(12)
+#define PT_OPTION                      BIT(11)
+#define PVC_EG_TAG_S                   8
+#define PVC_EG_TAG_M                   0x700
+#define VLAN_ATTR_S                    6
+#define VLAN_ATTR_M                    0xc0
+#define PVC_PORT_STAG                  BIT(5)
+#define BC_LKYV_EN                     BIT(4)
+#define MC_LKYV_EN                     BIT(3)
+#define UC_LKYV_EN                     BIT(2)
+#define ACC_FRM_S                      0
+#define ACC_FRM_M                      0x03
+
+/* Values of VLAN_ATTR */
+#define VA_USER_PORT                   0
+#define VA_STACK_PORT                  1
+#define VA_TRANSLATION_PORT            2
+#define VA_TRANSPARENT_PORT            3
+
+/* Fields of PPBV */
+#define GRP_PORT_PRI_S(g)              (((g) % 2) * 16 + 13)
+#define GRP_PORT_PRI_M                 0x07
+#define GRP_PORT_VID_S(g)              (((g) % 2) * 16)
+#define GRP_PORT_VID_M                 0xfff
+
+#define PORT_MAC_CTRL_BASE             0x3000
+#define PORT_MAC_CTRL_PORT_OFFSET      0x100
+#define PORT_MAC_CTRL_REG(p, r)                (PORT_MAC_CTRL_BASE + \
+                                       (p) * PORT_MAC_CTRL_PORT_OFFSET + (r))
+#define PMCR(p)                                PORT_MAC_CTRL_REG(p, 0x00)
+#define PMEEECR(p)                     PORT_MAC_CTRL_REG(p, 0x04)
+#define PMSR(p)                                PORT_MAC_CTRL_REG(p, 0x08)
+#define PINT_EN(p)                     PORT_MAC_CTRL_REG(p, 0x10)
+#define PINT_STS(p)                    PORT_MAC_CTRL_REG(p, 0x14)
+
+#define GMACCR                         (PORT_MAC_CTRL_BASE + 0xe0)
+#define TXCRC_EN                       BIT(19)
+#define RXCRC_EN                       BIT(18)
+#define PRMBL_LMT_EN                   BIT(17)
+#define MTCC_LMT_S                     9
+#define MTCC_LMT_M                     0x1e00
+#define MAX_RX_JUMBO_S                 2
+#define MAX_RX_JUMBO_M                 0x3c
+#define MAX_RX_PKT_LEN_S               0
+#define MAX_RX_PKT_LEN_M               0x3
+
+/* Values of MAX_RX_PKT_LEN */
+#define RX_PKT_LEN_1518                        0
+#define RX_PKT_LEN_1536                        1
+#define RX_PKT_LEN_1522                        2
+#define RX_PKT_LEN_MAX_JUMBO           3
+
+/* Fields of PMCR */
+#define IPG_CFG_S                      18
+#define IPG_CFG_M                      0xc0000
+#define EXT_PHY                                BIT(17)
+#define MAC_MODE                       BIT(16)
+#define MAC_TX_EN                      BIT(14)
+#define MAC_RX_EN                      BIT(13)
+#define MAC_PRE                                BIT(11)
+#define BKOFF_EN                       BIT(9)
+#define BACKPR_EN                      BIT(8)
+#define FORCE_EEE1G                    BIT(7)
+#define FORCE_EEE1000                  BIT(6)
+#define FORCE_RX_FC                    BIT(5)
+#define FORCE_TX_FC                    BIT(4)
+#define FORCE_SPD_S                    2
+#define FORCE_SPD_M                    0x0c
+#define FORCE_DPX                      BIT(1)
+#define FORCE_LINK                     BIT(0)
+
+/* Fields of PMSR */
+#define EEE1G_STS                      BIT(7)
+#define EEE100_STS                     BIT(6)
+#define RX_FC_STS                      BIT(5)
+#define TX_FC_STS                      BIT(4)
+#define MAC_SPD_STS_S                  2
+#define MAC_SPD_STS_M                  0x0c
+#define MAC_DPX_STS                    BIT(1)
+#define MAC_LNK_STS                    BIT(0)
+
+/* Values of MAC_SPD_STS */
+#define MAC_SPD_10                     0
+#define MAC_SPD_100                    1
+#define MAC_SPD_1000                   2
+#define MAC_SPD_2500                   3
+
+/* Values of IPG_CFG */
+#define IPG_96BIT                      0
+#define IPG_96BIT_WITH_SHORT_IPG       1
+#define IPG_64BIT                      2
+
+#define MIB_COUNTER_BASE               0x4000
+#define MIB_COUNTER_PORT_OFFSET                0x100
+#define MIB_COUNTER_REG(p, r)          (MIB_COUNTER_BASE + \
+                                       (p) * MIB_COUNTER_PORT_OFFSET + (r))
+#define STATS_TDPC                     0x00
+#define STATS_TCRC                     0x04
+#define STATS_TUPC                     0x08
+#define STATS_TMPC                     0x0C
+#define STATS_TBPC                     0x10
+#define STATS_TCEC                     0x14
+#define STATS_TSCEC                    0x18
+#define STATS_TMCEC                    0x1C
+#define STATS_TDEC                     0x20
+#define STATS_TLCEC                    0x24
+#define STATS_TXCEC                    0x28
+#define STATS_TPPC                     0x2C
+#define STATS_TL64PC                   0x30
+#define STATS_TL65PC                   0x34
+#define STATS_TL128PC                  0x38
+#define STATS_TL256PC                  0x3C
+#define STATS_TL512PC                  0x40
+#define STATS_TL1024PC                 0x44
+#define STATS_TOC                      0x48
+#define STATS_RDPC                     0x60
+#define STATS_RFPC                     0x64
+#define STATS_RUPC                     0x68
+#define STATS_RMPC                     0x6C
+#define STATS_RBPC                     0x70
+#define STATS_RAEPC                    0x74
+#define STATS_RCEPC                    0x78
+#define STATS_RUSPC                    0x7C
+#define STATS_RFEPC                    0x80
+#define STATS_ROSPC                    0x84
+#define STATS_RJEPC                    0x88
+#define STATS_RPPC                     0x8C
+#define STATS_RL64PC                   0x90
+#define STATS_RL65PC                   0x94
+#define STATS_RL128PC                  0x98
+#define STATS_RL256PC                  0x9C
+#define STATS_RL512PC                  0xA0
+#define STATS_RL1024PC                 0xA4
+#define STATS_ROC                      0xA8
+#define STATS_RDPC_CTRL                        0xB0
+#define STATS_RDPC_ING                 0xB4
+#define STATS_RDPC_ARL                 0xB8
+
+#define SYS_CTRL                       0x7000
+#define SW_PHY_RST                     BIT(2)
+#define SW_SYS_RST                     BIT(1)
+#define SW_REG_RST                     BIT(0)
+
+#define SYS_INT_EN                     0x7008
+#define SYS_INT_STS                    0x700c
+#define MAC_PC_INT                     BIT(16)
+#define PHY_INT(p)                     BIT((p) + 8)
+#define PHY_LC_INT(p)                  BIT(p)
+
+#define PHY_IAC                                0x701c
+#define PHY_ACS_ST                     BIT(31)
+#define MDIO_REG_ADDR_S                        25
+#define MDIO_REG_ADDR_M                        0x3e000000
+#define MDIO_PHY_ADDR_S                        20
+#define MDIO_PHY_ADDR_M                        0x1f00000
+#define MDIO_CMD_S                     18
+#define MDIO_CMD_M                     0xc0000
+#define MDIO_ST_S                      16
+#define MDIO_ST_M                      0x30000
+#define MDIO_RW_DATA_S                 0
+#define MDIO_RW_DATA_M                 0xffff
+
+/* MDIO_CMD: MDIO commands */
+#define MDIO_CMD_ADDR                  0
+#define MDIO_CMD_WRITE                 1
+#define MDIO_CMD_READ                  2
+#define MDIO_CMD_READ_C45              3
+
+/* MDIO_ST: MDIO start field */
+#define MDIO_ST_C45                    0
+#define MDIO_ST_C22                    1
+
+#define HWSTRAP                                0x7800
+#define MHWSTRAP                       0x7804
+
+#endif /* _MT753X_REGS_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
new file mode 100644 (file)
index 0000000..fb2ee1c
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * OpenWrt swconfig support for MediaTek MT753x Gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <linux/if.h>
+#include <linux/list.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/netlink.h>
+#include <linux/bitops.h>
+#include <net/genetlink.h>
+#include <linux/delay.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/lockdep.h>
+#include <linux/workqueue.h>
+#include <linux/of_device.h>
+
+#include "mt753x.h"
+#include "mt753x_swconfig.h"
+#include "mt753x_regs.h"
+
+#define MT753X_PORT_MIB_TXB_ID 18      /* TxByte */
+#define MT753X_PORT_MIB_RXB_ID 37      /* RxByte */
+
+#define MIB_DESC(_s, _o, _n)   \
+       {                       \
+               .size = (_s),   \
+               .offset = (_o), \
+               .name = (_n),   \
+       }
+
+struct mt753x_mib_desc {
+       unsigned int size;
+       unsigned int offset;
+       const char *name;
+};
+
+static const struct mt753x_mib_desc mt753x_mibs[] = {
+       MIB_DESC(1, STATS_TDPC, "TxDrop"),
+       MIB_DESC(1, STATS_TCRC, "TxCRC"),
+       MIB_DESC(1, STATS_TUPC, "TxUni"),
+       MIB_DESC(1, STATS_TMPC, "TxMulti"),
+       MIB_DESC(1, STATS_TBPC, "TxBroad"),
+       MIB_DESC(1, STATS_TCEC, "TxCollision"),
+       MIB_DESC(1, STATS_TSCEC, "TxSingleCol"),
+       MIB_DESC(1, STATS_TMCEC, "TxMultiCol"),
+       MIB_DESC(1, STATS_TDEC, "TxDefer"),
+       MIB_DESC(1, STATS_TLCEC, "TxLateCol"),
+       MIB_DESC(1, STATS_TXCEC, "TxExcCol"),
+       MIB_DESC(1, STATS_TPPC, "TxPause"),
+       MIB_DESC(1, STATS_TL64PC, "Tx64Byte"),
+       MIB_DESC(1, STATS_TL65PC, "Tx65Byte"),
+       MIB_DESC(1, STATS_TL128PC, "Tx128Byte"),
+       MIB_DESC(1, STATS_TL256PC, "Tx256Byte"),
+       MIB_DESC(1, STATS_TL512PC, "Tx512Byte"),
+       MIB_DESC(1, STATS_TL1024PC, "Tx1024Byte"),
+       MIB_DESC(2, STATS_TOC, "TxByte"),
+       MIB_DESC(1, STATS_RDPC, "RxDrop"),
+       MIB_DESC(1, STATS_RFPC, "RxFiltered"),
+       MIB_DESC(1, STATS_RUPC, "RxUni"),
+       MIB_DESC(1, STATS_RMPC, "RxMulti"),
+       MIB_DESC(1, STATS_RBPC, "RxBroad"),
+       MIB_DESC(1, STATS_RAEPC, "RxAlignErr"),
+       MIB_DESC(1, STATS_RCEPC, "RxCRC"),
+       MIB_DESC(1, STATS_RUSPC, "RxUnderSize"),
+       MIB_DESC(1, STATS_RFEPC, "RxFragment"),
+       MIB_DESC(1, STATS_ROSPC, "RxOverSize"),
+       MIB_DESC(1, STATS_RJEPC, "RxJabber"),
+       MIB_DESC(1, STATS_RPPC, "RxPause"),
+       MIB_DESC(1, STATS_RL64PC, "Rx64Byte"),
+       MIB_DESC(1, STATS_RL65PC, "Rx65Byte"),
+       MIB_DESC(1, STATS_RL128PC, "Rx128Byte"),
+       MIB_DESC(1, STATS_RL256PC, "Rx256Byte"),
+       MIB_DESC(1, STATS_RL512PC, "Rx512Byte"),
+       MIB_DESC(1, STATS_RL1024PC, "Rx1024Byte"),
+       MIB_DESC(2, STATS_ROC, "RxByte"),
+       MIB_DESC(1, STATS_RDPC_CTRL, "RxCtrlDrop"),
+       MIB_DESC(1, STATS_RDPC_ING, "RxIngDrop"),
+       MIB_DESC(1, STATS_RDPC_ARL, "RxARLDrop")
+};
+
+enum {
+       /* Global attributes. */
+       MT753X_ATTR_ENABLE_VLAN,
+};
+
+struct mt753x_mapping {
+       char    *name;
+       u16     pvids[MT753X_NUM_PORTS];
+       u8      members[MT753X_NUM_VLANS];
+       u8      etags[MT753X_NUM_VLANS];
+       u16     vids[MT753X_NUM_VLANS];
+} mt753x_defaults[] = {
+       {
+               .name = "llllw",
+               .pvids = { 1, 1, 1, 1, 2, 2, 1 },
+               .members = { 0, 0x4f, 0x30 },
+               .etags = { 0, 0, 0 },
+               .vids = { 0, 1, 2 },
+       }, {
+               .name = "wllll",
+               .pvids = { 2, 1, 1, 1, 1, 2, 1 },
+               .members = { 0, 0x5e, 0x21 },
+               .etags = { 0, 0, 0 },
+               .vids = { 0, 1, 2 },
+       }, {
+               .name = "lwlll",
+               .pvids = { 1, 2, 1, 1, 1, 2, 1 },
+               .members = { 0, 0x5d, 0x22 },
+               .etags = { 0, 0, 0 },
+               .vids = { 0, 1, 2 },
+       },
+};
+
+struct mt753x_mapping *mt753x_find_mapping(struct device_node *np)
+{
+       const char *map;
+       int i;
+
+       if (of_property_read_string(np, "mediatek,portmap", &map))
+               return NULL;
+
+       for (i = 0; i < ARRAY_SIZE(mt753x_defaults); i++)
+               if (!strcmp(map, mt753x_defaults[i].name))
+                       return &mt753x_defaults[i];
+
+       return NULL;
+}
+
+static void mt753x_apply_mapping(struct gsw_mt753x *gsw,
+                                struct mt753x_mapping *map)
+{
+       int i = 0;
+
+       for (i = 0; i < MT753X_NUM_PORTS; i++)
+               gsw->port_entries[i].pvid = map->pvids[i];
+
+       for (i = 0; i < MT753X_NUM_VLANS; i++) {
+               gsw->vlan_entries[i].member = map->members[i];
+               gsw->vlan_entries[i].etags = map->etags[i];
+               gsw->vlan_entries[i].vid = map->vids[i];
+       }
+}
+
+static int mt753x_get_vlan_enable(struct switch_dev *dev,
+                                 const struct switch_attr *attr,
+                                 struct switch_val *val)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       val->value.i = gsw->global_vlan_enable;
+
+       return 0;
+}
+
+static int mt753x_set_vlan_enable(struct switch_dev *dev,
+                                 const struct switch_attr *attr,
+                                 struct switch_val *val)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       gsw->global_vlan_enable = val->value.i != 0;
+
+       return 0;
+}
+
+static int mt753x_get_port_pvid(struct switch_dev *dev, int port, int *val)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       if (port >= MT753X_NUM_PORTS)
+               return -EINVAL;
+
+       *val = mt753x_reg_read(gsw, PPBV1(port));
+       *val &= GRP_PORT_VID_M;
+
+       return 0;
+}
+
+static int mt753x_set_port_pvid(struct switch_dev *dev, int port, int pvid)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       if (port >= MT753X_NUM_PORTS)
+               return -EINVAL;
+
+       if (pvid < MT753X_MIN_VID || pvid > MT753X_MAX_VID)
+               return -EINVAL;
+
+       gsw->port_entries[port].pvid = pvid;
+
+       return 0;
+}
+
+static void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val)
+{
+       int i;
+
+       mt753x_reg_write(gsw, VTCR,
+                        VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
+                        (val & VTCR_VID_M));
+
+       for (i = 0; i < 300; i++) {
+               u32 val = mt753x_reg_read(gsw, VTCR);
+
+               if ((val & VTCR_BUSY) == 0)
+                       break;
+
+               usleep_range(1000, 1100);
+       }
+
+       if (i == 300)
+               dev_info(gsw->dev, "vtcr timeout\n");
+}
+
+static int mt753x_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       u32 member;
+       u32 etags;
+       int i;
+
+       val->len = 0;
+
+       if (val->port_vlan < 0 || val->port_vlan >= MT753X_NUM_VLANS)
+               return -EINVAL;
+
+       mt753x_vlan_ctrl(gsw, VTCR_READ_VLAN_ENTRY, val->port_vlan);
+
+       member = mt753x_reg_read(gsw, VAWD1);
+       member &= PORT_MEM_M;
+       member >>= PORT_MEM_S;
+
+       etags = mt753x_reg_read(gsw, VAWD2);
+
+       for (i = 0; i < MT753X_NUM_PORTS; i++) {
+               struct switch_port *p;
+               int etag;
+
+               if (!(member & BIT(i)))
+                       continue;
+
+               p = &val->value.ports[val->len++];
+               p->id = i;
+
+               etag = (etags >> PORT_ETAG_S(i)) & PORT_ETAG_M;
+
+               if (etag == ETAG_CTRL_TAG)
+                       p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED);
+               else if (etag != ETAG_CTRL_UNTAG)
+                       dev_info(gsw->dev,
+                                "vlan egress tag control neither untag nor tag.\n");
+       }
+
+       return 0;
+}
+
+static int mt753x_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       u8 member = 0;
+       u8 etags = 0;
+       int i;
+
+       if (val->port_vlan < 0 || val->port_vlan >= MT753X_NUM_VLANS ||
+           val->len > MT753X_NUM_PORTS)
+               return -EINVAL;
+
+       for (i = 0; i < val->len; i++) {
+               struct switch_port *p = &val->value.ports[i];
+
+               if (p->id >= MT753X_NUM_PORTS)
+                       return -EINVAL;
+
+               member |= BIT(p->id);
+
+               if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED))
+                       etags |= BIT(p->id);
+       }
+
+       gsw->vlan_entries[val->port_vlan].member = member;
+       gsw->vlan_entries[val->port_vlan].etags = etags;
+
+       return 0;
+}
+
+static int mt753x_set_vid(struct switch_dev *dev,
+                         const struct switch_attr *attr,
+                         struct switch_val *val)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       int vlan;
+       u16 vid;
+
+       vlan = val->port_vlan;
+       vid = (u16)val->value.i;
+
+       if (vlan < 0 || vlan >= MT753X_NUM_VLANS)
+               return -EINVAL;
+
+       if (vid < MT753X_MIN_VID || vid > MT753X_MAX_VID)
+               return -EINVAL;
+
+       gsw->vlan_entries[vlan].vid = vid;
+       return 0;
+}
+
+static int mt753x_get_vid(struct switch_dev *dev,
+                         const struct switch_attr *attr,
+                         struct switch_val *val)
+{
+       val->value.i = val->port_vlan;
+       return 0;
+}
+
+static int mt753x_get_port_link(struct switch_dev *dev, int port,
+                               struct switch_port_link *link)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       u32 speed, pmsr;
+
+       if (port < 0 || port >= MT753X_NUM_PORTS)
+               return -EINVAL;
+
+       pmsr = mt753x_reg_read(gsw, PMSR(port));
+
+       link->link = pmsr & MAC_LNK_STS;
+       link->duplex = pmsr & MAC_DPX_STS;
+       speed = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S;
+
+       switch (speed) {
+       case MAC_SPD_10:
+               link->speed = SWITCH_PORT_SPEED_10;
+               break;
+       case MAC_SPD_100:
+               link->speed = SWITCH_PORT_SPEED_100;
+               break;
+       case MAC_SPD_1000:
+               link->speed = SWITCH_PORT_SPEED_1000;
+               break;
+       case MAC_SPD_2500:
+               /* TODO: swconfig has no support for 2500 now */
+               link->speed = SWITCH_PORT_SPEED_UNKNOWN;
+               break;
+       }
+
+       return 0;
+}
+
+static int mt753x_set_port_link(struct switch_dev *dev, int port,
+                               struct switch_port_link *link)
+{
+#ifndef MODULE
+       if (port >= MT753X_NUM_PHYS)
+               return -EINVAL;
+
+       return switch_generic_set_link(dev, port, link);
+#else
+       return -ENOTSUPP;
+#endif
+}
+
+static u64 get_mib_counter(struct gsw_mt753x *gsw, int i, int port)
+{
+       unsigned int offset;
+       u64 lo, hi, hi2;
+
+       offset = mt753x_mibs[i].offset;
+
+       if (mt753x_mibs[i].size == 1)
+               return mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset));
+
+       do {
+               hi = mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
+               lo = mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset));
+               hi2 = mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
+       } while (hi2 != hi);
+
+       return (hi << 32) | lo;
+}
+
+static int mt753x_get_port_mib(struct switch_dev *dev,
+                              const struct switch_attr *attr,
+                              struct switch_val *val)
+{
+       static char buf[4096];
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       int i, len = 0;
+
+       if (val->port_vlan >= MT753X_NUM_PORTS)
+               return -EINVAL;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "Port %d MIB counters\n", val->port_vlan);
+
+       for (i = 0; i < ARRAY_SIZE(mt753x_mibs); ++i) {
+               u64 counter;
+
+               len += snprintf(buf + len, sizeof(buf) - len,
+                               "%-11s: ", mt753x_mibs[i].name);
+               counter = get_mib_counter(gsw, i, val->port_vlan);
+               len += snprintf(buf + len, sizeof(buf) - len, "%llu\n",
+                               counter);
+       }
+
+       val->value.s = buf;
+       val->len = len;
+       return 0;
+}
+
+static int mt753x_get_port_stats(struct switch_dev *dev, int port,
+                                struct switch_port_stats *stats)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       if (port < 0 || port >= MT753X_NUM_PORTS)
+               return -EINVAL;
+
+       stats->tx_bytes = get_mib_counter(gsw, MT753X_PORT_MIB_TXB_ID, port);
+       stats->rx_bytes = get_mib_counter(gsw, MT753X_PORT_MIB_RXB_ID, port);
+
+       return 0;
+}
+
+static void mt753x_port_isolation(struct gsw_mt753x *gsw)
+{
+       int i;
+
+       for (i = 0; i < MT753X_NUM_PORTS; i++)
+               mt753x_reg_write(gsw, PCR(i),
+                                BIT(gsw->cpu_port) << PORT_MATRIX_S);
+
+       mt753x_reg_write(gsw, PCR(gsw->cpu_port), PORT_MATRIX_M);
+
+       for (i = 0; i < MT753X_NUM_PORTS; i++)
+               mt753x_reg_write(gsw, PVC(i),
+                                (0x8100 << STAG_VPID_S) |
+                                (VA_TRANSPARENT_PORT << VLAN_ATTR_S));
+}
+
+static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid,
+                                   u8 ports, u8 etags)
+{
+       int port;
+       u32 val;
+
+       /* vlan port membership */
+       if (ports)
+               mt753x_reg_write(gsw, VAWD1,
+                                IVL_MAC | VTAG_EN | VENTRY_VALID |
+                                ((ports << PORT_MEM_S) & PORT_MEM_M));
+       else
+               mt753x_reg_write(gsw, VAWD1, 0);
+
+       /* egress mode */
+       val = 0;
+       for (port = 0; port < MT753X_NUM_PORTS; port++) {
+               if (etags & BIT(port))
+                       val |= ETAG_CTRL_TAG << PORT_ETAG_S(port);
+               else
+                       val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port);
+       }
+       mt753x_reg_write(gsw, VAWD2, val);
+
+       /* write to vlan table */
+       mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
+}
+
+static int mt753x_apply_config(struct switch_dev *dev)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       int i, j;
+       u8 tag_ports;
+       u8 untag_ports;
+
+       if (!gsw->global_vlan_enable) {
+               mt753x_port_isolation(gsw);
+               return 0;
+       }
+
+       /* set all ports as security mode */
+       for (i = 0; i < MT753X_NUM_PORTS; i++)
+               mt753x_reg_write(gsw, PCR(i),
+                                PORT_MATRIX_M | SECURITY_MODE);
+
+       /* check if a port is used in tag/untag vlan egress mode */
+       tag_ports = 0;
+       untag_ports = 0;
+
+       for (i = 0; i < MT753X_NUM_VLANS; i++) {
+               u8 member = gsw->vlan_entries[i].member;
+               u8 etags = gsw->vlan_entries[i].etags;
+
+               if (!member)
+                       continue;
+
+               for (j = 0; j < MT753X_NUM_PORTS; j++) {
+                       if (!(member & BIT(j)))
+                               continue;
+
+                       if (etags & BIT(j))
+                               tag_ports |= 1u << j;
+                       else
+                               untag_ports |= 1u << j;
+               }
+       }
+
+       /* set all untag-only ports as transparent and the rest as user port */
+       for (i = 0; i < MT753X_NUM_PORTS; i++) {
+               u32 pvc_mode = 0x8100 << STAG_VPID_S;
+
+               if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
+                       pvc_mode = (0x8100 << STAG_VPID_S) |
+                               (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
+
+               mt753x_reg_write(gsw, PVC(i), pvc_mode);
+       }
+
+       /* first clear the swtich vlan table */
+       for (i = 0; i < MT753X_NUM_VLANS; i++)
+               mt753x_write_vlan_entry(gsw, i, i, 0, 0);
+
+       /* now program only vlans with members to avoid
+        * clobbering remapped entries in later iterations
+        */
+       for (i = 0; i < MT753X_NUM_VLANS; i++) {
+               u16 vid = gsw->vlan_entries[i].vid;
+               u8 member = gsw->vlan_entries[i].member;
+               u8 etags = gsw->vlan_entries[i].etags;
+
+               if (member)
+                       mt753x_write_vlan_entry(gsw, i, vid, member, etags);
+       }
+
+       /* Port Default PVID */
+       for (i = 0; i < MT753X_NUM_PORTS; i++) {
+               int vlan = gsw->port_entries[i].pvid;
+               u16 pvid = 0;
+               u32 val;
+
+               if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member)
+                       pvid = gsw->vlan_entries[vlan].vid;
+
+               val = mt753x_reg_read(gsw, PPBV1(i));
+               val &= ~GRP_PORT_VID_M;
+               val |= pvid;
+               mt753x_reg_write(gsw, PPBV1(i), val);
+       }
+
+       return 0;
+}
+
+static int mt753x_reset_switch(struct switch_dev *dev)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+       int i;
+
+       memset(gsw->port_entries, 0, sizeof(gsw->port_entries));
+       memset(gsw->vlan_entries, 0, sizeof(gsw->vlan_entries));
+
+       /* set default vid of each vlan to the same number of vlan, so the vid
+        * won't need be set explicitly.
+        */
+       for (i = 0; i < MT753X_NUM_VLANS; i++)
+               gsw->vlan_entries[i].vid = i;
+
+       return 0;
+}
+
+static int mt753x_phy_read16(struct switch_dev *dev, int addr, u8 reg,
+                            u16 *value)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       *value = gsw->mii_read(gsw, addr, reg);
+
+       return 0;
+}
+
+static int mt753x_phy_write16(struct switch_dev *dev, int addr, u8 reg,
+                             u16 value)
+{
+       struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
+
+       gsw->mii_write(gsw, addr, reg, value);
+
+       return 0;
+}
+
+static const struct switch_attr mt753x_global[] = {
+       {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_vlan",
+               .description = "VLAN mode (1:enabled)",
+               .max = 1,
+               .id = MT753X_ATTR_ENABLE_VLAN,
+               .get = mt753x_get_vlan_enable,
+               .set = mt753x_set_vlan_enable,
+       }
+};
+
+static const struct switch_attr mt753x_port[] = {
+       {
+               .type = SWITCH_TYPE_STRING,
+               .name = "mib",
+               .description = "Get MIB counters for port",
+               .get = mt753x_get_port_mib,
+               .set = NULL,
+       },
+};
+
+static const struct switch_attr mt753x_vlan[] = {
+       {
+               .type = SWITCH_TYPE_INT,
+               .name = "vid",
+               .description = "VLAN ID (0-4094)",
+               .set = mt753x_set_vid,
+               .get = mt753x_get_vid,
+               .max = 4094,
+       },
+};
+
+static const struct switch_dev_ops mt753x_swdev_ops = {
+       .attr_global = {
+               .attr = mt753x_global,
+               .n_attr = ARRAY_SIZE(mt753x_global),
+       },
+       .attr_port = {
+               .attr = mt753x_port,
+               .n_attr = ARRAY_SIZE(mt753x_port),
+       },
+       .attr_vlan = {
+               .attr = mt753x_vlan,
+               .n_attr = ARRAY_SIZE(mt753x_vlan),
+       },
+       .get_vlan_ports = mt753x_get_vlan_ports,
+       .set_vlan_ports = mt753x_set_vlan_ports,
+       .get_port_pvid = mt753x_get_port_pvid,
+       .set_port_pvid = mt753x_set_port_pvid,
+       .get_port_link = mt753x_get_port_link,
+       .set_port_link = mt753x_set_port_link,
+       .get_port_stats = mt753x_get_port_stats,
+       .apply_config = mt753x_apply_config,
+       .reset_switch = mt753x_reset_switch,
+       .phy_read16 = mt753x_phy_read16,
+       .phy_write16 = mt753x_phy_write16,
+};
+
+int mt753x_swconfig_init(struct gsw_mt753x *gsw)
+{
+       struct device_node *np = gsw->dev->of_node;
+       struct switch_dev *swdev;
+       struct mt753x_mapping *map;
+       int ret;
+
+       if (of_property_read_u32(np, "mediatek,cpuport", &gsw->cpu_port))
+               gsw->cpu_port = MT753X_DFL_CPU_PORT;
+
+       swdev = &gsw->swdev;
+
+       swdev->name = gsw->name;
+       swdev->alias = gsw->name;
+       swdev->cpu_port = gsw->cpu_port;
+       swdev->ports = MT753X_NUM_PORTS;
+       swdev->vlans = MT753X_NUM_VLANS;
+       swdev->ops = &mt753x_swdev_ops;
+
+       ret = register_switch(swdev, NULL);
+       if (ret) {
+               dev_err(gsw->dev, "Failed to register switch %s\n",
+                       swdev->name);
+               return ret;
+       }
+
+       map = mt753x_find_mapping(gsw->dev->of_node);
+       if (map)
+               mt753x_apply_mapping(gsw, map);
+       mt753x_apply_config(swdev);
+
+       return 0;
+}
+
+void mt753x_swconfig_destroy(struct gsw_mt753x *gsw)
+{
+       unregister_switch(&gsw->swdev);
+}
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h
new file mode 100644 (file)
index 0000000..971a2cc
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * OpenWrt swconfig support for MediaTek MT753x Gigabit switch
+ *
+ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MT753X_SWCONFIG_H_
+#define _MT753X_SWCONFIG_H_
+
+#include <linux/switch.h>
+
+int mt753x_swconfig_init(struct gsw_mt753x *gsw);
+void mt753x_swconfig_destroy(struct gsw_mt753x *gsw);
+
+#endif /* _MT753X_SWCONFIG_H_ */
index 86b25ce33c9dec3f9036665c702f5ddf948d4d4c..1644a3ea68130cb20df6990767bd9e1e1f1b7c32 100644 (file)
@@ -1,9 +1,26 @@
 define Device/MTK-RFB1
-  DEVICE_TITLE := MTK7622 rfb1 AP 
+  DEVICE_TITLE := MTK7622 rfb1 AP
   DEVICE_DTS := mt7622-rfb1
   DEVICE_DTS_DIR := $(DTS_DIR)/mediatek
-  SUPPORTED_DEVICES := mt7622
   DEVICE_PACKAGES := kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-usb3 \
-                       kmod-ata-core kmod-ata-ahci-mtk 
+                       kmod-ata-core kmod-ata-ahci-mtk
 endef
 TARGET_DEVICES += MTK-RFB1
+
+define Device/MTK-LYNX-RFB1
+  DEVICE_TITLE := MTK7622 Lynx rfb1 AP
+  DEVICE_DTS := mt7622-lynx-rfb1
+  DEVICE_DTS_DIR := $(DTS_DIR)/mediatek
+  DEVICE_PACKAGES := kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-usb3 \
+                       kmod-ata-core kmod-ata-ahci-mtk
+endef
+TARGET_DEVICES += MTK-LYNX-RFB1
+
+define Device/BPI-R64
+  DEVICE_TITLE := Bannan Pi R64
+  DEVICE_DTS := mt7622-bananapi-bpi-r64
+  DEVICE_DTS_DIR := $(DTS_DIR)/mediatek
+  DEVICE_PACKAGES := kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-usb3 \
+                       kmod-ata-core kmod-ata-ahci-mtk
+endef
+TARGET_DEVICES += BPI-R64
diff --git a/target/linux/mediatek/mt7622/config-4.19 b/target/linux/mediatek/mt7622/config-4.19
new file mode 100755 (executable)
index 0000000..5e3ceb3
--- /dev/null
@@ -0,0 +1,596 @@
+CONFIG_64BIT=y
+CONFIG_AHCI_MTK=y
+# CONFIG_ANDROID_DEFAULT_SETTING is not set
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+CONFIG_ARCH_HAS_KCOV=y
+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_ARCH_INLINE_READ_LOCK=y
+CONFIG_ARCH_INLINE_READ_LOCK_BH=y
+CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_READ_UNLOCK=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_INLINE_SPIN_LOCK=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_INLINE_WRITE_LOCK=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_ARCH_MMAP_RND_BITS=18
+CONFIG_ARCH_MMAP_RND_BITS_MAX=24
+CONFIG_ARCH_MMAP_RND_BITS_MIN=18
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_SUPPORTS_INT128=y
+CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARM64=y
+# CONFIG_ARM64_16K_PAGES is not set
+CONFIG_ARM64_4K_PAGES=y
+# CONFIG_ARM64_64K_PAGES is not set
+CONFIG_ARM64_CONT_SHIFT=4
+# CONFIG_ARM64_CRYPTO is not set
+# CONFIG_ARM64_ERRATUM_1463225 is not set
+CONFIG_ARM64_HW_AFDBM=y
+# CONFIG_ARM64_LSE_ATOMICS is not set
+CONFIG_ARM64_PAGE_SHIFT=12
+CONFIG_ARM64_PAN=y
+CONFIG_ARM64_PA_BITS=48
+CONFIG_ARM64_PA_BITS_48=y
+# CONFIG_ARM64_PMEM is not set
+# CONFIG_ARM64_PTDUMP_DEBUGFS is not set
+# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set
+CONFIG_ARM64_SSBD=y
+CONFIG_ARM64_SVE=y
+# CONFIG_ARM64_SW_TTBR0_PAN is not set
+CONFIG_ARM64_UAO=y
+CONFIG_ARM64_VA_BITS=39
+CONFIG_ARM64_VA_BITS_39=y
+# CONFIG_ARM64_VA_BITS_48 is not set
+CONFIG_ARM64_VHE=y
+# CONFIG_ARMV8_DEPRECATED is not set
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_V2M=y
+CONFIG_ARM_GIC_V3=y
+CONFIG_ARM_GIC_V3_ITS=y
+CONFIG_ARM_GIC_V3_ITS_PCI=y
+CONFIG_ARM_MEDIATEK_CPUFREQ=y
+CONFIG_ARM_PMU=y
+CONFIG_ARM_PSCI_FW=y
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ATA=y
+CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_BT=y
+CONFIG_BT_BCM=y
+CONFIG_BT_BREDR=y
+CONFIG_BT_DEBUGFS=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_BCM=y
+# CONFIG_BT_HCIUART_INTEL is not set
+# CONFIG_BT_HCIUART_NOKIA is not set
+CONFIG_BT_HCIUART_QCA=y
+CONFIG_BT_HCIUART_SERDEV=y
+CONFIG_BT_HCIVHCI=y
+CONFIG_BT_HS=y
+CONFIG_BT_LE=y
+CONFIG_BT_MTKUART=y
+CONFIG_BT_QCA=y
+CONFIG_BUILD_BIN2C=y
+CONFIG_CC_HAS_ASM_GOTO=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLOCK_THERMAL=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_MEDIATEK=y
+CONFIG_COMMON_CLK_MT2712=y
+# CONFIG_COMMON_CLK_MT2712_BDPSYS is not set
+# CONFIG_COMMON_CLK_MT2712_IMGSYS is not set
+# CONFIG_COMMON_CLK_MT2712_JPGDECSYS is not set
+# CONFIG_COMMON_CLK_MT2712_MFGCFG is not set
+# CONFIG_COMMON_CLK_MT2712_MMSYS is not set
+# CONFIG_COMMON_CLK_MT2712_VDECSYS is not set
+# CONFIG_COMMON_CLK_MT2712_VENCSYS is not set
+# CONFIG_COMMON_CLK_MT6779 is not set
+# CONFIG_COMMON_CLK_MT6797 is not set
+CONFIG_COMMON_CLK_MT7622=y
+CONFIG_COMMON_CLK_MT7622_AUDSYS=y
+CONFIG_COMMON_CLK_MT7622_ETHSYS=y
+CONFIG_COMMON_CLK_MT7622_HIFSYS=y
+# CONFIG_COMMON_CLK_MT8173 is not set
+CONFIG_COMPAT=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_COMPAT_BINFMT_ELF=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15
+# CONFIG_CPUFREQ_DT is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_TIMES is not set
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_THERMAL=y
+CONFIG_CRC16=y
+# CONFIG_CRYPTO_ADIANTUM is not set
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_ECDH=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_CRYPTO_KPP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CUSTOM_KERNEL_LCM=""
+CONFIG_CUSTOM_LCM_X="0"
+CONFIG_CUSTOM_LCM_Y="0"
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_DEFAULT_NOOP=y
+# CONFIG_DEVAPC_ARCH_V1 is not set
+# CONFIG_DEVAPC_MT6779 is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMADEVICES=y
+CONFIG_DMATEST=y
+CONFIG_DMA_DIRECT_OPS=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_ENGINE_RAID=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DTC=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EINT_MTK=y
+# CONFIG_ENERGY_MODEL is not set
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ARCH_TOPOLOGY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GLOB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPS is not set
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_HAVE_ARM_SMCCC=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_BUGVERBOSE=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_EBPF_JIT=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_GENERIC_GUP=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_PATA_PLATFORM=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_RCU_TABLE_FREE=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_SCHED_AVG_IRQ=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HOLES_IN_ZONE=y
+# CONFIG_HUGETLBFS is not set
+CONFIG_ICPLUS_PHY=y
+CONFIG_IIO=y
+# CONFIG_IIO_BUFFER is not set
+# CONFIG_IIO_TRIGGER is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INLINE_READ_LOCK=y
+CONFIG_INLINE_READ_LOCK_BH=y
+CONFIG_INLINE_READ_LOCK_IRQ=y
+CONFIG_INLINE_READ_LOCK_IRQSAVE=y
+CONFIG_INLINE_READ_UNLOCK_BH=y
+CONFIG_INLINE_READ_UNLOCK_IRQRESTORE=y
+CONFIG_INLINE_SPIN_LOCK=y
+CONFIG_INLINE_SPIN_LOCK_BH=y
+CONFIG_INLINE_SPIN_LOCK_IRQ=y
+CONFIG_INLINE_SPIN_LOCK_IRQSAVE=y
+CONFIG_INLINE_SPIN_TRYLOCK=y
+CONFIG_INLINE_SPIN_TRYLOCK_BH=y
+CONFIG_INLINE_SPIN_UNLOCK_BH=y
+CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE=y
+CONFIG_INLINE_WRITE_LOCK=y
+CONFIG_INLINE_WRITE_LOCK_BH=y
+CONFIG_INLINE_WRITE_LOCK_IRQ=y
+CONFIG_INLINE_WRITE_LOCK_IRQSAVE=y
+CONFIG_INLINE_WRITE_UNLOCK_BH=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE=y
+# CONFIG_INTERCONNECT is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_IRQ_WORK=y
+CONFIG_JUMP_LABEL=y
+CONFIG_LCM_HEIGHT="1920"
+CONFIG_LCM_WIDTH="1080"
+# CONFIG_LEGACY_ENERGY_MODEL_DT is not set
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_LTO_NONE=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MARVELL_88Q_PHY is not set
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MEDIATEK_MT6577_AUXADC=y
+CONFIG_MEDIATEK_WATCHDOG=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_MTK=y
+# CONFIG_MMC_TIFM_SD is not set
+# CONFIG_MMPROFILE is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MT753X_GSW=y
+# CONFIG_MTD_GPT_PARTS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_CORE=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_MTK=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_FIRMWARE=y
+CONFIG_MTD_SPLIT_FIRMWARE_NAME="Kernel"
+CONFIG_MTD_SPLIT_FIT_FW=y
+CONFIG_MTD_SPLIT_UIMAGE_FW=y
+# CONFIG_MTK_AAL_SUPPORT is not set
+# CONFIG_MTK_ANDROID_DEFAULT_SETTING is not set
+# CONFIG_MTK_ATF_LOGGER is not set
+# CONFIG_MTK_BTIF is not set
+# CONFIG_MTK_CMDQ is not set
+# CONFIG_MTK_COMBO is not set
+# CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH is not set
+# CONFIG_MTK_CONN_LTE_IDC_SUPPORT is not set
+# CONFIG_MTK_CONN_MT3337_CHIP_SUPPORT is not set
+# CONFIG_MTK_CONSUMER_PARTIAL_UPDATE_SUPPORT is not set
+# CONFIG_MTK_DEVAPC is not set
+# CONFIG_MTK_DHCPV6C_WIFI is not set
+# CONFIG_MTK_DISPLAY_LOW_MEMORY_DEBUG_SUPPORT is not set
+CONFIG_MTK_DISP_PLATFORM=""
+# CONFIG_MTK_DRE30_SUPPORT is not set
+# CONFIG_MTK_DVFSRC is not set
+# CONFIG_MTK_EFUSE is not set
+# CONFIG_MTK_GED_SUPPORT is not set
+# CONFIG_MTK_GPS_SUPPORT is not set
+# CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT is not set
+# CONFIG_MTK_GPU_SUPPORT is not set
+CONFIG_MTK_GPU_VERSION=""
+CONFIG_MTK_HSDMA=y
+CONFIG_MTK_ICE_DEBUG=y
+CONFIG_MTK_INFRACFG=y
+# CONFIG_MTK_LCM is not set
+# CONFIG_MTK_LCM_DEVICE_TREE_SUPPORT is not set
+CONFIG_MTK_LCM_PHYSICAL_ROTATION=""
+# CONFIG_MTK_MERGE_INTERFACE_SUPPORT is not set
+# CONFIG_MTK_MET_CORE is not set
+# CONFIG_MTK_MET_MEM_ALLOC is not set
+# CONFIG_MTK_MMDVFS is not set
+# CONFIG_MTK_MMPROFILE_SUPPORT is not set
+# CONFIG_MTK_OD_SUPPORT is not set
+# CONFIG_MTK_OVERLAY_ENGINE_SUPPORT is not set
+CONFIG_MTK_PMIC_WRAP=y
+CONFIG_MTK_PQ_COLOR_MODE="DISP"
+# CONFIG_MTK_REBOOT_MODE is not set
+# CONFIG_MTK_ROUND_CORNER_SUPPORT is not set
+# CONFIG_MTK_SCHED_INTEROP is not set
+CONFIG_MTK_SCPSYS=y
+# CONFIG_MTK_SCPSYS_BRINGUP is not set
+# CONFIG_MTK_SPMTWAM is not set
+CONFIG_MTK_THERMAL=y
+CONFIG_MTK_TIMER=y
+# CONFIG_MTK_TINYSYS_SSPM_PLT_SUPPORT is not set
+# CONFIG_MTK_TINYSYS_SSPM_SUPPORT is not set
+# CONFIG_MTK_VIDEOX is not set
+# CONFIG_MTPROF is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_MEDIATEK_SOC=y
+CONFIG_NET_VENDOR_MEDIATEK=y
+CONFIG_NLS=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+CONFIG_NVMEM=y
+# CONFIG_NXP_TJA1100_PHY is not set
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_PADATA=y
+CONFIG_PARTITION_PERCPU=y
+CONFIG_PCI=y
+CONFIG_PCIE_MEDIATEK=y
+CONFIG_PCI_DEBUG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PERF_EVENTS=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_PHYLIB=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PHY_MTK_TPHY=y
+# CONFIG_PHY_MTK_UFS is not set
+# CONFIG_PHY_MTK_XSPHY is not set
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_MT2712 is not set
+# CONFIG_PINCTRL_MT6765 is not set
+# CONFIG_PINCTRL_MT6779 is not set
+# CONFIG_PINCTRL_MT6797 is not set
+CONFIG_PINCTRL_MT7622=y
+# CONFIG_PINCTRL_MT8173 is not set
+# CONFIG_PINCTRL_MT8183 is not set
+CONFIG_PINCTRL_MTK_MOORE=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_PM_GENERIC_DOMAINS_OF=y
+CONFIG_PM_OPP=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_PROC_UID is not set
+# CONFIG_PSI is not set
+CONFIG_PWM=y
+CONFIG_PWM_MEDIATEK=y
+# CONFIG_PWM_MTK_DISP is not set
+CONFIG_PWM_SYSFS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+# CONFIG_RANDOMIZE_BASE is not set
+CONFIG_RAS=y
+CONFIG_RATIONAL=y
+# CONFIG_RAVE_SP_CORE is not set
+CONFIG_RCU_NEED_SEGCBLIST=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_REALTEK_PHY=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MT6380=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_MT7622=y
+CONFIG_RTC_I2C_AND_SPI=y
+CONFIG_RTL8367S_GSW=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_SCHED_MC=y
+# CONFIG_SCHED_TUNE is not set
+CONFIG_SCSI=y
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+# CONFIG_SECURITY_PERF_EVENTS_RESTRICT is not set
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_8250_MT6577=y
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SG_POOL=y
+# CONFIG_SINGLE_PANEL_OUTPUT is not set
+CONFIG_SMP=y
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_MT65XX=y
+# CONFIG_SPI_MTK_QUADSPI is not set
+CONFIG_SPI_MTK_SNFI=y
+CONFIG_SRCU=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_EMULATION=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_OF=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
+CONFIG_USB=y
+CONFIG_USB_COMMON=y
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_MTK=y
+# CONFIG_USB_XHCI_PLATFORM is not set
+CONFIG_VMAP_STACK=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y
+CONFIG_WATCHDOG_PRETIMEOUT_GOV=y
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_XPS=y
+CONFIG_ZONE_DMA32=y
diff --git a/target/linux/mediatek/patches-4.19/0001-arm-dts-mediatek-add-basic-support-for-MT7629-SoC.patch b/target/linux/mediatek/patches-4.19/0001-arm-dts-mediatek-add-basic-support-for-MT7629-SoC.patch
new file mode 100755 (executable)
index 0000000..904f444
--- /dev/null
@@ -0,0 +1,94 @@
+From acb69c6600c3df52f0b3610801f3fd44c4392333 Mon Sep 17 00:00:00 2001
+Message-Id: <acb69c6600c3df52f0b3610801f3fd44c4392333.1559210220.git.ryder.lee@mediatek.com>
+From: Ryder Lee <ryder.lee@mediatek.com>
+Date: Wed, 13 Mar 2019 16:42:15 +0800
+Subject: [PATCH] arm: dts: mediatek: add basic support for MT7629 SoC
+
+This adds basic support for MT7629 reference board.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+ include/dt-bindings/reset/mt7629-resets.h |  71 ++++
+ 4 files changed, 704 insertions(+)
+ create mode 100644 include/dt-bindings/reset/mt7629-resets.h
+
+diff --git a/include/dt-bindings/reset/mt7629-resets.h b/include/dt-bindings/reset/mt7629-resets.h
+new file mode 100644
+index 000000000000..6bb85734f68d
+--- /dev/null
++++ b/include/dt-bindings/reset/mt7629-resets.h
+@@ -0,0 +1,71 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2019 MediaTek Inc.
++ */
++
++#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7629
++#define _DT_BINDINGS_RESET_CONTROLLER_MT7629
++
++/* INFRACFG resets */
++#define MT7629_INFRA_EMI_MPU_RST              0
++#define MT7629_INFRA_UART5_RST                        2
++#define MT7629_INFRA_CIRQ_EINT_RST            3
++#define MT7629_INFRA_APXGPT_RST                       4
++#define MT7629_INFRA_SCPSYS_RST                       5
++#define MT7629_INFRA_KP_RST                   6
++#define MT7629_INFRA_SPI1_RST                 7
++#define MT7629_INFRA_SPI4_RST                 8
++#define MT7629_INFRA_SYSTIMER_RST             9
++#define MT7629_INFRA_IRRX_RST                 10
++#define MT7629_INFRA_AO_BUS_RST                       16
++#define MT7629_INFRA_EMI_RST                  32
++#define MT7629_INFRA_APMIXED_RST              35
++#define MT7629_INFRA_MIPI_RST                 36
++#define MT7629_INFRA_TRNG_RST                 37
++#define MT7629_INFRA_SYSCIRQ_RST              38
++#define MT7629_INFRA_MIPI_CSI_RST             39
++#define MT7629_INFRA_GCE_FAXI_RST             40
++#define MT7629_INFRA_I2C_SRAM_RST             41
++#define MT7629_INFRA_IOMMU_RST                        47
++
++/* PERICFG resets */
++#define MT7629_PERI_UART0_SW_RST              0
++#define MT7629_PERI_UART1_SW_RST              1
++#define MT7629_PERI_UART2_SW_RST              2
++#define MT7629_PERI_BTIF_SW_RST                       6
++#define MT7629_PERI_PWN_SW_RST                        8
++#define MT7629_PERI_DMA_SW_RST                        11
++#define MT7629_PERI_NFI_SW_RST                        14
++#define MT7629_PERI_I2C0_SW_RST                       22
++#define MT7629_PERI_SPI0_SW_RST                       33
++#define MT7629_PERI_SPI1_SW_RST                       34
++#define MT7629_PERI_FLASHIF_SW_RST            36
++
++/* PCIe Subsystem resets */
++#define MT7629_PCIE1_CORE_RST                 19
++#define MT7629_PCIE1_MMIO_RST                 20
++#define MT7629_PCIE1_HRST                     21
++#define MT7629_PCIE1_USER_RST                 22
++#define MT7629_PCIE1_PIPE_RST                 23
++#define MT7629_PCIE0_CORE_RST                 27
++#define MT7629_PCIE0_MMIO_RST                 28
++#define MT7629_PCIE0_HRST                     29
++#define MT7629_PCIE0_USER_RST                 30
++#define MT7629_PCIE0_PIPE_RST                 31
++
++/* SSUSB Subsystem resets */
++#define MT7629_SSUSB_PHY_PWR_RST              3
++#define MT7629_SSUSB_MAC_PWR_RST              4
++
++/* ETH Subsystem resets */
++#define MT7629_ETHSYS_SYS_RST                 0
++#define MT7629_ETHSYS_MCM_RST                 2
++#define MT7629_ETHSYS_HSDMA_RST                       5
++#define MT7629_ETHSYS_FE_RST                  6
++#define MT7629_ETHSYS_ESW_RST                 16
++#define MT7629_ETHSYS_GMAC_RST                        23
++#define MT7629_ETHSYS_EPHY_RST                        24
++#define MT7629_ETHSYS_CRYPTO_RST              29
++#define MT7629_ETHSYS_PPE_RST                 31
++
++#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT7629 */
+-- 
+2.18.0
+
diff --git a/target/linux/mediatek/patches-4.19/0001-eth-sync-from-mtk-lede.patch b/target/linux/mediatek/patches-4.19/0001-eth-sync-from-mtk-lede.patch
new file mode 100644 (file)
index 0000000..c5521c4
--- /dev/null
@@ -0,0 +1,1658 @@
+Index: linux-4.19.57/drivers/net/ethernet/mediatek/Kconfig
+===================================================================
+--- linux-4.19.57.orig/drivers/net/ethernet/mediatek/Kconfig
++++ linux-4.19.57/drivers/net/ethernet/mediatek/Kconfig
+@@ -1,6 +1,6 @@
+ config NET_VENDOR_MEDIATEK
+       bool "MediaTek ethernet driver"
+-      depends on ARCH_MEDIATEK
++      depends on ARCH_MEDIATEK || RALINK
+       ---help---
+         If you have a Mediatek SoC with ethernet, say Y.
+Index: linux-4.19.57/drivers/net/ethernet/mediatek/Makefile
+===================================================================
+--- linux-4.19.57.orig/drivers/net/ethernet/mediatek/Makefile
++++ linux-4.19.57/drivers/net/ethernet/mediatek/Makefile
+@@ -2,4 +2,5 @@
+ # Makefile for the Mediatek SoCs built-in ethernet macs
+ #
+-obj-$(CONFIG_NET_MEDIATEK_SOC)                        += mtk_eth_soc.o
++obj-$(CONFIG_NET_MEDIATEK_SOC)                        += mtk_eth_soc.o mtk_sgmii.o \
++                                                 mtk_eth_path.o
+Index: linux-4.19.57/drivers/net/ethernet/mediatek/mtk_eth_path.c
+===================================================================
+--- /dev/null
++++ linux-4.19.57/drivers/net/ethernet/mediatek/mtk_eth_path.c
+@@ -0,0 +1,333 @@
++/*
++ *   Copyright (C) 2018 MediaTek Inc.
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation; version 2 of the License
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details.
++ *
++ *   Copyright (C) 2018 Sean Wang <sean.wang@mediatek.com>
++ */
++
++#include <linux/phy.h>
++#include <linux/regmap.h>
++
++#include "mtk_eth_soc.h"
++
++struct mtk_eth_muxc {
++      int (*set_path)(struct mtk_eth *eth, int path);
++};
++
++static const char * const mtk_eth_mux_name[] = {
++      "mux_gdm1_to_gmac1_esw", "mux_gmac2_gmac0_to_gephy",
++      "mux_u3_gmac2_to_qphy", "mux_gmac1_gmac2_to_sgmii_rgmii",
++      "mux_gmac12_to_gephy_sgmii",
++};
++
++static const char * const mtk_eth_path_name[] = {
++      "gmac1_rgmii", "gmac1_trgmii", "gmac1_sgmii", "gmac2_rgmii",
++      "gmac2_sgmii", "gmac2_gephy", "gdm1_esw",
++};
++
++static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
++{
++      u32 val, mask, set;
++      bool updated = true;
++
++      switch (path) {
++      case MTK_ETH_PATH_GMAC1_SGMII:
++              mask = ~(u32)MTK_MUX_TO_ESW;
++              set = 0;
++              break;
++      case MTK_ETH_PATH_GDM1_ESW:
++              mask = ~(u32)MTK_MUX_TO_ESW;
++              set = MTK_MUX_TO_ESW;
++              break;
++      default:
++              updated = false;
++              break;
++      };
++
++      if (updated) {
++              val = mtk_r32(eth, MTK_MAC_MISC);
++              val = (val & mask) | set;
++              mtk_w32(eth, val, MTK_MAC_MISC);
++      }
++
++      dev_info(eth->dev, "path %s in %s updated = %d\n",
++               mtk_eth_path_name[path], __func__, updated);
++
++      return 0;
++}
++
++static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
++{
++      unsigned int val = 0;
++      bool updated = true;
++
++      switch (path) {
++      case MTK_ETH_PATH_GMAC2_GEPHY:
++              val = ~(u32)GEPHY_MAC_SEL;
++              break;
++      default:
++              updated = false;
++              break;
++      }
++
++      if (updated)
++              regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
++
++      dev_info(eth->dev, "path %s in %s updated = %d\n",
++               mtk_eth_path_name[path], __func__, updated);
++
++      return 0;
++}
++
++static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
++{
++      unsigned int val = 0;
++      bool updated = true;
++
++      switch (path) {
++      case MTK_ETH_PATH_GMAC2_SGMII:
++              val = CO_QPHY_SEL;
++              break;
++      default:
++              updated = false;
++              break;
++      }
++
++      if (updated)
++              regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val);
++
++      dev_info(eth->dev, "path %s in %s updated = %d\n",
++               mtk_eth_path_name[path], __func__, updated);
++
++      return 0;
++}
++
++static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
++{
++      unsigned int val = 0;
++      bool updated = true;
++
++      switch (path) {
++      case MTK_ETH_PATH_GMAC1_SGMII:
++              val = SYSCFG0_SGMII_GMAC1;
++              break;
++      case MTK_ETH_PATH_GMAC2_SGMII:
++              val = SYSCFG0_SGMII_GMAC2;
++              break;
++      case MTK_ETH_PATH_GMAC1_RGMII:
++      case MTK_ETH_PATH_GMAC2_RGMII:
++              regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
++              val &= SYSCFG0_SGMII_MASK;
++
++              if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
++                  (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
++                      val = 0;
++              else
++                      updated = false;
++              break;
++      default:
++              updated = false;
++              break;
++      };
++
++      if (updated)
++              regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++                                 SYSCFG0_SGMII_MASK, val);
++
++      dev_info(eth->dev, "path %s in %s updated = %d\n",
++               mtk_eth_path_name[path], __func__, updated);
++
++      return 0;
++}
++
++static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
++{
++      unsigned int val = 0;
++      bool updated = true;
++
++      regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
++
++      switch (path) {
++      case MTK_ETH_PATH_GMAC1_SGMII:
++              val |= SYSCFG0_SGMII_GMAC1_V2;
++              break;
++      case MTK_ETH_PATH_GMAC2_GEPHY:
++              val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
++              break;
++      case MTK_ETH_PATH_GMAC2_SGMII:
++              val |= SYSCFG0_SGMII_GMAC2_V2;
++              break;
++      default:
++              updated = false;
++      };
++
++      if (updated)
++              regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++                                 SYSCFG0_SGMII_MASK, val);
++
++      if (!updated)
++              dev_info(eth->dev, "path %s no needs updatiion in %s\n",
++                       mtk_eth_path_name[path], __func__);
++
++      dev_info(eth->dev, "path %s in %s updated = %d\n",
++               mtk_eth_path_name[path], __func__, updated);
++
++      return 0;
++}
++
++static const struct mtk_eth_muxc mtk_eth_muxc[] = {
++      { .set_path = set_mux_gdm1_to_gmac1_esw, },
++      { .set_path = set_mux_gmac2_gmac0_to_gephy, },
++      { .set_path = set_mux_u3_gmac2_to_qphy, },
++      { .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii, },
++      { .set_path = set_mux_gmac12_to_gephy_sgmii, }
++};
++
++static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
++{
++      int i, err = 0;
++
++      if (!MTK_HAS_CAPS(eth->soc->caps, MTK_PATH_BIT(path))) {
++              dev_info(eth->dev, "path %s isn't support on the SoC\n",
++                       mtk_eth_path_name[path]);
++              return -EINVAL;
++      }
++
++      if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
++              return 0;
++
++      /* Setup MUX in path fabric */
++      for (i = 0; i < MTK_ETH_MUX_MAX; i++) {
++              if (MTK_HAS_CAPS(eth->soc->caps, MTK_MUX_BIT(i))) {
++                      err = mtk_eth_muxc[i].set_path(eth, path);
++                      if (err)
++                              goto out;
++              } else {
++                      dev_info(eth->dev, "mux %s isn't present on the SoC\n",
++                               mtk_eth_mux_name[i]);
++              }
++      }
++
++out:
++      return err;
++}
++
++static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
++{
++      unsigned int val = 0;
++      int sid, err, path;
++
++      path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
++                              MTK_ETH_PATH_GMAC2_SGMII;
++
++      /* Setup proper MUXes along the path */
++      err = mtk_eth_mux_setup(eth, path);
++      if (err)
++              return err;
++
++      /* The path GMAC to SGMII will be enabled once the SGMIISYS is being
++       * setup done.
++       */
++      regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
++
++      regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++                         SYSCFG0_SGMII_MASK, ~(u32)SYSCFG0_SGMII_MASK);
++
++      /* Decide how GMAC and SGMIISYS be mapped */
++      sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? 0 : mac_id;
++
++      /* Setup SGMIISYS with the determined property */
++      if (MTK_HAS_FLAGS(eth->sgmii->flags[sid], MTK_SGMII_PHYSPEED_AN))
++              err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
++      else
++              err = mtk_sgmii_setup_mode_force(eth->sgmii, sid);
++
++      if (err)
++              return err;
++
++      regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++                         SYSCFG0_SGMII_MASK, val);
++
++      return 0;
++}
++
++static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
++{
++      int err, path = 0;
++
++      if (mac_id == 1)
++              path = MTK_ETH_PATH_GMAC2_GEPHY;
++
++      if (!path)
++              return -EINVAL;
++
++      /* Setup proper MUXes along the path */
++      err = mtk_eth_mux_setup(eth, path);
++      if (err)
++              return err;
++
++      return 0;
++}
++
++static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
++{
++      int err, path;
++
++      path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
++                              MTK_ETH_PATH_GMAC2_RGMII;
++
++      /* Setup proper MUXes along the path */
++      err = mtk_eth_mux_setup(eth, path);
++      if (err)
++              return err;
++
++      return 0;
++}
++
++int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode)
++{
++      int err;
++
++      switch (phymode) {
++      case PHY_INTERFACE_MODE_TRGMII:
++      case PHY_INTERFACE_MODE_RGMII_TXID:
++      case PHY_INTERFACE_MODE_RGMII_RXID:
++      case PHY_INTERFACE_MODE_RGMII_ID:
++      case PHY_INTERFACE_MODE_RGMII:
++      case PHY_INTERFACE_MODE_MII:
++      case PHY_INTERFACE_MODE_REVMII:
++      case PHY_INTERFACE_MODE_RMII:
++              if (MTK_HAS_CAPS(eth->soc->caps, MTK_RGMII)) {
++                      err = mtk_gmac_rgmii_path_setup(eth, mac_id);
++                      if (err)
++                              return err;
++              }
++              break;
++      case PHY_INTERFACE_MODE_SGMII:
++              if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
++                      err = mtk_gmac_sgmii_path_setup(eth, mac_id);
++                      if (err)
++                              return err;
++              }
++              break;
++      case PHY_INTERFACE_MODE_GMII:
++              if (MTK_HAS_CAPS(eth->soc->caps, MTK_GEPHY)) {
++                      err = mtk_gmac_gephy_path_setup(eth, mac_id);
++                      if (err)
++                              return err;
++              }
++              break;
++      default:
++              break;
++      }
++
++      return 0;
++}
+Index: linux-4.19.57/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+===================================================================
+--- linux-4.19.57.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ linux-4.19.57/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -23,6 +23,7 @@
+ #include <linux/reset.h>
+ #include <linux/tcp.h>
+ #include <linux/interrupt.h>
++#include <linux/mdio.h>
+ #include <linux/pinctrl/devinfo.h>
+ #include "mtk_eth_soc.h"
+@@ -54,8 +55,10 @@ static const struct mtk_ethtool_stats {
+ };
+ static const char * const mtk_clks_source_name[] = {
+-      "ethif", "esw", "gp0", "gp1", "gp2", "trgpll", "sgmii_tx250m",
+-      "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll"
++      "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", "fe", "trgpll",
++      "sgmii_tx250m", "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb",
++      "sgmii2_tx250m", "sgmii2_rx250m", "sgmii2_cdr_ref", "sgmii2_cdr_fb",
++      "sgmii_ck", "eth2pll",
+ };
+ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
+@@ -84,8 +87,8 @@ static int mtk_mdio_busy_wait(struct mtk
+       return -1;
+ }
+-static u32 _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr,
+-                         u32 phy_register, u32 write_data)
++u32 _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr,
++                  u32 phy_register, u32 write_data)
+ {
+       if (mtk_mdio_busy_wait(eth))
+               return -1;
+@@ -103,7 +106,7 @@ static u32 _mtk_mdio_write(struct mtk_et
+       return 0;
+ }
+-static u32 _mtk_mdio_read(struct mtk_eth *eth, int phy_addr, int phy_reg)
++u32 _mtk_mdio_read(struct mtk_eth *eth, int phy_addr, int phy_reg)
+ {
+       u32 d;
+@@ -123,6 +126,34 @@ static u32 _mtk_mdio_read(struct mtk_eth
+       return d;
+ }
++u32 mtk_cl45_ind_read(struct mtk_eth *eth, u32 port, u32 devad, u32 reg, u32 *data)
++{
++      mutex_lock(&eth->mii_bus->mdio_lock);
++
++      _mtk_mdio_write(eth, port, MII_MMD_ACC_CTL_REG, devad);
++      _mtk_mdio_write(eth, port, MII_MMD_ADDR_DATA_REG, reg);
++      _mtk_mdio_write(eth, port, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
++      *data = _mtk_mdio_read(eth, port, MII_MMD_ADDR_DATA_REG);
++
++      mutex_unlock(&eth->mii_bus->mdio_lock);
++
++      return 0;
++}
++
++u32 mtk_cl45_ind_write(struct mtk_eth *eth, u32 port, u32 devad, u32 reg, u32 data)
++{
++      mutex_lock(&eth->mii_bus->mdio_lock);
++
++      _mtk_mdio_write(eth, port, MII_MMD_ACC_CTL_REG, devad);
++      _mtk_mdio_write(eth, port, MII_MMD_ADDR_DATA_REG, reg);
++      _mtk_mdio_write(eth, port, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
++      _mtk_mdio_write(eth, port, MII_MMD_ADDR_DATA_REG, data);
++
++      mutex_unlock(&eth->mii_bus->mdio_lock);
++
++      return 0;
++}
++
+ static int mtk_mdio_write(struct mii_bus *bus, int phy_addr,
+                         int phy_reg, u16 val)
+ {
+@@ -165,51 +196,12 @@ static void mtk_gmac0_rgmii_adjust(struc
+       mtk_w32(eth, val, TRGMII_TCK_CTRL);
+ }
+-static void mtk_gmac_sgmii_hw_setup(struct mtk_eth *eth, int mac_id)
+-{
+-      u32 val;
+-
+-      /* Setup the link timer and QPHY power up inside SGMIISYS */
+-      regmap_write(eth->sgmiisys, SGMSYS_PCS_LINK_TIMER,
+-                   SGMII_LINK_TIMER_DEFAULT);
+-
+-      regmap_read(eth->sgmiisys, SGMSYS_SGMII_MODE, &val);
+-      val |= SGMII_REMOTE_FAULT_DIS;
+-      regmap_write(eth->sgmiisys, SGMSYS_SGMII_MODE, val);
+-
+-      regmap_read(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, &val);
+-      val |= SGMII_AN_RESTART;
+-      regmap_write(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, val);
+-
+-      regmap_read(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+-      val &= ~SGMII_PHYA_PWD;
+-      regmap_write(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+-
+-      /* Determine MUX for which GMAC uses the SGMII interface */
+-      if (MTK_HAS_CAPS(eth->soc->caps, MTK_DUAL_GMAC_SHARED_SGMII)) {
+-              regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
+-              val &= ~SYSCFG0_SGMII_MASK;
+-              val |= !mac_id ? SYSCFG0_SGMII_GMAC1 : SYSCFG0_SGMII_GMAC2;
+-              regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+-
+-              dev_info(eth->dev, "setup shared sgmii for gmac=%d\n",
+-                       mac_id);
+-      }
+-
+-      /* Setup the GMAC1 going through SGMII path when SoC also support
+-       * ESW on GMAC1
+-       */
+-      if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_ESW | MTK_GMAC1_SGMII) &&
+-          !mac_id) {
+-              mtk_w32(eth, 0, MTK_MAC_MISC);
+-              dev_info(eth->dev, "setup gmac1 going through sgmii");
+-      }
+-}
+-
+ static void mtk_phy_link_adjust(struct net_device *dev)
+ {
+       struct mtk_mac *mac = netdev_priv(dev);
++      struct mtk_eth *eth = mac->hw;
+       u16 lcl_adv = 0, rmt_adv = 0;
++      u32 lcl_eee = 0, rmt_eee = 0;
+       u8 flowctrl;
+       u32 mcr = MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG |
+                 MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN |
+@@ -229,7 +221,7 @@ static void mtk_phy_link_adjust(struct n
+       };
+       if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
+-          !mac->id && !mac->trgmii)
++              !mac->id && !mac->trgmii)
+               mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
+       if (dev->phydev->link)
+@@ -259,7 +251,16 @@ static void mtk_phy_link_adjust(struct n
+                         flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
+                         flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
+       }
++      /*EEE capability*/
++      mtk_cl45_ind_read(eth, 0, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &lcl_eee);
++      mtk_cl45_ind_read(eth, 0, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, &rmt_eee);
++
++      if ((lcl_eee & rmt_eee & MDIO_EEE_1000T) == MDIO_EEE_1000T)
++              mcr |= MAC_MCR_MDIO_EEE_1000T;
++      if ((lcl_eee & rmt_eee & MDIO_EEE_100TX) == MDIO_EEE_100TX)
++              mcr |= MAC_MCR_MDIO_EEE_100TX;
++      /*Setup MCR*/
+       mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+       if (dev->phydev->link)
+@@ -290,10 +291,10 @@ static int mtk_phy_connect_node(struct m
+               return -ENODEV;
+       }
+-      dev_info(eth->dev,
+-               "connected mac %d to PHY at %s [uid=%08x, driver=%s]\n",
+-               mac->id, phydev_name(phydev), phydev->phy_id,
+-               phydev->drv->name);
++        dev_info(eth->dev,
++                 "connected mac %d to PHY at %s [uid=%08x, driver=%s]\n",
++                 mac->id, phydev_name(phydev), phydev->phy_id,
++                 phydev->drv->name);
+       return 0;
+ }
+@@ -304,6 +305,7 @@ static int mtk_phy_connect(struct net_de
+       struct mtk_eth *eth;
+       struct device_node *np;
+       u32 val;
++      int err;
+       eth = mac->hw;
+       np = of_parse_phandle(mac->of_node, "phy-handle", 0);
+@@ -313,6 +315,10 @@ static int mtk_phy_connect(struct net_de
+       if (!np)
+               return -ENODEV;
++      err = mtk_setup_hw_path(eth, mac->id, of_get_phy_mode(np));
++      if (err)
++              goto err_phy;
++
+       mac->ge_mode = 0;
+       switch (of_get_phy_mode(np)) {
+       case PHY_INTERFACE_MODE_TRGMII:
+@@ -323,10 +329,9 @@ static int mtk_phy_connect(struct net_de
+       case PHY_INTERFACE_MODE_RGMII:
+               break;
+       case PHY_INTERFACE_MODE_SGMII:
+-              if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII))
+-                      mtk_gmac_sgmii_hw_setup(eth, mac->id);
+               break;
+       case PHY_INTERFACE_MODE_MII:
++      case PHY_INTERFACE_MODE_GMII:
+               mac->ge_mode = 1;
+               break;
+       case PHY_INTERFACE_MODE_REVMII:
+@@ -355,7 +360,7 @@ static int mtk_phy_connect(struct net_de
+       dev->phydev->speed = 0;
+       dev->phydev->duplex = 0;
+-      if (of_phy_is_fixed_link(mac->of_node))
++      if (!strncmp(dev->phydev->drv->name, "Generic", 7))
+               dev->phydev->supported |=
+               SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+@@ -535,37 +540,37 @@ static void mtk_stats_update(struct mtk_
+ }
+ static void mtk_get_stats64(struct net_device *dev,
+-                          struct rtnl_link_stats64 *storage)
++                            struct rtnl_link_stats64 *storage)
+ {
+-      struct mtk_mac *mac = netdev_priv(dev);
+-      struct mtk_hw_stats *hw_stats = mac->hw_stats;
+-      unsigned int start;
+-
+-      if (netif_running(dev) && netif_device_present(dev)) {
+-              if (spin_trylock_bh(&hw_stats->stats_lock)) {
+-                      mtk_stats_update_mac(mac);
+-                      spin_unlock_bh(&hw_stats->stats_lock);
+-              }
+-      }
+-
+-      do {
+-              start = u64_stats_fetch_begin_irq(&hw_stats->syncp);
+-              storage->rx_packets = hw_stats->rx_packets;
+-              storage->tx_packets = hw_stats->tx_packets;
+-              storage->rx_bytes = hw_stats->rx_bytes;
+-              storage->tx_bytes = hw_stats->tx_bytes;
+-              storage->collisions = hw_stats->tx_collisions;
+-              storage->rx_length_errors = hw_stats->rx_short_errors +
+-                      hw_stats->rx_long_errors;
+-              storage->rx_over_errors = hw_stats->rx_overflow;
+-              storage->rx_crc_errors = hw_stats->rx_fcs_errors;
+-              storage->rx_errors = hw_stats->rx_checksum_errors;
+-              storage->tx_aborted_errors = hw_stats->tx_skip;
+-      } while (u64_stats_fetch_retry_irq(&hw_stats->syncp, start));
+-
+-      storage->tx_errors = dev->stats.tx_errors;
+-      storage->rx_dropped = dev->stats.rx_dropped;
+-      storage->tx_dropped = dev->stats.tx_dropped;
++        struct mtk_mac *mac = netdev_priv(dev);
++        struct mtk_hw_stats *hw_stats = mac->hw_stats;
++        unsigned int start;
++
++        if (netif_running(dev) && netif_device_present(dev)) {
++                if (spin_trylock_bh(&hw_stats->stats_lock)) {
++                        mtk_stats_update_mac(mac);
++                        spin_unlock_bh(&hw_stats->stats_lock);
++                }
++        }
++
++        do {
++                start = u64_stats_fetch_begin_irq(&hw_stats->syncp);
++                storage->rx_packets = hw_stats->rx_packets;
++                storage->tx_packets = hw_stats->tx_packets;
++                storage->rx_bytes = hw_stats->rx_bytes;
++                storage->tx_bytes = hw_stats->tx_bytes;
++                storage->collisions = hw_stats->tx_collisions;
++                storage->rx_length_errors = hw_stats->rx_short_errors +
++                        hw_stats->rx_long_errors;
++                storage->rx_over_errors = hw_stats->rx_overflow;
++                storage->rx_crc_errors = hw_stats->rx_fcs_errors;
++                storage->rx_errors = hw_stats->rx_checksum_errors;
++                storage->tx_aborted_errors = hw_stats->tx_skip;
++        } while (u64_stats_fetch_retry_irq(&hw_stats->syncp, start));
++
++        storage->tx_errors = dev->stats.tx_errors;
++        storage->rx_dropped = dev->stats.rx_dropped;
++        storage->tx_dropped = dev->stats.tx_dropped;
+ }
+ static inline int mtk_max_frag_size(int mtu)
+@@ -605,10 +610,10 @@ static int mtk_init_fq_dma(struct mtk_et
+       dma_addr_t dma_addr;
+       int i;
+-      eth->scratch_ring = dma_zalloc_coherent(eth->dev,
+-                                              cnt * sizeof(struct mtk_tx_dma),
+-                                              &eth->phy_scratch_ring,
+-                                              GFP_ATOMIC);
++      eth->scratch_ring = dma_alloc_coherent(eth->dev,
++                                             cnt * sizeof(struct mtk_tx_dma),
++                                             &eth->phy_scratch_ring,
++                                             GFP_ATOMIC | __GFP_ZERO);
+       if (unlikely(!eth->scratch_ring))
+               return -ENOMEM;
+@@ -623,6 +628,7 @@ static int mtk_init_fq_dma(struct mtk_et
+       if (unlikely(dma_mapping_error(eth->dev, dma_addr)))
+               return -ENOMEM;
++      memset(eth->scratch_ring, 0x0, sizeof(struct mtk_tx_dma) * cnt);
+       phy_ring_tail = eth->phy_scratch_ring +
+                       (sizeof(struct mtk_tx_dma) * (cnt - 1));
+@@ -673,7 +679,7 @@ static void mtk_tx_unmap(struct mtk_eth
+       }
+       tx_buf->flags = 0;
+       if (tx_buf->skb &&
+-          (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC))
++              (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC))
+               dev_kfree_skb_any(tx_buf->skb);
+       tx_buf->skb = NULL;
+ }
+@@ -689,6 +695,7 @@ static int mtk_tx_map(struct sk_buff *sk
+       unsigned int nr_frags;
+       int i, n_desc = 1;
+       u32 txd4 = 0, fport;
++      u32 qid = 0;
+       itxd = ring->next_free;
+       if (itxd == ring->last_free)
+@@ -708,9 +715,10 @@ static int mtk_tx_map(struct sk_buff *sk
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
+               txd4 |= TX_DMA_CHKSUM;
+-      /* VLAN header offload */
+-      if (skb_vlan_tag_present(skb))
+-              txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
++#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
++      qid = skb->mark & (MTK_QDMA_TX_MASK);
++      qid += (!mac->id) ? (MTK_QDMA_TX_MASK + 1) : 0;
++#endif
+       mapped_addr = dma_map_single(eth->dev, skb->data,
+                                    skb_headlen(skb), DMA_TO_DEVICE);
+@@ -727,6 +735,7 @@ static int mtk_tx_map(struct sk_buff *sk
+       /* TX SG offload */
+       txd = itxd;
+       nr_frags = skb_shinfo(skb)->nr_frags;
++
+       for (i = 0; i < nr_frags; i++) {
+               struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+               unsigned int offset = 0;
+@@ -753,10 +762,10 @@ static int mtk_tx_map(struct sk_buff *sk
+                               last_frag = true;
+                       WRITE_ONCE(txd->txd1, mapped_addr);
+-                      WRITE_ONCE(txd->txd3, (TX_DMA_SWC |
++                      WRITE_ONCE(txd->txd3, (TX_DMA_SWC | QID_LOW_BITS(qid) |
+                                              TX_DMA_PLEN0(frag_map_size) |
+                                              last_frag * TX_DMA_LS0));
+-                      WRITE_ONCE(txd->txd4, fport);
++                      WRITE_ONCE(txd->txd4, fport | QID_HIGH_BITS(qid));
+                       tx_buf = mtk_desc_to_tx_buf(ring, txd);
+                       memset(tx_buf, 0, sizeof(*tx_buf));
+@@ -775,9 +784,9 @@ static int mtk_tx_map(struct sk_buff *sk
+       /* store skb to cleanup */
+       itx_buf->skb = skb;
+-      WRITE_ONCE(itxd->txd4, txd4);
+       WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
+-                              (!nr_frags * TX_DMA_LS0)));
++                              (!nr_frags * TX_DMA_LS0)) | QID_LOW_BITS(qid));
++      WRITE_ONCE(itxd->txd4, txd4 | QID_HIGH_BITS(qid));
+       netdev_sent_queue(dev, skb->len);
+       skb_tx_timestamp(skb);
+@@ -922,7 +931,7 @@ drop:
+       return NETDEV_TX_OK;
+ }
+-static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth)
++struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth)
+ {
+       int i;
+       struct mtk_rx_ring *ring;
+@@ -991,10 +1000,24 @@ static int mtk_poll_rx(struct napi_struc
+                       break;
+               /* find out which mac the packet come from. values start at 1 */
++#if defined(CONFIG_NET_DSA)
++              mac = (trxd.rxd4 >> 22) & 0x1;
++              mac = (mac + 1) % 2;
++#else
+               mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
+-                    RX_DMA_FPORT_MASK;
+-              mac--;
+-
++                      RX_DMA_FPORT_MASK;
++              /* From QDMA(5). This is a external interface case of HWNAT.
++               * When the incoming frame comes from an external interface
++               * rather than GMAC1/GMAC2, HWNAT driver sends the original
++               * frame to PPE via PPD(ping pong device) for HWNAT RX
++               * frame learning. After learning, PPE transmit the
++               * original frame back to PPD again to run SW NAT path.
++               */
++              if (mac == 5)
++                      mac = 0;
++              else
++                      mac--;
++#endif
+               if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
+                            !eth->netdev[mac]))
+                       goto release_desc;
+@@ -1044,6 +1067,7 @@ static int mtk_poll_rx(struct napi_struc
+                   RX_DMA_VID(trxd.rxd3))
+                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+                                              RX_DMA_VID(trxd.rxd3));
++
+               skb_record_rx_queue(skb, 0);
+               napi_gro_receive(napi, skb);
+@@ -1128,7 +1152,7 @@ static int mtk_poll_tx(struct mtk_eth *e
+       }
+       if (mtk_queue_stopped(eth) &&
+-          (atomic_read(&ring->free_count) > ring->thresh))
++              (atomic_read(&ring->free_count) > ring->thresh))
+               mtk_wake_queue(eth);
+       return total;
+@@ -1220,11 +1244,14 @@ static int mtk_tx_alloc(struct mtk_eth *
+       if (!ring->buf)
+               goto no_tx_mem;
+-      ring->dma = dma_zalloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
+-                                      &ring->phys, GFP_ATOMIC);
++      ring->dma = dma_alloc_coherent(eth->dev,
++                                        MTK_DMA_SIZE * sz,
++                                        &ring->phys,
++                                        GFP_ATOMIC | __GFP_ZERO);
+       if (!ring->dma)
+               goto no_tx_mem;
++      memset(ring->dma, 0, MTK_DMA_SIZE * sz);
+       for (i = 0; i < MTK_DMA_SIZE; i++) {
+               int next = (i + 1) % MTK_DMA_SIZE;
+               u32 next_ptr = ring->phys + next * sz;
+@@ -1317,9 +1344,10 @@ static int mtk_rx_alloc(struct mtk_eth *
+                       return -ENOMEM;
+       }
+-      ring->dma = dma_zalloc_coherent(eth->dev,
+-                                      rx_dma_size * sizeof(*ring->dma),
+-                                      &ring->phys, GFP_ATOMIC);
++      ring->dma = dma_alloc_coherent(eth->dev,
++                                     rx_dma_size * sizeof(*ring->dma),
++                                     &ring->phys,
++                                     GFP_ATOMIC | __GFP_ZERO);
+       if (!ring->dma)
+               return -ENOMEM;
+@@ -1516,8 +1544,8 @@ static int mtk_hwlro_add_ipaddr(struct n
+       int hwlro_idx;
+       if ((fsp->flow_type != TCP_V4_FLOW) ||
+-          (!fsp->h_u.tcp_ip4_spec.ip4dst) ||
+-          (fsp->location > 1))
++              (!fsp->h_u.tcp_ip4_spec.ip4dst) ||
++              (fsp->location > 1))
+               return -EINVAL;
+       mac->hwlro_ip[fsp->location] = htonl(fsp->h_u.tcp_ip4_spec.ip4dst);
+@@ -1744,6 +1772,34 @@ static void mtk_tx_timeout(struct net_de
+       schedule_work(&eth->pending_work);
+ }
++static irqreturn_t mtk_handle_irq_tx_rx(int irq, void *_eth)
++{
++      struct mtk_eth *eth = _eth;
++      u32 tx_status, rx_status;
++
++      tx_status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
++
++      if (tx_status & MTK_TX_DONE_INT) {
++              if (likely(napi_schedule_prep(&eth->tx_napi))) {
++                      mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
++                      __napi_schedule(&eth->tx_napi);
++              }
++              mtk_w32(eth, tx_status, MTK_QMTK_INT_STATUS);
++      }
++
++      rx_status = mtk_r32(eth, MTK_PDMA_INT_STATUS);
++
++      if (rx_status & MTK_RX_DONE_INT) {
++              if (likely(napi_schedule_prep(&eth->rx_napi))) {
++                      mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
++                      __napi_schedule(&eth->rx_napi);
++              }
++              mtk_w32(eth, rx_status, MTK_PDMA_INT_STATUS);
++      }
++
++      return IRQ_HANDLED;
++}
++
+ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
+ {
+       struct mtk_eth *eth = _eth;
+@@ -1784,8 +1840,8 @@ static void mtk_poll_controller(struct n
+ static int mtk_start_dma(struct mtk_eth *eth)
+ {
+-      u32 rx_2b_offset = (NET_IP_ALIGN == 2) ? MTK_RX_2B_OFFSET : 0;
+       int err;
++      u32 rx_2b_offet = (NET_IP_ALIGN == 2) ? MTK_RX_2B_OFFSET : 0;
+       err = mtk_dma_init(eth);
+       if (err) {
+@@ -1801,7 +1857,7 @@ static int mtk_start_dma(struct mtk_eth
+               MTK_QDMA_GLO_CFG);
+       mtk_w32(eth,
+-              MTK_RX_DMA_EN | rx_2b_offset |
++              MTK_RX_DMA_EN | rx_2b_offet |
+               MTK_RX_BT_32DWORDS | MTK_MULTI_EN,
+               MTK_PDMA_GLO_CFG);
+@@ -1814,7 +1870,7 @@ static int mtk_open(struct net_device *d
+       struct mtk_eth *eth = mac->hw;
+       /* we run 2 netdevs on the same dma ring so we only bring it up once */
+-      if (!refcount_read(&eth->dma_refcnt)) {
++      if (!atomic_read(&eth->dma_refcnt)) {
+               int err = mtk_start_dma(eth);
+               if (err)
+@@ -1824,10 +1880,8 @@ static int mtk_open(struct net_device *d
+               napi_enable(&eth->rx_napi);
+               mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+               mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+-              refcount_set(&eth->dma_refcnt, 1);
+       }
+-      else
+-              refcount_inc(&eth->dma_refcnt);
++      atomic_inc(&eth->dma_refcnt);
+       phy_start(dev->phydev);
+       netif_start_queue(dev);
+@@ -1867,7 +1921,7 @@ static int mtk_stop(struct net_device *d
+       phy_stop(dev->phydev);
+       /* only shutdown DMA if this is the last user */
+-      if (!refcount_dec_and_test(&eth->dma_refcnt))
++      if (!atomic_dec_and_test(&eth->dma_refcnt))
+               return 0;
+       mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+@@ -1973,14 +2027,16 @@ static int mtk_hw_init(struct mtk_eth *e
+       val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+       mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+-      /* Enable RX VLan Offloading */
+-      mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
++      /* Disable RX VLan Offloading */
++      mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
++
++#if defined(CONFIG_NET_DSA)
++      mtk_w32(eth, 0x81000001, MTK_CDMP_IG_CTRL);
++#endif
+-      /* enable interrupt delay for RX */
+-      mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT);
++      mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_DELAY_INT);
++      mtk_w32(eth, 0x8f0f8f0f, MTK_QDMA_DELAY_INT);
+-      /* disable delay and normal interrupt */
+-      mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
+       mtk_tx_irq_disable(eth, ~0);
+       mtk_rx_irq_disable(eth, ~0);
+       mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
+@@ -2172,27 +2228,27 @@ static int mtk_cleanup(struct mtk_eth *e
+ }
+ static int mtk_get_link_ksettings(struct net_device *ndev,
+-                                struct ethtool_link_ksettings *cmd)
++                                  struct ethtool_link_ksettings *cmd)
+ {
+-      struct mtk_mac *mac = netdev_priv(ndev);
++        struct mtk_mac *mac = netdev_priv(ndev);
+-      if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+-              return -EBUSY;
++        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
++                return -EBUSY;
+-      phy_ethtool_ksettings_get(ndev->phydev, cmd);
++        phy_ethtool_ksettings_get(ndev->phydev, cmd);
+-      return 0;
++        return 0;
+ }
+ static int mtk_set_link_ksettings(struct net_device *ndev,
+-                                const struct ethtool_link_ksettings *cmd)
++                                  const struct ethtool_link_ksettings *cmd)
+ {
+-      struct mtk_mac *mac = netdev_priv(ndev);
++        struct mtk_mac *mac = netdev_priv(ndev);
+-      if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+-              return -EBUSY;
++        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
++                return -EBUSY;
+-      return phy_ethtool_ksettings_set(ndev->phydev, cmd);
++        return phy_ethtool_ksettings_set(ndev->phydev, cmd);
+ }
+ static void mtk_get_drvinfo(struct net_device *dev,
+@@ -2355,8 +2411,8 @@ static int mtk_set_rxnfc(struct net_devi
+ }
+ static const struct ethtool_ops mtk_ethtool_ops = {
+-      .get_link_ksettings     = mtk_get_link_ksettings,
+-      .set_link_ksettings     = mtk_set_link_ksettings,
++      .get_link_ksettings     = mtk_get_link_ksettings,
++        .set_link_ksettings     = mtk_set_link_ksettings,
+       .get_drvinfo            = mtk_get_drvinfo,
+       .get_msglevel           = mtk_get_msglevel,
+       .set_msglevel           = mtk_set_msglevel,
+@@ -2366,7 +2422,7 @@ static const struct ethtool_ops mtk_etht
+       .get_sset_count         = mtk_get_sset_count,
+       .get_ethtool_stats      = mtk_get_ethtool_stats,
+       .get_rxnfc              = mtk_get_rxnfc,
+-      .set_rxnfc              = mtk_set_rxnfc,
++      .set_rxnfc              = mtk_set_rxnfc,
+ };
+ static const struct net_device_ops mtk_netdev_ops = {
+@@ -2463,6 +2519,7 @@ static int mtk_probe(struct platform_dev
+ {
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct device_node *mac_np;
++      const struct of_device_id *match;
+       struct mtk_eth *eth;
+       int err;
+       int i;
+@@ -2471,7 +2528,8 @@ static int mtk_probe(struct platform_dev
+       if (!eth)
+               return -ENOMEM;
+-      eth->soc = of_device_get_match_data(&pdev->dev);
++      match = of_match_device(of_mtk_match, &pdev->dev);
++      eth->soc = (struct mtk_soc_data *)match->data;
+       eth->dev = &pdev->dev;
+       eth->base = devm_ioremap_resource(&pdev->dev, res);
+@@ -2489,26 +2547,37 @@ static int mtk_probe(struct platform_dev
+               return PTR_ERR(eth->ethsys);
+       }
+-      if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
+-              eth->sgmiisys =
+-              syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+-                                              "mediatek,sgmiisys");
+-              if (IS_ERR(eth->sgmiisys)) {
+-                      dev_err(&pdev->dev, "no sgmiisys regmap found\n");
+-                      return PTR_ERR(eth->sgmiisys);
++      if (MTK_HAS_CAPS(eth->soc->caps, MTK_INFRA)) {
++              eth->infra = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
++                                                         "mediatek,infracfg");
++              if (IS_ERR(eth->infra)) {
++                      dev_info(&pdev->dev, "no ethsys regmap found\n");
++                      return PTR_ERR(eth->infra);
+               }
+       }
++      if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
++              eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii),
++                                        GFP_KERNEL);
++              if (!eth->sgmii)
++                      return -ENOMEM;
++
++              err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node,
++                                   eth->soc->ana_rgc3);
++              if (err)
++                      return err;
++      }
++
+       if (eth->soc->required_pctl) {
+               eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                           "mediatek,pctl");
+               if (IS_ERR(eth->pctl)) {
+-                      dev_err(&pdev->dev, "no pctl regmap found\n");
++                      dev_info(&pdev->dev, "no pctl regmap found\n");
+                       return PTR_ERR(eth->pctl);
+               }
+       }
+-      for (i = 0; i < 3; i++) {
++      for (i = 0; i < eth->soc->irq_num; i++) {
+               eth->irq[i] = platform_get_irq(pdev, i);
+               if (eth->irq[i] < 0) {
+                       dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
+@@ -2552,15 +2621,22 @@ static int mtk_probe(struct platform_dev
+                       goto err_deinit_hw;
+       }
+-      err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+-                             dev_name(eth->dev), eth);
+-      if (err)
+-              goto err_free_dev;
++      if (eth->soc->irq_num > 1) {
++              err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
++                                     dev_name(eth->dev), eth);
++              if (err)
++                      goto err_free_dev;
+-      err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
+-                             dev_name(eth->dev), eth);
+-      if (err)
+-              goto err_free_dev;
++              err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
++                                     dev_name(eth->dev), eth);
++              if (err)
++                      goto err_free_dev;
++      } else {
++              err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq_tx_rx, 0,
++                                     dev_name(eth->dev), eth);
++              if (err)
++                      goto err_free_dev;
++      }
+       err = mtk_mdio_init(eth);
+       if (err)
+@@ -2626,27 +2702,48 @@ static int mtk_remove(struct platform_de
+ }
+ static const struct mtk_soc_data mt2701_data = {
+-      .caps = MTK_GMAC1_TRGMII | MTK_HWLRO,
++      .caps = MT7623_CAPS | MTK_HWLRO,
+       .required_clks = MT7623_CLKS_BITMAP,
+       .required_pctl = true,
++      .irq_num = 3,
+ };
+ static const struct mtk_soc_data mt7622_data = {
+-      .caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW | MTK_HWLRO,
++      .ana_rgc3 = 0x2028,
++      .caps = MT7622_CAPS | MTK_HWLRO,
+       .required_clks = MT7622_CLKS_BITMAP,
+       .required_pctl = false,
++      .irq_num = 3,
+ };
+ static const struct mtk_soc_data mt7623_data = {
+-      .caps = MTK_GMAC1_TRGMII | MTK_HWLRO,
++      .caps = MT7623_CAPS | MTK_HWLRO,
+       .required_clks = MT7623_CLKS_BITMAP,
+       .required_pctl = true,
++      .irq_num = 3,
++};
++
++static const struct mtk_soc_data leopard_data = {
++      .ana_rgc3 = 0x128,
++      .caps = LEOPARD_CAPS | MTK_HWLRO,
++      .required_clks = LEOPARD_CLKS_BITMAP,
++      .required_pctl = false,
++      .irq_num = 3,
++};
++
++static const struct mtk_soc_data mt7621_data = {
++      .caps = MT7621_CAPS,
++      .required_clks = MT7621_CLKS_BITMAP,
++      .required_pctl = false,
++      .irq_num = 1,
+ };
+ const struct of_device_id of_mtk_match[] = {
+       { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+       { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
+       { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
++      { .compatible = "mediatek,mt7629-eth", .data = &leopard_data},
++      { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data},
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, of_mtk_match);
+Index: linux-4.19.57/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+===================================================================
+--- linux-4.19.57.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ linux-4.19.57/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -15,13 +15,17 @@
+ #ifndef MTK_ETH_H
+ #define MTK_ETH_H
++#include <linux/dma-mapping.h>
++#include <linux/netdevice.h>
++#include <linux/of_net.h>
++#include <linux/u64_stats_sync.h>
+ #include <linux/refcount.h>
+ #define MTK_QDMA_PAGE_SIZE    2048
+ #define       MTK_MAX_RX_LENGTH       1536
+ #define MTK_TX_DMA_BUF_LEN    0x3fff
+-#define MTK_DMA_SIZE          256
+-#define MTK_NAPI_WEIGHT               64
++#define MTK_DMA_SIZE          2048
++#define MTK_NAPI_WEIGHT               256
+ #define MTK_MAC_COUNT         2
+ #define MTK_RX_ETH_HLEN               (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
+ #define MTK_RX_HLEN           (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
+@@ -36,8 +40,6 @@
+                                NETIF_MSG_TX_ERR)
+ #define MTK_HW_FEATURES               (NETIF_F_IP_CSUM | \
+                                NETIF_F_RXCSUM | \
+-                               NETIF_F_HW_VLAN_CTAG_TX | \
+-                               NETIF_F_HW_VLAN_CTAG_RX | \
+                                NETIF_F_SG | NETIF_F_TSO | \
+                                NETIF_F_TSO6 | \
+                                NETIF_F_IPV6_CSUM)
+@@ -76,6 +78,9 @@
+ #define MTK_CDMQ_IG_CTRL      0x1400
+ #define MTK_CDMQ_STAG_EN      BIT(0)
++/* CDMP Ingress Control Register */
++#define MTK_CDMP_IG_CTRL       0x400
++
+ /* CDMP Exgress Control Register */
+ #define MTK_CDMP_EG_CTRL      0x404
+@@ -225,8 +230,9 @@
+ #define MTK_TX_DONE_INT1      BIT(1)
+ #define MTK_TX_DONE_INT0      BIT(0)
+ #define MTK_RX_DONE_INT               MTK_RX_DONE_DLY
+-#define MTK_TX_DONE_INT               (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \
+-                               MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3)
++#define MTK_TX_DONE_DLY         BIT(28)
++#define MTK_TX_DONE_INT         MTK_TX_DONE_DLY
++
+ /* QDMA Interrupt grouping registers */
+ #define MTK_QDMA_INT_GRP1     0x1a20
+@@ -267,6 +273,12 @@
+ #define MTK_GDM1_TX_GBCNT     0x2400
+ #define MTK_STAT_OFFSET               0x40
++/* QDMA TX NUM */
++#define MTK_QDMA_TX_NUM               16
++#define MTK_QDMA_TX_MASK      ((MTK_QDMA_TX_NUM / 2) - 1)
++#define QID_LOW_BITS(x)               ((x) & 0xf)
++#define QID_HIGH_BITS(x)      ((((x) >> 4) & 0x3) & GENMASK(21, 20))
++
+ /* QDMA descriptor txd4 */
+ #define TX_DMA_CHKSUM         (0x7 << 29)
+ #define TX_DMA_TSO            BIT(28)
+@@ -316,6 +328,8 @@
+ #define MAC_MCR_RX_EN         BIT(13)
+ #define MAC_MCR_BACKOFF_EN    BIT(9)
+ #define MAC_MCR_BACKPR_EN     BIT(8)
++#define MAC_MCR_MDIO_EEE_1000T  BIT(7)
++#define MAC_MCR_MDIO_EEE_100TX  BIT(6)
+ #define MAC_MCR_FORCE_RX_FC   BIT(5)
+ #define MAC_MCR_FORCE_TX_FC   BIT(4)
+ #define MAC_MCR_SPEED_1000    BIT(3)
+@@ -368,9 +382,11 @@
+ #define ETHSYS_SYSCFG0                0x14
+ #define SYSCFG0_GE_MASK               0x3
+ #define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2)))
+-#define SYSCFG0_SGMII_MASK    (3 << 8)
+-#define SYSCFG0_SGMII_GMAC1   ((2 << 8) & GENMASK(9, 8))
+-#define SYSCFG0_SGMII_GMAC2   ((3 << 8) & GENMASK(9, 8))
++#define SYSCFG0_SGMII_MASK    GENMASK(9, 8)
++#define SYSCFG0_SGMII_GMAC1   ((2 << 8) & SYSCFG0_SGMII_MASK)
++#define SYSCFG0_SGMII_GMAC2   ((3 << 8) & SYSCFG0_SGMII_MASK)
++#define SYSCFG0_SGMII_GMAC1_V2        BIT(9)
++#define SYSCFG0_SGMII_GMAC2_V2        BIT(8)
+ /* ethernet subsystem clock register */
+ #define ETHSYS_CLKCFG0                0x2c
+@@ -398,6 +414,16 @@
+ #define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8
+ #define       SGMII_PHYA_PWD          BIT(4)
++/* Infrasys subsystem config registers */
++#define INFRA_MISC2           0x70c
++#define CO_QPHY_SEL           BIT(0)
++#define GEPHY_MAC_SEL         BIT(1)
++
++/*MDIO control*/
++#define MII_MMD_ACC_CTL_REG             0x0d
++#define MII_MMD_ADDR_DATA_REG           0x0e
++#define MMD_OP_MODE_DATA BIT(14)
++
+ struct mtk_rx_dma {
+       unsigned int rxd1;
+       unsigned int rxd2;
+@@ -462,15 +488,21 @@ enum mtk_tx_flags {
+  */
+ enum mtk_clks_map {
+       MTK_CLK_ETHIF,
++      MTK_CLK_SGMIITOP,
+       MTK_CLK_ESW,
+       MTK_CLK_GP0,
+       MTK_CLK_GP1,
+       MTK_CLK_GP2,
++      MTK_CLK_FE,
+       MTK_CLK_TRGPLL,
+       MTK_CLK_SGMII_TX_250M,
+       MTK_CLK_SGMII_RX_250M,
+       MTK_CLK_SGMII_CDR_REF,
+       MTK_CLK_SGMII_CDR_FB,
++      MTK_CLK_SGMII2_TX_250M,
++      MTK_CLK_SGMII2_RX_250M,
++      MTK_CLK_SGMII2_CDR_REF,
++      MTK_CLK_SGMII2_CDR_FB,
+       MTK_CLK_SGMII_CK,
+       MTK_CLK_ETH2PLL,
+       MTK_CLK_MAX
+@@ -488,6 +520,22 @@ enum mtk_clks_map {
+                                BIT(MTK_CLK_SGMII_CDR_FB) | \
+                                BIT(MTK_CLK_SGMII_CK) | \
+                                BIT(MTK_CLK_ETH2PLL))
++#define LEOPARD_CLKS_BITMAP     (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) |  \
++                              BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
++                              BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \
++                              BIT(MTK_CLK_SGMII_TX_250M) | \
++                              BIT(MTK_CLK_SGMII_RX_250M) | \
++                              BIT(MTK_CLK_SGMII_CDR_REF) | \
++                              BIT(MTK_CLK_SGMII_CDR_FB) | \
++                              BIT(MTK_CLK_SGMII2_TX_250M) | \
++                              BIT(MTK_CLK_SGMII2_RX_250M) | \
++                              BIT(MTK_CLK_SGMII2_CDR_REF) | \
++                              BIT(MTK_CLK_SGMII2_CDR_FB) | \
++                              BIT(MTK_CLK_SGMII_CK) | \
++                              BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP))
++
++#define MT7621_CLKS_BITMAP 0
++
+ enum mtk_dev_state {
+       MTK_HW_INIT,
+       MTK_RESETTING
+@@ -557,35 +605,149 @@ struct mtk_rx_ring {
+       u32 crx_idx_reg;
+ };
+-#define MTK_TRGMII                    BIT(0)
+-#define MTK_GMAC1_TRGMII              (BIT(1) | MTK_TRGMII)
+-#define MTK_ESW                               BIT(4)
+-#define MTK_GMAC1_ESW                 (BIT(5) | MTK_ESW)
+-#define MTK_SGMII                     BIT(8)
+-#define MTK_GMAC1_SGMII                       (BIT(9) | MTK_SGMII)
+-#define MTK_GMAC2_SGMII                       (BIT(10) | MTK_SGMII)
+-#define MTK_DUAL_GMAC_SHARED_SGMII    (BIT(11) | MTK_GMAC1_SGMII | \
+-                                       MTK_GMAC2_SGMII)
++enum mtk_eth_mux {
++      MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
++      MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
++      MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
++      MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
++      MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
++      MTK_ETH_MUX_MAX,
++};
++
++enum mtk_eth_path {
++      MTK_ETH_PATH_GMAC1_RGMII,
++      MTK_ETH_PATH_GMAC1_TRGMII,
++      MTK_ETH_PATH_GMAC1_SGMII,
++      MTK_ETH_PATH_GMAC2_RGMII,
++      MTK_ETH_PATH_GMAC2_SGMII,
++      MTK_ETH_PATH_GMAC2_GEPHY,
++      MTK_ETH_PATH_GDM1_ESW,
++      MTK_ETH_PATH_MAX,
++};
++
++/* Capability for function group */
++#define MTK_RGMII                     BIT(0)
++#define MTK_TRGMII                    BIT(1)
++#define MTK_SGMII                     BIT(2)
++#define MTK_ESW                               BIT(3)
++#define MTK_GEPHY                     BIT(4)
++#define MTK_MUX                               BIT(5)
++#define MTK_INFRA                     BIT(6)
++#define MTK_SHARED_SGMII              BIT(7)
++
++/* Capability for features on SoCs */
++#define MTK_PATH_BIT(x)               BIT((x) + 10)
++
++#define MTK_GMAC1_RGMII               \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GMAC1_RGMII) | MTK_RGMII)
++
++#define MTK_GMAC1_TRGMII      \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GMAC1_TRGMII) | MTK_TRGMII)
++
++#define MTK_GMAC1_SGMII               \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GMAC1_SGMII) | MTK_SGMII)
++
++#define MTK_GMAC2_RGMII               \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GMAC2_RGMII) | MTK_RGMII)
++
++#define MTK_GMAC2_SGMII               \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GMAC2_SGMII) | MTK_SGMII)
++
++#define MTK_GMAC2_GEPHY               \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GMAC2_GEPHY) | MTK_GEPHY)
++
++#define MTK_GDM1_ESW          \
++      (MTK_PATH_BIT(MTK_ETH_PATH_GDM1_ESW) | MTK_ESW)
++
++#define MTK_MUX_BIT(x)                BIT((x) + 20)
++
++/* Capability for MUXes present on SoCs */
++/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
++#define MTK_MUX_GDM1_TO_GMAC1_ESW     \
++      (MTK_MUX_BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW) | MTK_MUX)
++
++/* 0: GMAC2 -> GEPHY, 1: GMAC0 -> GePHY */
++#define MTK_MUX_GMAC2_GMAC0_TO_GEPHY  \
++      (MTK_MUX_BIT(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY) | MTK_MUX | MTK_INFRA)
++
++/* 0: U3 -> QPHY, 1: GMAC2 -> QPHY */
++#define MTK_MUX_U3_GMAC2_TO_QPHY      \
++      (MTK_MUX_BIT(MTK_ETH_MUX_U3_GMAC2_TO_QPHY) | MTK_MUX | MTK_INFRA)
++
++/* 2: GMAC1 -> SGMII, 3: GMAC2 -> SGMII */
++#define MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII    \
++      (MTK_MUX_BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII) | MTK_MUX | \
++       MTK_SHARED_SGMII)
++
++/* 0: GMACx -> GEPHY, 1: GMACx -> SGMII where x is 1 or 2 */
++#define MTK_MUX_GMAC12_TO_GEPHY_SGMII \
++      (MTK_MUX_BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII) | MTK_MUX)
++
+ #define MTK_HWLRO                     BIT(12)
++
+ #define MTK_HAS_CAPS(caps, _x)                (((caps) & (_x)) == (_x))
++#define MT7622_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | MTK_GMAC2_RGMII | \
++                    MTK_GMAC2_SGMII | MTK_GDM1_ESW | \
++                    MTK_MUX_GDM1_TO_GMAC1_ESW | \
++                    MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII)
++
++#define MT7623_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII)
++
++#define LEOPARD_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
++                    MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
++                    MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
++                    MTK_MUX_U3_GMAC2_TO_QPHY | \
++                    MTK_MUX_GMAC12_TO_GEPHY_SGMII)
++
++#define MT7621_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII)
++
+ /* struct mtk_eth_data -      This is the structure holding all differences
+  *                            among various plaforms
++ * @ana_rgc3:                 The offset for register ANA_RGC3 related to
++ *                            sgmiisys syscon
+  * @caps                      Flags shown the extra capability for the SoC
+  * @required_clks             Flags shown the bitmap for required clocks on
+  *                            the target SoC
+  * @required_pctl             A bool value to show whether the SoC requires
+  *                            the extra setup for those pins used by GMAC.
++ * @irq_num                   total eth irq num support in target SoC
+  */
+ struct mtk_soc_data {
++      u32             ana_rgc3;
+       u32             caps;
+       u32             required_clks;
+       bool            required_pctl;
++      u32             irq_num;
+ };
+ /* currently no SoC has more than 2 macs */
+ #define MTK_MAX_DEVS                  2
++struct mtk_eth_debug {
++      struct dentry *root;
++};
++
++#define MTK_SGMII_PHYSPEED_AN         BIT(31)
++#define MTK_SGMII_PHYSPEED_MASK               GENMASK(0, 2)
++#define MTK_SGMII_PHYSPEED_1000               BIT(0)
++#define MTK_SGMII_PHYSPEED_2500               BIT(1)
++#define MTK_HAS_FLAGS(flags, _x)      (((flags) & (_x)) == (_x))
++
++/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
++ *                    characteristics
++ * @regmap:           The register map pointing at the range used to setup
++ *                    SGMII modes
++ * @flags:            The enum refers to which mode the sgmii wants to run on
++ * @ana_rgc3:         The offset refers to register ANA_RGC3 related to regmap
++ */
++
++struct mtk_sgmii {
++      struct regmap   *regmap[MTK_MAX_DEVS];
++      u32             flags[MTK_MAX_DEVS];
++      u32             ana_rgc3;
++};
++
+ /* struct mtk_eth -   This is the main datasructure for holding the state
+  *                    of the driver
+  * @dev:              The device pointer
+@@ -601,14 +763,15 @@ struct mtk_soc_data {
+  * @msg_enable:               Ethtool msg level
+  * @ethsys:           The register map pointing at the range used to setup
+  *                    MII modes
+- * @sgmiisys:         The register map pointing at the range used to setup
+- *                    SGMII modes
++ * @infra:            The register map pointing at the range used to setup
++ *                    SGMII and GePHY path
+  * @pctl:             The register map pointing at the range used to setup
+  *                    GMAC port drive/slew values
+  * @dma_refcnt:               track how many netdevs are using the DMA engine
+  * @tx_ring:          Pointer to the memory holding info about the TX ring
+  * @rx_ring:          Pointer to the memory holding info about the RX ring
+- * @rx_ring_qdma:     Pointer to the memory holding info about the QDMA RX ring
++ * @rx_ring_qdma:     Pointer to the memory holding info about the QDMA RX
++ *                    ring
+  * @tx_napi:          The TX NAPI struct
+  * @rx_napi:          The RX NAPI struct
+  * @scratch_ring:     Newer SoCs need memory for a second HW managed TX ring
+@@ -619,13 +782,16 @@ struct mtk_soc_data {
+  * @pending_work:     The workqueue used to reset the dma ring
+  * @state:            Initialization and runtime state of the device
+  * @soc:              Holding specific data among vaious SoCs
++ * @debug:            Holding specific data for mtk_eth_dbg usage.
+  */
+ struct mtk_eth {
+       struct device                   *dev;
+       void __iomem                    *base;
+       spinlock_t                      page_lock;
++      /* spin_lock for enable/disable tx irq critial section */
+       spinlock_t                      tx_irq_lock;
++      /* spin_lock for enable/disable rx irq critial section */
+       spinlock_t                      rx_irq_lock;
+       struct net_device               dummy_dev;
+       struct net_device               *netdev[MTK_MAX_DEVS];
+@@ -634,10 +800,11 @@ struct mtk_eth {
+       u32                             msg_enable;
+       unsigned long                   sysclk;
+       struct regmap                   *ethsys;
+-      struct regmap                   *sgmiisys;
++      struct regmap                   *infra;
++      struct mtk_sgmii                *sgmii;
+       struct regmap                   *pctl;
+       bool                            hwlro;
+-      refcount_t                      dma_refcnt;
++      atomic_t                        dma_refcnt;
+       struct mtk_tx_ring              tx_ring;
+       struct mtk_rx_ring              rx_ring[MTK_MAX_RX_RING_NUM];
+       struct mtk_rx_ring              rx_ring_qdma;
+@@ -653,6 +820,7 @@ struct mtk_eth {
+       unsigned long                   state;
+       const struct mtk_soc_data       *soc;
++      struct mtk_eth_debug            debug;
+ };
+ /* struct mtk_mac -   the structure that holds the info about the MACs of the
+@@ -664,6 +832,7 @@ struct mtk_eth {
+  * @hw_stats:         Packet statistics counter
+  * @trgmii            Indicate if the MAC uses TRGMII connected to internal
+                       switch
++ * @phy_dev:          The attached PHY if available
+  */
+ struct mtk_mac {
+       int                             id;
+@@ -674,6 +843,7 @@ struct mtk_mac {
+       __be32                          hwlro_ip[MTK_MAX_LRO_IP_CNT];
+       int                             hwlro_ip_cnt;
+       bool                            trgmii;
++      struct phy_device               *phy_dev;
+ };
+ /* the struct describing the SoC. these are declared in the soc_xyz.c files */
+@@ -685,4 +855,10 @@ void mtk_stats_update_mac(struct mtk_mac
+ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
+ u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
++int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
++                 u32 ana_rgc3);
++int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
++int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id);
++int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode);
++
+ #endif /* MTK_ETH_H */
+Index: linux-4.19.57/drivers/net/ethernet/mediatek/mtk_sgmii.c
+===================================================================
+--- /dev/null
++++ linux-4.19.57/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -0,0 +1,114 @@
++/*
++ *   Copyright (C) 2018 MediaTek Inc.
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation; version 2 of the License
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details.
++ *
++ *   Copyright (C) 2018 Sean Wang <sean.wang@mediatek.com>
++ */
++
++#include <linux/mfd/syscon.h>
++#include <linux/of.h>
++#include <linux/regmap.h>
++
++#include "mtk_eth_soc.h"
++
++int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
++{
++      struct device_node *np;
++      const char *str;
++      int i, err;
++
++      ss->ana_rgc3 = ana_rgc3;
++
++      for (i = 0; i < MTK_MAX_DEVS; i++) {
++              np = of_parse_phandle(r, "mediatek,sgmiisys", i);
++              if (!np)
++                      break;
++
++              ss->regmap[i] = syscon_node_to_regmap(np);
++              if (IS_ERR(ss->regmap[i]))
++                      return PTR_ERR(ss->regmap[i]);
++
++              err = of_property_read_string(np, "mediatek,physpeed", &str);
++              if (err)
++                      return err;
++
++              if (!strcmp(str, "2500"))
++                      pr_info("sean debug physpeed = 2500\n");
++
++              if (!strcmp(str, "2500"))
++                      ss->flags[i] |= MTK_SGMII_PHYSPEED_2500;
++              else if (!strcmp(str, "1000"))
++                      ss->flags[i] |= MTK_SGMII_PHYSPEED_1000;
++              else if (!strcmp(str, "auto"))
++                      ss->flags[i] |= MTK_SGMII_PHYSPEED_AN;
++              else
++                      return -EINVAL;
++      }
++
++      return 0;
++}
++
++int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
++{
++      unsigned int val;
++
++      if (!ss->regmap[id])
++              return -EINVAL;
++
++      /* Setup the link timer and QPHY power up inside SGMIISYS */
++      regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
++                   SGMII_LINK_TIMER_DEFAULT);
++
++      regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
++      val |= SGMII_REMOTE_FAULT_DIS;
++      regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
++
++      regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
++      val |= SGMII_AN_RESTART;
++      regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
++
++      regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
++      val &= ~SGMII_PHYA_PWD;
++      regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
++
++      return 0;
++}
++
++int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id)
++{
++      unsigned int val;
++      int mode;
++
++      if (!ss->regmap[id])
++              return -EINVAL;
++
++      regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
++      val &= ~GENMASK(2, 3);
++      mode = ss->flags[id] & MTK_SGMII_PHYSPEED_MASK;
++      val |= (mode == MTK_SGMII_PHYSPEED_1000) ? 0 : BIT(2);
++      regmap_write(ss->regmap[id], ss->ana_rgc3, val);
++
++      /* disable SGMII AN */
++      regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
++      val &= ~BIT(12);
++      regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
++
++      /* SGMII force mode setting */
++      val = 0x31120019;
++      regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
++
++      /* Release PHYA power down state */
++      regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
++      val &= ~SGMII_PHYA_PWD;
++      regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
++
++      return 0;
++}
diff --git a/target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch b/target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch
new file mode 100644 (file)
index 0000000..6eba401
--- /dev/null
@@ -0,0 +1,1259 @@
+--- a/drivers/net/phy/mtk/mt753x/Makefile
++++ b/drivers/net/phy/mtk/mt753x/Makefile
+@@ -5,6 +5,6 @@
+ obj-$(CONFIG_MT753X_GSW)              += mt753x.o
+ mt753x-y                      += mt753x_mdio.o mt7530.o mt7531.o \
+-                                      mt753x_common.o mt753x_nl.o
++                                      mt753x_common.o mt753x_nl.o mt753x_phy.o
+--- a/drivers/net/phy/mtk/mt753x/mt7531.c
++++ b/drivers/net/phy/mtk/mt753x/mt7531.c
+@@ -454,6 +454,21 @@ static void mt7531_core_pll_setup(struct gsw_mt753x *gsw)
+ static int mt7531_internal_phy_calibration(struct gsw_mt753x *gsw)
+ {
++      u32 i;
++      int ret;
++
++      dev_info(gsw->dev,">>>>>>>>>>>>>>>>>>>>>>>>>>>>> START CALIBRATION:\n");
++      for (i = 0; i < 5; i++) {
++              dev_info(gsw->dev, "-------- gephy-calbration (port:%d) --------\n",
++                       i);
++              ret = mt753x_phy_calibration(gsw, i);
++
++              /* set Auto-negotiation with giga extension. */
++              gsw->mii_write(gsw, i, 0, 0x1340);
++              if (ret)
++                      return ret;
++      }
++
+       return 0;
+ }
+--- a/drivers/net/phy/mtk/mt753x/mt753x.h
++++ b/drivers/net/phy/mtk/mt753x/mt753x.h
+@@ -141,6 +141,8 @@ void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
+ void mt753x_irq_worker(struct work_struct *work);
+ void mt753x_irq_enable(struct gsw_mt753x *gsw);
++int mt753x_phy_calibration(struct gsw_mt753x *gsw, u8 phyaddr);
++
+ /* MDIO Indirect Access Registers */
+ #define MII_MMD_ACC_CTL_REG           0x0d
+ #define MMD_CMD_S                     14
+--- /dev/null
++++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
+@@ -0,0 +1,1061 @@
++// SPDX-License-Identifier:   GPL-2.0+
++/*
++ * Common part for MediaTek MT753x gigabit switch
++ *
++ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
++ *
++ * Author: Weijie Gao <weijie.gao@mediatek.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/delay.h>
++
++#include "mt753x.h"
++#include "mt753x_regs.h"
++#include "mt753x_phy.h"
++
++u32 tc_phy_read_dev_reg(struct gsw_mt753x *gsw, u32 port_num, u32 dev_addr, u32 reg_addr)
++{
++      u32 phy_val;
++    phy_val = gsw->mmd_read(gsw, port_num, dev_addr, reg_addr);
++    
++    //printk("switch phy cl45 r %d 0x%x 0x%x = %x\n",port_num, dev_addr, reg_addr, phy_val);
++      //switch_phy_read_cl45(port_num, dev_addr, reg_addr, &phy_val);
++      return phy_val;
++}
++
++void tc_phy_write_dev_reg(struct gsw_mt753x *gsw, u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data)
++{
++      u32 phy_val;
++    gsw->mmd_write(gsw, port_num, dev_addr, reg_addr, write_data);
++    phy_val = gsw->mmd_read(gsw, port_num, dev_addr, reg_addr);
++    //printk("switch phy cl45 w %d 0x%x 0x%x 0x%x --> read back 0x%x\n",port_num, dev_addr, reg_addr, write_data, phy_val);
++      //switch_phy_write_cl45(port_num, dev_addr, reg_addr, write_data);
++}
++
++void switch_phy_write(struct gsw_mt753x *gsw, u32 port_num, u32 reg_addr, u32 write_data){
++      gsw->mii_write(gsw, port_num, reg_addr, write_data);
++}
++
++u32 switch_phy_read(struct gsw_mt753x *gsw, u32 port_num, u32 reg_addr){
++      return gsw->mii_read(gsw, port_num, reg_addr);
++}
++
++const u8 MT753x_ZCAL_TO_R50ohm_GE_TBL_100[64] = {
++      127, 127, 127, 127, 127, 127, 127, 127,
++      127, 127, 127, 127, 127, 123, 122, 117,
++      115, 112, 103, 100, 98, 87, 85, 83,
++      81, 72, 70, 68, 66, 64, 55, 53,
++      52, 50, 49, 48, 38, 36, 35, 34,
++      33, 32, 22, 21, 20, 19, 18, 17,
++      16, 7, 6, 5, 4, 3, 2, 1,
++      0, 0, 0, 0, 0, 0, 0, 0
++};
++
++const u8 MT753x_TX_OFFSET_TBL[64] = {
++      0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
++      0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
++      0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,
++      0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0,
++      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++      0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
++};
++
++u8 ge_cal_flag;
++
++u8 all_ge_ana_cal_wait(struct gsw_mt753x *gsw, u32 delay, u32 phyaddr) // for EN7512 
++{
++      u8 all_ana_cal_status;  
++      u32 cnt, tmp_1e_17c;
++      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017c, 0x0001);     // da_calin_flag pull high
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++      //printk("delay = %d\n", delay);
++      
++      cnt = 10000;
++      do {
++              udelay(delay);
++              cnt--;
++              all_ana_cal_status = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17b) & 0x1;
++
++      } while ((all_ana_cal_status == 0) && (cnt != 0));
++
++
++      if(all_ana_cal_status == 1) {
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
++              return all_ana_cal_status;
++      } else {
++              tmp_1e_17c = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c);
++              if ((tmp_1e_17c & 0x1) != 1) {
++                      pr_info("FIRST MDC/MDIO write error\n");
++                      pr_info("FIRST 1e_17c = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c));
++
++              }
++              printk("re-K again\n");
++        
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++              cnt = 10000;
++              do {
++                      udelay(delay);
++                      cnt--;
++                      tmp_1e_17c = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c);
++                      if ((tmp_1e_17c & 0x1) != 1) {
++                              pr_info("SECOND MDC/MDIO write error\n");
++                              pr_info("SECOND 1e_17c = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c));
++                              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++                              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++                              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++                      }
++              } while ((cnt != 0) && (tmp_1e_17c == 0));
++
++              cnt = 10000;
++              do {
++                      udelay(delay);
++                      cnt--;
++                      all_ana_cal_status = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17b) & 0x1;
++      
++              } while ((all_ana_cal_status == 0) && (cnt != 0));
++      
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
++      }
++
++    if(all_ana_cal_status == 0){
++        pr_info("!!!!!!!!!!!! dev1Eh_reg17b ERROR\n");
++    }
++      
++      return all_ana_cal_status;
++}
++
++
++
++
++int ge_cal_rext(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
++{
++      u8 rg_zcal_ctrl, all_ana_cal_status;
++      u16 ad_cal_comp_out_init;
++      u16 dev1e_e0_ana_cal_r5;
++      int calibration_polarity;
++      u8 cnt = 0;
++      u16 dev1e_17a_tmp, dev1e_e0_tmp;
++
++      /* *** Iext/Rext Cal start ************ */
++      all_ana_cal_status = ANACAL_INIT;
++      /* analog calibration enable, Rext calibration enable */
++      /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */
++      /* 1e_dc[0]:rg_txvos_calen */
++      /* 1e_e1[4]:rg_cal_refsel(0:1.2V) */
++      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x1110)
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1110);
++      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0000);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0);
++      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e1, 0x0000);
++      //tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x10);
++      
++      rg_zcal_ctrl = 0x20;/* start with 0 dB */
++      dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0xe0); // get default value
++      /* 1e_e0[5:0]:rg_zcal_ctrl */
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0xe0, rg_zcal_ctrl);
++      all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr);/* delay 20 usec */
++
++      if (all_ana_cal_status == 0) {
++              all_ana_cal_status = ANACAL_ERROR;
++              printk(" GE Rext AnaCal ERROR init!   \r\n");
++              return -1;
++      }
++      /* 1e_17a[8]:ad_cal_comp_out */
++      ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a) >> 8) & 0x1;
++      if (ad_cal_comp_out_init == 1)
++              calibration_polarity = -1;
++      else /* ad_cal_comp_out_init == 0 */
++              calibration_polarity = 1;
++      cnt = 0;
++      while (all_ana_cal_status < ANACAL_ERROR) {
++              cnt++;
++              rg_zcal_ctrl += calibration_polarity;
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0xe0, (rg_zcal_ctrl));
++              all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); /* delay 20 usec */
++              dev1e_17a_tmp = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a);
++              if (all_ana_cal_status == 0) {
++                      all_ana_cal_status = ANACAL_ERROR;
++                      printk("  GE Rext AnaCal ERROR 2!   \r\n");
++                      return -1;
++              } else if (((dev1e_17a_tmp >> 8) & 0x1) != ad_cal_comp_out_init) {
++                      all_ana_cal_status = ANACAL_FINISH;
++                      //printk("  GE Rext AnaCal Done! (%d)(0x%x)  \r\n", cnt, rg_zcal_ctrl);
++              } else {
++                      dev1e_17a_tmp = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a);
++                      dev1e_e0_tmp =  tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0xe0);
++                      if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) {
++                              all_ana_cal_status = ANACAL_SATURATION;  /* need to FT(IC fail?) */
++                              printk(" GE Rext AnaCal Saturation!  \r\n");
++                              rg_zcal_ctrl = 0x20;  /* 0 dB */
++                      } 
++              }
++      }
++
++      if (all_ana_cal_status == ANACAL_ERROR) {
++              rg_zcal_ctrl = 0x20;  /* 0 dB */
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++      } else if(all_ana_cal_status == ANACAL_FINISH){
++              //tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, ((rg_zcal_ctrl << 8) | rg_zcal_ctrl));
++              printk("0x1e-e0 = %x\n", tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x00e0));
++              /* ****  1f_115[2:0] = rg_zcal_ctrl[5:3]  // Mog review */
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1f, 0x0115, ((rg_zcal_ctrl & 0x3f) >> 3));
++              printk("0x1f-115 = %x\n", tc_phy_read_dev_reg(gsw,  PHY0, 0x1f, 0x115));
++              printk("  GE Rext AnaCal Done! (%d)(0x%x)  \r\n", cnt, rg_zcal_ctrl);
++              ge_cal_flag = 1;
++      } else {
++              printk("GE Rxet cal something wrong2\n");
++      }
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
++}
++
++//-----------------------------------------------------------------
++int ge_cal_r50(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
++{
++      u8 rg_zcal_ctrl, all_ana_cal_status, calibration_pair;
++      u16 ad_cal_comp_out_init;
++      u16 dev1e_e0_ana_cal_r5;
++      int calibration_polarity;
++      u8 cnt = 0;
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);  // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  // 1e_dc[0]:rg_txvos_calen
++
++      for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
++              rg_zcal_ctrl = 0x20;                                            // start with 0 dB
++              dev1e_e0_ana_cal_r5 = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00e0) & (~0x003f));
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));    // 1e_e0[5:0]:rg_zcal_ctrl
++              if(calibration_pair == ANACAL_PAIR_A)
++              {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1101);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);       
++                      //printk("R50 pair A 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
++
++              }
++              else if(calibration_pair == ANACAL_PAIR_B)
++              {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x1000);       // 1e_dc[12]:rg_zcalen_b
++                      //printk("R50 pair B 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db),tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
++
++              }
++              else if(calibration_pair == ANACAL_PAIR_C)
++              {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0100);       // 1e_dc[8]:rg_zcalen_c
++                      //printk("R50 pair C 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
++
++              }
++              else // if(calibration_pair == ANACAL_PAIR_D)
++              {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0010);       // 1e_dc[4]:rg_zcalen_d
++                      //printk("R50 pair D 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
++
++              }
++
++              all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
++              if(all_ana_cal_status == 0)
++              {
++                      all_ana_cal_status = ANACAL_ERROR;      
++                      printk( "GE R50 AnaCal ERROR init!   \r\n");
++                      return -1;
++              }
++      
++              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8) & 0x1;                // 1e_17a[8]:ad_cal_comp_out    
++              if(ad_cal_comp_out_init == 1)
++                      calibration_polarity = -1;
++              else
++                      calibration_polarity = 1;
++
++              cnt = 0;
++              while(all_ana_cal_status < ANACAL_ERROR)
++              {
++                      cnt ++;
++                      rg_zcal_ctrl += calibration_polarity;
++                      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++                      all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
++
++                      if(all_ana_cal_status == 0)
++                      {
++                              all_ana_cal_status = ANACAL_ERROR;      
++                              printk( "  GE R50 AnaCal ERROR 2!   \r\n");
++                              return -1;
++                      }
++                      else if(((tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8)&0x1) != ad_cal_comp_out_init) 
++                      {
++                              all_ana_cal_status = ANACAL_FINISH;     
++                      }
++                      else {
++                              if((rg_zcal_ctrl == 0x3F)||(rg_zcal_ctrl == 0x00))      
++                              {
++                                      all_ana_cal_status = ANACAL_SATURATION;  // need to FT
++                                      printk( " GE R50 AnaCal Saturation!  \r\n");
++                              }
++                      }
++              }
++              
++              if(all_ana_cal_status == ANACAL_ERROR) {        
++                      rg_zcal_ctrl = 0x20;  // 0 dB
++                      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++              }
++              else {
++                      rg_zcal_ctrl = MT753x_ZCAL_TO_R50ohm_GE_TBL_100[rg_zcal_ctrl - 9];      // wait Mog zcal/r50 mapping table
++                      printk( " GE R50 AnaCal Done! (%d) (0x%x)(0x%x) \r\n", cnt, rg_zcal_ctrl, (rg_zcal_ctrl|0x80));
++              }
++              
++              if(calibration_pair == ANACAL_PAIR_A) {
++                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174) & (~0x7f00);
++                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174);
++                      //printk( " GE-a 1e_174(0x%x)(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));       // 1e_174[15:8]
++                      //printk( " GE-a 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++              }
++              else if(calibration_pair == ANACAL_PAIR_B) {
++                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174) & (~0x007f);
++                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174);
++                      //printk( " GE-b 1e_174(0x%x)(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++                      
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));       // 1e_174[7:0]
++                      //printk( " GE-b 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++              }
++              else if(calibration_pair == ANACAL_PAIR_C) {
++                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175) & (~0x7f00);
++                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));       // 1e_175[15:8]
++                      //printk( " GE-c 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++              } else {// if(calibration_pair == ANACAL_PAIR_D) 
++                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175) & (~0x007f);
++                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));       // 1e_175[7:0]
++                      //printk( " GE-d 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++              }
++              //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00e0, ((rg_zcal_ctrl<<8)|rg_zcal_ctrl));
++      }
++      
++      printk( " GE 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
++}
++
++int ge_cal_tx_offset(struct gsw_mt753x *gsw,  u8 phyaddr, u32 delay)
++{
++      u8 all_ana_cal_status, calibration_pair;
++      u16 ad_cal_comp_out_init;
++      int calibration_polarity, tx_offset_temp;
++      u8 tx_offset_reg_shift, tabl_idx, i;
++      u8 cnt = 0;
++      u16 tx_offset_reg, reg_temp, cal_temp;
++      //switch_phy_write(phyaddr, R0, 0x2100);//harry tmp
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0100);  // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);  // 1e_dc[0]:rg_txvos_calen
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0096, 0x8000);       // 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);       // 1e_3e
++      for(i = 0; i <= 4; i++)
++              tc_phy_write_dev_reg(gsw, i, 0x1e, 0x00dd, 0x0000);     
++      for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++)
++      {
++              tabl_idx = 31;
++              tx_offset_temp = MT753x_TX_OFFSET_TBL[tabl_idx];
++
++              if(calibration_pair == ANACAL_PAIR_A) {
++                      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5010);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);                               // 1e_dd[12]:rg_txg_calen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_0V));   // 1e_17d:dac_in0_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_0V));   // 1e_181:dac_in1_a
++                      //printk("tx offset pairA 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
++                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0172) & (~0x3f00));
++                      tx_offset_reg_shift = 8;                                                                        // 1e_172[13:8]
++                      tx_offset_reg = 0x0172;
++
++                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++              } else if(calibration_pair == ANACAL_PAIR_B) {
++                      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5018);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);                               // 1e_dd[8]:rg_txg_calen_b
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_0V));   // 1e_17e:dac_in0_b
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_0V));   // 1e_182:dac_in1_b
++                      //printk("tx offset pairB 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
++                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0172) & (~0x003f));
++                      tx_offset_reg_shift = 0;                                                                        // 1e_172[5:0]
++                      tx_offset_reg = 0x0172;
++                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++              } else if(calibration_pair == ANACAL_PAIR_C) {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);                               // 1e_dd[4]:rg_txg_calen_c
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_0V));   // 1e_17f:dac_in0_c
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_0V));   // 1e_183:dac_in1_c
++                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0173) & (~0x3f00));
++                      //printk("tx offset pairC 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
++                      tx_offset_reg_shift = 8;                                                                        // 1e_173[13:8]
++                      tx_offset_reg = 0x0173;
++                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++              } else {// if(calibration_pair == ANACAL_PAIR_D)
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);                               // 1e_dd[0]:rg_txg_calen_d
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_0V));   // 1e_180:dac_in0_d
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_0V));   // 1e_184:dac_in1_d
++                      //printk("tx offset pairD 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
++                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0173) & (~0x003f));
++                      tx_offset_reg_shift = 0;                                                                        // 1e_173[5:0]
++                      tx_offset_reg = 0x0173;
++                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++              }
++              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));      // 1e_172, 1e_173
++              all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
++              if(all_ana_cal_status == 0) {
++                      all_ana_cal_status = ANACAL_ERROR;      
++                      printk( " GE Tx offset AnaCal ERROR init!   \r\n");
++                      return -1;
++              }
++      
++              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1;         // 1e_17a[8]:ad_cal_comp_out    
++              if(ad_cal_comp_out_init == 1)
++                      calibration_polarity = 1;
++              else
++                      calibration_polarity = -1;
++
++              cnt = 0;
++              //printk("TX offset cnt = %d, tabl_idx= %x, offset_val = %x\n", cnt, tabl_idx, MT753x_TX_OFFSET_TBL[tabl_idx]);
++              while(all_ana_cal_status < ANACAL_ERROR) {
++                      
++                      cnt ++;
++                      tabl_idx += calibration_polarity;
++                      //tx_offset_temp += calibration_polarity;
++                      //cal_temp = tx_offset_temp;
++                      cal_temp = MT753x_TX_OFFSET_TBL[tabl_idx];
++                      //printk("TX offset cnt = %d, tabl_idx= %x, offset_val = %x\n", cnt, tabl_idx, MT753x_TX_OFFSET_TBL[tabl_idx]);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(cal_temp<<tx_offset_reg_shift)));
++
++                      all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
++                      if(all_ana_cal_status == 0) {
++                              all_ana_cal_status = ANACAL_ERROR;      
++                              printk( " GE Tx offset AnaCal ERROR init 2!   \r\n");
++                              return -1;
++                      } else if(((tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8)&0x1) != ad_cal_comp_out_init) {
++                              all_ana_cal_status = ANACAL_FINISH;     
++                      } else {
++                              if((tabl_idx == 0)||(tabl_idx == 0x3f)) {
++                                      all_ana_cal_status = ANACAL_SATURATION;  // need to FT
++                                      printk( " GE Tx offset AnaCal Saturation!  \r\n");
++                              }
++                      }
++              }
++              
++              if(all_ana_cal_status == ANACAL_ERROR) {        
++                      tx_offset_temp = TX_AMP_OFFSET_0MV;
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++              } else {
++                      printk( " GE Tx offset AnaCal Done! (pair-%d)(%d)(0x%x) 0x1e_%x=0x%x\n", calibration_pair, cnt, MT753x_TX_OFFSET_TBL[tabl_idx], tx_offset_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg));
++              }
++      }
++
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, 0x0000);
++      
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);  // disable analog calibration circuit
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);       // disable analog calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);       // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);       // disable Tx VLD force mode
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);       // disable Tx offset/amplitude calibration circuit      
++}
++
++int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
++{
++      u8      all_ana_cal_status, calibration_pair, i;
++      u16     ad_cal_comp_out_init;
++      int     calibration_polarity;
++      u32     tx_amp_reg_shift; 
++      u16     reg_temp;
++      u32     tx_amp_temp, tx_amp_reg, cnt=0, tx_amp_reg_100;
++      u32 debug_tmp, reg_backup, reg_tmp; 
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);  // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);  // 1e_dc[0]:rg_txvos_calen
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x0010);  // 1e_e1[4]:select 1V
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);       // 1e_3e:enable Tx VLD
++
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x11, 0xff00);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27a, 0x33);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0xc9, 0xffff);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x300, 0x4);
++      for(i = 0; i <= 4; i++)
++              tc_phy_write_dev_reg(gsw, i, 0x1e, 0x00dd, 0x0000);
++      for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
++              tx_amp_temp = 0x20;     // start with 0 dB
++
++              if(calibration_pair == ANACAL_PAIR_A) {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);                               // 1e_dd[12]:tx_a amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_2V));   // 1e_17d:dac_in0_a     
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_2V));   // 1e_181:dac_in1_a
++                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x012) & (~0xfc00));
++                      tx_amp_reg_shift = 10;                                                                          // 1e_12[15:10]
++                      tx_amp_reg = 0x12;
++                      tx_amp_reg_100 = 0x16;
++              } else if(calibration_pair == ANACAL_PAIR_B) {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);                               // 1e_dd[8]:tx_b amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_2V));   // 1e_17e:dac_in0_b
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_2V));   // 1e_182:dac_in1_b
++                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x017) & (~0x3f00));
++                      tx_amp_reg_shift = 8;                                                                           // 1e_17[13:8]
++                      tx_amp_reg = 0x17;
++                      tx_amp_reg_100 = 0x18;
++              } else if(calibration_pair == ANACAL_PAIR_C) {
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);                               // 1e_dd[4]:tx_c amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_2V));   // 1e_17f:dac_in0_c
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_2V));   // 1e_183:dac_in1_c
++                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x019) & (~0x3f00));
++                      tx_amp_reg_shift = 8;                                                                           // 1e_19[13:8]
++                      tx_amp_reg = 0x19;
++                      tx_amp_reg_100 = 0x20;
++              } else { //if(calibration_pair == ANACAL_PAIR_D)
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);                               // 1e_dd[0]:tx_d amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_2V));   // 1e_180:dac_in0_d
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_2V));   // 1e_184:dac_in1_d
++                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x021) & (~0x3f00));
++                      tx_amp_reg_shift = 8;                                                                           // 1e_21[13:8]
++                      tx_amp_reg = 0x21;
++                      tx_amp_reg_100 = 0x22;
++              }
++              tc_phy_write_dev_reg( gsw, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));   // 1e_12, 1e_17, 1e_19, 1e_21
++              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++              all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr);  // delay 20 usec
++              if(all_ana_cal_status == 0) {
++                      all_ana_cal_status = ANACAL_ERROR;      
++                      printk( " GE Tx amp AnaCal ERROR init init!   \r\n");
++                      return -1;
++              }
++      
++              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8) & 0x1;                // 1e_17a[8]:ad_cal_comp_out
++              if(ad_cal_comp_out_init == 1)
++                      calibration_polarity = -1;
++              else
++                      calibration_polarity = 1;
++
++              cnt =0;
++              while(all_ana_cal_status < ANACAL_ERROR) {
++                      cnt ++;
++                      tx_amp_temp += calibration_polarity;
++                      //printk("tx_amp : %x, 1e %x = %x\n", tx_amp_temp, tx_amp_reg, (reg_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++                      tc_phy_write_dev_reg( gsw, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++                      all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
++                      if(all_ana_cal_status == 0) {
++                              all_ana_cal_status = ANACAL_ERROR;      
++                              printk( " GE Tx amp AnaCal ERROR 2!   \r\n");
++                              return -1;
++                      } else if(((tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8)&0x1) != ad_cal_comp_out_init) {
++                              //printk("TX AMP ANACAL_FINISH\n");
++                              all_ana_cal_status = ANACAL_FINISH;
++                              if (phyaddr == 0) {
++                                      if (calibration_pair == ANACAL_PAIR_A)
++                                              tx_amp_temp = tx_amp_temp - 2;
++                                      else if(calibration_pair == ANACAL_PAIR_B)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                                      else if(calibration_pair == ANACAL_PAIR_C)
++                                              tx_amp_temp = tx_amp_temp - 2;
++                                      else if(calibration_pair == ANACAL_PAIR_D)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                              } else if (phyaddr == 1) {
++                                      if (calibration_pair == ANACAL_PAIR_A)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                                      else if(calibration_pair == ANACAL_PAIR_B)
++                                              tx_amp_temp = tx_amp_temp ;
++                                      else if(calibration_pair == ANACAL_PAIR_C)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                                      else if(calibration_pair == ANACAL_PAIR_D)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                              } else if (phyaddr == 2) {
++                                      if (calibration_pair == ANACAL_PAIR_A)
++                                              tx_amp_temp = tx_amp_temp;
++                                      else if(calibration_pair == ANACAL_PAIR_B)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                                      else if(calibration_pair == ANACAL_PAIR_C)
++                                              tx_amp_temp = tx_amp_temp;
++                                      else if(calibration_pair == ANACAL_PAIR_D)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                              } else if (phyaddr == 3) {
++                                      tx_amp_temp = tx_amp_temp;
++                              } else if (phyaddr == 4) {
++                                      if (calibration_pair == ANACAL_PAIR_A)
++                                              tx_amp_temp = tx_amp_temp;
++                                      else if(calibration_pair == ANACAL_PAIR_B)
++                                              tx_amp_temp = tx_amp_temp - 1;
++                                      else if(calibration_pair == ANACAL_PAIR_C)
++                                              tx_amp_temp = tx_amp_temp;
++                                      else if(calibration_pair == ANACAL_PAIR_D)
++                                              tx_amp_temp = tx_amp_temp;
++                              }                                                               
++                              reg_temp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, tx_amp_reg)&(~0xff00);
++                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
++                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
++                              if (phyaddr == 0) {
++                                      if ((tx_amp_reg == 0x12) || (tx_amp_reg == 0x17)) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 7));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if (tx_amp_reg_100 == 0x16) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp+1+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                                      if (tx_amp_reg_100 == 0x18) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                              } else if (phyaddr == 1) {
++                                      if (tx_amp_reg == 0x12) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 9));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if (tx_amp_reg == 0x17){
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 7));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if (tx_amp_reg_100 == 0x16) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                                      if (tx_amp_reg_100 == 0x18) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp-1+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                              } else if (phyaddr == 2) {
++                                      if ((tx_amp_reg == 0x12) || (tx_amp_reg == 0x17)) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 6));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if ((tx_amp_reg_100 == 0x16) || (tx_amp_reg_100 == 0x18)) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp-1+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                              } else if (phyaddr == 3) {
++                                      if (tx_amp_reg == 0x12) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 4));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if (tx_amp_reg == 0x17) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 7));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if (tx_amp_reg_100 == 0x16) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp-2+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                                      if (tx_amp_reg_100 == 0x18) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp-1+3)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                              } else if (phyaddr == 4) {
++                                      if ((tx_amp_reg == 0x12) || (tx_amp_reg == 0x17)) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, ((tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)) + 5));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                                      }
++                                      if (tx_amp_reg_100 == 0x16) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp-2+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                                      if (tx_amp_reg_100 == 0x18) {
++                                              //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp-1+4)<<tx_amp_reg_shift)));
++                                              //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100));
++                                      }
++                              }       
++
++                              if (calibration_pair == ANACAL_PAIR_A){
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x12);
++                                      reg_tmp = ((reg_backup & 0xfc00) >> 10);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0xfc00));
++                                      reg_backup |= (reg_tmp << 10);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x12, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x12);
++                                      //printk("PORT[%d] 1e.012 = %x (OFFSET_1000M_PAIR_A)\n", phyaddr, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x16);
++                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f));
++                                      reg_backup |= (reg_tmp << 0);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x16, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x16);
++                                      //printk("PORT[%d] 1e.016 = %x (OFFSET_TESTMODE_1000M_PAIR_A)\n", phyaddr, reg_backup);
++                              }
++                              else if(calibration_pair == ANACAL_PAIR_B){
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x17);
++                                      reg_tmp = ((reg_backup & 0x3f00) >> 8);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f00));
++                                      reg_backup |= (reg_tmp << 8);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x17, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x17);
++                                      //printk("PORT[%d] 1e.017 = %x (OFFSET_1000M_PAIR_B)\n", phyaddr, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x18);
++                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f));
++                                      reg_backup |= (reg_tmp << 0);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x18);
++                                      //printk("PORT[%d] 1e.018 = %x (OFFSET_TESTMODE_1000M_PAIR_B)\n", phyaddr, reg_backup);
++                              }
++                              else if(calibration_pair == ANACAL_PAIR_C){
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x19);
++                                      reg_tmp = ((reg_backup & 0x3f00) >> 8);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f00));
++                                      reg_backup |= (reg_tmp << 8);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x19, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x19);
++                                      //printk("PORT[%d] 1e.019 = %x (OFFSET_1000M_PAIR_C)\n", phyaddr, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x20);
++                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f));
++                                      reg_backup |= (reg_tmp << 0);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x20, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x20);
++                                      //printk("PORT[%d] 1e.020 = %x (OFFSET_TESTMODE_1000M_PAIR_C)\n", phyaddr, reg_backup);
++                              }
++                              else if(calibration_pair == ANACAL_PAIR_D){
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x21);
++                                      reg_tmp = ((reg_backup & 0x3f00) >> 8);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f00));
++                                      reg_backup |= (reg_tmp << 8);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x21, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x21);
++                                      //printk("PORT[%d] 1e.021 = %x (OFFSET_1000M_PAIR_D)\n", phyaddr, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x22);
++                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
++                                      reg_tmp -= 8;
++                                      reg_backup = (reg_backup & (~0x3f));
++                                      reg_backup |= (reg_tmp << 0);
++                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x22, reg_backup);
++                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x22);
++                                      //printk("PORT[%d] 1e.022 = %x (OFFSET_TESTMODE_1000M_PAIR_D)\n", phyaddr, reg_backup);
++                              }
++
++                              if (calibration_pair == ANACAL_PAIR_A){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x12);
++                                      //printk("1e.012 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x16);
++                                      //printk("1e.016 = 0x%x\n", debug_tmp);
++                              }
++      
++                              else if(calibration_pair == ANACAL_PAIR_B){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x17);
++                                      //printk("1e.017 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x18);
++                                      //printk("1e.018 = 0x%x\n", debug_tmp);
++                              }
++                              else if(calibration_pair == ANACAL_PAIR_C){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x19);
++                                      //printk("1e.019 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x20);
++                                      //printk("1e.020 = 0x%x\n", debug_tmp);
++                              }
++                              else if(calibration_pair == ANACAL_PAIR_D){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x21);
++                                      //printk("1e.021 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x22);
++                                      //printk("1e.022 = 0x%x\n", debug_tmp);
++                              }
++
++
++                              printk( " GE Tx amp AnaCal Done! (pair-%d)(1e_%x = 0x%x)\n", calibration_pair, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
++                              
++                      } else {
++                              if((tx_amp_temp == 0x3f)||(tx_amp_temp == 0x00)) {
++                                      all_ana_cal_status = ANACAL_SATURATION;  // need to FT
++                                      printk( " GE Tx amp AnaCal Saturation!  \r\n");
++                              }
++                      }
++              }
++
++              if(all_ana_cal_status == ANACAL_ERROR) {        
++                      tx_amp_temp = 0x20;
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, (reg_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++              }
++      }
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, 0x0000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, 0x0000);
++      
++      /* disable analog calibration circuit */
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);       // disable analog calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);       // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);       // disable Tx VLD force mode
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);       // disable Tx offset/amplitude calibration circuit
++      
++      
++
++      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x273, 0x2000);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0xc9, 0x0fff);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x145, 0x1000);
++
++}
++
++//-----------------------------------------------------------------
++
++int phy_calibration(struct gsw_mt753x *gsw, u8 phyaddr)
++{
++      u32     reg_tmp,reg_tmp0, reg_tmp1, i;
++      u32 CALDLY = 40;
++      int ret;
++      /* set [12]AN disable, [8]full duplex, [13/6]1000Mbps */
++      //tc_phy_write_dev_reg(phyaddr, 0x0,  0x0140);
++      switch_phy_write(gsw, phyaddr, R0, 0x140);
++
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x145, 0x1010);/* fix mdi */
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, RG_185, 0);/* disable tx slew control */
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x100, 0xc000);/* BG voltage output */
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x403, 0x1099); //bypass efuse
++
++#if (1)
++      //      1f_27c[12:8] cr_da_tx_i2mpb_10m Trimming TX bias setup(@10M)
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x1f1f);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x3300);
++
++      reg_tmp1 = tc_phy_read_dev_reg(gsw,  PHY0, 0x1f, 0x27c);
++      //dev1Fh_reg273h TXVLD DA register      - Adjust voltage mode TX amplitude.
++      //tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x273, 0x1000);
++      //reg_tmp1 = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x273);
++      //printk("reg_tmp1273 = %x\n", reg_tmp1);
++      /*1e_11 TX  overshoot Enable (PAIR A/B/C/D) in gbe mode*/
++
++      reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x11);
++      reg_tmp = reg_tmp | (0xf << 12);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x11, reg_tmp);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x10);
++      /* calibration start ============ */
++      printk("CALDLY = %d\n", CALDLY);
++      if(ge_cal_flag == 0){
++              ret = ge_cal_rext(gsw, 0, CALDLY);
++              if (ret == -1){
++                      printk("ge_cal_rext error K port =%d\n", phyaddr);
++                      return ret;
++              }
++              ge_cal_flag = 1;
++      }
++
++      /* *** R50 Cal start ***************************** */
++      /*phyaddress = 0*/
++      ret = ge_cal_r50(gsw, phyaddr, CALDLY);
++      if (ret == -1){
++              printk("R50 error K port =%d\n", phyaddr);
++              return ret;
++      }
++      /* *** R50 Cal end *** */
++      /* *** Tx offset Cal start *********************** */
++      ret = ge_cal_tx_offset(gsw, phyaddr, CALDLY);
++      if (ret == -1){
++              printk("ge_cal_tx_offset error K port =%d\n", phyaddr);
++              return ret;
++      }
++      /* *** Tx offset Cal end *** */
++
++      /* *** Tx Amp Cal start *** */
++      ret = ge_cal_tx_amp(gsw, phyaddr, CALDLY);
++      if (ret == -1){
++              printk("ge_cal_tx_amp error K port =%d\n", phyaddr);
++              return ret;
++      }
++      /* *** Tx Amp Cal end *** */
++      /*tmp maybe changed*/
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x1111);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27b, 0x47);
++      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x273, 0x2000);
++
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3a8, 0x0810);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3aa, 0x0008);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3ab, 0x0810);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3ad, 0x0008);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3ae, 0x0106);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3b0, 0x0001);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3b1, 0x0106);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3b3, 0x0001);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18c, 0x0001);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18d, 0x0001);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18e, 0x0001);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18f, 0x0001);
++
++      /*da_tx_bias1_b_tx_standby = 5'b10 (dev1eh_reg3aah[12:8])*/
++      reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x3aa);
++      reg_tmp = reg_tmp & ~(0x1f00);
++      reg_tmp = reg_tmp | 0x2 << 8;
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3aa, reg_tmp);
++
++      /*da_tx_bias1_a_tx_standby = 5'b10 (dev1eh_reg3a9h[4:0])*/
++      reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x3a9);
++      reg_tmp = reg_tmp & ~(0x1f);
++      reg_tmp = reg_tmp | 0x2;
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3a9, reg_tmp);
++#endif
++}
++
++void rx_dc_offset(struct gsw_mt753x *gsw, u8 phyaddr)
++{
++    u32 reg_tmp1;
++
++    pr_info("PORT %d RX_DC_OFFSET\n", phyaddr);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x96, 0x8000);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x37, 0x3);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x107, 0x4000);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x171, 0x1e5);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x39, 0x200f);
++    udelay(40);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x39, 0x000f);
++    udelay(40);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x171, 0x65);
++}
++
++void check_rx_dc_offset_pair_a(struct gsw_mt753x *gsw, u8 phyaddr)
++{
++    u32 reg_tmp;
++    u8 reg_val;
++
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x114f);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairA output = %x\n", reg_tmp);
++    udelay(40);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1142);
++    udelay(40);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairA output = %x\n", reg_tmp);
++    if ((reg_tmp & 0x80) != 0)
++        reg_tmp = (~reg_tmp) + 1;
++    if ((reg_tmp & 0xff) >4)
++        pr_info("pairA RX_DC_OFFSET error");
++}
++
++void check_rx_dc_offset_pair_b(struct gsw_mt753x *gsw, u8 phyaddr)
++{
++    u32 reg_tmp;
++    u8 reg_val;
++
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1151);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairB output = %x\n", reg_tmp);
++    udelay(40);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1143);
++    udelay(40);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairB output = %x\n", reg_tmp);
++    if ((reg_tmp & 0x80) != 0)
++        reg_tmp = (~reg_tmp) + 1;
++    if ((reg_tmp & 0xff) >4)
++        pr_info("pairB RX_DC_OFFSET error");
++}
++
++void check_rx_dc_offset_pair_c(struct gsw_mt753x *gsw, u8 phyaddr)
++{
++    u32 reg_tmp;
++    u8 reg_val;
++
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1153);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairC output = %x\n", reg_tmp);
++    udelay(40);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1144);
++    udelay(40);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairC output = %x\n", reg_tmp);
++    if ((reg_tmp & 0x80) != 0)
++        reg_tmp = (~reg_tmp) + 1;
++    if ((reg_tmp & 0xff) >4)
++        pr_info("pairC RX_DC_OFFSET error");
++}
++
++void check_rx_dc_offset_pair_d(struct gsw_mt753x *gsw, u8 phyaddr)
++{
++    u32 reg_tmp;
++    u8 reg_val;
++
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1155);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairD output = %x\n", reg_tmp);
++    udelay(40);
++    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1145);
++    udelay(40);
++    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
++    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairD output = %x\n", reg_tmp);
++    if ((reg_tmp & 0x80) != 0)
++        reg_tmp = (~reg_tmp) + 1;
++    if ((reg_tmp & 0xff) >4)
++        pr_info("pairD RX_DC_OFFSET error");
++}
++
++
++int mt753x_phy_calibration(struct gsw_mt753x *gsw, u8 phyaddr){
++
++      int ret;
++
++      phy_calibration(gsw, phyaddr);
++
++      /*eye pic*/
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0, 0x187);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x1, 0x1c9);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x2, 0x1c6);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3, 0x182);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x4, 0x208);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x5, 0x205);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x6, 0x384);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x7, 0x3cb);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x8, 0x3c4);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x9, 0x30a);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0xa, 0x00b);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0xb, 0x002);
++
++      rx_dc_offset(gsw, phyaddr);
++      check_rx_dc_offset_pair_a(gsw, phyaddr);
++      check_rx_dc_offset_pair_b(gsw, phyaddr);
++      check_rx_dc_offset_pair_c(gsw, phyaddr);
++      check_rx_dc_offset_pair_d(gsw, phyaddr);
++
++      return ret;
++}
+diff --git a/target/linux/generic/files/drivers/net/phy/mtk/mt753x/mt753x_phy.h b/target/linux/generic/files/drivers/net/phy/mtk/mt753x/mt753x_phy.h
+new file mode 100755
+--- /dev/null
++++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.h
+@@ -0,0 +1,145 @@
++/* SPDX-License-Identifier:   GPL-2.0+ */
++/*
++ * Register definitions for MediaTek MT753x Gigabit switches
++ *
++ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
++ *
++ * Author: Weijie Gao <weijie.gao@mediatek.com>
++ */
++
++#ifndef _MT753X_PHY_H_
++#define _MT753X_PHY_H_
++
++#include <linux/bitops.h>
++
++/*phy calibration use*/
++#define DEV_1E                                0x1E
++/*global device 0x1f, always set P0*/
++#define DEV_1F                                0x1F
++
++
++/************IEXT/REXT CAL***************/
++/* bits range: for example BITS(16,23) = 0xFF0000*/
++#define BITS(m, n)   (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
++#define ANACAL_INIT                   0x01
++#define ANACAL_ERROR                  0xFD
++#define ANACAL_SATURATION             0xFE
++#define       ANACAL_FINISH                   0xFF
++#define ANACAL_PAIR_A                 0
++#define ANACAL_PAIR_B                 1
++#define ANACAL_PAIR_C                 2
++#define ANACAL_PAIR_D                 3
++#define DAC_IN_0V                     0x00
++#define DAC_IN_2V                     0xf0
++#define TX_AMP_OFFSET_0MV             0x20
++#define TX_AMP_OFFSET_VALID_BITS      6
++
++#define R0                            0
++#define PHY0                          0
++#define PHY1                          1
++#define PHY2                          2
++#define PHY3                          3
++#define PHY4                          4
++#define ANA_TEST_MODE                 BITS(8, 15)
++#define TST_TCLK_SEL                  BITs(6, 7)
++#define ANA_TEST_VGA_RG                       0x100
++
++#define FORCE_MDI_CROSS_OVER          BITS(3, 4)
++#define T10_TEST_CTL_RG                       0x145
++#define RG_185                                0x185
++#define RG_TX_SLEW                    BIT(0)
++#define ANA_CAL_0                     0xdb
++#define RG_CAL_CKINV                  BIT(12)
++#define RG_ANA_CALEN                  BIT(8)
++#define RG_REXT_CALEN                 BIT(4)
++#define RG_ZCALEN_A                   BIT(0)
++#define ANA_CAL_1                     0xdc
++#define RG_ZCALEN_B                   BIT(12)
++#define RG_ZCALEN_C                   BIT(8)
++#define RG_ZCALEN_D                   BIT(4)
++#define RG_TXVOS_CALEN                        BIT(0)
++#define ANA_CAL_6                     0xe1
++#define RG_CAL_REFSEL                 BIT(4)
++#define RG_CAL_COMP_PWD                       BIT(0)
++#define ANA_CAL_5                     0xe0
++#define RG_REXT_TRIM                  BITs(8, 13)
++#define RG_ZCAL_CTRL                  BITs(0, 5)
++#define RG_17A                                0x17a
++#define AD_CAL_COMP_OUT                       BIT(8)
++#define RG_17B                                0x17b
++#define AD_CAL_CLK                    bit(0)
++#define RG_17C                                0x17c
++#define DA_CALIN_FLAG                 bit(0)
++/************R50 CAL****************************/
++#define RG_174                                0x174
++#define RG_R50OHM_RSEL_TX_A_EN                BIT[15]
++#define CR_R50OHM_RSEL_TX_A           BITS[8:14]
++#define RG_R50OHM_RSEL_TX_B_EN                BIT[7]
++#define CR_R50OHM_RSEL_TX_B           BITS[6:0]
++#define RG_175                                0x175
++#define RG_R50OHM_RSEL_TX_C_EN                BITS[15]
++#define CR_R50OHM_RSEL_TX_C           BITS[8:14]
++#define RG_R50OHM_RSEL_TX_D_EN                BIT[7]
++#define CR_R50OHM_RSEL_TX_D           BITS[0:6]
++/**********TX offset Calibration***************************/
++#define RG_95                         0x96
++#define BYPASS_TX_OFFSET_CAL          BIT(15)
++#define RG_3E                         0x3e
++#define BYPASS_PD_TXVLD_A             BIT(15)
++#define BYPASS_PD_TXVLD_B             BIT(14)
++#define BYPASS_PD_TXVLD_C             BIT(13)
++#define BYPASS_PD_TXVLD_D             BIT(12)
++#define BYPASS_PD_TX_10M              BIT(11)
++#define POWER_DOWN_TXVLD_A            BIT(7)
++#define POWER_DOWN_TXVLD_B            BIT(6)
++#define POWER_DOWN_TXVLD_C            BIT(5)
++#define POWER_DOWN_TXVLD_D            BIT(4)
++#define POWER_DOWN_TX_10M             BIT(3)
++#define RG_DD                         0xdd
++#define RG_TXG_CALEN_A                        BIT(12)
++#define RG_TXG_CALEN_B                        BIT(8)
++#define RG_TXG_CALEN_C                        BIT(4)
++#define RG_TXG_CALEN_D                        BIT(0)
++#define RG_17D                                0x17D
++#define FORCE_DASN_DAC_IN0_A          BIT(15)
++#define DASN_DAC_IN0_A                        BITS(0, 9)
++#define RG_17E                                0x17E
++#define FORCE_DASN_DAC_IN0_B          BIT(15)
++#define DASN_DAC_IN0_B                        BITS(0, 9)
++#define RG_17F                                0x17F
++
++#define FORCE_DASN_DAC_IN0_C          BIT(15)
++#define DASN_DAC_IN0_C                        BITS(0, 9)
++#define RG_180                                0x180
++#define FORCE_DASN_DAC_IN0_D          BIT(15)
++#define DASN_DAC_IN0_D                        BITS(0, 9)
++
++#define RG_181                                0x181
++#define FORCE_DASN_DAC_IN1_A          BIT(15)
++#define DASN_DAC_IN1_A                        BITS(0, 9)
++#define RG_182                                0x182
++#define FORCE_DASN_DAC_IN1_B          BIT(15)
++#define DASN_DAC_IN1_B                        BITS(0, 9)
++#define RG_183                                0x183
++#define FORCE_DASN_DAC_IN1_C          BIT15]
++#define DASN_DAC_IN1_C                        BITS(0, 9)
++#define RG_184                                0x184
++#define FORCE_DASN_DAC_IN1_D          BIT(15)
++#define DASN_DAC_IN1_D                        BITS(0, 9)
++#define RG_172                                0x172
++#define CR_TX_AMP_OFFSET_A            BITS(8, 13)
++#define CR_TX_AMP_OFFSET_B            BITS(0, 5)
++#define RG_173                                0x173
++#define CR_TX_AMP_OFFSET_C            BITS(8, 13)
++#define CR_TX_AMP_OFFSET_D            BITS(0, 5)
++/**********TX Amp Calibration ***************************/
++#define RG_12                         0x12
++#define DA_TX_I2MPB_A_GBE             BITS(10, 15)
++#define RG_17                         0x17
++#define DA_TX_I2MPB_B_GBE             BITS(8, 13)
++#define RG_19                         0x19
++#define DA_TX_I2MPB_C_GBE             BITS(8, 13)
++#define RG_21                         0x21
++#define DA_TX_I2MPB_D_GBE             BITS(8, 13)
++
++#endif /* _MT753X_REGS_H_ */
diff --git a/target/linux/mediatek/patches-4.19/0003-switch-add-mt7531.patch b/target/linux/mediatek/patches-4.19/0003-switch-add-mt7531.patch
new file mode 100644 (file)
index 0000000..65e56e4
--- /dev/null
@@ -0,0 +1,23 @@
+Index: linux-4.19.57/drivers/net/phy/Kconfig
+===================================================================
+--- linux-4.19.57.orig/drivers/net/phy/Kconfig
++++ linux-4.19.57/drivers/net/phy/Kconfig
+@@ -292,6 +292,8 @@ config RTL8367B_PHY
+ endif # RTL8366_SMI
++source "drivers/net/phy/mtk/mt753x/Kconfig"
++
+ comment "MII PHY device drivers"
+ config SFP
+Index: linux-4.19.57/drivers/net/phy/Makefile
+===================================================================
+--- linux-4.19.57.orig/drivers/net/phy/Makefile
++++ linux-4.19.57/drivers/net/phy/Makefile
+@@ -100,3 +100,5 @@ obj-$(CONFIG_STE10XP)              += ste10Xp.o
+ obj-$(CONFIG_TERANETICS_PHY)  += teranetics.o
+ obj-$(CONFIG_VITESSE_PHY)     += vitesse.o
+ obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
++obj-$(CONFIG_MT753X_GSW)        += mtk/mt753x/
++
diff --git a/target/linux/mediatek/patches-4.19/0227-arm-dts-Add-Unielec-U7623-DTS.patch b/target/linux/mediatek/patches-4.19/0227-arm-dts-Add-Unielec-U7623-DTS.patch
new file mode 100644 (file)
index 0000000..d6e6371
--- /dev/null
@@ -0,0 +1,419 @@
+From 004eb24e939b5b31f828333f37fb5cb2a877d6f2 Mon Sep 17 00:00:00 2001
+From: Kristian Evensen <kristian.evensen@gmail.com>
+Date: Sun, 17 Jun 2018 14:41:47 +0200
+Subject: [PATCH] arm: dts: Add Unielec U7623 DTS
+
+---
+ arch/arm/boot/dts/Makefile                         |   1 +
+ .../dts/mt7623a-unielec-u7623-02-emmc-512M.dts     |  18 +
+ .../boot/dts/mt7623a-unielec-u7623-02-emmc.dtsi    | 366 +++++++++++++++++++++
+ 3 files changed, 385 insertions(+)
+ create mode 100644 arch/arm/boot/dts/mt7623a-unielec-u7623-02-emmc-512M.dts
+ create mode 100644 arch/arm/boot/dts/mt7623a-unielec-u7623-02-emmc.dtsi
+
+Index: linux-4.19.57/arch/arm/boot/dts/Makefile
+===================================================================
+--- linux-4.19.57.orig/arch/arm/boot/dts/Makefile
++++ linux-4.19.57/arch/arm/boot/dts/Makefile
+@@ -1193,6 +1193,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
+       mt7623a-rfb-nand.dtb \
+       mt7623n-rfb-emmc.dtb \
+       mt7623n-bananapi-bpi-r2.dtb \
++      mt7623a-unielec-u7623-02-emmc-512M.dtb \
+       mt8127-moose.dtb \
+       mt8135-evbp1.dtb
+ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
+Index: linux-4.19.57/arch/arm/boot/dts/mt7623a-unielec-u7623-02-emmc-512M.dts
+===================================================================
+--- /dev/null
++++ linux-4.19.57/arch/arm/boot/dts/mt7623a-unielec-u7623-02-emmc-512M.dts
+@@ -0,0 +1,18 @@
++/*
++ * Copyright 2018 Kristian Evensen <kristian.evensen@gmail.com>
++ *
++ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++ */
++
++/dts-v1/;
++#include "mt7623a-unielec-u7623-02-emmc.dtsi"
++
++/ {
++      model = "UniElec U7623-02 eMMC (512M RAM)";
++      compatible = "unielec,u7623-02-emmc-512m", "unielec,u7623-02-emmc", "mediatek,mt7623";
++
++      memory@80000000 {
++              device_type = "memory";
++              reg = <0 0x80000000 0 0x20000000>;
++      };
++};
+Index: linux-4.19.57/arch/arm/boot/dts/mt7623a-unielec-u7623-02-emmc.dtsi
+===================================================================
+--- /dev/null
++++ linux-4.19.57/arch/arm/boot/dts/mt7623a-unielec-u7623-02-emmc.dtsi
+@@ -0,0 +1,366 @@
++/*
++ * Copyright 2018 Kristian Evensen <kristian.evensen@gmail.com>
++ *
++ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++ */
++
++#include <dt-bindings/input/input.h>
++#include "mt7623.dtsi"
++#include "mt6323.dtsi"
++
++/ {
++      compatible = "unielec,u7623-02-emmc", "mediatek,mt7623";
++
++      aliases {
++              serial2 = &uart2;
++      };
++
++      chosen {
++              bootargs = "root=/dev/mmcblk0p2 rootfstype=squashfs,f2fs";
++              stdout-path = "serial2:115200n8";
++      };
++
++      cpus {
++              cpu@0 {
++                      proc-supply = <&mt6323_vproc_reg>;
++              };
++
++              cpu@1 {
++                      proc-supply = <&mt6323_vproc_reg>;
++              };
++
++              cpu@2 {
++                      proc-supply = <&mt6323_vproc_reg>;
++              };
++
++              cpu@3 {
++                      proc-supply = <&mt6323_vproc_reg>;
++              };
++      };
++
++      reg_1p8v: regulator-1p8v {
++              compatible = "regulator-fixed";
++              regulator-name = "fixed-1.8V";
++              regulator-min-microvolt = <1800000>;
++              regulator-max-microvolt = <1800000>;
++              regulator-boot-on;
++              regulator-always-on;
++      };
++
++      reg_3p3v: regulator-3p3v {
++              compatible = "regulator-fixed";
++              regulator-name = "fixed-3.3V";
++              regulator-min-microvolt = <3300000>;
++              regulator-max-microvolt = <3300000>;
++              regulator-boot-on;
++              regulator-always-on;
++      };
++
++      reg_5v: regulator-5v {
++              compatible = "regulator-fixed";
++              regulator-name = "fixed-5V";
++              regulator-min-microvolt = <5000000>;
++              regulator-max-microvolt = <5000000>;
++              regulator-boot-on;
++              regulator-always-on;
++      };
++
++      gpio-keys {
++              compatible = "gpio-keys";
++              pinctrl-names = "default";
++              pinctrl-0 = <&key_pins_a>;
++
++              factory {
++                      label = "factory";
++                      linux,code = <KEY_RESTART>;
++                      gpios = <&pio 256 GPIO_ACTIVE_LOW>;
++              };
++      };
++
++      leds {
++              compatible = "gpio-leds";
++              pinctrl-names = "default";
++              pinctrl-0 = <&led_pins_unielec>;
++
++              led3 {
++                      label = "u7623-01:green:led3";
++                      gpios = <&pio 14 GPIO_ACTIVE_LOW>;
++                      default-state = "off";
++              };
++
++              led4 {
++                      label = "u7623-01:green:led4";
++                      gpios = <&pio 15 GPIO_ACTIVE_LOW>;
++                      default-state = "off";
++              };
++      };
++
++      mt7530: switch@0 {
++              compatible = "mediatek,mt7530";
++              #address-cells = <1>;
++              #size-cells = <0>;
++      };
++};
++
++&crypto {
++      status = "okay";
++};
++
++&eth {
++      status = "okay";
++
++      gmac0: mac@0 {
++              compatible = "mediatek,eth-mac";
++              reg = <0>;
++              phy-mode = "trgmii";
++
++              fixed-link {
++                      speed = <1000>;
++                      full-duplex;
++                      pause;
++              };
++      };
++
++      mdio: mdio-bus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              phy5: ethernet-phy@5 {
++                      reg = <5>;
++                      phy-mode = "rgmii-rxid";
++              };
++      };
++};
++
++&mt7530 {
++      compatible = "mediatek,mt7530";
++      #address-cells = <1>;
++      #size-cells = <0>;
++      reg = <0>;
++      pinctrl-names = "default";
++      mediatek,mcm;
++      resets = <&ethsys 2>;
++      reset-names = "mcm";
++      core-supply = <&mt6323_vpa_reg>;
++      io-supply = <&mt6323_vemc3v3_reg>;
++
++      dsa,mii-bus = <&mdio>;
++
++      ports {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              reg = <0>;
++
++              port@0 {
++                      reg = <0>;
++                      label = "lan0";
++                      cpu = <&cpu_port0>;
++              };
++
++              port@1 {
++                      reg = <1>;
++                      label = "lan1";
++                      cpu = <&cpu_port0>;
++              };
++
++              port@2 {
++                      reg = <2>;
++                      label = "lan2";
++                      cpu = <&cpu_port0>;
++              };
++
++              port@3 {
++                      reg = <3>;
++                      label = "lan3";
++                      cpu = <&cpu_port0>;
++              };
++
++              port@4 {
++                      reg = <4>;
++                      label = "wan";
++                      cpu = <&cpu_port0>;
++              };
++
++              cpu_port0: port@6 {
++                      reg = <6>;
++                      label = "cpu";
++                      ethernet = <&gmac0>;
++                      phy-mode = "trgmii";
++
++                      fixed-link {
++                              speed = <1000>;
++                              full-duplex;
++                      };
++              };
++      };
++};
++
++&mmc0 {
++      pinctrl-names = "default", "state_uhs";
++      pinctrl-0 = <&mmc0_pins_default>;
++      pinctrl-1 = <&mmc0_pins_uhs>;
++      status = "okay";
++      bus-width = <8>;
++      max-frequency = <50000000>;
++      cap-mmc-highspeed;
++      vmmc-supply = <&reg_3p3v>;
++      vqmmc-supply = <&reg_1p8v>;
++      non-removable;
++};
++
++&pio {
++      key_pins_a: keys-alt {
++              pins-keys {
++                      pinmux = <MT7623_PIN_256_GPIO256_FUNC_GPIO256>,
++                               <MT7623_PIN_257_GPIO257_FUNC_GPIO257>;
++                      input-enable;
++              };
++      };
++
++      led_pins_unielec: leds-unielec {
++              pins-leds {
++                      pinmux = <MT7623_PIN_14_GPIO14_FUNC_GPIO14>,
++                               <MT7623_PIN_15_GPIO15_FUNC_GPIO15>;
++              };
++      };
++
++      mmc0_pins_default: mmc0default {
++              pins_cmd_dat {
++                      pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7>,
++                               <MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6>,
++                               <MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5>,
++                               <MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4>,
++                               <MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3>,
++                               <MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2>,
++                               <MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1>,
++                               <MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
++                               <MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
++                      input-enable;
++                      bias-pull-up;
++              };
++
++              pins_clk {
++                      pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
++                      bias-pull-down;
++              };
++
++              pins_rst {
++                      pinmux = <MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB>;
++                      bias-pull-up;
++              };
++      };
++
++      mmc0_pins_uhs: mmc0 {
++              pins_cmd_dat {
++                      pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7>,
++                               <MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6>,
++                               <MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5>,
++                               <MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4>,
++                               <MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3>,
++                               <MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2>,
++                               <MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1>,
++                               <MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
++                               <MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
++                      input-enable;
++                      drive-strength = <MTK_DRIVE_2mA>;
++                      bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
++              };
++
++              pins_clk {
++                      pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
++                      drive-strength = <MTK_DRIVE_2mA>;
++                      bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
++              };
++
++              pins_rst {
++                      pinmux = <MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB>;
++                      bias-pull-up;
++              };
++      };
++
++      pwm_pins_a: pwm@0 {
++              pins_pwm {
++                      pinmux = <MT7623_PIN_203_PWM0_FUNC_PWM0>,
++                               <MT7623_PIN_204_PWM1_FUNC_PWM1>,
++                               <MT7623_PIN_205_PWM2_FUNC_PWM2>,
++                               <MT7623_PIN_206_PWM3_FUNC_PWM3>,
++                               <MT7623_PIN_207_PWM4_FUNC_PWM4>;
++              };
++      };
++
++      uart2_pins_b: uart@2 {
++              pins_dat {
++                      pinmux = <MT7623_PIN_200_URXD2_FUNC_URXD2>,
++                               <MT7623_PIN_201_UTXD2_FUNC_UTXD2>;
++              };
++      };
++
++      pcie_default: pcie_pin_default {
++              pins_cmd_dat {
++                      pinmux = <MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N>,
++                               <MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N>;
++                      bias-disable;
++              };
++      };
++};
++
++&pwm {
++      pinctrl-names = "default";
++      pinctrl-0 = <&pwm_pins_a>;
++      status = "okay";
++};
++
++&pwrap {
++      mt6323 {
++              mt6323led: led {
++                      compatible = "mediatek,mt6323-led";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      led@0 {
++                              reg = <0>;
++                              label = "led0";
++                              default-state = "off";
++                      };
++              };
++      };
++};
++
++&uart2 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart2_pins_b>;
++      status = "okay";
++};
++
++&usb1 {
++      vusb33-supply = <&reg_3p3v>;
++      vbus-supply = <&reg_3p3v>;
++      status = "okay";
++};
++
++&u3phy1 {
++      status = "okay";
++};
++
++&u3phy2 {
++      status = "okay";
++      mediatek,phy-switch = <&hifsys>;
++};
++
++&pcie {
++      pinctrl-names = "default";
++      pinctrl-0 = <&pcie_default>;
++      status = "okay";
++
++      pcie@1,0 {
++              status = "okay";
++      };
++
++      pcie@2,0 {
++              status = "okay";
++      };
++};
++
++&pcie1_phy {
++      status = "okay";
++};
++
diff --git a/target/linux/mediatek/patches-4.19/0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch b/target/linux/mediatek/patches-4.19/0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch
new file mode 100755 (executable)
index 0000000..fcfb3dc
--- /dev/null
@@ -0,0 +1,48 @@
+From a2479dc254ebe31c84fbcfda73f35e2321576494 Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Tue, 19 Mar 2019 13:57:38 +0800
+Subject: [PATCH 1/6] mtd: mtk ecc: move mtk ecc header file to include/mtd
+
+Change-Id: I8dc1d30e21b40d68ef5efd9587012f82970156a5
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ drivers/mtd/nand/raw/mtk_ecc.c                        | 3 +--
+ drivers/mtd/nand/raw/mtk_nand.c                       | 2 +-
+ {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h | 0
+ 3 files changed, 2 insertions(+), 3 deletions(-)
+ rename {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h (100%)
+
+diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
+index 6432bd70c3b3..32e9784b0d4f 100644
+--- a/drivers/mtd/nand/raw/mtk_ecc.c
++++ b/drivers/mtd/nand/raw/mtk_ecc.c
+@@ -23,8 +23,7 @@
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/mutex.h>
+-
+-#include "mtk_ecc.h"
++#include <linux/mtd/mtk_ecc.h>
+ #define ECC_IDLE_MASK         BIT(0)
+ #define ECC_IRQ_EN            BIT(0)
+diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
+index 57b5ed1699e3..e201f1417fba 100644
+--- a/drivers/mtd/nand/raw/mtk_nand.c
++++ b/drivers/mtd/nand/raw/mtk_nand.c
+@@ -25,7 +25,7 @@
+ #include <linux/iopoll.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+-#include "mtk_ecc.h"
++#include <linux/mtd/mtk_ecc.h>
+ /* NAND controller register definition */
+ #define NFI_CNFG              (0x00)
+diff --git a/drivers/mtd/nand/raw/mtk_ecc.h b/include/linux/mtd/mtk_ecc.h
+similarity index 100%
+rename from drivers/mtd/nand/raw/mtk_ecc.h
+rename to include/linux/mtd/mtk_ecc.h
+-- 
+2.20.1
+
diff --git a/target/linux/mediatek/patches-4.19/0303-mtd-spinand-disable-on-die-ECC.patch b/target/linux/mediatek/patches-4.19/0303-mtd-spinand-disable-on-die-ECC.patch
new file mode 100755 (executable)
index 0000000..eeb096a
--- /dev/null
@@ -0,0 +1,36 @@
+From b341f120cfc9ca1dfd48364b7f36ac2c1fbdea43 Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Wed, 3 Apr 2019 16:30:01 +0800
+Subject: [PATCH 3/6] mtd: spinand: disable on-die ECC
+
+Change-Id: I9745adaed5295202fabbe8ab8947885c57a5b847
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ drivers/mtd/nand/spi/core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
+index 30f83649c481..3b6eac391350 100644
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -554,7 +554,7 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
+       int ret = 0;
+       if (ops->mode != MTD_OPS_RAW && spinand->eccinfo.ooblayout)
+-              enable_ecc = true;
++              enable_ecc = false;
+       mutex_lock(&spinand->lock);
+@@ -602,7 +602,7 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to,
+       int ret = 0;
+       if (ops->mode != MTD_OPS_RAW && mtd->ooblayout)
+-              enable_ecc = true;
++              enable_ecc = false;
+       mutex_lock(&spinand->lock);
+-- 
+2.20.1
+
diff --git a/target/linux/mediatek/patches-4.19/0304-dt-bindings-ARM-MediaTek-Document-devicetree-binding.patch b/target/linux/mediatek/patches-4.19/0304-dt-bindings-ARM-MediaTek-Document-devicetree-binding.patch
new file mode 100755 (executable)
index 0000000..a605fd1
--- /dev/null
@@ -0,0 +1,66 @@
+From 28ec0b7e48bb27435a8b3134019b88628faf497f Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Tue, 11 Dec 2018 17:37:28 +0800
+Subject: [PATCH 4/6] dt-bindings: ARM: MediaTek: Document devicetree bindings
+ for SPI NAND interface
+
+Change-Id: I9ece142055ae27100da95826fb3ea1960c2994e6
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ .../devicetree/bindings/spi/spi-mtk-snfi.txt  | 44 +++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-mtk-snfi.txt
+
+diff --git a/Documentation/devicetree/bindings/spi/spi-mtk-snfi.txt b/Documentation/devicetree/bindings/spi/spi-mtk-snfi.txt
+new file mode 100644
+index 000000000000..a09c476c5289
+--- /dev/null
++++ b/Documentation/devicetree/bindings/spi/spi-mtk-snfi.txt
+@@ -0,0 +1,44 @@
++MediaTek SoCs SPI NAND FLASH interface (SNFI) DT binding
++
++This file documents the device tree bindings for MTK SoCs SPI NAND controller.
++Note that Parallel Nand and SPI NAND is alternative on MTK SoCs.
++
++Required properties:
++- compatible:         should be "mediatek,mt7622-snfi"
++- reg:                        base physical address and size of SNFI.
++- interrupts:         interrupts of SNFI.
++- clocks:             SNFI required clocks.
++- clock-names:                SNFI clocks internal names.
++- #address-cells:     NAND chip index, should be 1.
++- #size-cells:                Should be 0.
++
++Example:
++      snfi: spi@1100d000 {
++              compatible = "mediatek,mt7622-snfi";
++              reg = <0 0x1100d000 0 0x1000>;
++              interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
++              clocks = <&pericfg CLK_PERI_NFI_PD>,
++                       <&pericfg CLK_PERI_SNFI_PD>;
++              clock-names = "nfi_clk", "spi_clk";
++              ecc-engine = <&bch>;
++              #address-cells = <1>;
++              #size-cells = <0>;
++      };
++
++Subnodes properties:
++- Should use spi-nand framework, see Documentation/devicetree/bindings/mtd/spi-nand.txt
++
++Example:
++&snfi {
++      pinctrl-names = "default";
++      pinctrl-0 = <&serial_nand_pins>;
++      status = "okay";
++
++      spi_nand@0 {
++              #address-cells = <1>;
++              #size-cells = <1>;
++              compatible = "spi-nand";
++              spi-max-frequency = <104000000>;
++              reg = <0>;
++      };
++};
+-- 
+2.20.1
+
diff --git a/target/linux/mediatek/patches-4.19/0306-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch b/target/linux/mediatek/patches-4.19/0306-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch
new file mode 100644 (file)
index 0000000..c307abe
--- /dev/null
@@ -0,0 +1,1235 @@
+From 1ecb38eabd90efe93957d0a822a167560c39308a Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Wed, 20 Mar 2019 16:19:51 +0800
+Subject: [PATCH 6/6] spi: spi-mem: MediaTek: Add SPI NAND Flash interface
+ driver for MediaTek MT7622
+
+Change-Id: I3e78406bb9b46b0049d3988a5c71c7069e4f809c
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ drivers/spi/Kconfig        |    9 +
+ drivers/spi/Makefile       |    1 +
+ drivers/spi/spi-mtk-snfi.c | 1183 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1193 insertions(+)
+ create mode 100644 drivers/spi/spi-mtk-snfi.c
+
+Index: linux-4.19.48/drivers/spi/spi-mtk-snfi.c
+===================================================================
+--- /dev/null
++++ linux-4.19.48/drivers/spi/spi-mtk-snfi.c
+@@ -0,0 +1,1183 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Driver for MediaTek SPI Nand interface
++ *
++ * Copyright (C) 2018 MediaTek Inc.
++ * Authors:   Xiangsheng Hou  <xiangsheng.hou@mediatek.com>
++ *
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/iopoll.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/mtk_ecc.h>
++#include <linux/mtd/spinand.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/spi-mem.h>
++
++/* NAND controller register definition */
++/* NFI control */
++#define NFI_CNFG              0x00
++#define               CNFG_DMA                BIT(0)
++#define               CNFG_READ_EN            BIT(1)
++#define               CNFG_DMA_BURST_EN       BIT(2)
++#define               CNFG_BYTE_RW            BIT(6)
++#define               CNFG_HW_ECC_EN          BIT(8)
++#define               CNFG_AUTO_FMT_EN        BIT(9)
++#define               CNFG_OP_PROGRAM         (3UL << 12)
++#define               CNFG_OP_CUST            (6UL << 12)
++#define NFI_PAGEFMT           0x04
++#define               PAGEFMT_512             0
++#define               PAGEFMT_2K              1
++#define               PAGEFMT_4K              2
++#define               PAGEFMT_FDM_SHIFT       8
++#define               PAGEFMT_FDM_ECC_SHIFT   12
++#define NFI_CON                       0x08
++#define               CON_FIFO_FLUSH          BIT(0)
++#define               CON_NFI_RST             BIT(1)
++#define               CON_BRD                 BIT(8)
++#define               CON_BWR                 BIT(9)
++#define               CON_SEC_SHIFT           12
++#define NFI_INTR_EN           0x10
++#define               INTR_AHB_DONE_EN        BIT(6)
++#define NFI_INTR_STA          0x14
++#define NFI_CMD                       0x20
++#define NFI_STA                       0x60
++#define               STA_EMP_PAGE            BIT(12)
++#define               NAND_FSM_MASK           (0x1f << 24)
++#define               NFI_FSM_MASK            (0xf << 16)
++#define NFI_ADDRCNTR          0x70
++#define               CNTR_MASK               GENMASK(16, 12)
++#define               ADDRCNTR_SEC_SHIFT      12
++#define               ADDRCNTR_SEC(val) \
++              (((val) & CNTR_MASK) >> ADDRCNTR_SEC_SHIFT)
++#define NFI_STRADDR           0x80
++#define NFI_BYTELEN           0x84
++#define NFI_CSEL              0x90
++#define NFI_FDML(x)           (0xa0 + (x) * sizeof(u32) * 2)
++#define NFI_FDMM(x)           (0xa4 + (x) * sizeof(u32) * 2)
++#define NFI_MASTER_STA                0x224
++#define               MASTER_STA_MASK         0x0fff
++/* NFI_SPI control */
++#define SNFI_MAC_OUTL         0x504
++#define SNFI_MAC_INL          0x508
++#define SNFI_RD_CTL2          0x510
++#define               RD_CMD_MASK             0x00ff
++#define               RD_DUMMY_SHIFT          8
++#define SNFI_RD_CTL3          0x514
++#define               RD_ADDR_MASK            0xffff
++#define SNFI_MISC_CTL         0x538
++#define               RD_MODE_X2              BIT(16)
++#define               RD_MODE_X4              (2UL << 16)
++#define               RD_QDUAL_IO             (4UL << 16)
++#define               RD_MODE_MASK            (7UL << 16)
++#define               RD_CUSTOM_EN            BIT(6)
++#define               WR_CUSTOM_EN            BIT(7)
++#define               WR_X4_EN                BIT(20)
++#define               SW_RST                  BIT(28)
++#define SNFI_MISC_CTL2                0x53c
++#define               WR_LEN_SHIFT            16
++#define SNFI_PG_CTL1          0x524
++#define               WR_LOAD_CMD_SHIFT       8
++#define SNFI_PG_CTL2          0x528
++#define               WR_LOAD_ADDR_MASK       0xffff
++#define SNFI_MAC_CTL          0x500
++#define               MAC_WIP                 BIT(0)
++#define               MAC_WIP_READY           BIT(1)
++#define               MAC_TRIG                BIT(2)
++#define               MAC_EN                  BIT(3)
++#define               MAC_SIO_SEL             BIT(4)
++#define SNFI_STA_CTL1         0x550
++#define               SPI_STATE_IDLE          0xf
++#define SNFI_CNFG             0x55c
++#define               SNFI_MODE_EN            BIT(0)
++#define SNFI_GPRAM_DATA               0x800
++#define               SNFI_GPRAM_MAX_LEN      16
++
++/* Dummy command trigger NFI to spi mode */
++#define NAND_CMD_DUMMYREAD    0x00
++#define NAND_CMD_DUMMYPROG    0x80
++
++#define MTK_TIMEOUT           500000
++#define MTK_RESET_TIMEOUT     1000000
++#define MTK_SNFC_MIN_SPARE    16
++#define KB(x)                 ((x) * 1024UL)
++
++/*
++ * supported spare size of each IP.
++ * order should be the same with the spare size bitfiled defination of
++ * register NFI_PAGEFMT.
++ */
++static const u8 spare_size_mt7622[] = {
++      16, 26, 27, 28
++};
++
++struct mtk_snfi_caps {
++      const u8 *spare_size;
++      u8 num_spare_size;
++      u32 nand_sec_size;
++      u8 nand_fdm_size;
++      u8 nand_fdm_ecc_size;
++      u8 ecc_parity_bits;
++      u8 pageformat_spare_shift;
++      u8 bad_mark_swap;
++};
++
++struct mtk_snfi_bad_mark_ctl {
++      void (*bm_swap)(struct spi_mem *mem, u8 *buf, int raw);
++      u32 sec;
++      u32 pos;
++};
++
++struct mtk_snfi_nand_chip {
++      struct mtk_snfi_bad_mark_ctl bad_mark;
++      u32 spare_per_sector;
++};
++
++struct mtk_snfi_clk {
++      struct clk *nfi_clk;
++      struct clk *spi_clk;
++};
++
++struct mtk_snfi {
++      const struct mtk_snfi_caps *caps;
++      struct mtk_snfi_nand_chip snfi_nand;
++      struct mtk_snfi_clk clk;
++      struct mtk_ecc_config ecc_cfg;
++      struct mtk_ecc *ecc;
++      struct completion done;
++      struct device *dev;
++
++      void __iomem *regs;
++
++      u8 *buffer;
++};
++
++static inline u8 *oob_ptr(struct spi_mem *mem, int i)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u8 *poi;
++
++      /* map the sector's FDM data to free oob:
++       * the beginning of the oob area stores the FDM data of bad mark
++       */
++
++      if (i < snfi_nand->bad_mark.sec)
++              poi = spinand->oobbuf + (i + 1) * snfi->caps->nand_fdm_size;
++      else if (i == snfi_nand->bad_mark.sec)
++              poi = spinand->oobbuf;
++      else
++              poi = spinand->oobbuf + i * snfi->caps->nand_fdm_size;
++
++      return poi;
++}
++
++static inline int mtk_data_len(struct spi_mem *mem)
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++
++      return snfi->caps->nand_sec_size + snfi_nand->spare_per_sector;
++}
++
++static inline u8 *mtk_oob_ptr(struct spi_mem *mem,
++                            const u8 *p, int i)
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++
++      return (u8 *)p + i * mtk_data_len(mem) + snfi->caps->nand_sec_size;
++}
++
++static void mtk_snfi_bad_mark_swap(struct spi_mem *mem,
++                                 u8 *buf, int raw)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u32 bad_pos = snfi_nand->bad_mark.pos;
++
++      if (raw)
++              bad_pos += snfi_nand->bad_mark.sec * mtk_data_len(mem);
++      else
++              bad_pos += snfi_nand->bad_mark.sec * snfi->caps->nand_sec_size;
++
++      swap(spinand->oobbuf[0], buf[bad_pos]);
++}
++
++static void mtk_snfi_set_bad_mark_ctl(struct mtk_snfi_bad_mark_ctl *bm_ctl,
++                                    struct spi_mem *mem)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++
++      bm_ctl->bm_swap = mtk_snfi_bad_mark_swap;
++      bm_ctl->sec = mtd->writesize / mtk_data_len(mem);
++      bm_ctl->pos = mtd->writesize % mtk_data_len(mem);
++}
++
++static void mtk_snfi_mac_enable(struct mtk_snfi *snfi)
++{
++      u32 mac;
++
++      mac = readl(snfi->regs + SNFI_MAC_CTL);
++      mac &= ~MAC_SIO_SEL;
++      mac |= MAC_EN;
++
++      writel(mac, snfi->regs + SNFI_MAC_CTL);
++}
++
++static int mtk_snfi_mac_trigger(struct mtk_snfi *snfi)
++{
++      u32 mac, reg;
++      int ret = 0;
++
++      mac = readl(snfi->regs + SNFI_MAC_CTL);
++      mac |= MAC_TRIG;
++      writel(mac, snfi->regs + SNFI_MAC_CTL);
++
++      ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, reg,
++                                      reg & MAC_WIP_READY, 10,
++                                      MTK_TIMEOUT);
++      if (ret < 0) {
++              dev_err(snfi->dev, "polling wip ready for read timeout\n");
++              return -EIO;
++      }
++
++      ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, reg,
++                                      !(reg & MAC_WIP), 10,
++                                      MTK_TIMEOUT);
++      if (ret < 0) {
++              dev_err(snfi->dev, "polling flash update timeout\n");
++              return -EIO;
++      }
++
++      return ret;
++}
++
++static void mtk_snfi_mac_leave(struct mtk_snfi *snfi)
++{
++      u32 mac;
++
++      mac = readl(snfi->regs + SNFI_MAC_CTL);
++      mac &= ~(MAC_TRIG | MAC_EN | MAC_SIO_SEL);
++      writel(mac, snfi->regs + SNFI_MAC_CTL);
++}
++
++static int mtk_snfi_mac_op(struct mtk_snfi *snfi)
++{
++      int ret = 0;
++
++      mtk_snfi_mac_enable(snfi);
++
++      ret = mtk_snfi_mac_trigger(snfi);
++      if (ret)
++              return ret;
++
++      mtk_snfi_mac_leave(snfi);
++
++      return ret;
++}
++
++static irqreturn_t mtk_snfi_irq(int irq, void *id)
++{
++      struct mtk_snfi *snfi = id;
++      u16 sta, ien;
++
++      sta = readw(snfi->regs + NFI_INTR_STA);
++      ien = readw(snfi->regs + NFI_INTR_EN);
++
++      if (!(sta & ien))
++              return IRQ_NONE;
++
++      writew(~sta & ien, snfi->regs + NFI_INTR_EN);
++      complete(&snfi->done);
++
++      return IRQ_HANDLED;
++}
++
++static int mtk_snfi_enable_clk(struct device *dev, struct mtk_snfi_clk *clk)
++{
++      int ret;
++
++      ret = clk_prepare_enable(clk->nfi_clk);
++      if (ret) {
++              dev_err(dev, "failed to enable nfi clk\n");
++              return ret;
++      }
++
++      ret = clk_prepare_enable(clk->spi_clk);
++      if (ret) {
++              dev_err(dev, "failed to enable spi clk\n");
++              clk_disable_unprepare(clk->nfi_clk);
++              return ret;
++      }
++
++      return 0;
++}
++
++static void mtk_snfi_disable_clk(struct mtk_snfi_clk *clk)
++{
++      clk_disable_unprepare(clk->nfi_clk);
++      clk_disable_unprepare(clk->spi_clk);
++}
++
++static int mtk_snfi_reset(struct mtk_snfi *snfi)
++{
++      u32 val;
++      int ret;
++
++      /* SW reset controller */
++      val = readl(snfi->regs + SNFI_MISC_CTL) | SW_RST;
++      writel(val, snfi->regs + SNFI_MISC_CTL);
++
++      ret = readw_poll_timeout(snfi->regs + SNFI_STA_CTL1, val,
++                               !(val & SPI_STATE_IDLE), 50,
++                               MTK_RESET_TIMEOUT);
++      if (ret) {
++              dev_warn(snfi->dev, "spi state active in reset [0x%x] = 0x%x\n",
++                       SNFI_STA_CTL1, val);
++              return ret;
++      }
++
++      val = readl(snfi->regs + SNFI_MISC_CTL);
++      val &= ~SW_RST;
++      writel(val, snfi->regs + SNFI_MISC_CTL);
++
++      /* reset all registers and force the NFI master to terminate */
++      writew(CON_FIFO_FLUSH | CON_NFI_RST, snfi->regs + NFI_CON);
++      ret = readw_poll_timeout(snfi->regs + NFI_STA, val,
++                               !(val & (NFI_FSM_MASK | NAND_FSM_MASK)), 50,
++                               MTK_RESET_TIMEOUT);
++      if (ret) {
++              dev_warn(snfi->dev, "nfi active in reset [0x%x] = 0x%x\n",
++                       NFI_STA, val);
++              return ret;
++      }
++
++      return 0;
++}
++
++static int mtk_snfi_set_spare_per_sector(struct spinand_device *spinand,
++                                       const struct mtk_snfi_caps *caps,
++                                       u32 *sps)
++{
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      const u8 *spare = caps->spare_size;
++      u32 sectors, i, closest_spare = 0;
++
++      sectors = mtd->writesize / caps->nand_sec_size;
++      *sps = mtd->oobsize / sectors;
++
++      if (*sps < MTK_SNFC_MIN_SPARE)
++              return -EINVAL;
++
++      for (i = 0; i < caps->num_spare_size; i++) {
++              if (*sps >= spare[i] && spare[i] >= spare[closest_spare]) {
++                      closest_spare = i;
++                      if (*sps == spare[i])
++                              break;
++              }
++      }
++
++      *sps = spare[closest_spare];
++
++      return 0;
++}
++
++static void mtk_snfi_read_fdm_data(struct spi_mem *mem,
++                                 u32 sectors)
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      const struct mtk_snfi_caps *caps = snfi->caps;
++      u32 vall, valm;
++      int i, j;
++      u8 *oobptr;
++
++      for (i = 0; i < sectors; i++) {
++              oobptr = oob_ptr(mem, i);
++              vall = readl(snfi->regs + NFI_FDML(i));
++              valm = readl(snfi->regs + NFI_FDMM(i));
++
++              for (j = 0; j < caps->nand_fdm_size; j++)
++                      oobptr[j] = (j >= 4 ? valm : vall) >> ((j % 4) * 8);
++      }
++}
++
++static void mtk_snfi_write_fdm_data(struct spi_mem *mem,
++                                  u32 sectors)
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      const struct mtk_snfi_caps *caps = snfi->caps;
++      u32 vall, valm;
++      int i, j;
++      u8 *oobptr;
++
++      for (i = 0; i < sectors; i++) {
++              oobptr = oob_ptr(mem, i);
++              vall = 0;
++              valm = 0;
++              for (j = 0; j < 8; j++) {
++                      if (j < 4)
++                              vall |= (j < caps->nand_fdm_size ? oobptr[j] :
++                                       0xff) << (j * 8);
++                      else
++                              valm |= (j < caps->nand_fdm_size ? oobptr[j] :
++                                       0xff) << ((j - 4) * 8);
++              }
++              writel(vall, snfi->regs + NFI_FDML(i));
++              writel(valm, snfi->regs + NFI_FDMM(i));
++      }
++}
++
++static int mtk_snfi_update_ecc_stats(struct spi_mem *mem,
++                                   u8 *buf, u32 sectors)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct mtk_ecc_stats stats;
++      int rc, i;
++
++      rc = readl(snfi->regs + NFI_STA) & STA_EMP_PAGE;
++      if (rc) {
++              memset(buf, 0xff, sectors * snfi->caps->nand_sec_size);
++              for (i = 0; i < sectors; i++)
++                      memset(spinand->oobbuf, 0xff,
++                             snfi->caps->nand_fdm_size);
++              return 0;
++      }
++
++      mtk_ecc_get_stats(snfi->ecc, &stats, sectors);
++      mtd->ecc_stats.corrected += stats.corrected;
++      mtd->ecc_stats.failed += stats.failed;
++
++      return 0;
++}
++
++static int mtk_snfi_hw_runtime_config(struct spi_mem *mem)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      struct nand_device *nand = mtd_to_nanddev(mtd);
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      const struct mtk_snfi_caps *caps = snfi->caps;
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u32 fmt, spare, i = 0;
++      int ret;
++
++      ret = mtk_snfi_set_spare_per_sector(spinand, caps, &spare);
++      if (ret)
++              return ret;
++
++      /* calculate usable oob bytes for ecc parity data */
++      snfi_nand->spare_per_sector = spare;
++      spare -= caps->nand_fdm_size;
++
++      nand->memorg.oobsize = snfi_nand->spare_per_sector
++              * (mtd->writesize / caps->nand_sec_size);
++      mtd->oobsize = nanddev_per_page_oobsize(nand);
++
++      snfi->ecc_cfg.strength = (spare << 3) / caps->ecc_parity_bits;
++      mtk_ecc_adjust_strength(snfi->ecc, &snfi->ecc_cfg.strength);
++
++      switch (mtd->writesize) {
++      case 512:
++              fmt = PAGEFMT_512;
++              break;
++      case KB(2):
++              fmt = PAGEFMT_2K;
++              break;
++      case KB(4):
++              fmt = PAGEFMT_4K;
++              break;
++      default:
++              dev_err(snfi->dev, "invalid page len: %d\n", mtd->writesize);
++              return -EINVAL;
++      }
++
++      /* Setup PageFormat */
++      while (caps->spare_size[i] != snfi_nand->spare_per_sector) {
++              i++;
++              if (i == (caps->num_spare_size - 1)) {
++                      dev_err(snfi->dev, "invalid spare size %d\n",
++                              snfi_nand->spare_per_sector);
++                      return -EINVAL;
++              }
++      }
++
++      fmt |= i << caps->pageformat_spare_shift;
++      fmt |= caps->nand_fdm_size << PAGEFMT_FDM_SHIFT;
++      fmt |= caps->nand_fdm_ecc_size << PAGEFMT_FDM_ECC_SHIFT;
++      writel(fmt, snfi->regs + NFI_PAGEFMT);
++
++      snfi->ecc_cfg.len = caps->nand_sec_size + caps->nand_fdm_ecc_size;
++
++      mtk_snfi_set_bad_mark_ctl(&snfi_nand->bad_mark, mem);
++
++      return 0;
++}
++
++static int mtk_snfi_read_from_cache(struct spi_mem *mem,
++                                  const struct spi_mem_op *op, int oob_on)
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      u32 sectors = mtd->writesize / snfi->caps->nand_sec_size;
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u32 reg, len, col_addr = 0;
++      int dummy_cycle, ret;
++      dma_addr_t dma_addr;
++
++      len = sectors * (snfi->caps->nand_sec_size
++            + snfi_nand->spare_per_sector);
++
++      dma_addr = dma_map_single(snfi->dev, snfi->buffer,
++                                len, DMA_FROM_DEVICE);
++      ret = dma_mapping_error(snfi->dev, dma_addr);
++      if (ret) {
++              dev_err(snfi->dev, "dma mapping error\n");
++              return -EINVAL;
++      }
++
++      /* set Read cache command and dummy cycle */
++      dummy_cycle = (op->dummy.nbytes << 3) >> (ffs(op->dummy.buswidth) - 1);
++      reg = ((op->cmd.opcode & RD_CMD_MASK) |
++             (dummy_cycle << RD_DUMMY_SHIFT));
++      writel(reg, snfi->regs + SNFI_RD_CTL2);
++
++      writel((col_addr & RD_ADDR_MASK), snfi->regs + SNFI_RD_CTL3);
++
++      reg = readl(snfi->regs + SNFI_MISC_CTL);
++      reg |= RD_CUSTOM_EN;
++      reg &= ~(RD_MODE_MASK | WR_X4_EN);
++
++      /* set data and addr buswidth */
++      if (op->data.buswidth == 4)
++              reg |= RD_MODE_X4;
++      else if (op->data.buswidth == 2)
++              reg |= RD_MODE_X2;
++
++      if (op->addr.buswidth == 4 || op->addr.buswidth == 2)
++              reg |= RD_QDUAL_IO;
++      writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++      writel(len, snfi->regs + SNFI_MISC_CTL2);
++      writew(sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON);
++      reg = readw(snfi->regs + NFI_CNFG);
++      reg |= CNFG_READ_EN | CNFG_DMA_BURST_EN | CNFG_DMA | CNFG_OP_CUST;
++
++      if (!oob_on) {
++              reg |= CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN;
++              writew(reg, snfi->regs + NFI_CNFG);
++
++              snfi->ecc_cfg.mode = ECC_NFI_MODE;
++              snfi->ecc_cfg.sectors = sectors;
++              snfi->ecc_cfg.op = ECC_DECODE;
++              ret = mtk_ecc_enable(snfi->ecc, &snfi->ecc_cfg);
++              if (ret) {
++                      dev_err(snfi->dev, "ecc enable failed\n");
++                      /* clear NFI_CNFG */
++                      reg &= ~(CNFG_READ_EN | CNFG_DMA_BURST_EN | CNFG_DMA |
++                              CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN);
++                      writew(reg, snfi->regs + NFI_CNFG);
++                      goto out;
++              }
++      } else {
++              writew(reg, snfi->regs + NFI_CNFG);
++      }
++
++      writel(lower_32_bits(dma_addr), snfi->regs + NFI_STRADDR);
++      readw(snfi->regs + NFI_INTR_STA);
++      writew(INTR_AHB_DONE_EN, snfi->regs + NFI_INTR_EN);
++
++      init_completion(&snfi->done);
++
++      /* set dummy command to trigger NFI enter SPI mode */
++      writew(NAND_CMD_DUMMYREAD, snfi->regs + NFI_CMD);
++      reg = readl(snfi->regs + NFI_CON) | CON_BRD;
++      writew(reg, snfi->regs + NFI_CON);
++
++      ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500));
++      if (!ret) {
++              dev_err(snfi->dev, "read ahb done timeout\n");
++              writew(0, snfi->regs + NFI_INTR_EN);
++              ret = -ETIMEDOUT;
++              goto out;
++      }
++
++      ret = readl_poll_timeout_atomic(snfi->regs + NFI_BYTELEN, reg,
++                                      ADDRCNTR_SEC(reg) >= sectors, 10,
++                                      MTK_TIMEOUT);
++      if (ret < 0) {
++              dev_err(snfi->dev, "polling read byte len timeout\n");
++              ret = -EIO;
++      } else {
++              if (!oob_on) {
++                      ret = mtk_ecc_wait_done(snfi->ecc, ECC_DECODE);
++                      if (ret) {
++                              dev_warn(snfi->dev, "wait ecc done timeout\n");
++                      } else {
++                              mtk_snfi_update_ecc_stats(mem, snfi->buffer,
++                                                        sectors);
++                              mtk_snfi_read_fdm_data(mem, sectors);
++                      }
++              }
++      }
++
++      if (oob_on)
++              goto out;
++
++      mtk_ecc_disable(snfi->ecc);
++out:
++      dma_unmap_single(snfi->dev, dma_addr, len, DMA_FROM_DEVICE);
++      writel(0, snfi->regs + NFI_CON);
++      writel(0, snfi->regs + NFI_CNFG);
++      reg = readl(snfi->regs + SNFI_MISC_CTL);
++      reg &= ~RD_CUSTOM_EN;
++      writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++      return ret;
++}
++
++static int mtk_snfi_write_to_cache(struct spi_mem *mem,
++                                 const struct spi_mem_op *op,
++                                 int oob_on)
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      u32 sectors = mtd->writesize / snfi->caps->nand_sec_size;
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u32 reg, len, col_addr = 0;
++      dma_addr_t dma_addr;
++      int ret;
++
++      len = sectors * (snfi->caps->nand_sec_size
++            + snfi_nand->spare_per_sector);
++
++      dma_addr = dma_map_single(snfi->dev, snfi->buffer, len,
++                                DMA_TO_DEVICE);
++      ret = dma_mapping_error(snfi->dev, dma_addr);
++      if (ret) {
++              dev_err(snfi->dev, "dma mapping error\n");
++              return -EINVAL;
++      }
++
++      /* set program load cmd and address */
++      reg = (op->cmd.opcode << WR_LOAD_CMD_SHIFT);
++      writel(reg, snfi->regs + SNFI_PG_CTL1);
++      writel(col_addr & WR_LOAD_ADDR_MASK, snfi->regs + SNFI_PG_CTL2);
++
++      reg = readl(snfi->regs + SNFI_MISC_CTL);
++      reg |= WR_CUSTOM_EN;
++      reg &= ~(RD_MODE_MASK | WR_X4_EN);
++
++      if (op->data.buswidth == 4)
++              reg |= WR_X4_EN;
++      writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++      writel(len << WR_LEN_SHIFT, snfi->regs + SNFI_MISC_CTL2);
++      writew(sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON);
++
++      reg = readw(snfi->regs + NFI_CNFG);
++      reg &= ~(CNFG_READ_EN | CNFG_BYTE_RW);
++      reg |= CNFG_DMA | CNFG_DMA_BURST_EN | CNFG_OP_PROGRAM;
++
++      if (!oob_on) {
++              reg |= CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN;
++              writew(reg, snfi->regs + NFI_CNFG);
++
++              snfi->ecc_cfg.mode = ECC_NFI_MODE;
++              snfi->ecc_cfg.op = ECC_ENCODE;
++              ret = mtk_ecc_enable(snfi->ecc, &snfi->ecc_cfg);
++              if (ret) {
++                      dev_err(snfi->dev, "ecc enable failed\n");
++                      /* clear NFI_CNFG */
++                      reg &= ~(CNFG_DMA_BURST_EN | CNFG_DMA |
++                                      CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN);
++                      writew(reg, snfi->regs + NFI_CNFG);
++                      dma_unmap_single(snfi->dev, dma_addr, len,
++                                       DMA_FROM_DEVICE);
++                      goto out;
++              }
++              /* write OOB into the FDM registers (OOB area in MTK NAND) */
++              mtk_snfi_write_fdm_data(mem, sectors);
++      } else {
++              writew(reg, snfi->regs + NFI_CNFG);
++      }
++      writel(lower_32_bits(dma_addr), snfi->regs + NFI_STRADDR);
++      readw(snfi->regs + NFI_INTR_STA);
++      writew(INTR_AHB_DONE_EN, snfi->regs + NFI_INTR_EN);
++
++      init_completion(&snfi->done);
++
++      /* set dummy command to trigger NFI enter SPI mode */
++      writew(NAND_CMD_DUMMYPROG, snfi->regs + NFI_CMD);
++      reg = readl(snfi->regs + NFI_CON) | CON_BWR;
++      writew(reg, snfi->regs + NFI_CON);
++
++      ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500));
++      if (!ret) {
++              dev_err(snfi->dev, "custom program done timeout\n");
++              writew(0, snfi->regs + NFI_INTR_EN);
++              ret = -ETIMEDOUT;
++              goto ecc_disable;
++      }
++
++      ret = readl_poll_timeout_atomic(snfi->regs + NFI_ADDRCNTR, reg,
++                                      ADDRCNTR_SEC(reg) >= sectors,
++                                      10, MTK_TIMEOUT);
++      if (ret)
++              dev_err(snfi->dev, "hwecc write timeout\n");
++
++ecc_disable:
++      mtk_ecc_disable(snfi->ecc);
++
++out:
++      dma_unmap_single(snfi->dev, dma_addr, len, DMA_TO_DEVICE);
++      writel(0, snfi->regs + NFI_CON);
++      writel(0, snfi->regs + NFI_CNFG);
++      reg = readl(snfi->regs + SNFI_MISC_CTL);
++      reg &= ~WR_CUSTOM_EN;
++      writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++      return ret;
++}
++
++static int mtk_snfi_read(struct spi_mem *mem,
++                       const struct spi_mem_op *op)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u32 col_addr = op->addr.val;
++      int i, ret, sectors, oob_on = false;
++
++      if (col_addr == mtd->writesize)
++              oob_on = true;
++
++      ret = mtk_snfi_read_from_cache(mem, op, oob_on);
++      if (ret) {
++              dev_warn(snfi->dev, "read from cache fail\n");
++              return ret;
++      }
++
++      sectors = mtd->writesize / snfi->caps->nand_sec_size;
++      for (i = 0; i < sectors; i++) {
++              if (oob_on)
++                      memcpy(oob_ptr(mem, i),
++                             mtk_oob_ptr(mem, snfi->buffer, i),
++                             snfi->caps->nand_fdm_size);
++
++              if (i == snfi_nand->bad_mark.sec && snfi->caps->bad_mark_swap)
++                      snfi_nand->bad_mark.bm_swap(mem, snfi->buffer,
++                                                      oob_on);
++      }
++
++      if (!oob_on)
++              memcpy(spinand->databuf, snfi->buffer, mtd->writesize);
++
++      return ret;
++}
++
++static int mtk_snfi_write(struct spi_mem *mem,
++                        const struct spi_mem_op *op)
++{
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++      u32 ret, i, sectors, col_addr = op->addr.val;
++      int oob_on = false;
++
++      if (col_addr == mtd->writesize)
++              oob_on = true;
++
++      sectors = mtd->writesize / snfi->caps->nand_sec_size;
++      memset(snfi->buffer, 0xff, mtd->writesize + mtd->oobsize);
++
++      if (!oob_on)
++              memcpy(snfi->buffer, spinand->databuf, mtd->writesize);
++
++      for (i = 0; i < sectors; i++) {
++              if (i == snfi_nand->bad_mark.sec && snfi->caps->bad_mark_swap)
++                      snfi_nand->bad_mark.bm_swap(mem, snfi->buffer, oob_on);
++
++              if (oob_on)
++                      memcpy(mtk_oob_ptr(mem, snfi->buffer, i),
++                             oob_ptr(mem, i),
++                             snfi->caps->nand_fdm_size);
++      }
++
++      ret = mtk_snfi_write_to_cache(mem, op, oob_on);
++      if (ret)
++              dev_warn(snfi->dev, "write to cache fail\n");
++
++      return ret;
++}
++
++static int mtk_snfi_command_exec(struct mtk_snfi *snfi,
++                               const u8 *txbuf, u8 *rxbuf,
++                               const u32 txlen, const u32 rxlen)
++{
++      u32 tmp, i, j, reg, m;
++      u8 *p_tmp = (u8 *)(&tmp);
++      int ret = 0;
++
++      /* Moving tx data to NFI_SPI GPRAM */
++      for (i = 0, m = 0; i < txlen; ) {
++              for (j = 0, tmp = 0; i < txlen && j < 4; i++, j++)
++                      p_tmp[j] = txbuf[i];
++
++              writel(tmp, snfi->regs + SNFI_GPRAM_DATA + m);
++              m += 4;
++      }
++
++      writel(txlen, snfi->regs + SNFI_MAC_OUTL);
++      writel(rxlen, snfi->regs + SNFI_MAC_INL);
++      ret = mtk_snfi_mac_op(snfi);
++      if (ret)
++              return ret;
++
++      /* For NULL input data, this loop will be skipped */
++      if (rxlen)
++              for (i = 0, m = 0; i < rxlen; ) {
++                      reg = readl(snfi->regs +
++                                          SNFI_GPRAM_DATA + m);
++                      for (j = 0; i < rxlen && j < 4; i++, j++, rxbuf++) {
++                              if (m == 0 && i == 0)
++                                      j = i + txlen;
++                              *rxbuf = (reg >> (j * 8)) & 0xFF;
++                      }
++                      m += 4;
++              }
++
++      return ret;
++}
++
++/*
++ * mtk_snfi_exec_op - to process command/data to send to the
++ * SPI NAND by mtk controller
++ */
++static int mtk_snfi_exec_op(struct spi_mem *mem,
++                          const struct spi_mem_op *op)
++
++{
++      struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++      struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++      struct mtd_info *mtd = spinand_to_mtd(spinand);
++      struct nand_device *nand = mtd_to_nanddev(mtd);
++      const struct spi_mem_op *read_cache;
++      const struct spi_mem_op *write_cache;
++      u32 tmpbufsize, txlen = 0, rxlen = 0;
++      u8 *txbuf, *rxbuf = NULL, *buf;
++      int i, ret = 0;
++
++      ret = mtk_snfi_reset(snfi);
++      if (ret) {
++              dev_warn(snfi->dev, "reset spi memory controller fail\n");
++              return ret;
++      }
++
++      /*if bbt initial, framework have detect nand information */
++      if (nand->bbt.cache) {
++              read_cache = spinand->op_templates.read_cache;
++              write_cache = spinand->op_templates.write_cache;
++
++              ret = mtk_snfi_hw_runtime_config(mem);
++              if (ret)
++                      return ret;
++
++              /* For Read/Write with cache, Erase use framework flow */
++              if (op->cmd.opcode == read_cache->cmd.opcode) {
++                      ret = mtk_snfi_read(mem, op);
++                      if (ret)
++                              dev_warn(snfi->dev, "snfi read fail\n");
++                      return ret;
++              } else if (op->cmd.opcode == write_cache->cmd.opcode) {
++                      ret = mtk_snfi_write(mem, op);
++                      if (ret)
++                              dev_warn(snfi->dev, "snfi write fail\n");
++                      return ret;
++              }
++      }
++
++      tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
++                   op->dummy.nbytes + op->data.nbytes;
++
++      txbuf = kzalloc(tmpbufsize, GFP_KERNEL);
++      if (!txbuf)
++              return -ENOMEM;
++
++      txbuf[txlen++] = op->cmd.opcode;
++
++      if (op->addr.nbytes)
++              for (i = 0; i < op->addr.nbytes; i++)
++                      txbuf[txlen++] = op->addr.val >>
++                                      (8 * (op->addr.nbytes - i - 1));
++
++      txlen += op->dummy.nbytes;
++
++      if (op->data.dir == SPI_MEM_DATA_OUT)
++              for (i = 0; i < op->data.nbytes; i++) {
++                      buf = (u8 *)op->data.buf.out;
++                      txbuf[txlen++] = buf[i];
++              }
++
++      if (op->data.dir == SPI_MEM_DATA_IN) {
++              rxbuf = (u8 *)op->data.buf.in;
++              rxlen += op->data.nbytes;
++      }
++
++      ret = mtk_snfi_command_exec(snfi, txbuf, rxbuf, txlen, rxlen);
++      kfree(txbuf);
++
++      return ret;
++}
++
++static int mtk_snfi_init(struct mtk_snfi *snfi)
++{
++      int ret;
++
++      /* Reset the state machine and data FIFO */
++      ret = mtk_snfi_reset(snfi);
++      if (ret) {
++              dev_warn(snfi->dev, "MTK reset controller fail\n");
++              return ret;
++      }
++
++      snfi->buffer = devm_kzalloc(snfi->dev, 4096 + 256, GFP_KERNEL);
++      if (!snfi->buffer)
++              return  -ENOMEM;
++
++      /* Clear interrupt, read clear. */
++      readw(snfi->regs + NFI_INTR_STA);
++      writew(0, snfi->regs + NFI_INTR_EN);
++
++      writel(0, snfi->regs + NFI_CON);
++      writel(0, snfi->regs + NFI_CNFG);
++
++      /* Change to NFI_SPI mode. */
++      writel(SNFI_MODE_EN, snfi->regs + SNFI_CNFG);
++
++      return 0;
++}
++
++static int mtk_snfi_check_buswidth(u8 width)
++{
++      switch (width) {
++      case 1:
++      case 2:
++      case 4:
++              return 0;
++
++      default:
++              break;
++      }
++
++      return -ENOTSUPP;
++}
++
++static bool mtk_snfi_supports_op(struct spi_mem *mem,
++                               const struct spi_mem_op *op)
++{
++      int ret = 0;
++
++      /* For MTK Spi Nand controller, cmd buswidth just support 1 bit*/
++      if (op->cmd.buswidth != 1)
++              ret = -ENOTSUPP;
++
++      if (op->addr.nbytes)
++              ret |= mtk_snfi_check_buswidth(op->addr.buswidth);
++
++      if (op->dummy.nbytes)
++              ret |= mtk_snfi_check_buswidth(op->dummy.buswidth);
++
++      if (op->data.nbytes)
++              ret |= mtk_snfi_check_buswidth(op->data.buswidth);
++
++      if (ret)
++              return false;
++
++      return true;
++}
++
++static const struct spi_controller_mem_ops mtk_snfi_ops = {
++      .supports_op = mtk_snfi_supports_op,
++      .exec_op = mtk_snfi_exec_op,
++};
++
++static const struct mtk_snfi_caps snfi_mt7622 = {
++      .spare_size = spare_size_mt7622,
++      .num_spare_size = 4,
++      .nand_sec_size = 512,
++      .nand_fdm_size = 8,
++      .nand_fdm_ecc_size = 1,
++      .ecc_parity_bits = 13,
++      .pageformat_spare_shift = 4,
++      .bad_mark_swap = 0,
++};
++
++static const struct of_device_id mtk_snfi_id_table[] = {
++      { .compatible = "mediatek,mt7622-snfi", .data = &snfi_mt7622, },
++      {  /* sentinel */ }
++};
++
++static int mtk_snfi_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct device_node *np = dev->of_node;
++      struct spi_controller *ctlr;
++      struct mtk_snfi *snfi;
++      struct resource *res;
++      int ret = 0, irq;
++
++      ctlr = spi_alloc_master(&pdev->dev, sizeof(*snfi));
++      if (!ctlr)
++              return -ENOMEM;
++
++      snfi = spi_controller_get_devdata(ctlr);
++      snfi->caps = of_device_get_match_data(dev);
++      snfi->dev = dev;
++
++      snfi->ecc = of_mtk_ecc_get(np);
++      if (IS_ERR_OR_NULL(snfi->ecc))
++              goto err_put_master;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      snfi->regs = devm_ioremap_resource(dev, res);
++      if (IS_ERR(snfi->regs)) {
++              ret = PTR_ERR(snfi->regs);
++              goto release_ecc;
++      }
++
++      /* find the clocks */
++      snfi->clk.nfi_clk = devm_clk_get(dev, "nfi_clk");
++      if (IS_ERR(snfi->clk.nfi_clk)) {
++              dev_err(dev, "no nfi clk\n");
++              ret = PTR_ERR(snfi->clk.nfi_clk);
++              goto release_ecc;
++      }
++
++      snfi->clk.spi_clk = devm_clk_get(dev, "spi_clk");
++      if (IS_ERR(snfi->clk.spi_clk)) {
++              dev_err(dev, "no spi clk\n");
++              ret = PTR_ERR(snfi->clk.spi_clk);
++              goto release_ecc;
++      }
++
++      ret = mtk_snfi_enable_clk(dev, &snfi->clk);
++      if (ret)
++              goto release_ecc;
++
++      /* find the irq */
++      irq = platform_get_irq(pdev, 0);
++      if (irq < 0) {
++              dev_err(dev, "no snfi irq resource\n");
++              ret = -EINVAL;
++              goto clk_disable;
++      }
++
++      ret = devm_request_irq(dev, irq, mtk_snfi_irq, 0, "mtk-snfi", snfi);
++      if (ret) {
++              dev_err(dev, "failed to request snfi irq\n");
++              goto clk_disable;
++      }
++
++      ret = dma_set_mask(dev, DMA_BIT_MASK(32));
++      if (ret) {
++              dev_err(dev, "failed to set dma mask\n");
++              goto clk_disable;
++      }
++
++      ctlr->dev.of_node = np;
++      ctlr->mem_ops = &mtk_snfi_ops;
++
++      platform_set_drvdata(pdev, snfi);
++      ret = mtk_snfi_init(snfi);
++      if (ret) {
++              dev_err(dev, "failed to init snfi\n");
++              goto clk_disable;
++      }
++
++      ret = devm_spi_register_master(dev, ctlr);
++      if (ret)
++              goto clk_disable;
++
++      return 0;
++
++clk_disable:
++      mtk_snfi_disable_clk(&snfi->clk);
++
++release_ecc:
++      mtk_ecc_release(snfi->ecc);
++
++err_put_master:
++      spi_master_put(ctlr);
++
++      dev_err(dev, "MediaTek SPI NAND interface probe failed %d\n", ret);
++      return ret;
++}
++
++static int mtk_snfi_remove(struct platform_device *pdev)
++{
++      struct mtk_snfi *snfi = platform_get_drvdata(pdev);
++
++      mtk_snfi_disable_clk(&snfi->clk);
++
++      return 0;
++}
++
++static int mtk_snfi_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct mtk_snfi *snfi = platform_get_drvdata(pdev);
++
++      mtk_snfi_disable_clk(&snfi->clk);
++
++      return 0;
++}
++
++static int mtk_snfi_resume(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct mtk_snfi *snfi = dev_get_drvdata(dev);
++      int ret;
++
++      ret = mtk_snfi_enable_clk(dev, &snfi->clk);
++      if (ret)
++              return ret;
++
++      ret = mtk_snfi_init(snfi);
++      if (ret)
++              dev_err(dev, "failed to init snfi controller\n");
++
++      return ret;
++}
++
++static struct platform_driver mtk_snfi_driver = {
++      .driver = {
++              .name   = "mtk-snfi",
++              .of_match_table = mtk_snfi_id_table,
++      },
++      .probe          = mtk_snfi_probe,
++      .remove         = mtk_snfi_remove,
++      .suspend        = mtk_snfi_suspend,
++      .resume         = mtk_snfi_resume,
++};
++
++module_platform_driver(mtk_snfi_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou@mediatek.com>");
++MODULE_DESCRIPTION("Mediatek SPI Memory Interface Driver");
+Index: linux-4.19.48/drivers/spi/Kconfig
+===================================================================
+--- linux-4.19.48.orig/drivers/spi/Kconfig
++++ linux-4.19.48/drivers/spi/Kconfig
+@@ -389,6 +389,15 @@ config SPI_MT65XX
+         say Y or M here.If you are not sure, say N.
+         SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
++config SPI_MTK_SNFI
++       tristate "MediaTek SPI NAND interface"
++       select MTD_SPI_NAND
++       help
++         This selects the SPI NAND FLASH interface(SNFI),
++         which could be found on MediaTek Soc.
++         Say Y or M here.If you are not sure, say N.
++         Note Parallel Nand and SPI NAND is alternative on MediaTek SoCs.
++
+ config SPI_NUC900
+       tristate "Nuvoton NUC900 series SPI"
+       depends on ARCH_W90X900
+Index: linux-4.19.48/drivers/spi/Makefile
+===================================================================
+--- linux-4.19.48.orig/drivers/spi/Makefile
++++ linux-4.19.48/drivers/spi/Makefile
+@@ -57,6 +57,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC)                += spi-mp
+ obj-$(CONFIG_SPI_MPC52xx_PSC)         += spi-mpc52xx-psc.o
+ obj-$(CONFIG_SPI_MPC52xx)             += spi-mpc52xx.o
+ obj-$(CONFIG_SPI_MT65XX)                += spi-mt65xx.o
++obj-$(CONFIG_SPI_MTK_SNFI)              += spi-mtk-snfi.o
+ obj-$(CONFIG_SPI_MXS)                 += spi-mxs.o
+ obj-$(CONFIG_SPI_NUC900)              += spi-nuc900.o
+ obj-$(CONFIG_SPI_OC_TINY)             += spi-oc-tiny.o
diff --git a/target/linux/mediatek/patches-4.19/0900-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-4.19/0900-bt-mtk-serial-fix.patch
new file mode 100755 (executable)
index 0000000..ae1ef16
--- /dev/null
@@ -0,0 +1,37 @@
+diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
+index ebfb0bd..2b9ba39 100644
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -80,6 +80,7 @@  struct serial8250_config {
+ #define UART_CAP_MINI (1 << 17)       /* Mini UART on BCM283X family lacks:
+                                        * STOP PARITY EPAR SPAR WLEN5 WLEN6
+                                        */
++#define UART_CAP_NMOD (1 << 18)       /* UART doesn't do termios */
+ #define UART_BUG_QUOT (1 << 0)        /* UART has buggy quot LSB */
+ #define UART_BUG_TXEN (1 << 1)        /* UART has buggy TX IIR status */
+diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
+index c39482b..e4a69a0 100644
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -297,7 +297,7 @@ 
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO |
+                                 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+-              .flags          = UART_CAP_FIFO,
++              .flags          = UART_CAP_FIFO | UART_CAP_NMOD,
+       },
+       [PORT_NPCM] = {
+               .name           = "Nuvoton 16550",
+@@ -2663,6 +2663,11 @@  static unsigned int serial8250_get_baud_rate(struct uart_port *port,
+       unsigned long flags;
+       unsigned int baud, quot, frac = 0;
++      if (up->capabilities & UART_CAP_NMOD) {
++              termios->c_cflag = 0;
++              return;
++      }
++
+       if (up->capabilities & UART_CAP_MINI) {
+               termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR);
+               if ((termios->c_cflag & CSIZE) == CS5 ||