aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/files-4.19
diff options
context:
space:
mode:
authorJohn Crispin <john@phrozen.org>2019-08-02 10:33:28 +0200
committerJohn Crispin <john@phrozen.org>2019-08-02 10:36:11 +0200
commit66458c49aa14ebc9ba2e4f9b6a323b8ff122807b (patch)
tree43cd8477d8341136c691d49b139038b14793f635 /target/linux/mediatek/files-4.19
parentcb49e46a8a4526d86270ced3ba3aa90225ca82d7 (diff)
downloadupstream-66458c49aa14ebc9ba2e4f9b6a323b8ff122807b.tar.gz
upstream-66458c49aa14ebc9ba2e4f9b6a323b8ff122807b.tar.bz2
upstream-66458c49aa14ebc9ba2e4f9b6a323b8ff122807b.zip
mediatek: add v4.19 support
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>
Diffstat (limited to 'target/linux/mediatek/files-4.19')
-rwxr-xr-xtarget/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-lynx-rfb.dts314
-rwxr-xr-xtarget/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-rfb.dts294
-rwxr-xr-xtarget/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629.dtsi423
-rw-r--r--target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/a.patch19
-rw-r--r--target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts574
-rwxr-xr-xtarget/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-lynx-rfb1.dts605
-rwxr-xr-xtarget/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts576
-rwxr-xr-xtarget/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622.dtsi903
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig4
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile11
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c602
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h14
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c851
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h14
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h232
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c94
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c740
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c386
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h47
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h298
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c695
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h19
22 files changed, 7715 insertions, 0 deletions
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
index 0000000000..f3fadd301a
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-lynx-rfb.dts
@@ -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
index 0000000000..8043238fea
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629-rfb.dts
@@ -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
index 0000000000..53f47796b8
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm/boot/dts/mt7629.dtsi
@@ -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
index 0000000000..7312b476c0
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/a.patch
@@ -0,0 +1,19 @@
+[?25l[?2004h[?25h[?1049h[?1h=[?2004h[?12h[?12l[?25l"mt7622-lynx-rfb1.dts" 605L, 11203C/*
+ * 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;};[?25h
+ [?25lType :qa! and press <Enter> to abandon all changes and exit Vim[?25h[?2004l[?1l>[?1049lVim: Caught deadly signal TERM
+Vim: Finished.
+ \ 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
index 0000000000..62a876c02f
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
@@ -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
index 0000000000..1045851509
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-lynx-rfb1.dts
@@ -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
index 0000000000..3805c5c4ce
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -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
index 0000000000..3fdd06a8d3
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -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
index 0000000000..cf83c6a436
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig
@@ -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
index 0000000000..3829bacfe9
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile
@@ -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
index 0000000000..45d4984c1a
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c
@@ -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
index 0000000000..b4c8a02861
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h
@@ -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
index 0000000000..4d44141a61
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c
@@ -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
index 0000000000..736cb0c349
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h
@@ -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
index 0000000000..b9bca5416f
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h
@@ -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
index 0000000000..c836a63607
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c
@@ -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
index 0000000000..695713eed4
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
@@ -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
index 0000000000..756df4e21f
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c
@@ -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
index 0000000000..f6a1df34e6
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h
@@ -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
index 0000000000..15255277ab
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h
@@ -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
index 0000000000..fb2ee1c1b7
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
@@ -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
index 0000000000..971a2cc90a
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h
@@ -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_ */