[][Add MT7531 phy setting to dsa driver]
[Description]
Add MT7531 phy setting to dsa driver including
1. Disable EEE in default.
2. Adjust line driving for better link quality.
3. Adjust 100M eye diagram for compliance test.
4. Enable link down power saving.
5. Enable auto down shift from 1G to 100M if 1G signal is unstable.
6. SW phy calibration is disabled, and use calibration data in efuse.
[Release-log]
Add MT7531 phy setting to dsa driver including
1. Disable EEE in default.
2. Adjust line driving for better link quality.
3. Adjust 100M eye diagram for compliance test.
4. Enable link down power saving.
5. Enable auto down shift from 1G to 100M if 1G signal is unstable.
Change-Id: Id67a66e853dec76428961b2bc25c495f16f246d5
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4720227
diff --git a/target/linux/mediatek/patches-5.4/742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch b/target/linux/mediatek/patches-5.4/742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
new file mode 100644
index 0000000..ca7e083
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
@@ -0,0 +1,1687 @@
+Index: linux-5.4.124/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.124.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.124/drivers/net/dsa/mt7530.c
+@@ -1830,6 +1830,8 @@ mt7531_setup(struct dsa_switch *ds)
+ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ }
+
++ mt7531_phy_setup(ds);
++
+ /* Group and enable unused ports as a standalone dumb switch. */
+ setup_unused_ports(ds, unused_pm);
+
+Index: linux-5.4.124/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.124.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.124/drivers/net/dsa/mt7530.h
+@@ -782,4 +782,5 @@ static inline void INIT_MT7530_DUMMY_POL
+ p->reg = reg;
+ }
+
++int mt7531_phy_setup(struct dsa_switch *ds);
+ #endif /* __MT7530_H */
+Index: linux-5.4.124/drivers/net/dsa/mt7531_phy.c
+===================================================================
+--- /dev/null
++++ linux-5.4.124/drivers/net/dsa/mt7531_phy.c
+@@ -0,0 +1,1378 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Common part for MediaTek MT753x gigabit switch
++ *
++ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
++ *
++ * Author: Weijie Gao <weijie.gao@mediatek.com>
++ */
++
++#include <linux/delay.h>
++#include <linux/hrtimer.h>
++#include <linux/kernel.h>
++#include <net/dsa.h>
++#include "mt7530.h"
++#include "mt7531_phy.h"
++
++#define MT7531_NUM_PHYS 5
++
++static u32 tc_phy_read_dev_reg(struct dsa_switch *ds, u32 port_num, u32 dev_addr, u32 reg_addr)
++{
++ struct mt7530_priv *priv = ds->priv;
++ u32 phy_val;
++ u32 addr;
++
++ addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
++ phy_val = priv->info->phy_read(ds, port_num, addr);
++
++ //printk("switch phy cl45 r %d 0x%x 0x%x = %x\n",port_num, dev_addr, reg_addr, phy_val);
++ return phy_val;
++}
++
++static void tc_phy_write_dev_reg(struct dsa_switch *ds, u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data)
++{
++ struct mt7530_priv *priv = ds->priv;
++ u32 addr;
++
++ addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
++
++ priv->info->phy_write(ds, port_num, addr, write_data);
++
++ //u32 phy_val = priv->info->phy_read(ds, port_num, 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);
++}
++
++static void switch_phy_write(struct dsa_switch *ds, u32 port_num, u32 reg_addr, u32 write_data){
++ struct mt7530_priv *priv = ds->priv;
++
++ priv->info->phy_write(ds, port_num, reg_addr, write_data);
++}
++
++static u32 switch_phy_read(struct dsa_switch *ds, u32 port_num, u32 reg_addr){
++ struct mt7530_priv *priv = ds->priv;
++
++ return priv->info->phy_read(ds, port_num, reg_addr);
++}
++
++static void mt753x_tr_write(struct dsa_switch *ds, int addr, u8 ch, u8 node, u8 daddr,
++ u32 data)
++{
++ ktime_t timeout;
++ u32 timeout_us;
++ u32 val;
++
++ switch_phy_write(ds, addr, PHY_CL22_PAGE_CTRL, PHY_TR_PAGE);
++
++ val = switch_phy_read(ds, addr, PHY_TR_CTRL);
++
++ timeout_us = 100000;
++ timeout = ktime_add_us(ktime_get(), timeout_us);
++ while (1) {
++ val = switch_phy_read(ds, addr, PHY_TR_CTRL);
++
++ if (!!(val & PHY_TR_PKT_XMT_STA))
++ break;
++
++ if (ktime_compare(ktime_get(), timeout) > 0)
++ goto out;
++ }
++
++ switch_phy_write(ds, addr, PHY_TR_LOW_DATA, PHY_TR_LOW_VAL(data));
++ switch_phy_write(ds, addr, PHY_TR_HIGH_DATA, PHY_TR_HIGH_VAL(data));
++ val = PHY_TR_PKT_XMT_STA | (PHY_TR_WRITE << PHY_TR_WR_S) |
++ (ch << PHY_TR_CH_ADDR_S) | (node << PHY_TR_NODE_ADDR_S) |
++ (daddr << PHY_TR_DATA_ADDR_S);
++ switch_phy_write(ds, addr, PHY_TR_CTRL, val);
++
++ timeout_us = 100000;
++ timeout = ktime_add_us(ktime_get(), timeout_us);
++ while (1) {
++ val = switch_phy_read(ds, addr, PHY_TR_CTRL);
++
++ if (!!(val & PHY_TR_PKT_XMT_STA))
++ break;
++
++ if (ktime_compare(ktime_get(), timeout) > 0)
++ goto out;
++ }
++out:
++ switch_phy_write(ds, addr, PHY_CL22_PAGE_CTRL, 0);
++}
++
++static int mt753x_tr_read(struct dsa_switch *ds, int addr, u8 ch, u8 node, u8 daddr)
++{
++ ktime_t timeout;
++ u32 timeout_us;
++ u32 val;
++ u8 val_h;
++
++ switch_phy_write(ds, addr, PHY_CL22_PAGE_CTRL, PHY_TR_PAGE);
++
++ val = switch_phy_read(ds, addr, PHY_TR_CTRL);
++
++ timeout_us = 100000;
++ timeout = ktime_add_us(ktime_get(), timeout_us);
++ while (1) {
++ val = switch_phy_read(ds, addr, PHY_TR_CTRL);
++
++ if (!!(val & PHY_TR_PKT_XMT_STA))
++ break;
++
++ if (ktime_compare(ktime_get(), timeout) > 0) {
++ switch_phy_write(ds, addr, PHY_CL22_PAGE_CTRL, 0);
++ return -ETIMEDOUT;
++ }
++ }
++
++ val = PHY_TR_PKT_XMT_STA | (PHY_TR_READ << PHY_TR_WR_S) |
++ (ch << PHY_TR_CH_ADDR_S) | (node << PHY_TR_NODE_ADDR_S) |
++ (daddr << PHY_TR_DATA_ADDR_S);
++ switch_phy_write(ds, addr, PHY_TR_CTRL, val);
++
++ timeout_us = 100000;
++ timeout = ktime_add_us(ktime_get(), timeout_us);
++ while (1) {
++ val = switch_phy_read(ds, addr, PHY_TR_CTRL);
++
++ if (!!(val & PHY_TR_PKT_XMT_STA))
++ break;
++
++ if (ktime_compare(ktime_get(), timeout) > 0) {
++ switch_phy_write(ds, addr, PHY_CL22_PAGE_CTRL, 0);
++ return -ETIMEDOUT;
++ }
++ }
++
++ val = switch_phy_read(ds, addr, PHY_TR_LOW_DATA);
++ val_h = switch_phy_read(ds, addr, PHY_TR_HIGH_DATA);
++ val |= (val_h << 16);
++
++ switch_phy_write(ds, addr, PHY_CL22_PAGE_CTRL, 0);
++
++ return val;
++}
++
++static const u8 MT753x_ZCAL_TO_R50ohm_GE_TBL_100[64] = {
++ 127, 127, 127, 127, 127, 127, 127, 127,
++ 127, 127, 127, 127, 127, 123, 122, 117,
++ 115, 112, 103, 100, 98, 87, 85, 83,
++ 81, 72, 70, 68, 66, 64, 55, 53,
++ 52, 50, 49, 48, 38, 36, 35, 34,
++ 33, 32, 22, 21, 20, 19, 18, 17,
++ 16, 7, 6, 5, 4, 3, 2, 1,
++ 0, 0, 0, 0, 0, 0, 0, 0
++};
++
++static const u8 MT753x_TX_OFFSET_TBL[64] = {
++ 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
++ 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
++ 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,
++ 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0,
++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
++};
++
++static u8 ge_cal_flag;
++
++static u8 all_ge_ana_cal_wait(struct dsa_switch *ds, u32 delay, u32 phyaddr)
++{
++ u8 all_ana_cal_status;
++ u32 cnt, tmp_1e_17c;
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017c, 0x0001); // da_calin_flag pull high
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0x0001);
++ //printk("delay = %d\n", delay);
++
++ cnt = 10000;
++ do {
++ udelay(delay);
++ cnt--;
++ all_ana_cal_status = tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x17b) & 0x1;
++
++ } while ((all_ana_cal_status == 0) && (cnt != 0));
++
++
++ if(all_ana_cal_status == 1) {
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0);
++ return all_ana_cal_status;
++ } else {
++ tmp_1e_17c = tc_phy_read_dev_reg(ds, 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(ds, PHY0, 0x1e, 0x17c));
++
++ }
++ printk("re-K again\n");
++
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0x0001);
++ cnt = 10000;
++ do {
++ udelay(delay);
++ cnt--;
++ tmp_1e_17c = tc_phy_read_dev_reg(ds, 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(ds, PHY0, 0x1e, 0x17c));
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0x0001);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0x0001);
++ tc_phy_write_dev_reg(ds, 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(ds, PHY0, 0x1e, 0x17b) & 0x1;
++
++ } while ((all_ana_cal_status == 0) && (cnt != 0));
++
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x17c, 0);
++ }
++
++ if(all_ana_cal_status == 0){
++ pr_info("!!!!!!!!!!!! dev1Eh_reg17b ERROR\n");
++ }
++
++ return all_ana_cal_status;
++}
++
++
++
++
++static int ge_cal_rext(struct dsa_switch *ds, u8 phyaddr, u32 delay)
++{
++ u8 rg_zcal_ctrl, all_ana_cal_status;
++ u16 ad_cal_comp_out_init;
++ u16 dev1e_e0_ana_cal_r5;
++ int calibration_polarity;
++ u8 cnt = 0;
++ u16 dev1e_17a_tmp, dev1e_e0_tmp;
++
++ /* *** Iext/Rext Cal start ************ */
++ all_ana_cal_status = ANACAL_INIT;
++ /* analog calibration enable, Rext calibration enable */
++ /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */
++ /* 1e_dc[0]:rg_txvos_calen */
++ /* 1e_e1[4]:rg_cal_refsel(0:1.2V) */
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x1110)
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00db, 0x1110);
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0000);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00dc, 0);
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e1, 0x0000);
++ //tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e1, 0x10);
++
++ rg_zcal_ctrl = 0x20;/* start with 0 dB */
++ dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0xe0); // get default value
++ /* 1e_e0[5:0]:rg_zcal_ctrl */
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0xe0, rg_zcal_ctrl);
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, 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(ds, PHY0, 0x1e, 0x017a) >> 8) & 0x1;
++ if (ad_cal_comp_out_init == 1)
++ calibration_polarity = -1;
++ else /* ad_cal_comp_out_init == 0 */
++ calibration_polarity = 1;
++ cnt = 0;
++ while (all_ana_cal_status < ANACAL_ERROR) {
++ cnt++;
++ rg_zcal_ctrl += calibration_polarity;
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0xe0, (rg_zcal_ctrl));
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, delay, phyaddr); /* delay 20 usec */
++ dev1e_17a_tmp = tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a);
++ if (all_ana_cal_status == 0) {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk(" GE Rext AnaCal ERROR 2! \r\n");
++ return -1;
++ } else if (((dev1e_17a_tmp >> 8) & 0x1) != ad_cal_comp_out_init) {
++ all_ana_cal_status = ANACAL_FINISH;
++ //printk(" GE Rext AnaCal Done! (%d)(0x%x) \r\n", cnt, rg_zcal_ctrl);
++ } else {
++ dev1e_17a_tmp = tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a);
++ dev1e_e0_tmp = tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0xe0);
++ if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) {
++ all_ana_cal_status = ANACAL_SATURATION; /* need to FT(IC fail?) */
++ printk(" GE Rext AnaCal Saturation! \r\n");
++ rg_zcal_ctrl = 0x20; /* 0 dB */
++ }
++ }
++ }
++
++ if (all_ana_cal_status == ANACAL_ERROR) {
++ rg_zcal_ctrl = 0x20; /* 0 dB */
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++ } else if(all_ana_cal_status == ANACAL_FINISH){
++ //tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e0, ((rg_zcal_ctrl << 8) | rg_zcal_ctrl));
++ printk("0x1e-e0 = %x\n", tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x00e0));
++ /* **** 1f_115[2:0] = rg_zcal_ctrl[5:3] // Mog review */
++ tc_phy_write_dev_reg(ds, PHY0, 0x1f, 0x0115, ((rg_zcal_ctrl & 0x3f) >> 3));
++ printk("0x1f-115 = %x\n", tc_phy_read_dev_reg(ds, PHY0, 0x1f, 0x115));
++ printk(" GE Rext AnaCal Done! (%d)(0x%x) \r\n", cnt, rg_zcal_ctrl);
++ ge_cal_flag = 1;
++ } else {
++ printk("GE Rxet cal something wrong2\n");
++ }
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00db, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00db, 0x0000);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00dc, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dc, 0x0000);
++
++ return 0;
++}
++
++//-----------------------------------------------------------------
++static int ge_cal_r50(struct dsa_switch *ds, u8 phyaddr, u32 delay)
++{
++ u8 rg_zcal_ctrl, all_ana_cal_status, calibration_pair;
++ u16 ad_cal_comp_out_init;
++ u16 dev1e_e0_ana_cal_r5;
++ int calibration_polarity;
++ u8 cnt = 0;
++ tc_phy_write_dev_reg(ds, 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(ds, PHY0, 0x1e, 0x00dc, 0x0000); // 1e_dc[0]:rg_txvos_calen
++
++ for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
++ rg_zcal_ctrl = 0x20; // start with 0 dB
++ dev1e_e0_ana_cal_r5 = (tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x00e0) & (~0x003f));
++ tc_phy_write_dev_reg(ds, 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(ds, 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(ds, phyaddr, 0x1e, 0x00dc, 0x0000);
++ //printk("R50 pair A 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x00dc));
++
++ }
++ else if(calibration_pair == ANACAL_PAIR_B)
++ {
++ tc_phy_write_dev_reg(ds, 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(ds, 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(ds, phyaddr, 0x1e, 0x00db),tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x00dc));
++
++ }
++ else if(calibration_pair == ANACAL_PAIR_C)
++ {
++ tc_phy_write_dev_reg(ds, 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(ds, 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(ds, phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x00dc));
++
++ }
++ else // if(calibration_pair == ANACAL_PAIR_D)
++ {
++ tc_phy_write_dev_reg(ds, 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(ds, 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(ds, phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x00dc));
++
++ }
++
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, delay, phyaddr); // delay 20 usec
++ if(all_ana_cal_status == 0)
++ {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk( "GE R50 AnaCal ERROR init! \r\n");
++ return -1;
++ }
++
++ ad_cal_comp_out_init = (tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
++ if(ad_cal_comp_out_init == 1)
++ calibration_polarity = -1;
++ else
++ calibration_polarity = 1;
++
++ cnt = 0;
++ while(all_ana_cal_status < ANACAL_ERROR)
++ {
++ cnt ++;
++ rg_zcal_ctrl += calibration_polarity;
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, delay, phyaddr); // delay 20 usec
++
++ if(all_ana_cal_status == 0)
++ {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk( " GE R50 AnaCal ERROR 2! \r\n");
++ return -1;
++ }
++ else if(((tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a)>>8)&0x1) != ad_cal_comp_out_init)
++ {
++ all_ana_cal_status = ANACAL_FINISH;
++ }
++ else {
++ if((rg_zcal_ctrl == 0x3F)||(rg_zcal_ctrl == 0x00))
++ {
++ all_ana_cal_status = ANACAL_SATURATION; // need to FT
++ printk( " GE R50 AnaCal Saturation! \r\n");
++ }
++ }
++ }
++
++ if(all_ana_cal_status == ANACAL_ERROR) {
++ rg_zcal_ctrl = 0x20; // 0 dB
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
++ }
++ else {
++ rg_zcal_ctrl = MT753x_ZCAL_TO_R50ohm_GE_TBL_100[rg_zcal_ctrl - 9]; // wait Mog zcal/r50 mapping table
++ printk( " GE R50 AnaCal Done! (%d) (0x%x)(0x%x) \r\n", cnt, rg_zcal_ctrl, (rg_zcal_ctrl|0x80));
++ }
++
++ if(calibration_pair == ANACAL_PAIR_A) {
++ ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174) & (~0x7f00);
++ //ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174);
++ //printk( " GE-a 1e_174(0x%x)(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++ }
++ else if(calibration_pair == ANACAL_PAIR_B) {
++ ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174) & (~0x007f);
++ //ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174);
++ //printk( " GE-b 1e_174(0x%x)(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++ }
++ else if(calibration_pair == ANACAL_PAIR_C) {
++ ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175) & (~0x7f00);
++ //ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175);
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++ } else {// if(calibration_pair == ANACAL_PAIR_D)
++ ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175) & (~0x007f);
++ //ad_cal_comp_out_init = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175);
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++ }
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00e0, ((rg_zcal_ctrl<<8)|rg_zcal_ctrl));
++ }
++
++ printk( " GE 1e_174(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0175));
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00db, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00db, 0x0000);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00dc, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dc, 0x0000);
++
++ return 0;
++}
++
++static int ge_cal_tx_offset(struct dsa_switch *ds, u8 phyaddr, u32 delay)
++{
++ u8 all_ana_cal_status, calibration_pair;
++ u16 ad_cal_comp_out_init;
++ int calibration_polarity, tx_offset_temp;
++ u8 tx_offset_reg_shift, tabl_idx, i;
++ u8 cnt = 0;
++ u16 tx_offset_reg, reg_temp, cal_temp;
++ //switch_phy_write(phyaddr, R0, 0x2100);//harry tmp
++ tc_phy_write_dev_reg(ds, 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(ds, PHY0, 0x1e, 0x00dc, 0x0001); // 1e_dc[0]:rg_txvos_calen
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0096, 0x8000); // 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x003e, 0xf808); // 1e_3e
++ for(i = 0; i <= 4; i++)
++ tc_phy_write_dev_reg(ds, i, 0x1e, 0x00dd, 0x0000);
++ for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++)
++ {
++ tabl_idx = 31;
++ tx_offset_temp = MT753x_TX_OFFSET_TBL[tabl_idx];
++
++ if(calibration_pair == ANACAL_PAIR_A) {
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5010);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x1000); // 1e_dd[12]:rg_txg_calen_a
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_0V)); // 1e_17d:dac_in0_a
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0172) & (~0x3f00));
++ tx_offset_reg_shift = 8; // 1e_172[13:8]
++ tx_offset_reg = 0x0172;
++
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++ } else if(calibration_pair == ANACAL_PAIR_B) {
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5018);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x0100); // 1e_dd[8]:rg_txg_calen_b
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_0V)); // 1e_17e:dac_in0_b
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0172) & (~0x003f));
++ tx_offset_reg_shift = 0; // 1e_172[5:0]
++ tx_offset_reg = 0x0172;
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++ } else if(calibration_pair == ANACAL_PAIR_C) {
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x0010); // 1e_dd[4]:rg_txg_calen_c
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_0V)); // 1e_17f:dac_in0_c
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_0V)); // 1e_183:dac_in1_c
++ reg_temp = (tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x0173) & (~0x3f00));
++ //printk("tx offset pairC 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
++ tx_offset_reg_shift = 8; // 1e_173[13:8]
++ tx_offset_reg = 0x0173;
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++ } else {// if(calibration_pair == ANACAL_PAIR_D)
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x0001); // 1e_dd[0]:rg_txg_calen_d
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_0V)); // 1e_180:dac_in0_d
++ tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x0173) & (~0x003f));
++ tx_offset_reg_shift = 0; // 1e_173[5:0]
++ tx_offset_reg = 0x0173;
++ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++ }
++ tc_phy_write_dev_reg(ds, 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(ds, delay, phyaddr); // delay 20 usec
++ if(all_ana_cal_status == 0) {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk( " GE Tx offset AnaCal ERROR init! \r\n");
++ return -1;
++ }
++
++ ad_cal_comp_out_init = (tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
++ if(ad_cal_comp_out_init == 1)
++ calibration_polarity = 1;
++ else
++ calibration_polarity = -1;
++
++ cnt = 0;
++ //printk("TX offset cnt = %d, tabl_idx= %x, offset_val = %x\n", cnt, tabl_idx, MT753x_TX_OFFSET_TBL[tabl_idx]);
++ while(all_ana_cal_status < ANACAL_ERROR) {
++
++ cnt ++;
++ tabl_idx += calibration_polarity;
++ //tx_offset_temp += calibration_polarity;
++ //cal_temp = tx_offset_temp;
++ cal_temp = MT753x_TX_OFFSET_TBL[tabl_idx];
++ //printk("TX offset cnt = %d, tabl_idx= %x, offset_val = %x\n", cnt, tabl_idx, MT753x_TX_OFFSET_TBL[tabl_idx]);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(cal_temp<<tx_offset_reg_shift)));
++
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, delay, phyaddr); // delay 20 usec
++ if(all_ana_cal_status == 0) {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk( " GE Tx offset AnaCal ERROR init 2! \r\n");
++ return -1;
++ } else if(((tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a)>>8)&0x1) != ad_cal_comp_out_init) {
++ all_ana_cal_status = ANACAL_FINISH;
++ } else {
++ if((tabl_idx == 0)||(tabl_idx == 0x3f)) {
++ all_ana_cal_status = ANACAL_SATURATION; // need to FT
++ printk( " GE Tx offset AnaCal Saturation! \r\n");
++ }
++ }
++ }
++
++ if(all_ana_cal_status == ANACAL_ERROR) {
++ tx_offset_temp = TX_AMP_OFFSET_0MV;
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
++ } else {
++ printk( " GE Tx offset AnaCal Done! (pair-%d)(%d)(0x%x) 0x1e_%x=0x%x\n", calibration_pair, cnt, MT753x_TX_OFFSET_TBL[tabl_idx], tx_offset_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_offset_reg));
++ }
++ }
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017d, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017e, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017f, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0180, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0181, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0182, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0183, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0184, 0x0000);
++
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x003e, 0x0000); // disable Tx VLD force mode
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x0000); // disable Tx offset/amplitude calibration circuit
++
++ return 0;
++}
++
++u16 tx_amp_check_thres(int pair, u32 reg, u16 val, s16 offset)
++{
++ if ((offset < 0 && (0 - offset) > TX_AMP_MAX_OFFSET) ||
++ (offset > TX_AMP_MAX_OFFSET)) {
++ pr_info(" offset=%d exceed tx amp max offset=%d\n", offset, TX_AMP_MAX_OFFSET);
++ return val;
++ }
++
++ if (offset < 0 && val < TX_AMP_LOW_TS - offset) {
++ if (val < TX_AMP_LOWEST_TS - offset) {
++ pr_info(" GE Tx amp AnaCal underflow! (pair-%d)(1e_%x) seed 0x%x < 0x%x)\n",
++ pair, reg, val, TX_AMP_LOWEST_TS - offset);
++ }
++ return 0;
++ }
++
++ if (offset >= 0 && val > TX_AMP_HIGH_TS - offset) {
++ if ( val > TX_AMP_HIGHEST_TS - offset) {
++ pr_info(" GE Tx amp AnaCal overflow! (pair-%d)(1e_%x) seed = 0x%x > 0x%x)\n",
++ pair, reg, val, TX_AMP_HIGHEST_TS - offset);
++ }
++ return TX_AMP_MAX;
++ }
++
++ return val + offset;
++}
++
++static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
++{
++ u8 all_ana_cal_status, calibration_pair, i;
++ u16 ad_cal_comp_out_init;
++ int calibration_polarity;
++ u32 tx_amp_reg_shift;
++ u16 reg_temp;
++ u32 tx_amp_temp, tx_amp_reg, cnt=0, tx_amp_reg_100;
++ u32 debug_tmp, reg_backup, reg_tmp;
++ u32 orig_1e_11, orig_1f_300;
++
++ tc_phy_write_dev_reg(ds, 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(ds, PHY0, 0x1e, 0x00dc, 0x0001); // 1e_dc[0]:rg_txvos_calen
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e1, 0x0010); // 1e_e1[4]:select 1V
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x003e, 0xf808); // 1e_3e:enable Tx VLD
++
++ orig_1e_11 = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x11);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x11, 0xff00);
++// tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x27a, 0x33);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0xc9, 0xffff);
++ orig_1f_300 = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x300);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x300, 0x4);
++ for(i = 0; i <= 4; i++)
++ tc_phy_write_dev_reg(ds, i, 0x1e, 0x00dd, 0x0000);
++ for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
++ tx_amp_temp = 0x20; // start with 0 dB
++
++ if(calibration_pair == ANACAL_PAIR_A) {
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x1000); // 1e_dd[12]:tx_a amp calibration enable
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_2V)); // 1e_17d:dac_in0_a
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_2V)); // 1e_181:dac_in1_a
++ reg_temp = (tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x00dd, 0x0100); // 1e_dd[8]:tx_b amp calibration enable
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_2V)); // 1e_17e:dac_in0_b
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_2V)); // 1e_182:dac_in1_b
++ reg_temp = (tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x00dd, 0x0010); // 1e_dd[4]:tx_c amp calibration enable
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_2V)); // 1e_17f:dac_in0_c
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_2V)); // 1e_183:dac_in1_c
++ reg_temp = (tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x00dd, 0x0001); // 1e_dd[0]:tx_d amp calibration enable
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_2V)); // 1e_180:dac_in0_d
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_2V)); // 1e_184:dac_in1_d
++ reg_temp = (tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x021) & (~0x3f00));
++ tx_amp_reg_shift = 8; // 1e_21[13:8]
++ tx_amp_reg = 0x21;
++ tx_amp_reg_100 = 0x22;
++ }
++ tc_phy_write_dev_reg( ds, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift))); // 1e_12, 1e_17, 1e_19, 1e_21
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, delay, phyaddr); // delay 20 usec
++ if(all_ana_cal_status == 0) {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk( " GE Tx amp AnaCal ERROR init init! \r\n");
++ return -1;
++ }
++
++ ad_cal_comp_out_init = (tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
++ if(ad_cal_comp_out_init == 1)
++ calibration_polarity = -1;
++ else
++ calibration_polarity = 1;
++
++ cnt =0;
++ while(all_ana_cal_status < ANACAL_ERROR) {
++ cnt ++;
++ tx_amp_temp += calibration_polarity;
++ //printk("tx_amp : %x, 1e %x = %x\n", tx_amp_temp, tx_amp_reg, (reg_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++ tc_phy_write_dev_reg( ds, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100, (tx_amp_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++ all_ana_cal_status = all_ge_ana_cal_wait(ds, delay, phyaddr); // delay 20 usec
++ if(all_ana_cal_status == 0) {
++ all_ana_cal_status = ANACAL_ERROR;
++ printk( " GE Tx amp AnaCal ERROR 2! \r\n");
++ return -1;
++ } else if(((tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x017a)>>8)&0x1) != ad_cal_comp_out_init) {
++ //printk("TX AMP ANACAL_FINISH\n");
++ all_ana_cal_status = ANACAL_FINISH;
++ if (phyaddr == 0) {
++ if (calibration_pair == ANACAL_PAIR_A)
++ tx_amp_temp = tx_amp_temp - 2;
++ else if(calibration_pair == ANACAL_PAIR_B)
++ tx_amp_temp = tx_amp_temp - 1;
++ else if(calibration_pair == ANACAL_PAIR_C)
++ tx_amp_temp = tx_amp_temp - 2;
++ else if(calibration_pair == ANACAL_PAIR_D)
++ tx_amp_temp = tx_amp_temp - 1;
++ } else if (phyaddr == 1) {
++ if (calibration_pair == ANACAL_PAIR_A)
++ tx_amp_temp = tx_amp_temp - 1;
++ else if(calibration_pair == ANACAL_PAIR_B)
++ tx_amp_temp = tx_amp_temp ;
++ else if(calibration_pair == ANACAL_PAIR_C)
++ tx_amp_temp = tx_amp_temp - 1;
++ else if(calibration_pair == ANACAL_PAIR_D)
++ tx_amp_temp = tx_amp_temp - 1;
++ } else if (phyaddr == 2) {
++ if (calibration_pair == ANACAL_PAIR_A)
++ tx_amp_temp = tx_amp_temp;
++ else if(calibration_pair == ANACAL_PAIR_B)
++ tx_amp_temp = tx_amp_temp - 1;
++ else if(calibration_pair == ANACAL_PAIR_C)
++ tx_amp_temp = tx_amp_temp;
++ else if(calibration_pair == ANACAL_PAIR_D)
++ tx_amp_temp = tx_amp_temp - 1;
++ } else if (phyaddr == 3) {
++ tx_amp_temp = tx_amp_temp;
++ } else if (phyaddr == 4) {
++ if (calibration_pair == ANACAL_PAIR_A)
++ tx_amp_temp = tx_amp_temp;
++ else if(calibration_pair == ANACAL_PAIR_B)
++ tx_amp_temp = tx_amp_temp - 1;
++ else if(calibration_pair == ANACAL_PAIR_C)
++ tx_amp_temp = tx_amp_temp;
++ else if(calibration_pair == ANACAL_PAIR_D)
++ tx_amp_temp = tx_amp_temp;
++ }
++ reg_temp = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg)&(~0xff00);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
++ if (phyaddr == 0) {
++ if ((tx_amp_reg == 0x12) || (tx_amp_reg == 0x17)) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 7);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if (tx_amp_reg_100 == 0x16) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, 1+4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ if (tx_amp_reg_100 == 0x18) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, 4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ } else if (phyaddr == 1) {
++ if (tx_amp_reg == 0x12) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 9);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if (tx_amp_reg == 0x17){
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 7);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if (tx_amp_reg_100 == 0x16) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, 4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ if (tx_amp_reg_100 == 0x18) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, -1+4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ } else if (phyaddr == 2) {
++ if ((tx_amp_reg == 0x12) || (tx_amp_reg == 0x17)) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 6);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if ((tx_amp_reg_100 == 0x16) || (tx_amp_reg_100 == 0x18)) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, -1+4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ } else if (phyaddr == 3) {
++ if (tx_amp_reg == 0x12) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if (tx_amp_reg == 0x17) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 7);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if (tx_amp_reg_100 == 0x16) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, -2+4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ if (tx_amp_reg_100 == 0x18) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, -1+3);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ } else if (phyaddr == 4) {
++ if ((tx_amp_reg == 0x12) || (tx_amp_reg == 0x17)) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg, tx_amp_temp, 5);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, ((reg_tmp|((tx_amp_temp)<<tx_amp_reg_shift))));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg));
++ }
++ if (tx_amp_reg_100 == 0x16) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, -2+4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
++ if (tx_amp_reg_100 == 0x18) {
++ //printk("before : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ reg_tmp = tx_amp_check_thres(calibration_pair, tx_amp_reg_100, tx_amp_temp, -1+4);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((reg_tmp)<<tx_amp_reg_shift)));
++ //printk("after : PORT[%d] 1e_%x = %x\n", phyaddr, tx_amp_reg_100, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100));
++ }
+ }
++
++ if (calibration_pair == ANACAL_PAIR_A){
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x12);
++ reg_tmp = ((reg_backup & 0xfc00) >> 10);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = 0x0000;
++ reg_backup |= ((tx_amp_temp << 10) | (tx_amp_temp << 0));
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x12, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x12);
++ //printk("PORT[%d] 1e.012 = %x (OFFSET_1000M_PAIR_A)\n", phyaddr, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x16);
++ reg_tmp = ((reg_backup & 0x3f) >> 0);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = (reg_backup & (~0x3f));
++ reg_backup |= (tx_amp_temp << 0);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x16, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x17);
++ reg_tmp = ((reg_backup & 0x3f00) >> 8);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = 0x0000;
++ reg_backup |= ((tx_amp_temp << 8) | (tx_amp_temp << 0));
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x17, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x17);
++ //printk("PORT[%d] 1e.017 = %x (OFFSET_1000M_PAIR_B)\n", phyaddr, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x18);
++ reg_tmp = ((reg_backup & 0x3f) >> 0);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = (reg_backup & (~0x3f));
++ reg_backup |= (tx_amp_temp << 0);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x18, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x19);
++ reg_tmp = ((reg_backup & 0x3f00) >> 8);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = (reg_backup & (~0x3f00));
++ reg_backup |= (tx_amp_temp << 8);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x19, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x19);
++ //printk("PORT[%d] 1e.019 = %x (OFFSET_1000M_PAIR_C)\n", phyaddr, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x20);
++ reg_tmp = ((reg_backup & 0x3f) >> 0);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = (reg_backup & (~0x3f));
++ reg_backup |= (tx_amp_temp << 0);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x20, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x21);
++ reg_tmp = ((reg_backup & 0x3f00) >> 8);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = (reg_backup & (~0x3f00));
++ reg_backup |= (tx_amp_temp << 8);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x21, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x21);
++ //printk("PORT[%d] 1e.021 = %x (OFFSET_1000M_PAIR_D)\n", phyaddr, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x22);
++ reg_tmp = ((reg_backup & 0x3f) >> 0);
++ tx_amp_temp = tx_amp_check_thres(calibration_pair, tx_amp_reg, reg_tmp, -8);
++ reg_backup = (reg_backup & (~0x3f));
++ reg_backup |= (tx_amp_temp << 0);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x22, reg_backup);
++ reg_backup = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x12);
++ //printk("1e.012 = 0x%x\n", debug_tmp);
++ debug_tmp = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x17);
++ //printk("1e.017 = 0x%x\n", debug_tmp);
++ debug_tmp = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x19);
++ //printk("1e.019 = 0x%x\n", debug_tmp);
++ debug_tmp = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1e, 0x21);
++ //printk("1e.021 = 0x%x\n", debug_tmp);
++ debug_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x22);
++ //printk("1e.022 = 0x%x\n", debug_tmp);
++ }
++
++
++ printk( " GE Tx amp AnaCal Done! (pair-%d)(1e_%x = 0x%x)(0x%x)\n", calibration_pair, tx_amp_reg, tc_phy_read_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg), reg_tmp);
++
++ } else {
++ if((tx_amp_temp == 0x3f)||(tx_amp_temp == 0x00)) {
++ all_ana_cal_status = ANACAL_SATURATION; // need to FT
++ printk( " GE Tx amp AnaCal Saturation! \r\n");
++ }
++ }
++ }
++
++ if(all_ana_cal_status == ANACAL_ERROR) {
++ tx_amp_temp = 0x20;
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg, (reg_temp|(tx_amp_temp<<tx_amp_reg_shift)));
++ }
++ }
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017d, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017e, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x017f, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0180, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0181, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0182, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0183, 0x0000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x0184, 0x0000);
++
++ /* disable analog calibration circuit */
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00db, 0x0000);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x003e, 0x0000); // disable Tx VLD force mode
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x00dd, 0x0000); // disable Tx offset/amplitude calibration circuit
++
++
++
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x273, 0x2000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0xc9, 0x0fff);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x145, 0x1000);
++
++ /* Restore CR to default */
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x11, orig_1e_11);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x300, orig_1f_300);
++
++ return 0;
++}
++
++//-----------------------------------------------------------------
++
++static int phy_calibration(struct dsa_switch *ds, u8 phyaddr)
++{
++ //u32 reg_tmp,reg_tmp0, reg_tmp1, i;
++ u32 reg_tmp;
++ u32 CALDLY = 40;
++ u32 orig_1e_11, orig_1e_185, orig_1e_e1, orig_1f_100;
++ int ret;
++
++ /* Use SW calibration data. */
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x403);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x403, reg_tmp | BIT(3));
++ /* set [12]AN disable, [8]full duplex, [13/6]1000Mbps */
++ //tc_phy_write_dev_reg(phyaddr, 0x0, 0x0140);
++ switch_phy_write(ds, phyaddr, R0, 0x140);
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x145, 0x1010);/* fix mdi */
++ orig_1e_185 = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, RG_185);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, RG_185, 0);/* disable tx slew control */
++ orig_1f_100 = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x100);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x100, 0xc000);/* BG voltage output */
++ //tc_phy_write_dev_reg(ds, 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(ds, phyaddr, 0x1f, 0x27c, 0x1f1f);
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x27c, 0x3300);
++
++ //reg_tmp1 = tc_phy_read_dev_reg(ds, 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(ds, phyaddr, 0x1f, 0x273, 0x1000);
++ //reg_tmp1 = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x273);
++ //printk("reg_tmp1273 = %x\n", reg_tmp1);
++ /*1e_11 TX overshoot Enable (PAIR A/B/C/D) in gbe mode*/
++
++ orig_1e_11 = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x11);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x11);
++ reg_tmp = reg_tmp | (0xf << 12);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x11, reg_tmp);
++ orig_1e_e1 = tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0x00e1);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e1, 0x10);
++ /* calibration start ============ */
++ printk("CALDLY = %d\n", CALDLY);
++ if(ge_cal_flag == 0){
++ ret = ge_cal_rext(ds, 0, CALDLY);
++ if (ret == -1){
++ printk("ge_cal_rext error K port =%d\n", phyaddr);
++ return ret;
++ }
++ ge_cal_flag = 1;
++ }
++
++ /* *** R50 Cal start ***************************** */
++ /*phyaddress = 0*/
++ ret = ge_cal_r50(ds, phyaddr, CALDLY);
++ if (ret == -1){
++ printk("R50 error K port =%d\n", phyaddr);
++ return ret;
++ }
++ /* *** R50 Cal end *** */
++ /* *** Tx offset Cal start *********************** */
++ ret = ge_cal_tx_offset(ds, phyaddr, CALDLY);
++ if (ret == -1){
++ printk("ge_cal_tx_offset error K port =%d\n", phyaddr);
++ return ret;
++ }
++ /* *** Tx offset Cal end *** */
++
++ /* *** Tx Amp Cal start *** */
++ ret = ge_cal_tx_amp(ds, phyaddr, CALDLY);
++ if (ret == -1){
++ printk("ge_cal_tx_amp error K port =%d\n", phyaddr);
++ return ret;
++ }
++ /* *** Tx Amp Cal end *** */
++ /*tmp maybe changed*/
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x27c, 0x1111);
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x27b, 0x47);
++ //tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x273, 0x2000);
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3a8, 0x0810);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3aa, 0x0008);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3ab, 0x0810);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3ad, 0x0008);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3ae, 0x0106);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3b0, 0x0001);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3b1, 0x0106);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3b3, 0x0001);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x18c, 0x0001);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x18d, 0x0001);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x18e, 0x0001);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x18f, 0x0001);
++
++ /*da_tx_bias1_b_tx_standby = 5'b10 (dev1eh_reg3aah[12:8])*/
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x3aa);
++ reg_tmp = reg_tmp & ~(0x1f00);
++ reg_tmp = reg_tmp | 0x2 << 8;
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3aa, reg_tmp);
++
++ /*da_tx_bias1_a_tx_standby = 5'b10 (dev1eh_reg3a9h[4:0])*/
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1e, 0x3a9);
++ reg_tmp = reg_tmp & ~(0x1f);
++ reg_tmp = reg_tmp | 0x2;
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x3a9, reg_tmp);
++
++ /* Restore CR to default */
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, RG_185, orig_1e_185);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x100, orig_1f_100);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x11, orig_1e_11);
++ tc_phy_write_dev_reg(ds, PHY0, 0x1e, 0x00e1, orig_1e_e1);
++#endif
++ return 0;
++}
++
++static void rx_dc_offset(struct dsa_switch *ds, u8 phyaddr)
++{
++ pr_info("PORT %d RX_DC_OFFSET\n", phyaddr);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x96, 0x8000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x37, 0x3);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x107, 0x4000);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x171, 0x1e5);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x39, 0x200f);
++ udelay(40);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x39, 0x000f);
++ udelay(40);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x171, 0x65);
++}
++
++static void check_rx_dc_offset_pair_a(struct dsa_switch *ds, u8 phyaddr)
++{
++ u32 reg_tmp;
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x114f);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("before pairA output = %x\n", reg_tmp);
++ udelay(40);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1142);
++ udelay(40);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("after pairA output = %x\n", reg_tmp);
++ if ((reg_tmp & 0x80) != 0)
++ reg_tmp = (~reg_tmp) + 1;
++ if ((reg_tmp & 0xff) >4)
++ pr_info("pairA RX_DC_OFFSET error");
++}
++
++static void check_rx_dc_offset_pair_b(struct dsa_switch *ds, u8 phyaddr)
++{
++ u32 reg_tmp;
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1151);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("before pairB output = %x\n", reg_tmp);
++ udelay(40);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1143);
++ udelay(40);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("after pairB output = %x\n", reg_tmp);
++ if ((reg_tmp & 0x80) != 0)
++ reg_tmp = (~reg_tmp) + 1;
++ if ((reg_tmp & 0xff) >4)
++ pr_info("pairB RX_DC_OFFSET error");
++}
++
++static void check_rx_dc_offset_pair_c(struct dsa_switch *ds, u8 phyaddr)
++{
++ u32 reg_tmp;
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1153);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("before pairC output = %x\n", reg_tmp);
++ udelay(40);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1144);
++ udelay(40);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("after pairC output = %x\n", reg_tmp);
++ if ((reg_tmp & 0x80) != 0)
++ reg_tmp = (~reg_tmp) + 1;
++ if ((reg_tmp & 0xff) >4)
++ pr_info("pairC RX_DC_OFFSET error");
++}
++
++static void check_rx_dc_offset_pair_d(struct dsa_switch *ds, u8 phyaddr)
++{
++ u32 reg_tmp;
++
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1155);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("before pairD output = %x\n", reg_tmp);
++ udelay(40);
++ tc_phy_write_dev_reg(ds, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1145);
++ udelay(40);
++ reg_tmp = tc_phy_read_dev_reg(ds, phyaddr, 0x1f, 0x1a);
++ reg_tmp = reg_tmp & 0xff;
++ pr_info("after pairD output = %x\n", reg_tmp);
++ if ((reg_tmp & 0x80) != 0)
++ reg_tmp = (~reg_tmp) + 1;
++ if ((reg_tmp & 0xff) >4)
++ pr_info("pairD RX_DC_OFFSET error");
++}
++
++/* 12 registers for TX_MLT3 waveform tuning.
++ * 012 345 678 9ab
++ * 1 __
++ * _/ \_
++ * 0_/ \
++ * \_ _/
++ * -1 \__/
++ */
++static void mt7531_phy_100m_eye_diag_setting(struct dsa_switch *ds, u32 port)
++{
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x0, 0x187);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x1, 0x1c9);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x2, 0x1c6);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x3, 0x182);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x4, 0x208);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x5, 0x205);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x6, 0x384);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x7, 0x3cb);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x8, 0x3c4);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0x9, 0x30a);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0xa, 0x00b);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_TX_MLT3_BASE + 0xb, 0x002);
++}
++
++static void mt7531_phy_setting(struct dsa_switch *ds)
++{
++ int i;
++ u32 val;
++
++ for (i = 0; i < MT7531_NUM_PHYS; i++) {
++ mt7531_phy_100m_eye_diag_setting(ds, i);
++
++ /* Enable HW auto downshift */
++ switch_phy_write(ds, i, 0x1f, 0x1);
++ val = switch_phy_read(ds, i, PHY_EXT_REG_14);
++ val |= PHY_EN_DOWN_SHFIT;
++ switch_phy_write(ds, i, PHY_EXT_REG_14, val);
++
++ /* Decrease SlvDPSready time */
++ val = mt753x_tr_read(ds, i, PMA_CH, PMA_NOD, PMA_17);
++ val &= ~SLV_DSP_READY_TIME_M;
++ val |= 0xc << SLV_DSP_READY_TIME_S;
++ mt753x_tr_write(ds, i, PMA_CH, PMA_NOD, PMA_17, val);
++
++ /* Enable Random Update Mechanism */
++ val = mt753x_tr_read(ds, i, PMA_CH, PMA_NOD, PMA_18);
++ val |= ENABLE_RANDOM_UPDATE_TRIGGER;
++ mt753x_tr_write(ds, i, PMA_CH, PMA_NOD, PMA_18, val);
++
++ /* PHY link down power saving enable */
++ val = switch_phy_read(ds, i, PHY_EXT_REG_17);
++ val |= PHY_LINKDOWN_POWER_SAVING_EN;
++ switch_phy_write(ds, i, PHY_EXT_REG_17, val);
++
++ val = tc_phy_read_dev_reg(ds, i, PHY_DEV1E, PHY_DEV1E_REG_0C6);
++ val &= ~PHY_POWER_SAVING_M;
++ val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
++ tc_phy_write_dev_reg(ds, i, PHY_DEV1E, PHY_DEV1E_REG_0C6, val);
++
++ /* Timing Recovery for GbE slave mode */
++ mt753x_tr_write(ds, i, PMA_CH, PMA_NOD, PMA_01, 0x6fb90a);
++ mt753x_tr_write(ds, i, DSP_CH, DSP_NOD, DSP_06, 0x2ebaef);
++ val = tc_phy_read_dev_reg(ds, i, PHY_DEV1E, PHY_DEV1E_REG_234);
++ val |= TR_OPEN_LOOP_EN;
++ tc_phy_write_dev_reg(ds, i, PHY_DEV1E, PHY_DEV1E_REG_234, val);
++
++ /* Enable Asymmetric Pause Capability */
++ val = switch_phy_read(ds, i, MII_ADVERTISE);
++ val |= ADVERTISE_PAUSE_ASYM;
++ switch_phy_write(ds, i, MII_ADVERTISE, val);
++ }
++}
++
++static void mt7531_adjust_line_driving(struct dsa_switch *ds, u32 port)
++{
++ /* For ADC timing margin window for LDO calibration */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, RXADC_LDO_CONTROL_2, 0x2222);
++
++ /* Adjust AD sample timing */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, RXADC_CONTROL_3, 0x4444);
++
++ /* Adjust Line driver current for different mode */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, TXVLD_DA_271, 0x2ca5);
++
++ /* Adjust Line driver current for different mode */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, TXVLD_DA_272, 0xc6b);
++
++ /* Adjust Line driver gain for 10BT from 1000BT calibration result */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, TXVLD_DA_273, 0x3000);
++
++ /* Adjust RX Echo path filter */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_0FE, 0x2);
++
++ /* Adjust RX HVGA bias current */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_41, 0x3333);
++
++ /* Adjust TX class AB driver 1 */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x384);
++
++ /* Adjust TX class AB driver 2 */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0x1114);
++
++ /* Adjust DAC delay for TX Pairs */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_13, 0x404);
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_14, 0x404);
++
++ /* Adjust DAC digital delay for TX Delay */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, PHY_DEV1F_REG_44, 0xc0);
++
++ /* Adjust Line driver compensation cap for stability concern due to
++ * increase current.
++ */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1F, PHY_DEV1F_REG_26A, 0x3333);
++}
++
++static void mt7531_eee_setting(struct dsa_switch *ds, u32 port)
++{
++ u32 val;
++
++ /* Disable EEE */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
++
++ /* Disable generate signal to clear the scramble_lock when lpi mode */
++ val = tc_phy_read_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_189);
++ val &= ~DESCRAMBLER_CLEAR_EN;
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_189, val);
++
++ /* Roll back EEE Slave Mode */
++ tc_phy_write_dev_reg(ds, port, 0x1e, 0x2d1, 0);
++ mt753x_tr_write(ds, port, DSP_CH, DSP_NOD, DSP_08, 0x1b);
++ mt753x_tr_write(ds, port, DSP_CH, DSP_NOD, DSP_0f, 0);
++ mt753x_tr_write(ds, port, DSP_CH, DSP_NOD, DSP_10, 0x5000);
++
++ /* Adjust 100_mse_threshold */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_123, 0xffff);
++
++ /* Disable mcc */
++ tc_phy_write_dev_reg(ds, port, PHY_DEV1E, PHY_DEV1E_REG_A6, 0x300);
++}
++
++int mt7531_phy_setup(struct dsa_switch *ds)
++{
++ int ret;
++ int i;
++
++ mt7531_phy_setting(ds);
++
++ for (i = 0; i < MT7531_NUM_PHYS; i++) {
++ mt7531_adjust_line_driving(ds, i);
++ mt7531_eee_setting(ds, i);
++ }
++
++ /*for (i = 0; i < MT7531_NUM_PHYS; i++) {
++ ret = phy_calibration(ds, i);
++
++ rx_dc_offset(ds, i);
++ check_rx_dc_offset_pair_a(ds, i);
++ check_rx_dc_offset_pair_b(ds, i);
++ check_rx_dc_offset_pair_c(ds, i);
++ check_rx_dc_offset_pair_d(ds, i);
++
++ switch_phy_write(ds, i, 0, 0x1040);
++ }*/
++
++ return ret;
++}
+Index: linux-5.4.124/drivers/net/dsa/mt7531_phy.h
+===================================================================
+--- /dev/null
++++ linux-5.4.124/drivers/net/dsa/mt7531_phy.h
+@@ -0,0 +1,262 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Register definitions for MediaTek MT753x Gigabit switches
++ *
++ * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
++ *
++ * Author: Weijie Gao <weijie.gao@mediatek.com>
++ */
++
++#ifndef _MT753X_PHY_H_
++#define _MT753X_PHY_H_
++
++#include <linux/bitops.h>
++
++/*phy calibration use*/
++#define DEV_1E 0x1E
++/*global device 0x1f, always set P0*/
++#define DEV_1F 0x1F
++
++
++/************IEXT/REXT CAL***************/
++/* bits range: for example BITS(16,23) = 0xFF0000*/
++#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
++#define ANACAL_INIT 0x01
++#define ANACAL_ERROR 0xFD
++#define ANACAL_SATURATION 0xFE
++#define ANACAL_FINISH 0xFF
++#define ANACAL_PAIR_A 0
++#define ANACAL_PAIR_B 1
++#define ANACAL_PAIR_C 2
++#define ANACAL_PAIR_D 3
++#define DAC_IN_0V 0x00
++#define DAC_IN_2V 0xf0
++#define TX_AMP_OFFSET_0MV 0x20
++#define TX_AMP_OFFSET_VALID_BITS 6
++
++#define R0 0
++#define PHY0 0
++#define PHY1 1
++#define PHY2 2
++#define PHY3 3
++#define PHY4 4
++#define ANA_TEST_MODE BITS(8, 15)
++#define TST_TCLK_SEL BITs(6, 7)
++#define ANA_TEST_VGA_RG 0x100
++
++#define FORCE_MDI_CROSS_OVER BITS(3, 4)
++#define T10_TEST_CTL_RG 0x145
++#define RG_185 0x185
++#define RG_TX_SLEW BIT(0)
++#define ANA_CAL_0 0xdb
++#define RG_CAL_CKINV BIT(12)
++#define RG_ANA_CALEN BIT(8)
++#define RG_REXT_CALEN BIT(4)
++#define RG_ZCALEN_A BIT(0)
++#define ANA_CAL_1 0xdc
++#define RG_ZCALEN_B BIT(12)
++#define RG_ZCALEN_C BIT(8)
++#define RG_ZCALEN_D BIT(4)
++#define RG_TXVOS_CALEN BIT(0)
++#define ANA_CAL_6 0xe1
++#define RG_CAL_REFSEL BIT(4)
++#define RG_CAL_COMP_PWD BIT(0)
++#define ANA_CAL_5 0xe0
++#define RG_REXT_TRIM BITs(8, 13)
++#define RG_ZCAL_CTRL BITs(0, 5)
++#define RG_17A 0x17a
++#define AD_CAL_COMP_OUT BIT(8)
++#define RG_17B 0x17b
++#define AD_CAL_CLK bit(0)
++#define RG_17C 0x17c
++#define DA_CALIN_FLAG bit(0)
++/************R50 CAL****************************/
++#define RG_174 0x174
++#define RG_R50OHM_RSEL_TX_A_EN BIT[15]
++#define CR_R50OHM_RSEL_TX_A BITS[8:14]
++#define RG_R50OHM_RSEL_TX_B_EN BIT[7]
++#define CR_R50OHM_RSEL_TX_B BITS[6:0]
++#define RG_175 0x175
++#define RG_R50OHM_RSEL_TX_C_EN BITS[15]
++#define CR_R50OHM_RSEL_TX_C BITS[8:14]
++#define RG_R50OHM_RSEL_TX_D_EN BIT[7]
++#define CR_R50OHM_RSEL_TX_D BITS[0:6]
++/**********TX offset Calibration***************************/
++#define RG_95 0x96
++#define BYPASS_TX_OFFSET_CAL BIT(15)
++#define RG_3E 0x3e
++#define BYPASS_PD_TXVLD_A BIT(15)
++#define BYPASS_PD_TXVLD_B BIT(14)
++#define BYPASS_PD_TXVLD_C BIT(13)
++#define BYPASS_PD_TXVLD_D BIT(12)
++#define BYPASS_PD_TX_10M BIT(11)
++#define POWER_DOWN_TXVLD_A BIT(7)
++#define POWER_DOWN_TXVLD_B BIT(6)
++#define POWER_DOWN_TXVLD_C BIT(5)
++#define POWER_DOWN_TXVLD_D BIT(4)
++#define POWER_DOWN_TX_10M BIT(3)
++#define RG_DD 0xdd
++#define RG_TXG_CALEN_A BIT(12)
++#define RG_TXG_CALEN_B BIT(8)
++#define RG_TXG_CALEN_C BIT(4)
++#define RG_TXG_CALEN_D BIT(0)
++#define RG_17D 0x17D
++#define FORCE_DASN_DAC_IN0_A BIT(15)
++#define DASN_DAC_IN0_A BITS(0, 9)
++#define RG_17E 0x17E
++#define FORCE_DASN_DAC_IN0_B BIT(15)
++#define DASN_DAC_IN0_B BITS(0, 9)
++#define RG_17F 0x17F
++
++#define FORCE_DASN_DAC_IN0_C BIT(15)
++#define DASN_DAC_IN0_C BITS(0, 9)
++#define RG_180 0x180
++#define FORCE_DASN_DAC_IN0_D BIT(15)
++#define DASN_DAC_IN0_D BITS(0, 9)
++
++#define RG_181 0x181
++#define FORCE_DASN_DAC_IN1_A BIT(15)
++#define DASN_DAC_IN1_A BITS(0, 9)
++#define RG_182 0x182
++#define FORCE_DASN_DAC_IN1_B BIT(15)
++#define DASN_DAC_IN1_B BITS(0, 9)
++#define RG_183 0x183
++#define FORCE_DASN_DAC_IN1_C BIT(15)
++#define DASN_DAC_IN1_C BITS(0, 9)
++#define RG_184 0x184
++#define FORCE_DASN_DAC_IN1_D BIT(15)
++#define DASN_DAC_IN1_D BITS(0, 9)
++#define RG_172 0x172
++#define CR_TX_AMP_OFFSET_A BITS(8, 13)
++#define CR_TX_AMP_OFFSET_B BITS(0, 5)
++#define RG_173 0x173
++#define CR_TX_AMP_OFFSET_C BITS(8, 13)
++#define CR_TX_AMP_OFFSET_D BITS(0, 5)
++/**********TX Amp Calibration ***************************/
++#define RG_12 0x12
++#define DA_TX_I2MPB_A_GBE BITS(10, 15)
++#define RG_17 0x17
++#define DA_TX_I2MPB_B_GBE BITS(8, 13)
++#define RG_19 0x19
++#define DA_TX_I2MPB_C_GBE BITS(8, 13)
++#define RG_21 0x21
++#define DA_TX_I2MPB_D_GBE BITS(8, 13)
++#define TX_AMP_MAX 0x3f
++#define TX_AMP_MAX_OFFSET 0xb
++#define TX_AMP_HIGHEST_TS ((TX_AMP_MAX) + 3)
++#define TX_AMP_LOWEST_TS (0 - 3)
++#define TX_AMP_HIGH_TS (TX_AMP_MAX)
++#define TX_AMP_LOW_TS 0
++
++/* PHY Extend Register 0x14 bitmap of define */
++#define PHY_EXT_REG_14 0x14
++
++/* Fields of PHY_EXT_REG_14 */
++#define PHY_EN_DOWN_SHFIT BIT(4)
++
++/* PHY Extend Register 0x17 bitmap of define */
++#define PHY_EXT_REG_17 0x17
++
++/* Fields of PHY_EXT_REG_17 */
++#define PHY_LINKDOWN_POWER_SAVING_EN BIT(4)
++
++/* PHY PMA Register 0x17 bitmap of define */
++#define SLV_DSP_READY_TIME_S 15
++#define SLV_DSP_READY_TIME_M (0xff << SLV_DSP_READY_TIME_S)
++
++/* PHY PMA Register 0x18 bitmap of define */
++#define ENABLE_RANDOM_UPDATE_TRIGGER BIT(8)
++
++/* PHY EEE Register bitmap of define */
++#define PHY_DEV07 0x07
++#define PHY_DEV07_REG_03C 0x3c
++
++/* PHY DEV 0x1e Register bitmap of define */
++#define PHY_DEV1E 0x1e
++#define PHY_DEV1F 0x1f
++
++/* Proprietory Control Register of Internal Phy device 0x1e */
++#define PHY_TX_MLT3_BASE 0x0
++#define PHY_DEV1E_REG_13 0x13
++#define PHY_DEV1E_REG_14 0x14
++#define PHY_DEV1E_REG_41 0x41
++#define PHY_DEV1E_REG_A6 0xa6
++#define RXADC_CONTROL_3 0xc2
++#define PHY_DEV1E_REG_0C6 0xc6
++#define RXADC_LDO_CONTROL_2 0xd3
++#define PHY_DEV1E_REG_0FE 0xfe
++#define PHY_DEV1E_REG_123 0x123
++#define PHY_DEV1E_REG_189 0x189
++#define PHY_DEV1E_REG_234 0x234
++
++/* Proprietory Control Register of Internal Phy device 0x1f */
++#define PHY_DEV1F_REG_44 0x44
++#define PHY_DEV1F_REG_268 0x268
++#define PHY_DEV1F_REG_269 0x269
++#define PHY_DEV1F_REG_26A 0x26A
++#define TXVLD_DA_271 0x271
++#define TXVLD_DA_272 0x272
++#define TXVLD_DA_273 0x273
++
++/* Fields of PHY_DEV1E_REG_0C6 */
++#define PHY_POWER_SAVING_S 8
++#define PHY_POWER_SAVING_M 0x300
++#define PHY_POWER_SAVING_TX 0x0
++
++/* Fields of PHY_DEV1E_REG_189 */
++#define DESCRAMBLER_CLEAR_EN 0x1
++
++/* Fields of PHY_DEV1E_REG_234 */
++#define TR_OPEN_LOOP_EN BIT(0)
++
++/* Internal GPHY Page Control Register */
++#define PHY_CL22_PAGE_CTRL 0x1f
++#define PHY_TR_PAGE 0x52b5
++
++/* Internal GPHY Token Ring Access Registers */
++#define PHY_TR_CTRL 0x10
++#define PHY_TR_LOW_DATA 0x11
++#define PHY_TR_HIGH_DATA 0x12
++
++/* Fields of PHY_TR_CTRL */
++#define PHY_TR_PKT_XMT_STA BIT(15)
++#define PHY_TR_WR_S 13
++#define PHY_TR_CH_ADDR_S 11
++#define PHY_TR_NODE_ADDR_S 7
++#define PHY_TR_DATA_ADDR_S 1
++
++enum phy_tr_wr {
++ PHY_TR_WRITE = 0,
++ PHY_TR_READ = 1,
++};
++
++/* Helper macro for GPHY Token Ring Access */
++#define PHY_TR_LOW_VAL(x) ((x) & 0xffff)
++#define PHY_TR_HIGH_VAL(x) (((x) & 0xff0000) >> 16)
++
++/* Token Ring Channels */
++#define PMA_CH 0x1
++#define DSP_CH 0x2
++
++/* Token Ring Nodes */
++#define PMA_NOD 0xf
++#define DSP_NOD 0xd
++
++/* Token Ring register range */
++enum tr_pma_reg_addr {
++ PMA_MIN = 0x0,
++ PMA_01 = 0x1,
++ PMA_17 = 0x17,
++ PMA_18 = 0x18,
++ PMA_MAX = 0x3d,
++};
++
++enum tr_dsp_reg_addr {
++ DSP_MIN = 0x0,
++ DSP_06 = 0x6,
++ DSP_08 = 0x8,
++ DSP_0f = 0xf,
++ DSP_10 = 0x10,
++ DSP_MAX = 0x3e,
++};
++#endif /* _MT753X_REGS_H_ */
+Index: linux-5.4.124/drivers/net/dsa/Makefile
+===================================================================
+--- linux-5.4.124.orig/drivers/net/dsa/Makefile
++++ linux-5.4.124/drivers/net/dsa/Makefile
+@@ -6,7 +6,8 @@ ifdef CONFIG_NET_DSA_LOOP
+ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o
+ endif
+ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
+-obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
++obj-$(CONFIG_NET_DSA_MT7530) += mt7530-dsa.o
++mt7530-dsa-objs := mt7530.o mt7531_phy.o
+ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
+ obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
+ obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o