From: John Crispin Date: Wed, 28 Aug 2019 13:20:22 +0000 (+0200) Subject: mediatek: update v4.19 switch support to latest vendor version X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=4685fc0cf161f40cac638b11a03b4c2761416a22;p=oweals%2Fopenwrt.git mediatek: update v4.19 switch support to latest vendor version Signed-off-by: John Crispin --- diff --git a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts index 62a876c02f..557745ed90 100644 --- a/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/target/linux/mediatek/files-4.19/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* * Copyright (c) 2018 MediaTek Inc. * Author: Ryder Lee - * - * SPDX-License-Identifier: (GPL-2.0 OR MIT) */ /dts-v1/; @@ -16,13 +15,8 @@ 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 { @@ -49,10 +43,17 @@ wps { label = "wps"; linux,code = ; - gpios = <&pio 102 GPIO_ACTIVE_LOW>; + gpios = <&pio 102 GPIO_ACTIVE_HIGH>; }; }; + gsw: gsw@0 { + compatible = "mediatek,mt753x"; + mediatek,ethsys = <ðsys>; + #address-cells = <1>; + #size-cells = <0>; + }; + leds { compatible = "gpio-leds"; @@ -69,13 +70,6 @@ }; }; - gsw: gsw@0 { - compatible = "mediatek,mt753x"; - mediatek,ethsys = <ðsys>; - #address-cells = <1>; - #size-cells = <0>; - }; - memory { reg = <0 0x40000000 0 0x40000000>; }; @@ -105,6 +99,7 @@ regulator-boot-on; regulator-always-on; }; + }; &bch { @@ -122,23 +117,59 @@ }; ð { - pinctrl-names = "default"; - pinctrl-0 = <ð_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; }; }; }; @@ -540,35 +571,3 @@ pinctrl-0 = <&watchdog_pins>; status = "okay"; }; - -&gsw { - mediatek,mdio = <&mdio>; - mediatek,portmap = "llllw"; - mediatek,mdio_master_pinmux = <0>; - reset-gpios = <&pio 54 0>; - interrupt-parent = <&pio>; - interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - status = "okay"; - - port5: port@5 { - compatible = "mediatek,mt753x-port"; - reg = <5>; - phy-mode = "rgmii"; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - port6: port@6 { - compatible = "mediatek,mt753x-port"; - reg = <6>; - phy-mode = "sgmii"; - fixed-link { - speed = <2500>; - full-duplex; - }; - }; -}; - - diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig index cf83c6a436..d9e0230cf0 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig @@ -1,4 +1,3 @@ config MT753X_GSW tristate "Driver for the MediaTek MT753x switch" - diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile index 3829bacfe9..7aae451cd1 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile @@ -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 diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c index 45d4984c1a..014b83be9e 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -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); diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h index b4c8a02861..ef2d68417a 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h @@ -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_ diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c index 4d44141a61..5b9f359168 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -66,6 +62,11 @@ /* 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 @@ -142,7 +145,7 @@ #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. */ diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h index 736cb0c349..e4ef81e94a 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h @@ -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_ diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h index b9bca5416f..317b31ddcc 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _MT753X_H_ @@ -22,13 +18,10 @@ #include #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_ */ diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c index c836a63607..18f925956d 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -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); } diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c index 695713eed4..8a9a45c0be 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -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); diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c index 756df4e21f..78aecd34ed 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -17,10 +13,6 @@ #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), } }; diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h index f6a1df34e6..3c06273802 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _MT753X_NL_H_ diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h index 15255277ab..0c91b8e0ec 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _MT753X_REGS_H_ diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c index fb2ee1c1b7..b601b90fb1 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -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; diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h index 971a2cc90a..b877d8957e 100644 --- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h @@ -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 - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _MT753X_SWCONFIG_H_ #define _MT753X_SWCONFIG_H_ +#ifdef CONFIG_SWCONFIG #include +#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 index 0000000000..f3c8c38f3e --- /dev/null +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c @@ -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 index 0000000000..66c9cf984e --- /dev/null +++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h @@ -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_ */ diff --git a/target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch b/target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch index 8e4ef2ae1b..544ab753bf 100644 --- a/target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch +++ b/target/linux/mediatek/patches-4.19/0003-mt7531-gsw-internal_phy_calibration.patch @@ -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){ @@ -108,7 +121,10 @@ +{ + 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); @@ -122,10 +138,45 @@ + 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; +} + @@ -141,6 +192,12 @@ + 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); @@ -148,15 +205,18 @@ + //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; @@ -180,7 +240,7 @@ + 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 */ + } @@ -188,12 +248,13 @@ + } + + 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); @@ -215,38 +276,38 @@ + 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)); + + } @@ -259,7 +320,7 @@ + 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 @@ -293,11 +354,11 @@ + } + + 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)); + } + @@ -305,7 +366,7 @@ + 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) { @@ -313,18 +374,18 @@ + //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)); @@ -345,10 +406,11 @@ + 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 ++) @@ -358,45 +420,45 @@ + + 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<>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 @@ -431,7 +493,7 @@ + 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"); + } + } @@ -454,12 +516,12 @@ + 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) @@ -470,11 +532,11 @@ + 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); @@ -483,36 +545,36 @@ + 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; @@ -527,7 +589,7 @@ + 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 @@ -685,6 +747,7 @@ + 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; @@ -692,6 +755,7 @@ + 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); @@ -701,6 +765,7 @@ + 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; @@ -708,6 +773,7 @@ + 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); @@ -717,6 +783,7 @@ + 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; @@ -724,6 +791,7 @@ + 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); @@ -733,6 +801,7 @@ + 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; @@ -740,12 +809,45 @@ + 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"); + } + } @@ -767,11 +869,11 @@ + + /* 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 + + + @@ -788,18 +890,28 @@ + 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); @@ -856,11 +968,13 @@ + 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; @@ -872,7 +986,7 @@ +{ + 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); @@ -892,11 +1006,13 @@ + 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) @@ -911,11 +1027,13 @@ + 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) @@ -930,11 +1048,13 @@ + 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) @@ -949,11 +1069,13 @@ + 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) @@ -989,6 +1111,8 @@ + + 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 @@