mediatek: update v4.19 switch support to latest vendor version
authorJohn Crispin <john@phrozen.org>
Wed, 28 Aug 2019 13:20:22 +0000 (15:20 +0200)
committerJohn Crispin <john@phrozen.org>
Wed, 28 Aug 2019 13:20:22 +0000 (15:20 +0200)
Signed-off-by: John Crispin <john@phrozen.org>
18 files changed:
target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c [new file with mode: 0644]
target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h [new file with mode: 0644]
target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch

index 62a876c02ff835b6aa1a0f9c59d56eb06d542c73..557745ed9024343dfbf3c06a11c7129395b547ef 100644 (file)
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (c) 2018 MediaTek Inc.
  * Author: Ryder Lee <ryder.lee@mediatek.com>
- *
- * SPDX-License-Identifier: (GPL-2.0 OR MIT)
  */
 
 /dts-v1/;
        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";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
        };
 
        cpus {
                wps {
                        label = "wps";
                        linux,code = <KEY_WPS_BUTTON>;
-                       gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+                       gpios = <&pio 102 GPIO_ACTIVE_HIGH>;
                };
        };
 
+       gsw: gsw@0 {
+               compatible = "mediatek,mt753x";
+               mediatek,ethsys = <&ethsys>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
        leds {
                compatible = "gpio-leds";
 
                };
        };
 
-       gsw: gsw@0 {
-               compatible = "mediatek,mt753x";
-               mediatek,ethsys = <&ethsys>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
-
        memory {
                reg = <0 0x40000000 0 0x40000000>;
        };
                regulator-boot-on;
                regulator-always-on;
        };
+
 };
 
 &bch {
 };
 
 &eth {
-       pinctrl-names = "default";
-       pinctrl-0 = <&eth_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 = <&phy5>;
+               phy-mode = "rgmii";
+               fixed-link {
+                       speed = <1000>;
+                       full-duplex;
+                       pause;
+               };
        };
-
        mdio: mdio-bus {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+};
 
-               phy5: ethernet-phy@5 {
-                       reg = <5>;
-                       phy-mode = "sgmii";
+&gsw {
+       mediatek,mdio = <&mdio>;
+       mediatek,portmap = "wllll";
+       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;
                };
        };
 };
        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;
-               };
-       };
-};
-
-
index cf83c6a436ea2140012abd09fd3cd0790723ff12..d9e0230cf076512380deaa1b21cdc5b55b2832b0 100644 (file)
@@ -1,4 +1,3 @@
 
 config MT753X_GSW
        tristate "Driver for the MediaTek MT753x switch"
-
index 3829bacfe9fffc9ed9f0c944c819b33e9980ba6b..7aae451cd169a12156fcd8c22bab6de0e7407da4 100644 (file)
@@ -7,5 +7,5 @@ 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
-
+                                       mt753x_common.o mt753x_vlan.o \
+                                       mt753x_nl.o
index 45d4984c1a7d1acd10a508534caf5fedb6918719..014b83be9ecc7446b8e1065d49fac82bfcf1d345 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Driver for MediaTek MT7530 gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <linux/kernel.h>
@@ -276,19 +272,73 @@ static void mt7530_core_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
        gsw->mmd_write(gsw, 0, 0x1f, reg, val);
 }
 
+static void mt7530_trgmii_setting(struct gsw_mt753x *gsw)
+{
+       u16 i;
+
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0780);
+       mdelay(1);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87);
+       mdelay(1);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87);
+
+       /* PLL BIAS enable */
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
+                             RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN);
+       mdelay(1);
+
+       /* PLL LPF enable */
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
+                             RG_SYSPLL_DDSFBK_EN |
+                             RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
+
+       /* sys PLL enable */
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP2,
+                             RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
+                             (1 << RG_SYSPLL_POSDIV_S));
+
+       /* LCDDDS PWDS */
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP7,
+                             (3 << RG_LCCDS_C_S) |
+                             RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
+       mdelay(1);
+
+       /* Enable MT7530 TRGMII clock */
+       mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN);
+
+       /* lower Tx Driving */
+       for (i = 0 ; i < NUM_TRGMII_ODT; i++)
+               mt753x_reg_write(gsw, TRGMII_TD_ODT(i),
+                                (4 << TX_DM_DRVP_S) | (4 << TX_DM_DRVN_S));
+}
+
+static void mt7530_rgmii_setting(struct gsw_mt753x *gsw)
+{
+       u32 val;
+
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0c80);
+       mdelay(1);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87);
+       mdelay(1);
+       mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87);
+
+       val = mt753x_reg_read(gsw, TRGMII_TXCTRL);
+       val &= ~TXC_INV;
+       mt753x_reg_write(gsw, TRGMII_TXCTRL, val);
+
+       mt753x_reg_write(gsw, TRGMII_TCK_CTRL,
+                        (8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S));
+}
+
 static int mt7530_mac_port_setup(struct gsw_mt753x *gsw)
 {
        u32 hwstrap, p6ecr = 0, p5mcr, p6mcr, phyad;
 
-       hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+       hwstrap = mt753x_reg_read(gsw, MHWSTRAP);
        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;
-
+       hwstrap |= P5_INTF_SEL_GMAC5;
        if (!gsw->port5_cfg.enabled) {
                p5mcr = FORCE_MODE;
                hwstrap |= P5_INTF_DIS_S;
@@ -358,10 +408,11 @@ parse_p6:
 
                switch (gsw->port6_cfg.phy_mode) {
                case PHY_INTERFACE_MODE_RGMII:
+                       p6ecr = BIT(1);
                        break;
                case PHY_INTERFACE_MODE_TRGMII:
                        /* set MT7530 central align */
-                       p6ecr = BIT(1); /* TODO: confirm this */
+                       p6ecr = BIT(0);
                        break;
                default:
                        dev_info(gsw->dev, "%s is not supported by port6\n",
@@ -382,8 +433,7 @@ parse_p6:
 
 static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
 {
-       u32 hwstrap, val, ncpo1, ssc_delta;
-       int i;
+       u32 hwstrap;
 
        hwstrap = mt753x_reg_read(gsw, HWSTRAP);
 
@@ -418,48 +468,23 @@ static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
                break;
        }
 
+       hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+       hwstrap |= CHG_TRAP;
+       if (gsw->direct_phy_access)
+               hwstrap &= ~C_MDIO_BPS_S;
+       else
+               hwstrap |= C_MDIO_BPS_S;
+
+       mt753x_reg_write(gsw, MHWSTRAP, hwstrap);
+
        if (gsw->port6_cfg.enabled &&
            gsw->port6_cfg.phy_mode == PHY_INTERFACE_MODE_TRGMII) {
-               ncpo1 = 0x1400;
-               ssc_delta = 0x57;
+               mt7530_trgmii_setting(gsw);
        } else {
                /* RGMII */
-               ncpo1 = 0x0c80;
-               ssc_delta = 0x87;
+               mt7530_rgmii_setting(gsw);
        }
 
-       /* 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 |
@@ -519,13 +544,17 @@ static void mt7530_phy_setting(struct gsw_mt753x *gsw)
        }
 }
 
+static inline bool get_phy_access_mode(const struct device_node *np)
+{
+       return of_property_read_bool(np, "mt7530,direct-phy-access");
+}
+
 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");
+       gsw->direct_phy_access = get_phy_access_mode(gsw->dev->of_node);
 
        /* Force MT7530 to use (in)direct PHY access */
        val = mt753x_reg_read(gsw, HWSTRAP);
index b4c8a02861c2c603a3e04695a7f0cc5924b4d71d..ef2d68417a72f5d145945ffa878420ffec444908 100644 (file)
@@ -1,7 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
+ * Copyright (c) 2018 MediaTek Inc.
  */
 
 #ifndef _MT7530_H_
index 4d44141a619556fead0b8da0b68fdbb19f4f27a6..5b9f35916863444e997e0b0941d53a5acfbbd0f7 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Driver for MediaTek MT7531 gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Zhanguo Ju <zhanguo.ju@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <linux/kernel.h>
 /* PHY ENABLE Register bitmap define */
 #define PHY_DEV1F                      0x1f
 #define PHY_DEV1F_REG_44               0x44
+#define PHY_DEV1F_REG_104              0x104
+#define PHY_DEV1F_REG_10A              0x10a
+#define PHY_DEV1F_REG_10B              0x10b
+#define PHY_DEV1F_REG_10C              0x10c
+#define PHY_DEV1F_REG_10D              0x10d
 #define PHY_DEV1F_REG_268              0x268
 #define PHY_DEV1F_REG_269              0x269
 #define PHY_DEV1F_REG_403              0x403
@@ -74,6 +75,8 @@
 #define GBE_EFUSE_SETTING              BIT(3)
 #define PHY_EN_BYPASS_MODE             BIT(4)
 #define POWER_ON_OFF                   BIT(5)
+#define PHY_PLL_M                      GENMASK(9, 8)
+#define PHY_PLL_SEL(x)                 (((x) << 8) & GENMASK(9, 8))
 
 /* PHY EEE Register bitmap of define */
 #define PHY_DEV07                      0x07
 #define ANA_PLLGP_CR5                  0x78bc
 
 /* GPIO mode define */
-#define GPIO_MODE_REGS(x)              (0x7c0c + ((x / 8) * 4))
+#define GPIO_MODE_REGS(x)              (0x7c0c + (((x) / 8) * 4))
 #define GPIO_MODE_S                    4
 
 /* GPIO GROUP IOLB SMT0 Control */
@@ -638,6 +641,68 @@ static int mt7531_set_gpio_pinmux(struct gsw_mt753x *gsw)
        return 0;
 }
 
+static void mt7531_phy_pll_setup(struct gsw_mt753x *gsw)
+{
+       u32 hwstrap;
+       u32 val;
+
+       hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+
+       switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) {
+       case XTAL_25MHZ:
+               /* disable pll auto calibration */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608);
+
+               /* change pll sel */
+               val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
+                                    PHY_DEV1F_REG_403);
+               val &= ~(PHY_PLL_M);
+               val |= PHY_PLL_SEL(3);
+               gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
+
+               /* set divider ratio */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F,
+                              PHY_DEV1F_REG_10A, 0x1009);
+
+               /* set divider ratio */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0x7c6);
+
+               /* capacitance and resistance adjustment */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F,
+                              PHY_DEV1F_REG_10C, 0xa8be);
+
+               break;
+       case XTAL_40MHZ:
+               /* disable pll auto calibration */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608);
+
+               /* change pll sel */
+               val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
+                                    PHY_DEV1F_REG_403);
+               val &= ~(PHY_PLL_M);
+               val |= PHY_PLL_SEL(3);
+               gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
+
+               /* set divider ratio */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F,
+                              PHY_DEV1F_REG_10A, 0x1018);
+
+               /* set divider ratio */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0xc676);
+
+               /* capacitance and resistance adjustment */
+               gsw->mmd_write(gsw, 0, PHY_DEV1F,
+                              PHY_DEV1F_REG_10C, 0xd8be);
+               break;
+       }
+
+       /* power down pll. additional delay is not required via mdio access */
+       gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x10);
+
+       /* power up pll */
+       gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x14);
+}
+
 static void mt7531_phy_setting(struct gsw_mt753x *gsw)
 {
        int i;
@@ -694,7 +759,7 @@ static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
        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);
+       gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2ca5);
 
        /* Adjust Line driver current for different mode */
        gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_272, 0xc6b);
@@ -709,10 +774,10 @@ static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
        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);
+       gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x388);
 
        /* Adjust TX class AB driver 2 */
-       gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0xaaaa);
+       gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0x4448);
 }
 
 static void mt7531_eee_setting(struct gsw_mt753x *gsw, u32 port)
@@ -797,6 +862,8 @@ static int mt7531_sw_post_init(struct gsw_mt753x *gsw)
        int i;
        u32 val;
 
+       mt7531_phy_pll_setup(gsw);
+
        /* Internal PHYs are disabled by default. SW should enable them.
         * Note that this may already be enabled in bootloader stage.
         */
index 736cb0c349ddc0bb4aec052a6b9a05bf8f44b12e..e4ef81e94a0b5a7d001812671c5e78baf459ebbc 100644 (file)
@@ -1,7 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
+ * Copyright (c) 2018 MediaTek Inc.
  */
 
 #ifndef _MT7531_H_
index b9bca5416f4aca978cedddea0d8abe3f46e89f38..317b31ddccefdd020d8e452b2cfefc99b1fa708d 100644 (file)
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Driver for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifndef _MT753X_H_
 #include <linux/switch.h>
 #endif
 
+#include "mt753x_vlan.h"
+
 #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
@@ -40,16 +33,6 @@ enum mt753x_model {
        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;
@@ -82,7 +65,7 @@ struct gsw_mt753x {
        struct mt753x_port_cfg port5_cfg;
        struct mt753x_port_cfg port6_cfg;
 
-       bool phy_status_poll;
+       int phy_status_poll;
        struct mt753x_phy phys[MT753X_NUM_PHYS];
 
        int phy_link_sts;
@@ -93,14 +76,13 @@ struct gsw_mt753x {
 
 #ifdef CONFIG_SWCONFIG
        struct switch_dev swdev;
+       u32 cpu_port;
+#endif
 
+       int global_vlan_enable;
        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);
 
@@ -228,5 +210,4 @@ void mt753x_irq_enable(struct gsw_mt753x *gsw);
 #define MT753X_REG_PAGE_ADDR_M         0xffc0
 #define MT753X_REG_ADDR_S              2
 #define MT753X_REG_ADDR_M              0x3c
-
 #endif /* _MT753X_H_ */
index c836a636074b4a63732c2642c15b862dfedef455..18f925956d9ce38fa96be20d3c674d9b3cbc48f8 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Common part for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <linux/kernel.h>
@@ -56,8 +52,8 @@ static void display_port_link_status(struct gsw_mt753x *gsw, u32 port)
        }
 
        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");
+               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);
        }
index 695713eed4bc0760106195187a2866c08a2d3126..8a9a45c0be8deaa871f82f8076d32560188fde0e 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Driver for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <linux/kernel.h>
@@ -232,6 +228,11 @@ void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
        mutex_unlock(&gsw->mii_lock);
 }
 
+static inline int mt753x_get_duplex(const struct device_node *np)
+{
+       return of_property_read_bool(np, "full-duplex");
+}
+
 static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
 {
        struct device_node *port_np;
@@ -279,9 +280,7 @@ static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
                        u32 speed;
 
                        port_cfg->force_link = 1;
-                       port_cfg->duplex = of_property_read_bool(
-                                               fixed_link_node,
-                                               "full-duplex");
+                       port_cfg->duplex = mt753x_get_duplex(fixed_link_node);
 
                        if (of_property_read_u32(fixed_link_node, "speed",
                                                 &speed)) {
@@ -331,6 +330,7 @@ static void mt753x_remove_gsw(struct gsw_mt753x *gsw)
        mutex_unlock(&mt753x_devs_lock);
 }
 
+
 struct gsw_mt753x *mt753x_get_gsw(u32 id)
 {
        struct gsw_mt753x *dev;
@@ -416,150 +416,6 @@ static int mt753x_hw_reset(struct gsw_mt753x *gsw)
        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;
@@ -580,6 +436,7 @@ static int mt753x_probe(struct platform_device *pdev)
        struct mii_bus *mdio_bus;
        int ret = -EINVAL;
        struct chip_rev rev;
+       struct mt753x_mapping *map;
        int i;
 
        mdio = of_parse_phandle(np, "mediatek,mdio", 0);
@@ -599,12 +456,21 @@ static int mt753x_probe(struct platform_device *pdev)
        mutex_init(&gsw->mii_lock);
 
        /* Switch hard reset */
-       mt753x_hw_reset(gsw);
+       if (mt753x_hw_reset(gsw))
+               goto fail;
 
        /* Fetch the SMI address dirst */
        if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
                gsw->smi_addr = MT753X_DFL_SMI_ADDR;
 
+       /* Get LAN/WAN port mapping */
+       map = mt753x_find_mapping(np);
+       if (map) {
+               mt753x_apply_mapping(gsw, map);
+               gsw->global_vlan_enable = 1;
+               dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
+       }
+
        /* Load MAC port configurations */
        mt753x_load_port_cfg(gsw);
 
@@ -653,11 +519,7 @@ static int mt753x_probe(struct platform_device *pdev)
 
        mt753x_add_gsw(gsw);
 
-       mt753x_mdio_register(gsw);
-
-#ifdef CONFIG_SWCONFIG
        mt753x_swconfig_init(gsw);
-#endif
 
        if (sw->post_init)
                sw->post_init(gsw);
@@ -687,10 +549,6 @@ static int mt753x_remove(struct platform_device *pdev)
        mt753x_swconfig_destroy(gsw);
 #endif
 
-       mt753x_disconnect_internal_phys(gsw);
-
-       mdiobus_unregister(gsw->gphy_bus);
-
        mt753x_remove_gsw(gsw);
 
        platform_set_drvdata(pdev, NULL);
index 756df4e21fed5a89c1ddc3e6f216fa6760549355..78aecd34edff4e6170a46148ec199a3f39b71e81 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Configuration layer for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <linux/types.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;
@@ -61,7 +53,6 @@ static const struct genl_ops mt753x_nl_ops[] = {
 };
 
 static struct genl_family mt753x_nl_family = {
-//     .id =           GENL_ID_GENERATE,
        .name =         MT753X_GENL_NAME,
        .version =      MT753X_GENL_VERSION,
        .maxattr =      MT753X_NR_ATTR_TYPE,
@@ -208,7 +199,8 @@ 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;
+       int value;
+       int ret = 0;
 
        phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
        devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
@@ -252,7 +244,7 @@ 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;
+       int ret = 0;
 
        phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
        devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
@@ -312,12 +304,14 @@ static const struct mt753x_nl_cmd_item mt753x_nl_cmds[] = {
                .cmd = MT753X_CMD_READ,
                .require_dev = true,
                .process = mt753x_nl_reply_read,
-               MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_read_attrs)
+               .required_attrs = mt753x_nl_cmd_read_attrs,
+               .nr_required_attrs = ARRAY_SIZE(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)
+               .required_attrs = mt753x_nl_cmd_write_attrs,
+               .nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_write_attrs),
        }
 };
 
index f6a1df34e6b11aefa30a73b8d939e9c81b4c89a4..3c062738027f404956a921a503ed665af40c2c3d 100644 (file)
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Driver for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifndef _MT753X_NL_H_
index 15255277ab363d7696fe64b76557b1e35d920db5..0c91b8e0ecb7c1022fa24016dd98a5469e15c8f2 100644 (file)
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Register definitions for MediaTek MT753x Gigabit switches
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifndef _MT753X_REGS_H_
index fb2ee1c1b73724524d85ef57c4391a5315c8a2f0..b601b90fb1fca4a652d54127a0db3afe78720efc 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * OpenWrt swconfig support for MediaTek MT753x Gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <linux/if.h>
@@ -93,64 +89,6 @@ enum {
        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)
@@ -201,27 +139,6 @@ static int mt753x_set_port_pvid(struct switch_dev *dev, int port, int 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);
@@ -447,114 +364,16 @@ static void mt753x_port_isolation(struct gsw_mt753x *gsw)
                                 (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);
-       }
+       mt753x_apply_vlan_config(gsw);
 
        return 0;
 }
@@ -659,7 +478,6 @@ 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))
@@ -676,14 +494,11 @@ int mt753x_swconfig_init(struct gsw_mt753x *gsw)
 
        ret = register_switch(swdev, NULL);
        if (ret) {
-               dev_err(gsw->dev, "Failed to register switch %s\n",
-                       swdev->name);
+               dev_notice(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;
index 971a2cc90a862b11d15572ad9670135fb6828f73..b877d8957e9b2d36e5ddf630b6d837792db2e12d 100644 (file)
@@ -1,19 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * OpenWrt swconfig support for MediaTek MT753x Gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
  * Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifndef _MT753X_SWCONFIG_H_
 #define _MT753X_SWCONFIG_H_
 
+#ifdef CONFIG_SWCONFIG
 #include <linux/switch.h>
+#include "mt753x.h"
 
 int mt753x_swconfig_init(struct gsw_mt753x *gsw);
 void mt753x_swconfig_destroy(struct gsw_mt753x *gsw);
+#else
+static inline int mt753x_swconfig_init(struct gsw_mt753x *gsw)
+{
+       mt753x_apply_vlan_config(gsw);
+
+       return 0;
+}
+
+static inline void mt753x_swconfig_destroy(struct gsw_mt753x *gsw)
+{
+}
+#endif
 
 #endif /* _MT753X_SWCONFIG_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c
new file mode 100644 (file)
index 0000000..f3c8c38
--- /dev/null
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#include "mt753x.h"
+#include "mt753x_regs.h"
+
+struct mt753x_mapping mt753x_def_mapping[] = {
+       {
+               .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 },
+       },
+};
+
+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 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);
+}
+
+void mt753x_apply_vlan_config(struct gsw_mt753x *gsw)
+{
+       int i, j;
+       u8 tag_ports;
+       u8 untag_ports;
+
+       /* 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 switch 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);
+       }
+}
+
+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_def_mapping); i++)
+               if (!strcmp(map, mt753x_def_mapping[i].name))
+                       return &mt753x_def_mapping[i];
+
+       return NULL;
+}
+
+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];
+       }
+}
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h
new file mode 100644 (file)
index 0000000..66c9cf9
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef _MT753X_VLAN_H_
+#define _MT753X_VLAN_H_
+
+#define MT753X_NUM_PORTS       7
+#define MT753X_NUM_VLANS       4095
+#define MT753X_MAX_VID         4095
+#define MT753X_MIN_VID         0
+
+struct gsw_mt753x;
+
+struct mt753x_port_entry {
+       u16     pvid;
+};
+
+struct mt753x_vlan_entry {
+       u16     vid;
+       u8      member;
+       u8      etags;
+};
+
+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];
+};
+
+extern struct mt753x_mapping mt753x_defaults[];
+
+void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val);
+void mt753x_apply_vlan_config(struct gsw_mt753x *gsw);
+struct mt753x_mapping *mt753x_find_mapping(struct device_node *np);
+void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map);
+#endif /* _MT753X_VLAN_H_ */
index 8e4ef2ae1b06a2dec986c07e096e11964c5b6510..544ab753bf8facbfe440c333e11ef8de1ddb5e7e 100644 (file)
@@ -1,36 +1,44 @@
 --- a/drivers/net/phy/mtk/mt753x/Makefile
 +++ b/drivers/net/phy/mtk/mt753x/Makefile
-@@ -7,5 +7,5 @@ obj-$(CONFIG_MT753X_GSW)       += mt753x.o
- mt753x-$(CONFIG_SWCONFIG)     += mt753x_swconfig.o
+@@ -8,4 +8,4 @@
  
  mt753x-y                      += mt753x_mdio.o mt7530.o mt7531.o \
--                                      mt753x_common.o mt753x_nl.o
-+                                      mt753x_common.o mt753x_nl.o mt753x_phy.o
+                                       mt753x_common.o mt753x_vlan.o \
+-                                      mt753x_nl.o
++                                      mt753x_nl.o mt753x_phy.o
 --- a/drivers/net/phy/mtk/mt753x/mt7531.c
 +++ b/drivers/net/phy/mtk/mt753x/mt7531.c
-@@ -582,6 +582,18 @@ static void mt7531_core_pll_setup(struct
+@@ -454,6 +454,27 @@ static void mt7531_core_pll_setup(struct gsw_mt753x *gsw)
  
  static int mt7531_internal_phy_calibration(struct gsw_mt753x *gsw)
  {
 +      u32 i, val;
 +      int ret;
++
++      dev_info(gsw->dev,">>>>>>>>>>>>>>>>>>>>>>>>>>>>> START CALIBRATION:\n");
++
++      /* gphy value from sw path */
 +      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);
++
 +      for (i = 0; i < 5; i++) {
++              dev_info(gsw->dev, "-------- gephy-calbration (port:%d) --------\n",
++                       i);
 +              ret = mt753x_phy_calibration(gsw, i);
++
 +              /* set Auto-negotiation with giga extension. */
 +              gsw->mii_write(gsw, i, 0, 0x1340);
 +              if (ret)
 +                      return ret;
 +      }
++
        return 0;
  }
  
 --- a/drivers/net/phy/mtk/mt753x/mt753x.h
 +++ b/drivers/net/phy/mtk/mt753x/mt753x.h
-@@ -147,6 +147,8 @@ void mt753x_mmd_ind_write(struct gsw_mt7
+@@ -141,6 +141,8 @@ void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
  void mt753x_irq_worker(struct work_struct *work);
  void mt753x_irq_enable(struct gsw_mt753x *gsw);
  
@@ -41,7 +49,7 @@
  #define MMD_CMD_S                     14
 --- /dev/null
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
-@@ -0,0 +1,947 @@
+@@ -0,0 +1,1061 @@
 +// SPDX-License-Identifier:   GPL-2.0+
 +/*
 + * Common part for MediaTek MT753x gigabit switch
@@ -62,6 +70,9 @@
 +{
 +      u32 phy_val;
 +    phy_val = gsw->mmd_read(gsw, port_num, dev_addr, reg_addr);
++    
++    //printk("switch phy cl45 r %d 0x%x 0x%x = %x\n",port_num, dev_addr, reg_addr, phy_val);
++      //switch_phy_read_cl45(port_num, dev_addr, reg_addr, &phy_val);
 +      return phy_val;
 +}
 +
@@ -70,6 +81,8 @@
 +      u32 phy_val;
 +    gsw->mmd_write(gsw, port_num, dev_addr, reg_addr, write_data);
 +    phy_val = gsw->mmd_read(gsw, port_num, dev_addr, reg_addr);
++    //printk("switch phy cl45 w %d 0x%x 0x%x 0x%x --> read back 0x%x\n",port_num, dev_addr, reg_addr, write_data, phy_val);
++      //switch_phy_write_cl45(port_num, dev_addr, reg_addr, write_data);
 +}
 +
 +void switch_phy_write(struct gsw_mt753x *gsw, u32 port_num, u32 reg_addr, u32 write_data){
 +{
 +      u8 all_ana_cal_status;  
 +      u32 cnt, tmp_1e_17c;
++      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017c, 0x0001);     // da_calin_flag pull high
 +      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++      //printk("delay = %d\n", delay);
++      
 +      cnt = 10000;
 +      do {
 +              udelay(delay);
 +              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
 +              return all_ana_cal_status;
 +      } else {
-+              pr_info("MDC/MDIO error\n");
-+              return 0;
++              tmp_1e_17c = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c);
++              if ((tmp_1e_17c & 0x1) != 1) {
++                      pr_info("FIRST MDC/MDIO write error\n");
++                      pr_info("FIRST 1e_17c = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c));
++
++              }
++              printk("re-K again\n");
++        
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++              cnt = 10000;
++              do {
++                      udelay(delay);
++                      cnt--;
++                      tmp_1e_17c = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c);
++                      if ((tmp_1e_17c & 0x1) != 1) {
++                              pr_info("SECOND MDC/MDIO write error\n");
++                              pr_info("SECOND 1e_17c = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c));
++                              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++                              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++                              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
++                      }
++              } while ((cnt != 0) && (tmp_1e_17c == 0));
++
++              cnt = 10000;
++              do {
++                      udelay(delay);
++                      cnt--;
++                      all_ana_cal_status = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17b) & 0x1;
++      
++              } while ((all_ana_cal_status == 0) && (cnt != 0));
++      
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
 +      }
 +
++    if(all_ana_cal_status == 0){
++        pr_info("!!!!!!!!!!!! dev1Eh_reg17b ERROR\n");
++    }
++      
 +      return all_ana_cal_status;
 +}
 +
 +      u8 cnt = 0;
 +      u16 dev1e_17a_tmp, dev1e_e0_tmp;
 +
++      /* *** Iext/Rext Cal start ************ */
++      all_ana_cal_status = ANACAL_INIT;
++      /* analog calibration enable, Rext calibration enable */
++      /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */
++      /* 1e_dc[0]:rg_txvos_calen */
++      /* 1e_e1[4]:rg_cal_refsel(0:1.2V) */
 +      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x1110)
 +      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1110);
 +      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0000);
 +      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e1, 0x0000);
 +      //tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x10);
 +      
-+      rg_zcal_ctrl = 0x20;
-+      dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0xe0);
++      rg_zcal_ctrl = 0x20;/* start with 0 dB */
++      dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0xe0); // get default value
++      /* 1e_e0[5:0]:rg_zcal_ctrl */
 +      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0xe0, rg_zcal_ctrl);
 +      all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr);/* delay 20 usec */
++
 +      if (all_ana_cal_status == 0) {
 +              all_ana_cal_status = ANACAL_ERROR;
 +              printk(" GE Rext AnaCal ERROR init!   \r\n");
 +              return -1;
 +      }
++      /* 1e_17a[8]:ad_cal_comp_out */
 +      ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a) >> 8) & 0x1;
 +      if (ad_cal_comp_out_init == 1)
 +              calibration_polarity = -1;
 +                      dev1e_17a_tmp = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a);
 +                      dev1e_e0_tmp =  tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0xe0);
 +                      if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) {
-+                              all_ana_cal_status = ANACAL_SATURATION;
++                              all_ana_cal_status = ANACAL_SATURATION;  /* need to FT(IC fail?) */
 +                              printk(" GE Rext AnaCal Saturation!  \r\n");
 +                              rg_zcal_ctrl = 0x20;  /* 0 dB */
 +                      } 
 +      }
 +
 +      if (all_ana_cal_status == ANACAL_ERROR) {
-+              rg_zcal_ctrl = 0x20; 
++              rg_zcal_ctrl = 0x20;  /* 0 dB */
 +              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
 +      } else if(all_ana_cal_status == ANACAL_FINISH){
 +              //tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
 +              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, ((rg_zcal_ctrl << 8) | rg_zcal_ctrl));
 +              printk("0x1e-e0 = %x\n", tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x00e0));
++              /* ****  1f_115[2:0] = rg_zcal_ctrl[5:3]  // Mog review */
 +              tc_phy_write_dev_reg(gsw, PHY0, 0x1f, 0x0115, ((rg_zcal_ctrl & 0x3f) >> 3));
 +              printk("0x1f-115 = %x\n", tc_phy_read_dev_reg(gsw,  PHY0, 0x1f, 0x115));
 +              printk("  GE Rext AnaCal Done! (%d)(0x%x)  \r\n", cnt, rg_zcal_ctrl);
 +      u16 dev1e_e0_ana_cal_r5;
 +      int calibration_polarity;
 +      u8 cnt = 0;
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);  // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  // 1e_dc[0]:rg_txvos_calen
 +
 +      for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
-+              rg_zcal_ctrl = 0x20;
++              rg_zcal_ctrl = 0x20;                                            // start with 0 dB
 +              dev1e_e0_ana_cal_r5 = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x00e0) & (~0x003f));
-+              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++              tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));    // 1e_e0[5:0]:rg_zcal_ctrl
 +              if(calibration_pair == ANACAL_PAIR_A)
 +              {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1101);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1101);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
 +                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);       
 +                      //printk("R50 pair A 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
 +
 +              }
 +              else if(calibration_pair == ANACAL_PAIR_B)
 +              {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x1000);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x1000);       // 1e_dc[12]:rg_zcalen_b
 +                      //printk("R50 pair B 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db),tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
 +
 +              }
 +              else if(calibration_pair == ANACAL_PAIR_C)
 +              {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0100);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0100);       // 1e_dc[8]:rg_zcalen_c
 +                      //printk("R50 pair C 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
 +
 +              }
 +              else // if(calibration_pair == ANACAL_PAIR_D)
 +              {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0010);
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);       // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0010);       // 1e_dc[4]:rg_zcalen_d
 +                      //printk("R50 pair D 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x00dc));
 +
 +              }
 +                      return -1;
 +              }
 +      
-+              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8) & 0x1;
++              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8) & 0x1;                // 1e_17a[8]:ad_cal_comp_out    
 +              if(ad_cal_comp_out_init == 1)
 +                      calibration_polarity = -1;
 +              else
 +              }
 +              
 +              if(all_ana_cal_status == ANACAL_ERROR) {        
-+                      rg_zcal_ctrl = 0x20;
++                      rg_zcal_ctrl = 0x20;  // 0 dB
 +                      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
 +              }
 +              else {
-+                      rg_zcal_ctrl = MT753x_ZCAL_TO_R50ohm_GE_TBL_100[rg_zcal_ctrl - 9];
++                      rg_zcal_ctrl = MT753x_ZCAL_TO_R50ohm_GE_TBL_100[rg_zcal_ctrl - 9];      // wait Mog zcal/r50 mapping table
 +                      printk( " GE R50 AnaCal Done! (%d) (0x%x)(0x%x) \r\n", cnt, rg_zcal_ctrl, (rg_zcal_ctrl|0x80));
 +              }
 +              
 +                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174) & (~0x7f00);
 +                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174);
 +                      //printk( " GE-a 1e_174(0x%x)(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));       // 1e_174[15:8]
 +                      //printk( " GE-a 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
 +              }
 +              else if(calibration_pair == ANACAL_PAIR_B) {
 +                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174);
 +                      //printk( " GE-b 1e_174(0x%x)(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
 +                      
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));       // 1e_174[7:0]
 +                      //printk( " GE-b 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
 +              }
 +              else if(calibration_pair == ANACAL_PAIR_C) {
 +                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175) & (~0x7f00);
 +                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));       // 1e_175[15:8]
 +                      //printk( " GE-c 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
 +              } else {// if(calibration_pair == ANACAL_PAIR_D) 
 +                      ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175) & (~0x007f);
 +                      //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));       // 1e_175[7:0]
 +                      //printk( " GE-d 1e_174(0x%x), 1e_175(0x%x)  \r\n", tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x0175));
 +              }
 +              //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00e0, ((rg_zcal_ctrl<<8)|rg_zcal_ctrl));
 +      u8 tx_offset_reg_shift, tabl_idx, i;
 +      u8 cnt = 0;
 +      u16 tx_offset_reg, reg_temp, cal_temp;
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0100);
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0096, 0x8000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);
++      //switch_phy_write(phyaddr, R0, 0x2100);//harry tmp
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0100);  // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);  // 1e_dc[0]:rg_txvos_calen
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0096, 0x8000);       // 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);       // 1e_3e
 +      for(i = 0; i <= 4; i++)
 +              tc_phy_write_dev_reg(gsw, i, 0x1e, 0x00dd, 0x0000);     
 +      for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++)
 +
 +              if(calibration_pair == ANACAL_PAIR_A) {
 +                      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5010);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_0V));
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_0V));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);                               // 1e_dd[12]:rg_txg_calen_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_0V));   // 1e_17d:dac_in0_a
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_0V));   // 1e_181:dac_in1_a
 +                      //printk("tx offset pairA 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
 +                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0172) & (~0x3f00));
-+                      tx_offset_reg_shift = 8;
++                      tx_offset_reg_shift = 8;                                                                        // 1e_172[13:8]
 +                      tx_offset_reg = 0x0172;
 +
 +                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
 +              } else if(calibration_pair == ANACAL_PAIR_B) {
 +                      //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5018);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_0V));
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_0V));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);                               // 1e_dd[8]:rg_txg_calen_b
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_0V));   // 1e_17e:dac_in0_b
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_0V));   // 1e_182:dac_in1_b
 +                      //printk("tx offset pairB 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
 +                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0172) & (~0x003f));
-+                      tx_offset_reg_shift = 0;
++                      tx_offset_reg_shift = 0;                                                                        // 1e_172[5:0]
 +                      tx_offset_reg = 0x0172;
 +                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
 +              } else if(calibration_pair == ANACAL_PAIR_C) {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_0V));
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_0V));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);                               // 1e_dd[4]:rg_txg_calen_c
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_0V));   // 1e_17f:dac_in0_c
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_0V));   // 1e_183:dac_in1_c
 +                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0173) & (~0x3f00));
 +                      //printk("tx offset pairC 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
-+                      tx_offset_reg_shift = 8;
++                      tx_offset_reg_shift = 8;                                                                        // 1e_173[13:8]
 +                      tx_offset_reg = 0x0173;
 +                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
 +              } else {// if(calibration_pair == ANACAL_PAIR_D)
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_0V));
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_0V));
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);                               // 1e_dd[0]:rg_txg_calen_d
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_0V));   // 1e_180:dac_in0_d
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_0V));   // 1e_184:dac_in1_d
 +                      //printk("tx offset pairD 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
 +                      reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0173) & (~0x003f));
-+                      tx_offset_reg_shift = 0;
++                      tx_offset_reg_shift = 0;                                                                        // 1e_173[5:0]
 +                      tx_offset_reg = 0x0173;
 +                      //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
 +              }
-+              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++              tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));      // 1e_172, 1e_173
 +              all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
 +              if(all_ana_cal_status == 0) {
 +                      all_ana_cal_status = ANACAL_ERROR;      
 +                      return -1;
 +              }
 +      
-+              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1;
++              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1;         // 1e_17a[8]:ad_cal_comp_out    
 +              if(ad_cal_comp_out_init == 1)
 +                      calibration_polarity = 1;
 +              else
 +                              all_ana_cal_status = ANACAL_FINISH;     
 +                      } else {
 +                              if((tabl_idx == 0)||(tabl_idx == 0x3f)) {
-+                                      all_ana_cal_status = ANACAL_SATURATION;
++                                      all_ana_cal_status = ANACAL_SATURATION;  // need to FT
 +                                      printk( " GE Tx offset AnaCal Saturation!  \r\n");
 +                              }
 +                      }
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, 0x0000);
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, 0x0000);
 +      
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);  
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);       
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);  // disable analog calibration circuit
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);       // disable analog calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);       // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);       // disable Tx VLD force mode
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);       // disable Tx offset/amplitude calibration circuit      
 +}
 +
 +int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
 +      u32     tx_amp_reg_shift; 
 +      u16     reg_temp;
 +      u32     tx_amp_temp, tx_amp_reg, cnt=0, tx_amp_reg_100;
-+      u32     reg_backup, reg_tmp; 
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);          
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);          
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x0010);          
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);       
++      u32 debug_tmp, reg_backup, reg_tmp; 
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);  // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);  // 1e_dc[0]:rg_txvos_calen
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x0010);  // 1e_e1[4]:select 1V
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);       // 1e_3e:enable Tx VLD
 +
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x11, 0xff00);
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27a, 0x33);
 +      for(i = 0; i <= 4; i++)
 +              tc_phy_write_dev_reg(gsw, i, 0x1e, 0x00dd, 0x0000);
 +      for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
-+              tx_amp_temp = 0x20;
++              tx_amp_temp = 0x20;     // start with 0 dB
 +
 +              if(calibration_pair == ANACAL_PAIR_A) {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);                               // 1e_dd[12]
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_2V));   // 1e_17d
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_2V));   // 1e_181
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);                               // 1e_dd[12]:tx_a amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_2V));   // 1e_17d:dac_in0_a     
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_2V));   // 1e_181:dac_in1_a
 +                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x012) & (~0xfc00));
 +                      tx_amp_reg_shift = 10;                                                                          // 1e_12[15:10]
 +                      tx_amp_reg = 0x12;
 +                      tx_amp_reg_100 = 0x16;
 +              } else if(calibration_pair == ANACAL_PAIR_B) {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);                               // 1e_dd[8]
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_2V));   // 1e_17e
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_2V));   // 1e_182
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);                               // 1e_dd[8]:tx_b amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_2V));   // 1e_17e:dac_in0_b
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_2V));   // 1e_182:dac_in1_b
 +                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x017) & (~0x3f00));
 +                      tx_amp_reg_shift = 8;                                                                           // 1e_17[13:8]
 +                      tx_amp_reg = 0x17;
 +                      tx_amp_reg_100 = 0x18;
 +              } else if(calibration_pair == ANACAL_PAIR_C) {
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);                               // 1e_dd[4]
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_2V));   // 1e_17f
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_2V));   // 1e_183
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);                               // 1e_dd[4]:tx_c amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_2V));   // 1e_17f:dac_in0_c
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_2V));   // 1e_183:dac_in1_c
 +                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x019) & (~0x3f00));
 +                      tx_amp_reg_shift = 8;                                                                           // 1e_19[13:8]
 +                      tx_amp_reg = 0x19;
 +                      tx_amp_reg_100 = 0x20;
 +              } else { //if(calibration_pair == ANACAL_PAIR_D)
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);                               // 1e_dd[0]
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_2V));   // 1e_180
-+                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_2V));   // 1e_184
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);                               // 1e_dd[0]:tx_d amp calibration enable
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_2V));   // 1e_180:dac_in0_d
++                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_2V));   // 1e_184:dac_in1_d
 +                      reg_temp = (tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x021) & (~0x3f00));
 +                      tx_amp_reg_shift = 8;                                                                           // 1e_21[13:8]
 +                      tx_amp_reg = 0x21;
 +                      return -1;
 +              }
 +      
-+              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8) & 0x1;                // 1e_17a[8]
++              ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw,  PHY0, 0x1e, 0x017a)>>8) & 0x1;                // 1e_17a[8]:ad_cal_comp_out
 +              if(ad_cal_comp_out_init == 1)
 +                      calibration_polarity = -1;
 +              else
 +                                       reg_backup |= ((reg_tmp << 10) | (reg_tmp << 0));
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x12, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x12);
++                                      //printk("PORT[%d] 1e.012 = %x (OFFSET_1000M_PAIR_A)\n", phyaddr, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x16);
 +                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
 +                                      reg_tmp -= 8;
 +                                      reg_backup |= (reg_tmp << 0);
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x16, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x16);
++                                      //printk("PORT[%d] 1e.016 = %x (OFFSET_TESTMODE_1000M_PAIR_A)\n", phyaddr, reg_backup);
 +                              }
 +                              else if(calibration_pair == ANACAL_PAIR_B){
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x17);
 +                                       reg_backup |= ((reg_tmp << 8) | (reg_tmp << 0));
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x17, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x17);
++                                      //printk("PORT[%d] 1e.017 = %x (OFFSET_1000M_PAIR_B)\n", phyaddr, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x18);
 +                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
 +                                      reg_tmp -= 8;
 +                                      reg_backup |= (reg_tmp << 0);
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x18);
++                                      //printk("PORT[%d] 1e.018 = %x (OFFSET_TESTMODE_1000M_PAIR_B)\n", phyaddr, reg_backup);
 +                              }
 +                              else if(calibration_pair == ANACAL_PAIR_C){
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x19);
 +                                      reg_backup |= (reg_tmp << 8);
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x19, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x19);
++                                      //printk("PORT[%d] 1e.019 = %x (OFFSET_1000M_PAIR_C)\n", phyaddr, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x20);
 +                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
 +                                      reg_tmp -= 8;
 +                                      reg_backup |= (reg_tmp << 0);
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x20, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x20);
++                                      //printk("PORT[%d] 1e.020 = %x (OFFSET_TESTMODE_1000M_PAIR_C)\n", phyaddr, reg_backup);
 +                              }
 +                              else if(calibration_pair == ANACAL_PAIR_D){
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x21);
 +                                      reg_backup |= (reg_tmp << 8);
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x21, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x21);
++                                      //printk("PORT[%d] 1e.021 = %x (OFFSET_1000M_PAIR_D)\n", phyaddr, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x22);
 +                                      reg_tmp = ((reg_backup & 0x3f) >> 0);
 +                                      reg_tmp -= 8;
 +                                      reg_backup |= (reg_tmp << 0);
 +                                      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x22, reg_backup);
 +                                      reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x22);
++                                      //printk("PORT[%d] 1e.022 = %x (OFFSET_TESTMODE_1000M_PAIR_D)\n", phyaddr, reg_backup);
++                              }
++
++                              if (calibration_pair == ANACAL_PAIR_A){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x12);
++                                      //printk("1e.012 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x16);
++                                      //printk("1e.016 = 0x%x\n", debug_tmp);
++                              }
++      
++                              else if(calibration_pair == ANACAL_PAIR_B){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x17);
++                                      //printk("1e.017 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x18);
++                                      //printk("1e.018 = 0x%x\n", debug_tmp);
++                              }
++                              else if(calibration_pair == ANACAL_PAIR_C){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x19);
++                                      //printk("1e.019 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x20);
++                                      //printk("1e.020 = 0x%x\n", debug_tmp);
 +                              }
++                              else if(calibration_pair == ANACAL_PAIR_D){
++                                      //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x21);
++                                      //printk("1e.021 = 0x%x\n", debug_tmp);
++                                      debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x22);
++                                      //printk("1e.022 = 0x%x\n", debug_tmp);
++                              }
++
++
 +                              printk( " GE Tx amp AnaCal Done! (pair-%d)(1e_%x = 0x%x)\n", calibration_pair, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
 +                              
 +                      } else {
 +                              if((tx_amp_temp == 0x3f)||(tx_amp_temp == 0x00)) {
-+                                      all_ana_cal_status = ANACAL_SATURATION;
++                                      all_ana_cal_status = ANACAL_SATURATION;  // need to FT
 +                                      printk( " GE Tx amp AnaCal Saturation!  \r\n");
 +                              }
 +                      }
 +      
 +      /* disable analog calibration circuit */
 +      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);
-+      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);
++      tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);  // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);       // disable analog calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);       // disable Tx offset calibration circuit
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);       // disable Tx VLD force mode
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);       // disable Tx offset/amplitude calibration circuit
 +      
 +      
 +
 +      u32     reg_tmp,reg_tmp0, reg_tmp1, i;
 +      u32 CALDLY = 40;
 +      int ret;
++      /* set [12]AN disable, [8]full duplex, [13/6]1000Mbps */
++      //tc_phy_write_dev_reg(phyaddr, 0x0,  0x0140);
 +      switch_phy_write(gsw, phyaddr, R0, 0x140);
 +
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x145, 0x1010);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, RG_185, 0);
-+      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x100, 0xc000);
-+      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x403, 0x1099);
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x145, 0x1010);/* fix mdi */
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, RG_185, 0);/* disable tx slew control */
++      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x100, 0xc000);/* BG voltage output */
++      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x403, 0x1099); //bypass efuse
 +
 +#if (1)
++      //      1f_27c[12:8] cr_da_tx_i2mpb_10m Trimming TX bias setup(@10M)
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x1f1f);
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x3300);
 +
 +      reg_tmp1 = tc_phy_read_dev_reg(gsw,  PHY0, 0x1f, 0x27c);
++      //dev1Fh_reg273h TXVLD DA register      - Adjust voltage mode TX amplitude.
++      //tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0);
++      //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x273, 0x1000);
++      //reg_tmp1 = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x273);
++      //printk("reg_tmp1273 = %x\n", reg_tmp1);
++      /*1e_11 TX  overshoot Enable (PAIR A/B/C/D) in gbe mode*/
++
 +      reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x11);
 +      reg_tmp = reg_tmp | (0xf << 12);
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x11, reg_tmp);
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18e, 0x0001);
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18f, 0x0001);
 +
++      /*da_tx_bias1_b_tx_standby = 5'b10 (dev1eh_reg3aah[12:8])*/
 +      reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x3aa);
 +      reg_tmp = reg_tmp & ~(0x1f00);
 +      reg_tmp = reg_tmp | 0x2 << 8;
 +      tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3aa, reg_tmp);
 +
++      /*da_tx_bias1_a_tx_standby = 5'b10 (dev1eh_reg3a9h[4:0])*/
 +      reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x3a9);
 +      reg_tmp = reg_tmp & ~(0x1f);
 +      reg_tmp = reg_tmp | 0x2;
 +{
 +    u32 reg_tmp1;
 +
-+    //pr_info("PORT %d RX_DC_OFFSET\n", phyaddr);
++    pr_info("PORT %d RX_DC_OFFSET\n", phyaddr);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x96, 0x8000);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x37, 0x3);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x107, 0x4000);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x114f);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairA output = %x\n", reg_tmp);
 +    udelay(40);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1142);
 +    udelay(40);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairA output = %x\n", reg_tmp);
 +    if ((reg_tmp & 0x80) != 0)
 +        reg_tmp = (~reg_tmp) + 1;
 +    if ((reg_tmp & 0xff) >4)
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1151);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairB output = %x\n", reg_tmp);
 +    udelay(40);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1143);
 +    udelay(40);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairB output = %x\n", reg_tmp);
 +    if ((reg_tmp & 0x80) != 0)
 +        reg_tmp = (~reg_tmp) + 1;
 +    if ((reg_tmp & 0xff) >4)
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1153);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairC output = %x\n", reg_tmp);
 +    udelay(40);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1144);
 +    udelay(40);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairC output = %x\n", reg_tmp);
 +    if ((reg_tmp & 0x80) != 0)
 +        reg_tmp = (~reg_tmp) + 1;
 +    if ((reg_tmp & 0xff) >4)
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1155);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;
++    pr_info("before pairD output = %x\n", reg_tmp);
 +    udelay(40);
 +    tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1145);
 +    udelay(40);
 +    reg_tmp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1f, 0x1a);
 +    reg_tmp = reg_tmp & 0xff;   
++    pr_info("after pairD output = %x\n", reg_tmp);
 +    if ((reg_tmp & 0x80) != 0)
 +        reg_tmp = (~reg_tmp) + 1;
 +    if ((reg_tmp & 0xff) >4)
 +
 +      return ret;
 +}
+diff --git a/target/linux/generic/files/drivers/net/phy/mtk/mt753x/mt753x_phy.h b/target/linux/generic/files/drivers/net/phy/mtk/mt753x/mt753x_phy.h
+new file mode 100755
 --- /dev/null
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.h
 @@ -0,0 +1,145 @@