| /* Copyright 2016 MediaTek Inc. |
| * Author: Carlos Huang <carlos.huang@mediatek.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| #include "raether.h" |
| #include "ra_switch.h" |
| #include "ra_mac.h" |
| #include "raeth_reg.h" |
| |
| #define MT7622_CHIP_ID 0x08000008 |
| |
| void reg_bit_zero(void __iomem *addr, unsigned int bit, unsigned int len) |
| { |
| int reg_val; |
| int i; |
| |
| reg_val = sys_reg_read(addr); |
| for (i = 0; i < len; i++) |
| reg_val &= ~(1 << (bit + i)); |
| sys_reg_write(addr, reg_val); |
| } |
| |
| void reg_bit_one(void __iomem *addr, unsigned int bit, unsigned int len) |
| { |
| unsigned int reg_val; |
| unsigned int i; |
| |
| reg_val = sys_reg_read(addr); |
| for (i = 0; i < len; i++) |
| reg_val |= 1 << (bit + i); |
| sys_reg_write(addr, reg_val); |
| } |
| |
| u8 fe_cal_flag; |
| u8 fe_cal_flag_mdix; |
| u8 fe_cal_tx_offset_flag; |
| u8 fe_cal_tx_offset_flag_mdix; |
| u8 fe_cal_r50_flag; |
| u8 fe_cal_vbg_flag; |
| u32 iext_cal_result; |
| u32 r50_p0_cal_result; |
| u8 ge_cal_r50_flag; |
| u8 ge_cal_tx_offset_flag; |
| u8 ge_cal_flag; |
| int show_time; |
| static u8 ephy_addr_base; |
| |
| /* 50ohm_new*/ |
| const u8 ZCAL_TO_R50OHM_TBL_100[64] = { |
| 127, 121, 116, 115, 111, 109, 108, 104, |
| 102, 99, 97, 96, 77, 76, 73, 72, |
| 70, 69, 67, 66, 47, 46, 45, 43, |
| 42, 41, 40, 38, 37, 36, 35, 34, |
| 32, 16, 15, 14, 13, 12, 11, 10, |
| 9, 8, 7, 6, 6, 5, 4, 4, |
| 3, 2, 2, 1, 1, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| const u8 ZCAL_TO_R50ohm_GE_TBL_100[64] = { |
| 63, 63, 63, 63, 63, 63, 63, 63, |
| 63, 63, 63, 63, 63, 63, 63, 60, |
| 57, 55, 53, 51, 48, 46, 44, 42, |
| 40, 38, 37, 36, 34, 32, 30, 28, |
| 27, 26, 25, 23, 22, 21, 19, 18, |
| 16, 15, 14, 13, 12, 11, 10, 9, |
| 8, 7, 6, 5, 4, 4, 3, 2, |
| 1, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| const u8 ZCAL_TO_R50ohm_GE_TBL[64] = { |
| 63, 63, 63, 63, 63, 63, 63, 63, |
| 63, 63, 63, 63, 63, 63, 63, 60, |
| 57, 55, 53, 51, 48, 46, 44, 42, |
| 40, 38, 37, 36, 34, 32, 30, 28, |
| 27, 26, 25, 23, 22, 21, 19, 18, |
| 16, 15, 14, 13, 12, 11, 10, 9, |
| 8, 7, 6, 5, 4, 4, 3, 2, |
| 1, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| const u8 ZCAL_TO_REXT_TBL[64] = { |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 1, 1, 1, 1, 1, |
| 1, 2, 2, 2, 2, 2, 2, 3, |
| 3, 3, 3, 3, 3, 4, 4, 4, |
| 4, 4, 4, 4, 5, 5, 5, 5, |
| 5, 5, 6, 6, 6, 6, 6, 6, |
| 7, 7, 7, 7, 7, 7, 7, 7, |
| 7, 7, 7, 7, 7, 7, 7, 7 |
| }; |
| |
| const u8 ZCAL_TO_FILTER_TBL[64] = { |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 1, 1, |
| 1, 2, 2, 2, 3, 3, 3, 4, |
| 4, 4, 4, 5, 5, 5, 6, 6, |
| 7, 7, 7, 8, 8, 8, 9, 9, |
| 9, 10, 10, 10, 11, 11, 11, 11, |
| 12, 12, 12, 12, 12, 12, 12, 12 |
| }; |
| |
| void tc_phy_write_g_reg(u8 port_num, u8 page_num, |
| u8 reg_num, u32 reg_data) |
| { |
| u32 r31 = 0; |
| |
| r31 |= 0 << 15; /* global */ |
| r31 |= ((page_num & 0x7) << 12); /* page no */ |
| mii_mgr_write(port_num, 31, r31); /* change Global page */ |
| mii_mgr_write(port_num, reg_num, reg_data); |
| } |
| |
| void tc_phy_write_l_reg(u8 port_no, u8 page_no, |
| u8 reg_num, u32 reg_data) |
| { |
| u32 r31 = 0; |
| |
| r31 |= 1 << 15; /* local */ |
| r31 |= ((page_no & 0x7) << 12); /* page no */ |
| mii_mgr_write(port_no, 31, r31); /* select local page x */ |
| mii_mgr_write(port_no, reg_num, reg_data); |
| } |
| |
| u32 tc_phy_read_g_reg(u8 port_num, u8 page_num, u8 reg_num) |
| { |
| u32 phy_val; |
| |
| u32 r31 = 0; |
| |
| r31 |= 0 << 15; /* global */ |
| r31 |= ((page_num & 0x7) << 12); /* page no */ |
| mii_mgr_write(port_num, 31, r31); /* change Global page */ |
| mii_mgr_read(port_num, reg_num, &phy_val); |
| return phy_val; |
| } |
| |
| u32 tc_phy_read_l_reg(u8 port_no, u8 page_no, u8 reg_num) |
| { |
| u32 phy_val; |
| u32 r31 = 0; |
| |
| r31 |= 1 << 15; /* local */ |
| r31 |= ((page_no & 0x7) << 12); /* page no */ |
| mii_mgr_write(port_no, 31, r31); /* select local page x */ |
| mii_mgr_read(port_no, reg_num, &phy_val); |
| return phy_val; |
| } |
| |
| u32 tc_phy_read_dev_reg(u32 port_num, u32 dev_addr, u32 reg_addr) |
| { |
| u32 phy_val; |
| |
| mii_mgr_read_cl45(port_num, dev_addr, reg_addr, &phy_val); |
| return phy_val; |
| } |
| |
| void tc_phy_write_dev_reg(u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data) |
| { |
| mii_mgr_write_cl45(port_num, dev_addr, reg_addr, write_data); |
| } |
| |
| u32 tc_mii_read(u32 phy_addr, u32 phy_register) |
| { |
| u32 phy_val; |
| |
| mii_mgr_read(phy_addr, phy_register, &phy_val); |
| return phy_val; |
| } |
| |
| void tc_mii_write(u32 phy_addr, u32 phy_register, u32 write_data) |
| { |
| mii_mgr_write(phy_addr, phy_register, write_data); |
| } |
| |
| void clear_ckinv_ana_txvos(void) |
| { |
| u16 g7r24_tmp; |
| /*clear RG_CAL_CKINV/RG_ANA_CALEN/RG_TXVOS_CALEN*/ |
| /*g7r24[13]:0x0, RG_ANA_CALEN_P0*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp & (~0x2000))); |
| |
| /*g7r24[14]:0x0, RG_CAL_CKINV_P0*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp & (~0x4000))); |
| |
| /*g7r24[12]:0x0, DA_TXVOS_CALEN_P0*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp & (~0x1000))); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0); |
| } |
| |
| u8 all_fe_ana_cal_wait_txamp(u32 delay, u8 port_num) |
| { /* for EN7512 FE // allen_20160616 */ |
| u8 all_ana_cal_status; |
| u16 cnt, g7r24_temp; |
| |
| tc_phy_write_l_reg(FE_CAL_COMMON, 4, 23, (0x0000)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp & (~0x10)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp | 0x10); |
| |
| cnt = 1000; |
| do { |
| udelay(delay); |
| cnt--; |
| all_ana_cal_status = |
| ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) >> 1) & 0x1); |
| } while ((all_ana_cal_status == 0) && (cnt != 0)); |
| |
| tc_phy_write_l_reg(FE_CAL_COMMON, 4, 23, (0x0000)); |
| tc_phy_write_l_reg(port_num, 4, 23, (0x0000)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp & (~0x10)); |
| return all_ana_cal_status; |
| } |
| |
| u8 all_fe_ana_cal_wait(u32 delay, u8 port_num) |
| { |
| u8 all_ana_cal_status; |
| u16 cnt, g7r24_temp; |
| |
| tc_phy_write_l_reg(FE_CAL_COMMON, 4, 23, (0x0000)); |
| tc_phy_write_l_reg(port_num, 4, 23, (0x0000)); |
| |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp & (~0x10)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp | 0x10); |
| cnt = 1000; |
| do { |
| udelay(delay); |
| cnt--; |
| all_ana_cal_status = |
| ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) >> 1) & 0x1); |
| |
| } while ((all_ana_cal_status == 0) && (cnt != 0)); |
| |
| tc_phy_write_l_reg(FE_CAL_COMMON, 4, 23, (0x0000)); |
| tc_phy_write_l_reg(port_num, 4, 23, (0x0000)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp & (~0x10)); |
| |
| return all_ana_cal_status; |
| } |
| |
| void fe_cal_tx_amp(u8 port_num, u32 delay) |
| { |
| u8 all_ana_cal_status; |
| int ad_cal_comp_out_init; |
| u16 l3r25_temp, l0r26_temp, l2r20_temp; |
| u16 l2r23_temp = 0; |
| int calibration_polarity; |
| u8 tx_amp_reg_shift = 0; |
| int tx_amp_temp = 0, cnt = 0, phyaddr, tx_amp_cnt = 0; |
| u16 tx_amp_final; |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| |
| phyaddr = port_num + ephy_addr_base; |
| tx_amp_temp = 0x20; |
| /* *** Tx Amp Cal start ********************** */ |
| |
| /*Set device in 100M mode*/ |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| /*TXG output DC differential 1V*/ |
| tc_phy_write_g_reg(port_num, 2, 25, 0x10c0); |
| |
| tc_phy_write_g_reg(port_num, 1, 26, (0x8000 | DAC_IN_2V)); |
| tc_phy_write_g_reg(port_num, 4, 21, (0x0800)); /* set default */ |
| tc_phy_write_l_reg(port_num, 0, 30, (0x02c0)); |
| tc_phy_write_l_reg(port_num, 4, 21, (0x0000)); |
| |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, (0xc800)); |
| tc_phy_write_l_reg(port_num, 3, 25, (0xc800)); |
| |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x7000); |
| |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x400)); |
| |
| /*decide which port calibration RG_ZCALEN by port_num*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| l3r25_temp = l3r25_temp | 0x1000; |
| l3r25_temp = l3r25_temp & ~(0x200); |
| tc_phy_write_l_reg(port_num, 3, 25, l3r25_temp); |
| |
| /*DA_PGA_MDIX_STASTUS_P0=0(L0R26[15:14] = 0x01*/ |
| l0r26_temp = tc_phy_read_l_reg(port_num, 0, 26); |
| l0r26_temp = l0r26_temp & (~0xc000); |
| tc_phy_write_l_reg(port_num, 0, 26, 0x5203);/* Kant */ |
| |
| /*RG_RX2TX_EN_P0=0(L2R20[10] =0),*/ |
| l2r20_temp = tc_phy_read_l_reg(port_num, 2, 20); |
| l2r20_temp = l2r20_temp & (~0x400); |
| tc_phy_write_l_reg(port_num, 2, 20, l2r20_temp); |
| tc_phy_write_l_reg(port_num, 2, 23, (tx_amp_temp)); |
| |
| all_ana_cal_status = all_fe_ana_cal_wait_txamp(delay, port_num); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx amp AnaCal ERROR! (init) \r\n"); |
| } |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| |
| tx_amp_temp += calibration_polarity; |
| cnt = 0; |
| tx_amp_cnt = 0; |
| while (all_ana_cal_status < ANACAL_ERROR) { |
| tc_phy_write_l_reg(port_num, 2, 23, (tx_amp_temp)); |
| l2r23_temp = tc_phy_read_l_reg(port_num, 2, 23); |
| cnt++; |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| all_ana_cal_status = all_fe_ana_cal_wait_txamp(delay, port_num); |
| |
| if (((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24)) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| fe_cal_flag = 1; |
| } |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx amp AnaCal ERROR! (%d) \r\n", cnt); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1) != |
| ad_cal_comp_out_init) { |
| tx_amp_cnt++; |
| all_ana_cal_status = ANACAL_FINISH; |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| ad_cal_comp_out_init = |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| } else { |
| if ((l2r23_temp == 0x3f) || (l2r23_temp == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; |
| pr_info |
| (" Tx amp Cal Saturation(%d)(%x)(%x)\r\n", |
| cnt, tc_phy_read_l_reg(0, 3, 25), |
| tc_phy_read_l_reg(1, 3, 25)); |
| pr_info |
| (" Tx amp Cal Saturation(%x)(%x)(%x)\r\n", |
| tc_phy_read_l_reg(2, 3, 25), |
| tc_phy_read_l_reg(3, 3, 25), |
| tc_phy_read_l_reg(0, 2, 30)); |
| /* tx_amp_temp += calibration_polarity; */ |
| } else { |
| tx_amp_temp += calibration_polarity; |
| } |
| } |
| } |
| |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| l2r23_temp = tc_phy_read_l_reg(port_num, 2, 23); |
| tc_phy_write_l_reg(port_num, 2, 23, |
| ((tx_amp_temp << tx_amp_reg_shift))); |
| l2r23_temp = tc_phy_read_l_reg(port_num, 2, 23); |
| pr_info("[%d] %s, ANACAL_SATURATION\n", port_num, __func__); |
| } else { |
| if (ei_local->chip_name == MT7622_FE) { |
| if (port_num == 0) |
| l2r23_temp = l2r23_temp + 10; |
| else if (port_num == 1) |
| l2r23_temp = l2r23_temp + 11; |
| else if (port_num == 2) |
| l2r23_temp = l2r23_temp + 10; |
| else if (port_num == 3) |
| l2r23_temp = l2r23_temp + 9; |
| else if (port_num == 4) |
| l2r23_temp = l2r23_temp + 10; |
| } else if (ei_local->chip_name == LEOPARD_FE) { |
| if (port_num == 1) |
| l2r23_temp = l2r23_temp + 3; |
| else if (port_num == 2) |
| l2r23_temp = l2r23_temp + 3; |
| else if (port_num == 3) |
| l2r23_temp = l2r23_temp + 3 - 2; |
| else if (port_num == 4) |
| l2r23_temp = l2r23_temp + 2 - 1 + 2; |
| } |
| |
| tc_phy_write_l_reg(port_num, 2, 23, ((l2r23_temp) << tx_amp_reg_shift)); |
| fe_cal_flag = 1; |
| } |
| |
| tx_amp_final = tc_phy_read_l_reg(port_num, 2, 23) & 0x3f; |
| tc_phy_write_l_reg(port_num, 2, 24, ((tx_amp_final + 15) << 8) | 0x20); |
| |
| if (ei_local->chip_name == LEOPARD_FE) { |
| if (port_num == 1) |
| tc_phy_write_l_reg(port_num, 2, 24, ((tx_amp_final + 15 - 4) << 8) | 0x20); |
| else if (port_num == 2) |
| tc_phy_write_l_reg(port_num, 2, 24, ((tx_amp_final + 15 + 2) << 8) | 0x20); |
| else if (port_num == 3) |
| tc_phy_write_l_reg(port_num, 2, 24, ((tx_amp_final + 15 + 4) << 8) | 0x20); |
| else if (port_num == 4) |
| tc_phy_write_l_reg(port_num, 2, 24, ((tx_amp_final + 15 + 4) << 8) | 0x20); |
| } |
| |
| pr_info("[%d] - tx_amp_final = 0x%x\n", port_num, tx_amp_final); |
| |
| /*clear RG_CAL_CKINV/RG_ANA_CALEN/RG_TXVOS_CALEN*/ |
| clear_ckinv_ana_txvos(); |
| |
| tc_phy_write_l_reg(port_num, 3, 25, 0x0000); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, 0x0000); |
| tc_phy_write_g_reg(port_num, 1, 26, 0); |
| /* *** Tx Amp Cal end *** */ |
| } |
| |
| void fe_cal_tx_amp_mdix(u8 port_num, u32 delay) |
| { |
| u8 all_ana_cal_status; |
| int ad_cal_comp_out_init; |
| u16 l3r25_temp, l4r26_temp, l0r26_temp; |
| u16 l2r20_temp, l4r26_temp_amp; |
| int calibration_polarity; |
| int tx_amp_temp = 0, cnt = 0, phyaddr, tx_amp_cnt = 0; |
| u16 tx_amp_mdix_final; |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| |
| phyaddr = port_num + ephy_addr_base; |
| tx_amp_temp = 0x20; |
| /*Set device in 100M mode*/ |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| /*TXG output DC differential 0V*/ |
| tc_phy_write_g_reg(port_num, 2, 25, 0x10c0); |
| |
| tc_phy_write_g_reg(port_num, 1, 26, (0x8000 | DAC_IN_2V)); |
| tc_phy_write_g_reg(port_num, 4, 21, (0x0800)); /* set default */ |
| tc_phy_write_l_reg(port_num, 0, 30, (0x02c0));/*0x3f80 // l0r30[9], [7], [6], [1]*/ |
| tc_phy_write_l_reg(port_num, 4, 21, (0x0000)); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, (0xc800)); |
| tc_phy_write_l_reg(port_num, 3, 25, (0xc800)); /* 0xca00 */ |
| /* *** Tx Amp Cal start ********************** */ |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x7000); |
| /* pr_info(" g7r24[%d] = %x\n", port_num, tc_phy_read_g_reg(port_num, 7, 24)); */ |
| |
| /*RG_TXG_CALEN =1 l3r25[10]by port number*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x400)); |
| /*decide which port calibration RG_ZCALEN l3r25[12] by port_num*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| l3r25_temp = l3r25_temp | 0x1000; |
| l3r25_temp = l3r25_temp & ~(0x200); |
| tc_phy_write_l_reg(port_num, 3, 25, l3r25_temp); |
| |
| /*DA_PGA_MDIX_STASTUS_P0=0(L0R26[15:14] = 0x10) & RG_RX2TX_EN_P0=0(L2R20[10] =1),*/ |
| l0r26_temp = tc_phy_read_l_reg(port_num, 0, 26); |
| l0r26_temp = l0r26_temp & (~0xc000); |
| tc_phy_write_l_reg(port_num, 0, 26, 0x9203); /* Kant */ |
| l2r20_temp = tc_phy_read_l_reg(port_num, 2, 20); |
| l2r20_temp = l2r20_temp | 0x400; |
| tc_phy_write_l_reg(port_num, 2, 20, l2r20_temp); |
| |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x0400)); |
| /*DA_TX_I2MPB_MDIX L4R26[5:0]*/ |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| /* pr_info("111l4r26 =%x\n", tc_phy_read_l_reg(port_num, 4, 26)); */ |
| l4r26_temp = l4r26_temp & (~0x3f); |
| tc_phy_write_l_reg(port_num, 4, 26, (l4r26_temp | tx_amp_temp)); |
| /* pr_info("222l4r26 =%x\n", tc_phy_read_l_reg(port_num, 4, 26)); */ |
| all_ana_cal_status = all_fe_ana_cal_wait_txamp(delay, port_num); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx amp mdix AnaCal ERROR! (init) \r\n"); |
| } |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| /*ad_cal_comp_out_init = (tc_phy_read_l_reg(FE_CAL_COMMON, 4, 23) >> 4) & 0x1;*/ |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| /* pr_info("mdix ad_cal_comp_out_init = %d\n", ad_cal_comp_out_init); */ |
| if (ad_cal_comp_out_init == 1) { |
| calibration_polarity = -1; |
| /* tx_amp_temp = 0x10; */ |
| } else { |
| calibration_polarity = 1; |
| } |
| tx_amp_temp += calibration_polarity; |
| cnt = 0; |
| tx_amp_cnt = 0; |
| while (all_ana_cal_status < ANACAL_ERROR) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp & (~0x3f); |
| tc_phy_write_l_reg(port_num, 4, 26, (l4r26_temp | tx_amp_temp)); |
| l4r26_temp = (tc_phy_read_l_reg(port_num, 4, 26)); |
| l4r26_temp_amp = (tc_phy_read_l_reg(port_num, 4, 26)) & 0x3f; |
| cnt++; |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| all_ana_cal_status = all_fe_ana_cal_wait_txamp(delay, port_num); |
| |
| if (((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24)) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| fe_cal_flag_mdix = 1; |
| } |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx amp mdix AnaCal ERROR! (%d) \r\n", cnt); |
| } else if (((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24)) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| ad_cal_comp_out_init = |
| (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24)) & 0x1; |
| } else { |
| if ((l4r26_temp_amp == 0x3f) || (l4r26_temp_amp == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; |
| pr_info |
| (" Tx amp Cal mdix Saturation(%d)(%x)(%x)\r\n", |
| cnt, tc_phy_read_l_reg(0, 3, 25), |
| tc_phy_read_l_reg(1, 3, 25)); |
| pr_info |
| (" Tx amp Cal mdix Saturation(%x)(%x)(%x)\r\n", |
| tc_phy_read_l_reg(2, 3, 25), |
| tc_phy_read_l_reg(3, 3, 25), |
| tc_phy_read_l_reg(0, 2, 30)); |
| /* tx_amp_temp += calibration_polarity; */ |
| } else { |
| tx_amp_temp += calibration_polarity; |
| } |
| } |
| } |
| |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| pr_info(" FE-%d Tx amp AnaCal mdix Saturation! (%d)(l4r26=0x%x) \r\n", |
| phyaddr, cnt, l4r26_temp); |
| tc_phy_write_l_reg(port_num, 4, 26, |
| ((l4r26_temp & (~0x3f)) | tx_amp_temp)); |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| pr_info(" FE-%d Tx amp AnaCal mdix Saturation! (%d)(l4r26=0x%x) \r\n", |
| phyaddr, cnt, l4r26_temp); |
| pr_info("[%d] %s, ANACAL_SATURATION\n", port_num, __func__); |
| } else { |
| if (ei_local->chip_name == MT7622_FE) { |
| if (port_num == 0) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 10; |
| } else if (port_num == 1) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 11; |
| } else if (port_num == 2) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 9; |
| } else if (port_num == 3) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 9; |
| } else if (port_num == 4) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 9; |
| } |
| } else if (ei_local->chip_name == LEOPARD_FE) { |
| if (port_num == 1) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 4 - 2; |
| } else if (port_num == 2) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 3 - 1; |
| } else if (port_num == 3) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 4 - 3; |
| } else if (port_num == 4) { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| l4r26_temp = l4r26_temp + 4 - 2 + 1; |
| } |
| } |
| tc_phy_write_l_reg(port_num, 4, 26, l4r26_temp); |
| fe_cal_flag_mdix = 1; |
| } |
| |
| tx_amp_mdix_final = tc_phy_read_l_reg(port_num, 4, 26) & 0x3f; |
| tc_phy_write_l_reg(port_num, 4, 27, ((tx_amp_mdix_final + 15) << 8) | 0x20); |
| if (ei_local->chip_name == LEOPARD_FE) { |
| if (port_num == 2) |
| tc_phy_write_l_reg(port_num, 4, 27, |
| ((tx_amp_mdix_final + 15 + 1) << 8) | 0x20); |
| else if (port_num == 3) |
| tc_phy_write_l_reg(port_num, 4, 27, |
| ((tx_amp_mdix_final + 15 + 4) << 8) | 0x20); |
| else if (port_num == 4) |
| tc_phy_write_l_reg(port_num, 4, 27, |
| ((tx_amp_mdix_final + 15 + 4) << 8) | 0x20); |
| } |
| pr_info("[%d] - tx_amp_mdix_final = 0x%x\n", port_num, tx_amp_mdix_final); |
| |
| clear_ckinv_ana_txvos(); |
| tc_phy_write_l_reg(port_num, 3, 25, 0x0000); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, 0x0000); |
| tc_phy_write_g_reg(port_num, 1, 26, 0); |
| /* *** Tx Amp Cal end *** */ |
| } |
| |
| void fe_cal_tx_offset(u8 port_num, u32 delay) |
| { |
| u8 all_ana_cal_status; |
| int ad_cal_comp_out_init; |
| u16 l3r25_temp, l2r20_temp; |
| u16 g4r21_temp, l0r30_temp, l4r17_temp, l0r26_temp; |
| int calibration_polarity, tx_offset_temp; |
| int cal_temp = 0; |
| u8 tx_offset_reg_shift; |
| u8 cnt = 0, phyaddr, tx_amp_cnt = 0; |
| u16 tx_offset_final; |
| |
| phyaddr = port_num + ephy_addr_base; |
| /*Set device in 100M mode*/ |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| |
| /*// g4r21[11]:Hw bypass tx offset cal, Fw cal*/ |
| g4r21_temp = tc_phy_read_g_reg(port_num, 4, 21); |
| tc_phy_write_g_reg(port_num, 4, 21, (g4r21_temp | 0x0800)); |
| |
| /*l0r30[9], [7], [6], [1]*/ |
| l0r30_temp = tc_phy_read_l_reg(port_num, 0, 30); |
| tc_phy_write_l_reg(port_num, 0, 30, (l0r30_temp | 0x02c0)); |
| |
| /* tx_offset_temp = TX_AMP_OFFSET_0MV; */ |
| tx_offset_temp = 0x20; |
| tx_offset_reg_shift = 8; |
| tc_phy_write_g_reg(port_num, 1, 26, (0x8000 | DAC_IN_0V)); |
| |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x3000); |
| /* pr_info(" g7r24[%d] = %x\n", port_num, tc_phy_read_g_reg(port_num, 7, 24)); */ |
| /*RG_TXG_CALEN =1 by port number*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x400)); |
| /*decide which port calibration RG_ZCALEN by port_num*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x1000)); |
| |
| /*DA_PGA_MDIX_STASTUS_P0=0(L0R26[15:14] = 0x01) & RG_RX2TX_EN_P0=0(L2R20[10] =0),*/ |
| l0r26_temp = tc_phy_read_l_reg(port_num, 0, 26); |
| l0r26_temp = l0r26_temp & (~0xc000); |
| /* tc_phy_write_l_reg(port_num, 0, 26, (l0r26_temp | 0x4000)); */ |
| tc_phy_write_l_reg(port_num, 0, 26, 0x5203);/* Kant */ |
| /* pr_info("l0r26[%d] = %x\n", port_num, tc_phy_read_l_reg(port_num, 0, 26)); */ |
| l2r20_temp = tc_phy_read_l_reg(port_num, 2, 20); |
| l2r20_temp = l2r20_temp & (~0x400); |
| tc_phy_write_l_reg(port_num, 2, 20, l2r20_temp); |
| /* pr_info("l2r20[%d] = %x\n", port_num, tc_phy_read_l_reg(port_num, 2, 20)); */ |
| |
| tc_phy_write_l_reg(port_num, 4, 17, (0x0000)); |
| l4r17_temp = tc_phy_read_l_reg(port_num, 4, 17); |
| tc_phy_write_l_reg(port_num, 4, 17, |
| l4r17_temp | |
| (tx_offset_temp << tx_offset_reg_shift)); |
| /*wat AD_CAL_CLK = 1*/ |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx offset AnaCal ERROR! (init) \r\n"); |
| } |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| /*GET AD_CAL_COMP_OUT g724[0]*/ |
| /*ad_cal_comp_out_init = (tc_phy_read_l_reg(FE_CAL_COMMON, 4, 23) >> 4) & 0x1;*/ |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| cnt = 0; |
| tx_amp_cnt = 0; |
| tx_offset_temp += calibration_polarity; |
| |
| while ((all_ana_cal_status < ANACAL_ERROR) && (cnt < 254)) { |
| cnt++; |
| cal_temp = tx_offset_temp; |
| tc_phy_write_l_reg(port_num, 4, 17, |
| (cal_temp << tx_offset_reg_shift)); |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx offset AnaCal ERROR! (%d) \r\n", cnt); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| |
| ad_cal_comp_out_init = |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| } else { |
| l4r17_temp = tc_phy_read_l_reg(port_num, 4, 17); |
| |
| if ((tx_offset_temp == 0x3f) || (tx_offset_temp == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; |
| pr_info("tx offset ANACAL_SATURATION\n"); |
| } else { |
| tx_offset_temp += calibration_polarity; |
| } |
| } |
| } |
| |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| tx_offset_temp = TX_AMP_OFFSET_0MV; |
| l4r17_temp = tc_phy_read_l_reg(port_num, 4, 17); |
| tc_phy_write_l_reg(port_num, 4, 17, |
| (l4r17_temp | |
| (tx_offset_temp << tx_offset_reg_shift))); |
| pr_info("[%d] %s, ANACAL_SATURATION\n", port_num, __func__); |
| } else { |
| fe_cal_tx_offset_flag = 1; |
| } |
| tx_offset_final = (tc_phy_read_l_reg(port_num, 4, 17) & 0x3f00) >> 8; |
| pr_info("[%d] - tx_offset_final = 0x%x\n", port_num, tx_offset_final); |
| |
| clear_ckinv_ana_txvos(); |
| tc_phy_write_l_reg(port_num, 3, 25, 0x0000); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, 0x0000); |
| tc_phy_write_g_reg(port_num, 1, 26, 0); |
| } |
| |
| void fe_cal_tx_offset_mdix(u8 port_num, u32 delay) |
| { /* for MT7622 */ |
| u8 all_ana_cal_status; |
| int ad_cal_comp_out_init; |
| u16 l3r25_temp, l2r20_temp, l4r26_temp; |
| u16 g4r21_temp, l0r30_temp, l0r26_temp; |
| int calibration_polarity, tx_offset_temp; |
| int cal_temp = 0; |
| u8 tx_offset_reg_shift; |
| u8 cnt = 0, phyaddr; |
| u16 tx_offset_final_mdix; |
| |
| phyaddr = port_num + ephy_addr_base; |
| /*Set device in 100M mode*/ |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| |
| /*// g4r21[11]:Hw bypass tx offset cal, Fw cal*/ |
| g4r21_temp = tc_phy_read_g_reg(port_num, 4, 21); |
| tc_phy_write_g_reg(port_num, 4, 21, (g4r21_temp | 0x0800)); |
| |
| /*l0r30[9], [7], [6], [1]*/ |
| l0r30_temp = tc_phy_read_l_reg(port_num, 0, 30); |
| tc_phy_write_l_reg(port_num, 0, 30, (l0r30_temp | 0x02c0)); |
| |
| tx_offset_temp = 0x20; |
| tx_offset_reg_shift = 8; |
| tc_phy_write_g_reg(port_num, 1, 26, (0x8000 | DAC_IN_0V)); |
| |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x3000); |
| |
| /*RG_TXG_CALEN =1 by port number*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x400)); |
| |
| /*decide which port calibration RG_ZCALEN by port_num*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x1000)); |
| |
| /*DA_PGA_MDIX_STASTUS_P0=0(L0R26[15:14] = 0x10) & RG_RX2TX_EN_P0=1(L2R20[10] =1),*/ |
| l0r26_temp = tc_phy_read_l_reg(port_num, 0, 26); |
| l0r26_temp = l0r26_temp & (~0xc000); |
| tc_phy_write_l_reg(port_num, 0, 26, 0x9203); /* Kant */ |
| l2r20_temp = tc_phy_read_l_reg(port_num, 2, 20); |
| l2r20_temp = l2r20_temp | 0x400; |
| tc_phy_write_l_reg(port_num, 2, 20, l2r20_temp); |
| |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| tc_phy_write_l_reg(port_num, 4, 26, l4r26_temp & (~0x3f00)); |
| tc_phy_write_l_reg(port_num, 4, 26, |
| (l4r26_temp & ~0x3f00) | (cal_temp << tx_offset_reg_shift)); |
| |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx offset mdix AnaCal ERROR! (init) \r\n"); |
| } |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| |
| cnt = 0; |
| tx_offset_temp += calibration_polarity; |
| while ((all_ana_cal_status < ANACAL_ERROR) && (cnt < 254)) { |
| cnt++; |
| cal_temp = tx_offset_temp; |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| tc_phy_write_l_reg(port_num, 4, 26, |
| (l4r26_temp & ~0x3f00) | (cal_temp << tx_offset_reg_shift)); |
| |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE Tx offset mdix AnaCal ERROR! (%d) \r\n", cnt); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| ad_cal_comp_out_init = |
| tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| } else { |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| |
| if ((tx_offset_temp == 0x3f) || (tx_offset_temp == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; |
| pr_info("tx offset ANACAL_SATURATION\n"); |
| } else { |
| tx_offset_temp += calibration_polarity; |
| } |
| } |
| } |
| |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| tx_offset_temp = TX_AMP_OFFSET_0MV; |
| l4r26_temp = tc_phy_read_l_reg(port_num, 4, 26); |
| tc_phy_write_l_reg(port_num, 4, 26, |
| (l4r26_temp & (~0x3f00)) | (cal_temp << tx_offset_reg_shift)); |
| pr_info("[%d] %s, ANACAL_SATURATION\n", port_num, __func__); |
| } else { |
| fe_cal_tx_offset_flag_mdix = 1; |
| } |
| tx_offset_final_mdix = (tc_phy_read_l_reg(port_num, 4, 26) & 0x3f00) >> 8; |
| pr_info("[%d] - tx_offset_final_mdix = 0x%x\n", port_num, tx_offset_final_mdix); |
| |
| clear_ckinv_ana_txvos(); |
| tc_phy_write_l_reg(port_num, 3, 25, 0x0000); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, 0x0000); |
| tc_phy_write_g_reg(port_num, 1, 26, 0); |
| } |
| |
| void set_r50_leopard(u8 port_num, u32 r50_cal_result) |
| { |
| int rg_zcal_ctrl_tx, rg_zcal_ctrl_rx; |
| u16 l4r22_temp; |
| |
| rg_zcal_ctrl_rx = 0; |
| rg_zcal_ctrl_tx = 0; |
| pr_info("r50_cal_result = 0x%x\n", r50_cal_result); |
| if (port_num == 0) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)]; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)]; |
| } |
| if (port_num == 1) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 4; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 4; |
| } |
| if (port_num == 2) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 4; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 6; |
| } |
| if (port_num == 3) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 5; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 6; |
| } |
| if (port_num == 4) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 4; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result)] + 4; |
| } |
| if (rg_zcal_ctrl_tx > 0x7f) |
| rg_zcal_ctrl_tx = 0x7f; |
| if (rg_zcal_ctrl_rx > 0x7f) |
| rg_zcal_ctrl_rx = 0x7f; |
| /*R50OHM_RSEL_TX= LP4R22[14:8]*/ |
| tc_phy_write_l_reg(port_num, 4, 22, ((rg_zcal_ctrl_tx << 8))); |
| l4r22_temp = tc_phy_read_l_reg(port_num, 4, 22); |
| /*R50OHM_RSEL_RX= LP4R22[6:0]*/ |
| tc_phy_write_l_reg(port_num, 4, 22, |
| (l4r22_temp | (rg_zcal_ctrl_rx << 0))); |
| fe_cal_r50_flag = 1; |
| pr_info("[%d] - r50 final result l4r22[%d] = %x\n", port_num, |
| port_num, tc_phy_read_l_reg(port_num, 4, 22)); |
| } |
| |
| void set_r50_mt7622(u8 port_num, u32 r50_cal_result) |
| { |
| int rg_zcal_ctrl_tx, rg_zcal_ctrl_rx; |
| u16 l4r22_temp; |
| |
| rg_zcal_ctrl_rx = 0; |
| rg_zcal_ctrl_tx = 0; |
| pr_info("r50_cal_result = 0x%x\n", r50_cal_result); |
| |
| if (port_num == 0) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 5)]; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 5)]; |
| } |
| if (port_num == 1) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 3)]; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 3)]; |
| } |
| if (port_num == 2) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 4)]; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 5)]; |
| } |
| if (port_num == 3) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 4)]; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 3)]; |
| } |
| if (port_num == 4) { |
| rg_zcal_ctrl_tx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 4)]; |
| rg_zcal_ctrl_rx = ZCAL_TO_R50OHM_TBL_100[(r50_cal_result - 5)]; |
| } |
| /*R50OHM_RSEL_TX= LP4R22[14:8]*/ |
| tc_phy_write_l_reg(port_num, 4, 22, ((rg_zcal_ctrl_tx << 8))); |
| l4r22_temp = tc_phy_read_l_reg(port_num, 4, 22); |
| /*R50OHM_RSEL_RX= LP4R22[6:0]*/ |
| tc_phy_write_l_reg(port_num, 4, 22, |
| (l4r22_temp | (rg_zcal_ctrl_rx << 0))); |
| fe_cal_r50_flag = 1; |
| pr_info("[%d] - r50 final result l4r22[%d] = %x\n", port_num, |
| port_num, tc_phy_read_l_reg(port_num, 4, 22)); |
| } |
| |
| void fe_ge_r50_common(u8 port_num) |
| { |
| u16 l3r25_temp, g7r24_tmp, l4r23_temp; |
| u8 phyaddr; |
| |
| phyaddr = port_num; |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| /*g2r25[7:5]:0x110, BG voltage output*/ |
| tc_phy_write_g_reg(FE_CAL_COMMON, 2, 25, 0xf0c0); |
| |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x0000); |
| /*g7r24[13]:0x01, RG_ANA_CALEN_P0=1*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp | 0x2000)); |
| /*g7r24[14]:0x01, RG_CAL_CKINV_P0=1*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp | 0x4000)); |
| |
| /*g7r24[12]:0x01, DA_TXVOS_CALEN_P0=0*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp & (~0x1000))); |
| |
| /*DA_R50OHM_CAL_EN l4r23[0] = 0*/ |
| l4r23_temp = tc_phy_read_l_reg(port_num, 4, 23); |
| l4r23_temp = l4r23_temp & ~(0x01); |
| tc_phy_write_l_reg(port_num, 4, 23, l4r23_temp); |
| |
| /*RG_REXT_CALEN l2r25[13] = 0*/ |
| l3r25_temp = tc_phy_read_l_reg(FE_CAL_COMMON, 3, 25); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, (l3r25_temp & (~0x2000))); |
| } |
| |
| void fe_cal_r50(u8 port_num, u32 delay) |
| { |
| int rg_zcal_ctrl, all_ana_cal_status, rg_zcal_ctrl_tx, rg_zcal_ctrl_rx; |
| int ad_cal_comp_out_init; |
| u16 l3r25_temp, l0r4, g7r24_tmp, l4r23_temp; |
| int calibration_polarity; |
| u8 cnt = 0, phyaddr; |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| |
| phyaddr = port_num + ephy_addr_base; |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| /*g2r25[7:5]:0x110, BG voltage output*/ |
| tc_phy_write_g_reg(FE_CAL_COMMON, 2, 25, 0xf0c0); |
| |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x0000); |
| /*g7r24[13]:0x01, RG_ANA_CALEN_P0=1*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp | 0x2000)); |
| /*g7r24[14]:0x01, RG_CAL_CKINV_P0=1*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp | 0x4000)); |
| |
| /*g7r24[12]:0x01, DA_TXVOS_CALEN_P0=0*/ |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp & (~0x1000))); |
| |
| /* pr_info("g7r24 = %x\n", g7r24_tmp); */ |
| |
| /*DA_R50OHM_CAL_EN l4r23[0] = 1*/ |
| l4r23_temp = tc_phy_read_l_reg(port_num, 4, 23); |
| tc_phy_write_l_reg(port_num, 4, 23, (l4r23_temp | (0x01))); |
| |
| /*RG_REXT_CALEN l2r25[13] = 0*/ |
| l3r25_temp = tc_phy_read_l_reg(FE_CAL_COMMON, 3, 25); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, (l3r25_temp & (~0x2000))); |
| |
| /*decide which port calibration RG_ZCALEN by port_num*/ |
| l3r25_temp = tc_phy_read_l_reg(port_num, 3, 25); |
| tc_phy_write_l_reg(port_num, 3, 25, (l3r25_temp | 0x1000)); |
| |
| rg_zcal_ctrl = 0x20; /* start with 0 dB */ |
| g7r24_tmp = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (~0xfc0)); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_tmp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| |
| /*wait AD_CAL_COMP_OUT = 1*/ |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE R50 AnaCal ERROR! (init) \r\n"); |
| } |
| |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| |
| cnt = 0; |
| while ((all_ana_cal_status < ANACAL_ERROR) && (cnt < 254)) { |
| cnt++; |
| |
| rg_zcal_ctrl += calibration_polarity; |
| g7r24_tmp = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (~0xfc0)); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_tmp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" FE R50 AnaCal ERROR! (%d) \r\n", cnt); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 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; |
| pr_info(" FE R50 AnaCal Saturation! (%d) \r\n", |
| cnt); |
| } else { |
| l0r4 = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| l0r4 = l0r4 & 0x1; |
| } |
| } |
| } |
| if (port_num == 0) |
| r50_p0_cal_result = rg_zcal_ctrl; |
| |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| rg_zcal_ctrl = 0x20; /* 0 dB */ |
| rg_zcal_ctrl_tx = 0x7f; |
| rg_zcal_ctrl_rx = 0x7f; |
| pr_info("[%d] %s, ANACAL_SATURATION\n", port_num, __func__); |
| } else { |
| fe_cal_r50_flag = 1; |
| } |
| if (ei_local->chip_name == MT7622_FE) |
| set_r50_mt7622(port_num, rg_zcal_ctrl); |
| else if (ei_local->chip_name == LEOPARD_FE) |
| set_r50_leopard(port_num, rg_zcal_ctrl); |
| |
| clear_ckinv_ana_txvos(); |
| tc_phy_write_l_reg(port_num, 3, 25, 0x0000); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, 0x0000); |
| } |
| |
| void fe_cal_vbg(u8 port_num, u32 delay) |
| { |
| int rg_zcal_ctrl, all_ana_cal_status; |
| int ad_cal_comp_out_init, port_no; |
| u16 l3r25_temp, l0r4, g7r24_tmp, l3r26_temp; |
| int calibration_polarity; |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| u16 g2r22_temp, rg_bg_rasel; |
| u8 cnt = 0, phyaddr; |
| |
| rg_bg_rasel = 0; |
| ephy_addr_base = 0; |
| phyaddr = port_num + ephy_addr_base; |
| |
| tc_phy_write_g_reg(FE_CAL_COMMON, 2, 25, 0x30c0); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 0, 25, 0x0030); |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp | 0x2000)); |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp | 0x4000)); |
| |
| g7r24_tmp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, (g7r24_tmp & (~0x1000))); |
| |
| l3r25_temp = tc_phy_read_l_reg(FE_CAL_COMMON, 3, 25); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, (l3r25_temp | 0x2000)); |
| |
| for (port_no = port_num; port_no < 5; port_no++) { |
| l3r25_temp = tc_phy_read_l_reg(port_no, 3, 25); |
| tc_phy_write_l_reg(port_no, 3, 25, (l3r25_temp & (~0x1000))); |
| } |
| rg_zcal_ctrl = 0x0; /* start with 0 dB */ |
| |
| g7r24_tmp = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (~0xfc0)); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_tmp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" fe_cal_vbg ERROR! (init) \r\n"); |
| } |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| |
| cnt = 0; |
| while ((all_ana_cal_status < ANACAL_ERROR) && (cnt < 254)) { |
| cnt++; |
| rg_zcal_ctrl += calibration_polarity; |
| g7r24_tmp = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (~0xfc0)); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_tmp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| all_ana_cal_status = all_fe_ana_cal_wait(delay, port_num); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info("VBG ERROR(%d)status=%d\n", cnt, all_ana_cal_status); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 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; |
| pr_info(" VBG0 AnaCal Saturation! (%d) \r\n", |
| cnt); |
| } else { |
| l0r4 = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| l0r4 = l0r4 & 0x1; |
| } |
| } |
| } |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| rg_zcal_ctrl = 0x20; /* 0 dB */ |
| } else { |
| fe_cal_vbg_flag = 1; |
| } |
| |
| rg_zcal_ctrl = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (0xfc0)) >> 6; |
| iext_cal_result = rg_zcal_ctrl; |
| pr_info("iext_cal_result = 0x%x\n", iext_cal_result); |
| if (ei_local->chip_name == LEOPARD_FE) |
| rg_bg_rasel = ZCAL_TO_REXT_TBL[rg_zcal_ctrl]; |
| |
| l3r26_temp = tc_phy_read_l_reg(FE_CAL_COMMON, 3, 26); |
| l3r26_temp = l3r26_temp & (~0xfc0); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 26, l3r26_temp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| |
| g2r22_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 2, 22); |
| g2r22_temp = g2r22_temp & (~0xe00);/*[11:9]*/ |
| |
| if (ei_local->chip_name == LEOPARD_FE) { |
| rg_bg_rasel = rg_bg_rasel & 0x7; |
| tc_phy_write_g_reg(FE_CAL_COMMON, 2, 22, |
| g2r22_temp | (rg_bg_rasel << 9)); |
| } else if (ei_local->chip_name == MT7622_FE) { |
| rg_zcal_ctrl = rg_zcal_ctrl & 0x38; |
| tc_phy_write_g_reg(FE_CAL_COMMON, 2, 22, |
| g2r22_temp | (((rg_zcal_ctrl & 0x38) >> 3) << 9)); |
| } |
| clear_ckinv_ana_txvos(); |
| |
| tc_phy_write_l_reg(port_num, 3, 25, 0x0000); |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, 0x0000); |
| } |
| |
| #define CALDLY 40 |
| |
| void do_fe_phy_all_analog_cal(u8 port_num) |
| { |
| u16 l0r26_temp, l0r30_temp, l3r25_tmp; |
| u8 cnt = 0, phyaddr, i, iext_port; |
| u32 iext_s, iext_e, r50_s, r50_e, txo_s, txo_e, txa_s, txa_e; |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| |
| iext_port = 0; |
| ephy_addr_base = 0; |
| phyaddr = port_num + ephy_addr_base; |
| l0r26_temp = tc_phy_read_l_reg(port_num, 0, 26); |
| tc_phy_write_l_reg(port_num, 0, 26, 0x5600); |
| tc_phy_write_l_reg(port_num, 4, 21, 0x0000); |
| tc_phy_write_l_reg(port_num, 0, 0, 0x2100); |
| |
| l0r30_temp = tc_phy_read_l_reg(port_num, 0, 30); |
| |
| /*eye pic.*/ |
| tc_phy_write_g_reg(port_num, 5, 20, 0x0170); |
| tc_phy_write_g_reg(port_num, 5, 23, 0x0220); |
| tc_phy_write_g_reg(port_num, 5, 24, 0x0206); |
| tc_phy_write_g_reg(port_num, 5, 26, 0x0370); |
| tc_phy_write_g_reg(port_num, 5, 27, 0x02f2); |
| tc_phy_write_g_reg(port_num, 5, 29, 0x001b); |
| tc_phy_write_g_reg(port_num, 5, 30, 0x0002); |
| /*Yiron default setting*/ |
| for (i = port_num; i < 5; i++) { |
| tc_phy_write_g_reg(i, 3, 23, 0x0); |
| tc_phy_write_l_reg(i, 3, 23, 0x2004); |
| tc_phy_write_l_reg(i, 2, 21, 0x8551); |
| tc_phy_write_l_reg(i, 4, 17, 0x2000); |
| tc_phy_write_g_reg(i, 7, 20, 0x7c62); |
| tc_phy_write_l_reg(i, 4, 20, 0x4444); |
| tc_phy_write_l_reg(i, 2, 22, 0x1011); |
| tc_phy_write_l_reg(i, 4, 28, 0x1011); |
| tc_phy_write_l_reg(i, 4, 19, 0x2222); |
| tc_phy_write_l_reg(i, 4, 29, 0x2222); |
| tc_phy_write_l_reg(i, 2, 28, 0x3444); |
| tc_phy_write_l_reg(i, 2, 29, 0x04c6); |
| tc_phy_write_l_reg(i, 4, 30, 0x0006); |
| tc_phy_write_l_reg(i, 5, 16, 0x04c6); |
| } |
| if (ei_local->chip_name == LEOPARD_FE) { |
| tc_phy_write_l_reg(port_num, 0, 20, 0x0c0c); |
| tc_phy_write_dev_reg(0, 0x1e, 0x017d, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x017e, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x017f, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x0180, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x0181, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x0182, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x0183, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x0184, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x00db, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x00dc, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x003e, 0x0000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x00dd, 0x0000); |
| |
| /*eye pic.*/ |
| tc_phy_write_g_reg(1, 5, 19, 0x0100); |
| tc_phy_write_g_reg(1, 5, 20, 0x0161); |
| tc_phy_write_g_reg(1, 5, 21, 0x00f0); |
| tc_phy_write_g_reg(1, 5, 22, 0x0046); |
| tc_phy_write_g_reg(1, 5, 23, 0x0210); |
| tc_phy_write_g_reg(1, 5, 24, 0x0206); |
| tc_phy_write_g_reg(1, 5, 25, 0x0238); |
| tc_phy_write_g_reg(1, 5, 26, 0x0360); |
| tc_phy_write_g_reg(1, 5, 27, 0x02f2); |
| tc_phy_write_g_reg(1, 5, 28, 0x0240); |
| tc_phy_write_g_reg(1, 5, 29, 0x0010); |
| tc_phy_write_g_reg(1, 5, 30, 0x0002); |
| } |
| if (ei_local->chip_name == MT7622_FE) |
| iext_port = 0; |
| else if (ei_local->chip_name == LEOPARD_FE) |
| iext_port = 1; |
| |
| if (port_num == iext_port) { |
| /*****VBG & IEXT Calibration*****/ |
| cnt = 0; |
| while ((fe_cal_vbg_flag == 0) && (cnt < 0x03)) { |
| iext_s = jiffies; |
| fe_cal_vbg(port_num, 1); /* allen_20160608 */ |
| iext_e = jiffies; |
| if (show_time) |
| pr_info("port[%d] fe_cal_vbg time = %u\n", |
| port_num, (iext_e - iext_s) * 4); |
| cnt++; |
| if (fe_cal_vbg_flag == 0) |
| pr_info(" FE-%d VBG wait! (%d) \r\n", phyaddr, cnt); |
| } |
| fe_cal_vbg_flag = 0; |
| /**** VBG & IEXT Calibration end ****/ |
| } |
| |
| /* *** R50 Cal start *************************************** */ |
| cnt = 0; |
| while ((fe_cal_r50_flag == 0) && (cnt < 0x03)) { |
| r50_s = jiffies; |
| |
| fe_cal_r50(port_num, 1); |
| |
| r50_e = jiffies; |
| if (show_time) |
| pr_info("port[%d] fe_r50 time = %u\n", |
| port_num, (r50_e - r50_s) * 4); |
| cnt++; |
| if (fe_cal_r50_flag == 0) |
| pr_info(" FE-%d R50 wait! (%d) \r\n", phyaddr, cnt); |
| } |
| fe_cal_r50_flag = 0; |
| cnt = 0; |
| /* *** R50 Cal end *** */ |
| /* *** Tx offset Cal start ********************************* */ |
| |
| cnt = 0; |
| while ((fe_cal_tx_offset_flag == 0) && (cnt < 0x03)) { |
| txo_s = jiffies; |
| fe_cal_tx_offset(port_num, CALDLY); |
| txo_e = jiffies; |
| if (show_time) |
| pr_info("port[%d] fe_cal_tx_offset time = %u\n", |
| port_num, (txo_e - txo_s) * 4); |
| cnt++; |
| } |
| fe_cal_tx_offset_flag = 0; |
| cnt = 0; |
| |
| while ((fe_cal_tx_offset_flag_mdix == 0) && (cnt < 0x03)) { |
| txo_s = jiffies; |
| fe_cal_tx_offset_mdix(port_num, CALDLY); |
| txo_e = jiffies; |
| if (show_time) |
| pr_info("port[%d] fe_cal_tx_offset_mdix time = %u\n", |
| port_num, (txo_e - txo_s) * 4); |
| cnt++; |
| } |
| fe_cal_tx_offset_flag_mdix = 0; |
| cnt = 0; |
| /* *** Tx offset Cal end *** */ |
| |
| /* *** Tx Amp Cal start ************************************** */ |
| cnt = 0; |
| while ((fe_cal_flag == 0) && (cnt < 0x3)) { |
| txa_s = jiffies; |
| fe_cal_tx_amp(port_num, CALDLY); /* allen_20160608 */ |
| txa_e = jiffies; |
| if (show_time) |
| pr_info("port[%d] fe_cal_tx_amp time = %u\n", |
| port_num, (txa_e - txa_s) * 4); |
| cnt++; |
| } |
| fe_cal_flag = 0; |
| cnt = 0; |
| while ((fe_cal_flag_mdix == 0) && (cnt < 0x3)) { |
| txa_s = jiffies; |
| fe_cal_tx_amp_mdix(port_num, CALDLY); |
| txa_e = jiffies; |
| if (show_time) |
| pr_info("port[%d] fe_cal_tx_amp_mdix time = %u\n", |
| port_num, (txa_e - txa_s) * 4); |
| cnt++; |
| } |
| fe_cal_flag_mdix = 0; |
| cnt = 0; |
| |
| l3r25_tmp = tc_phy_read_l_reg(port_num, 3, 25); |
| l3r25_tmp = l3r25_tmp & ~(0x1000);/*[12] RG_ZCALEN = 0*/ |
| tc_phy_write_l_reg(port_num, 3, 25, l3r25_tmp); |
| tc_phy_write_g_reg(port_num, 1, 26, 0x0000); |
| tc_phy_write_l_reg(port_num, 0, 26, l0r26_temp); |
| tc_phy_write_l_reg(port_num, 0, 30, l0r30_temp); |
| tc_phy_write_g_reg(port_num, 1, 26, 0x0000); |
| tc_phy_write_l_reg(port_num, 0, 0, 0x3100); |
| /*enable flow control*/ |
| tc_phy_write_g_reg(port_num, 0, 4, 0x5e1); |
| } |
| |
| u8 all_ge_ana_cal_wait(unsigned int delay, u8 port_num) /* for EN7512 */ |
| { |
| u8 all_ana_cal_status; |
| u16 cnt, g7r24_temp; |
| |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp & (~0x10)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp | 0x10); |
| |
| cnt = 1000; |
| do { |
| udelay(delay); |
| cnt--; |
| all_ana_cal_status = |
| ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) >> 1) & 0x1); |
| |
| } while ((all_ana_cal_status == 0) && (cnt != 0)); |
| g7r24_temp = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_temp & (~0x10)); |
| |
| return all_ana_cal_status; |
| } |
| |
| void ge_cal_rext(u8 phyaddr, unsigned int 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(phyaddr, 0x1e, 0x00dc, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e1, 0x0000); |
| |
| rg_zcal_ctrl = 0x20;/* start with 0 dB */ |
| dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00e0); |
| /* 1e_e0[5:0]:rg_zcal_ctrl */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e0, (rg_zcal_ctrl)); |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr);/* delay 20 usec */ |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE Rext AnaCal ERROR! \r\n"); |
| } |
| /* 1e_17a[8]:ad_cal_comp_out */ |
| ad_cal_comp_out_init = (tc_phy_read_dev_reg(phyaddr, 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(phyaddr, 0x1e, 0x00e0, (rg_zcal_ctrl)); |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); /* delay 20 usec */ |
| dev1e_17a_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017a); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE Rext AnaCal ERROR! \r\n"); |
| } else if (((dev1e_17a_tmp >> 8) & 0x1) != ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| pr_info(" GE Rext AnaCal Done! (%d)(0x%x) \r\n", cnt, rg_zcal_ctrl); |
| } else { |
| dev1e_17a_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017a); |
| dev1e_e0_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0xe0); |
| if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; /* need to FT(IC fail?) */ |
| pr_info(" GE Rext AnaCal Saturation! \r\n"); |
| rg_zcal_ctrl = 0x20; /* 0 dB */ |
| } else { |
| pr_info(" GE Rxet cal (%d)(%d)(%d)(0x%x) \r\n", |
| cnt, ad_cal_comp_out_init, |
| ((dev1e_17a_tmp >> 8) & 0x1), dev1e_e0_tmp); |
| } |
| } |
| } |
| |
| if (all_ana_cal_status == ANACAL_ERROR) { |
| rg_zcal_ctrl = 0x20; /* 0 dB */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl)); |
| } else { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e0, ((rg_zcal_ctrl << 8) | rg_zcal_ctrl)); |
| /* **** 1f_115[2:0] = rg_zcal_ctrl[5:3] // Mog review */ |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x0115, ((rg_zcal_ctrl & 0x3f) >> 3)); |
| pr_info(" GE Rext AnaCal Done! (%d)(0x%x) \r\n", cnt, rg_zcal_ctrl); |
| ge_cal_flag = 1; |
| } |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x0000); |
| /* *** Iext/Rext Cal end *** */ |
| } |
| |
| void ge_cal_r50(u8 phyaddr, unsigned int delay) |
| { |
| u8 rg_zcal_ctrl, all_ana_cal_status, i; |
| u16 ad_cal_comp_out_init; |
| u16 dev1e_e0_ana_cal_r5; |
| int calibration_polarity; |
| u16 cal_pair, val_tmp, g7r24_tmp; |
| u16 dev1e_174_tmp, dev1e_175_tmp, l3r25_temp; |
| u8 rg_zcal_ctrl_filter, cnt = 0; |
| |
| /* *** R50 Cal start***************** */ |
| fe_ge_r50_common(phyaddr); |
| /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */ |
| /* 1e_dc[0]:rg_txvos_calen */ |
| /*disable RG_ZCALEN*/ |
| /*decide which port calibration RG_ZCALEN by port_num*/ |
| for (i = 1; i <= 4; i++) { |
| l3r25_temp = tc_phy_read_l_reg(i, 3, 25); |
| l3r25_temp = l3r25_temp & ~(0x1000); |
| tc_phy_write_l_reg(i, 3, 25, l3r25_temp); |
| } |
| for (cal_pair = ANACAL_PAIR_A; cal_pair <= ANACAL_PAIR_D; cal_pair++) { |
| rg_zcal_ctrl = 0x20;/* start with 0 dB */ |
| dev1e_e0_ana_cal_r5 = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00e0) & (~0x003f)); |
| /* 1e_e0[5:0]:rg_zcal_ctrl */ |
| if (cal_pair == ANACAL_PAIR_A) { |
| /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x1000); |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */ |
| /* 1e_dc[12]:rg_zcalen_b */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0100); |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */ |
| /* 1e_dc[8]:rg_zcalen_c */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0010); |
| |
| } else {/* if(cal_pair == ANACAL_PAIR_D) */ |
| |
| /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */ |
| /* 1e_dc[4]:rg_zcalen_d */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0001); |
| } |
| rg_zcal_ctrl = 0x20; /* start with 0 dB */ |
| g7r24_tmp = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (~0xfc0)); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, g7r24_tmp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| |
| /*wait AD_CAL_COMP_OUT = 1*/ |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE R50 AnaCal ERROR! (init) \r\n"); |
| } |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| |
| cnt = 0; |
| while ((all_ana_cal_status < ANACAL_ERROR) && (cnt < 254)) { |
| cnt++; |
| |
| rg_zcal_ctrl += calibration_polarity; |
| g7r24_tmp = (tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & (~0xfc0)); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, |
| g7r24_tmp | ((rg_zcal_ctrl & 0x3f) << 6)); |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); |
| |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE R50 AnaCal ERROR! (%d) \r\n", cnt); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 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; |
| pr_info(" GE R50 Cal Sat! rg_zcal_ctrl = 0x%x(%d)\n", |
| cnt, rg_zcal_ctrl); |
| } |
| } |
| } |
| |
| if ((all_ana_cal_status == ANACAL_ERROR) || |
| (all_ana_cal_status == ANACAL_SATURATION)) { |
| rg_zcal_ctrl = 0x20; /* 0 dB */ |
| rg_zcal_ctrl_filter = 8; /*default value*/ |
| } else { |
| /*DA_TX_R50*/ |
| rg_zcal_ctrl_filter = rg_zcal_ctrl; |
| rg_zcal_ctrl = ZCAL_TO_R50ohm_GE_TBL[rg_zcal_ctrl]; |
| /*DA_TX_FILTER*/ |
| rg_zcal_ctrl_filter = ZCAL_TO_FILTER_TBL[rg_zcal_ctrl_filter]; |
| rg_zcal_ctrl_filter = rg_zcal_ctrl_filter & 0xf; |
| rg_zcal_ctrl_filter = rg_zcal_ctrl_filter << 8 | rg_zcal_ctrl_filter; |
| } |
| if (all_ana_cal_status == ANACAL_FINISH) { |
| if (cal_pair == ANACAL_PAIR_A) { |
| dev1e_174_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0174); |
| dev1e_174_tmp = dev1e_174_tmp & ~(0xff00); |
| if (rg_zcal_ctrl > 4) { |
| val_tmp = (((rg_zcal_ctrl - 4) << 8) & 0xff00) | |
| dev1e_174_tmp; |
| } else { |
| val_tmp = (((0) << 8) & 0xff00) | dev1e_174_tmp; |
| } |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0174, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x03a0, rg_zcal_ctrl_filter); |
| |
| pr_info("R50_PAIR_A : 1e_174 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0174)); |
| pr_info("R50_PAIR_A : 1e_3a0 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x03a0)); |
| |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| dev1e_174_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0174); |
| dev1e_174_tmp = dev1e_174_tmp & (~0x007f); |
| if (rg_zcal_ctrl > 2) { |
| val_tmp = (((rg_zcal_ctrl - 2) << 0) & 0xff) | |
| dev1e_174_tmp; |
| } else { |
| val_tmp = (((0) << 0) & 0xff) | |
| dev1e_174_tmp; |
| } |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0174, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x03a1, rg_zcal_ctrl_filter); |
| pr_info("R50_PAIR_B : 1e_174 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0174)); |
| pr_info("R50_PAIR_B : 1e_3a1 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x03a1)); |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| dev1e_175_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0175); |
| dev1e_175_tmp = dev1e_175_tmp & (~0x7f00); |
| if (rg_zcal_ctrl > 4) { |
| val_tmp = dev1e_175_tmp | |
| (((rg_zcal_ctrl - 4) << 8) & 0xff00); |
| } else { |
| val_tmp = dev1e_175_tmp | (((0) << 8) & 0xff00); |
| } |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0175, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x03a2, rg_zcal_ctrl_filter); |
| pr_info("R50_PAIR_C : 1e_175 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0175)); |
| pr_info("R50_PAIR_C : 1e_3a2 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x03a2)); |
| |
| } else {/* if(cal_pair == ANACAL_PAIR_D) */ |
| dev1e_175_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0175); |
| dev1e_175_tmp = dev1e_175_tmp & (~0x007f); |
| if (rg_zcal_ctrl > 6) { |
| val_tmp = dev1e_175_tmp | |
| (((rg_zcal_ctrl - 6) << 0) & 0xff); |
| } else { |
| val_tmp = dev1e_175_tmp | |
| (((0) << 0) & 0xff); |
| } |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0175, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x03a3, rg_zcal_ctrl_filter); |
| pr_info("R50_PAIR_D : 1e_175 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0175)); |
| pr_info("R50_PAIR_D : 1e_3a3 = 0x%x\n", |
| tc_phy_read_dev_reg(phyaddr, 0x1e, 0x03a3)); |
| } |
| } |
| } |
| clear_ckinv_ana_txvos(); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x0000); |
| ge_cal_r50_flag = 1; |
| /* *** R50 Cal end *** */ |
| } |
| |
| void ge_cal_tx_amp(u8 phyaddr, unsigned int delay) |
| { |
| u8 all_ana_cal_status; |
| u16 ad_cal_comp_out_init; |
| int calibration_polarity; |
| u16 cal_pair; |
| u8 tx_amp_reg_shift; |
| u16 reg_temp, val_tmp, l3r25_temp, val_tmp_100; |
| u8 tx_amp_temp, tx_amp_reg, cnt = 0, tx_amp_reg_100; |
| |
| u16 tx_amp_temp_L, tx_amp_temp_M; |
| u16 tx_amp_L_100, tx_amp_M_100; |
| /* *** Tx Amp Cal start ***/ |
| tc_phy_write_l_reg(0, 0, 0, 0x0140); |
| |
| tc_phy_write_dev_reg(0, 0x1e, 0x3e, 0xf808); |
| tc_phy_write_dev_reg(0, 0x1e, 0x145, 0x5010); |
| tc_phy_write_dev_reg(0, 0x1e, 0x17d, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x17e, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x17f, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x180, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x181, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x182, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x183, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x184, 0x80f0); |
| tc_phy_write_dev_reg(0, 0x1e, 0x00db, 0x1000); |
| tc_phy_write_dev_reg(0, 0x1e, 0x00dc, 0x0001); |
| tc_phy_write_dev_reg(0, 0x1f, 0x300, 0x4); |
| tc_phy_write_dev_reg(0, 0x1f, 0x27a, 0x33); |
| tc_phy_write_g_reg(1, 2, 25, 0xf020); |
| tc_phy_write_dev_reg(0, 0x1f, 0x300, 0x14); |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x7000); |
| l3r25_temp = tc_phy_read_l_reg(FE_CAL_COMMON, 3, 25); |
| l3r25_temp = l3r25_temp | 0x200; |
| tc_phy_write_l_reg(FE_CAL_COMMON, 3, 25, l3r25_temp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x11, 0xff00); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0xc9, 0xffff); |
| tc_phy_write_g_reg(1, 2, 25, 0xb020); |
| |
| for (cal_pair = ANACAL_PAIR_A; cal_pair <= ANACAL_PAIR_D; cal_pair++) { |
| tx_amp_temp = 0x20; /* start with 0 dB */ |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x7000); |
| if (cal_pair == ANACAL_PAIR_A) { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x1000); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x012) & (~0xfc00)); |
| tx_amp_reg_shift = 10; |
| tx_amp_reg = 0x12; |
| tx_amp_reg_100 = 0x16; |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0100); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017) & (~0x3f00)); |
| tx_amp_reg_shift = 8; |
| tx_amp_reg = 0x17; |
| tx_amp_reg_100 = 0x18; |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0010); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x019) & (~0x3f00)); |
| tx_amp_reg_shift = 8; |
| tx_amp_reg = 0x19; |
| tx_amp_reg_100 = 0x20; |
| } else {/* if(cal_pair == ANACAL_PAIR_D) */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0001); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x021) & (~0x3f00)); |
| tx_amp_reg_shift = 8; |
| tx_amp_reg = 0x21; |
| tx_amp_reg_100 = 0x22; |
| } |
| /* 1e_12, 1e_17, 1e_19, 1e_21 */ |
| val_tmp = tx_amp_temp | (tx_amp_temp << tx_amp_reg_shift); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg_100, val_tmp); |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE Tx amp AnaCal ERROR! \r\n"); |
| } |
| /* 1e_17a[8]:ad_cal_comp_out */ |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| 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; |
| |
| val_tmp = (tx_amp_temp | (tx_amp_temp << tx_amp_reg_shift)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg_100, val_tmp); |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE Tx amp AnaCal ERROR!\n"); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| } else { |
| if ((tx_amp_temp == 0x3f) || (tx_amp_temp == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; |
| pr_info(" GE Tx amp AnaCal Saturation! \r\n"); |
| } |
| } |
| } |
| if (all_ana_cal_status == ANACAL_ERROR) { |
| pr_info("ANACAL_ERROR\n"); |
| tx_amp_temp = 0x20; |
| val_tmp = (reg_temp | (tx_amp_temp << tx_amp_reg_shift)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg, val_tmp); |
| } |
| |
| if (all_ana_cal_status == ANACAL_FINISH) { |
| if (cal_pair == ANACAL_PAIR_A) { |
| tx_amp_temp_M = tx_amp_temp + 9; |
| tx_amp_temp_L = tx_amp_temp + 18; |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| tx_amp_temp_M = tx_amp_temp + 8; |
| tx_amp_temp_L = tx_amp_temp + 22; |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| tx_amp_temp_M = tx_amp_temp + 9; |
| tx_amp_temp_L = tx_amp_temp + 9; |
| } else if (cal_pair == ANACAL_PAIR_D) { |
| tx_amp_temp_M = tx_amp_temp + 9; |
| tx_amp_temp_L = tx_amp_temp + 9; |
| } |
| if (tx_amp_temp_L >= 0x3f) |
| tx_amp_temp_L = 0x3f; |
| if (tx_amp_temp_M >= 0x3f) |
| tx_amp_temp_M = 0x3f; |
| val_tmp = ((tx_amp_temp_L) | |
| ((tx_amp_temp_M) << tx_amp_reg_shift)); |
| if (cal_pair == ANACAL_PAIR_A) { |
| if (tx_amp_temp < 6) |
| tx_amp_M_100 = 0; |
| else |
| tx_amp_M_100 = tx_amp_temp - 6; |
| |
| if ((tx_amp_temp + 9) >= 0x3f) |
| tx_amp_L_100 = 0x3f; |
| else |
| tx_amp_L_100 = tx_amp_temp + 9; |
| val_tmp_100 = ((tx_amp_L_100) | |
| ((tx_amp_M_100) << tx_amp_reg_shift)); |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| if (tx_amp_temp < 7) |
| tx_amp_M_100 = 0; |
| else |
| tx_amp_M_100 = tx_amp_temp - 7; |
| |
| if ((tx_amp_temp + 8) >= 0x3f) |
| tx_amp_L_100 = 0x3f; |
| else |
| tx_amp_L_100 = tx_amp_temp + 8; |
| val_tmp_100 = ((tx_amp_L_100) | |
| ((tx_amp_M_100) << tx_amp_reg_shift)); |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| if ((tx_amp_temp + 9) >= 0x3f) |
| tx_amp_L_100 = 0x3f; |
| else |
| tx_amp_L_100 = tx_amp_temp + 9; |
| tx_amp_M_100 = tx_amp_L_100; |
| val_tmp_100 = ((tx_amp_L_100) | |
| ((tx_amp_M_100) << tx_amp_reg_shift)); |
| } else if (cal_pair == ANACAL_PAIR_D) { |
| if ((tx_amp_temp + 9) >= 0x3f) |
| tx_amp_L_100 = 0x3f; |
| else |
| tx_amp_L_100 = tx_amp_temp + 9; |
| |
| tx_amp_M_100 = tx_amp_L_100; |
| val_tmp_100 = ((tx_amp_L_100) | |
| ((tx_amp_M_100) << tx_amp_reg_shift)); |
| } |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg, val_tmp); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_amp_reg_100, val_tmp_100); |
| |
| if (cal_pair == ANACAL_PAIR_A) { |
| pr_info("TX_AMP_PAIR_A : 1e_%x = 0x%x\n", |
| tx_amp_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg)); |
| pr_info("TX_AMP_PAIR_A : 1e_%x = 0x%x\n", |
| tx_amp_reg_100, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg_100)); |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| pr_info("TX_AMP_PAIR_B : 1e_%x = 0x%x\n", |
| tx_amp_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg)); |
| pr_info("TX_AMP_PAIR_B : 1e_%x = 0x%x\n", |
| tx_amp_reg_100, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg_100)); |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| pr_info("TX_AMP_PAIR_C : 1e_%x = 0x%x\n", |
| tx_amp_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg)); |
| pr_info("TX_AMP_PAIR_C : 1e_%x = 0x%x\n", |
| tx_amp_reg_100, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg_100)); |
| |
| } else {/* if(cal_pair == ANACAL_PAIR_D) */ |
| pr_info("TX_AMP_PAIR_D : 1e_%x = 0x%x\n", |
| tx_amp_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg)); |
| pr_info("TX_AMP_PAIR_D : 1e_%x = 0x%x\n", |
| tx_amp_reg_100, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_amp_reg_100)); |
| } |
| } |
| } |
| |
| ge_cal_flag = 1; |
| pr_info("GE_TX_AMP END\n"); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017d, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017e, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017f, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0180, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0181, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0182, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0183, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0184, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0x2000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0xc9, 0x0fff); |
| tc_phy_write_g_reg(1, 2, 25, 0xb020); |
| tc_phy_write_dev_reg(0, 0x1e, 0x145, 0x1000); |
| |
| /* disable analog calibration circuit */ |
| /* disable Tx offset calibration circuit */ |
| /* disable Tx VLD force mode */ |
| /* disable Tx offset/amplitude calibration circuit */ |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x003e, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0000); |
| /* *** Tx Amp Cal end *** */ |
| } |
| |
| void ge_cal_tx_offset(u8 phyaddr, unsigned int delay) |
| { |
| u8 all_ana_cal_status; |
| u16 ad_cal_comp_out_init; |
| int calibration_polarity, tx_offset_temp; |
| u16 cal_pair, cal_temp; |
| u8 tx_offset_reg_shift; |
| u16 tx_offset_reg, reg_temp, val_tmp; |
| u8 cnt = 0; |
| |
| tc_phy_write_l_reg(0, 0, 0, 0x2100); |
| |
| /* 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_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x0100); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0096, 0x8000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x003e, 0xf808);/* 1e_3e */ |
| tc_phy_write_g_reg(FE_CAL_COMMON, 7, 24, 0x3000); |
| |
| for (cal_pair = ANACAL_PAIR_A; cal_pair <= ANACAL_PAIR_D; cal_pair++) { |
| tx_offset_temp = 0x20; |
| |
| if (cal_pair == ANACAL_PAIR_A) { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5010); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x1000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017d, (0x8000 | DAC_IN_0V)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0181, (0x8000 | DAC_IN_0V)); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0172) & (~0x3f00)); |
| tx_offset_reg_shift = 8;/* 1e_172[13:8] */ |
| tx_offset_reg = 0x0172; |
| |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5018); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0100); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017e, (0x8000 | DAC_IN_0V)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0182, (0x8000 | DAC_IN_0V)); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0172) & (~0x003f)); |
| tx_offset_reg_shift = 0; |
| tx_offset_reg = 0x0172;/* 1e_172[5:0] */ |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0010); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017f, (0x8000 | DAC_IN_0V)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0183, (0x8000 | DAC_IN_0V)); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0173) & (~0x3f00)); |
| tx_offset_reg_shift = 8; |
| tx_offset_reg = 0x0173;/* 1e_173[13:8] */ |
| } else {/* if(cal_pair == ANACAL_PAIR_D) */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0180, (0x8000 | DAC_IN_0V)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0184, (0x8000 | DAC_IN_0V)); |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0173) & (~0x003f)); |
| tx_offset_reg_shift = 0; |
| tx_offset_reg = 0x0173;/* 1e_173[5:0] */ |
| } |
| /* 1e_172, 1e_173 */ |
| val_tmp = (reg_temp | (tx_offset_temp << tx_offset_reg_shift)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, val_tmp); |
| |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); /* delay 20 usec */ |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE Tx offset AnaCal ERROR! \r\n"); |
| } |
| ad_cal_comp_out_init = tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1; |
| if (ad_cal_comp_out_init == 1) |
| calibration_polarity = -1; |
| else |
| calibration_polarity = 1; |
| |
| cnt = 0; |
| tx_offset_temp += calibration_polarity; |
| while (all_ana_cal_status < ANACAL_ERROR) { |
| cnt++; |
| cal_temp = tx_offset_temp; |
| val_tmp = (reg_temp | (cal_temp << tx_offset_reg_shift)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, val_tmp); |
| |
| all_ana_cal_status = all_ge_ana_cal_wait(delay, phyaddr); |
| if (all_ana_cal_status == 0) { |
| all_ana_cal_status = ANACAL_ERROR; |
| pr_info(" GE Tx offset AnaCal ERROR! \r\n"); |
| } else if ((tc_phy_read_g_reg(FE_CAL_COMMON, 7, 24) & 0x1) != |
| ad_cal_comp_out_init) { |
| all_ana_cal_status = ANACAL_FINISH; |
| } else { |
| if ((tx_offset_temp == 0x3f) || (tx_offset_temp == 0x00)) { |
| all_ana_cal_status = ANACAL_SATURATION; |
| pr_info("GE tx offset ANACAL_SATURATION\n"); |
| /* tx_amp_temp += calibration_polarity; */ |
| } else { |
| tx_offset_temp += calibration_polarity; |
| } |
| } |
| } |
| if (all_ana_cal_status == ANACAL_ERROR) { |
| tx_offset_temp = 0x20; |
| val_tmp = (reg_temp | (tx_offset_temp << tx_offset_reg_shift)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, val_tmp); |
| } |
| |
| if (all_ana_cal_status == ANACAL_FINISH) { |
| if (cal_pair == ANACAL_PAIR_A) { |
| pr_info("TX_OFFSET_PAIR_A : 1e_%x = 0x%x\n", |
| tx_offset_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_offset_reg)); |
| } else if (cal_pair == ANACAL_PAIR_B) { |
| pr_info("TX_OFFSET_PAIR_B : 1e_%x = 0x%x\n", |
| tx_offset_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_offset_reg)); |
| } else if (cal_pair == ANACAL_PAIR_C) { |
| pr_info("TX_OFFSET_PAIR_C : 1e_%x = 0x%x\n", |
| tx_offset_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_offset_reg)); |
| |
| } else {/* if(cal_pair == ANACAL_PAIR_D) */ |
| pr_info("TX_OFFSET_PAIR_D : 1e_%x = 0x%x\n", |
| tx_offset_reg, |
| tc_phy_read_dev_reg(phyaddr, 0x1e, tx_offset_reg)); |
| } |
| } |
| } |
| ge_cal_tx_offset_flag = 1; |
| clear_ckinv_ana_txvos(); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017d, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017e, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x017f, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0180, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0181, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0182, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0183, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0184, 0x0000); |
| /* disable analog calibration circuit */ |
| /* disable Tx offset calibration circuit */ |
| /* disable Tx VLD force mode */ |
| /* disable Tx offset/amplitude calibration circuit */ |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x003e, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dd, 0x0000); |
| } |
| |
| void do_ge_phy_all_analog_cal(u8 phyaddr) |
| { |
| u16 reg0_temp, dev1e_145_temp, reg_temp; |
| u16 reg_tmp; |
| |
| tc_mii_write(phyaddr, 0x1f, 0x0000);/* g0 */ |
| reg0_temp = tc_mii_read(phyaddr, 0x0);/* keep the default value */ |
| /* set [12]AN disable, [8]full duplex, [13/6]1000Mbps */ |
| tc_mii_write(phyaddr, 0x0, 0x0140); |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x0100, 0xc000);/* BG voltage output */ |
| dev1e_145_temp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0145); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0145, 0x1010);/* fix mdi */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0185, 0x0000);/* disable tx slew control */ |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x27c, 0x1f1f); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x27c, 0x3300); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0); |
| |
| reg_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x11); |
| reg_tmp = reg_tmp | (0xf << 12); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x11, reg_tmp); |
| |
| /* calibration start ============ */ |
| ge_cal_flag = 1; /*GE calibration not calibration*/ |
| while (ge_cal_flag == 0) |
| ge_cal_rext(phyaddr, 100); |
| |
| /* *** R50 Cal start ***************************** */ |
| /*phyaddress = 0*/ |
| ge_cal_r50(phyaddr, CALDLY); |
| /* *** R50 Cal end *** */ |
| |
| /* *** Tx offset Cal start *********************** */ |
| ge_cal_tx_offset(phyaddr, CALDLY); |
| /* *** Tx offset Cal end *** */ |
| |
| /* *** Tx Amp Cal start *** */ |
| ge_cal_tx_amp(phyaddr, CALDLY); |
| /* *** Tx Amp Cal end *** */ |
| |
| /* *** Rx offset Cal start *************** */ |
| /* 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0096, 0x8000); |
| /* tx/rx_cal_criteria_value */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0037, 0x0033); |
| /* [14]: bypass all calibration, [11]: bypass adc offset cal analog */ |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0039) & (~0x4800)); |
| /* rx offset cal by Hw setup */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0039, reg_temp); |
| /* [12]: enable rtune calibration */ |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1f, 0x0107) & (~0x1000)); |
| /* disable rtune calibration */ |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x0107, reg_temp); |
| /* 1e_171[8:7]: bypass tx/rx dc offset cancellation process */ |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0171) & (~0x0180)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0171, (reg_temp | 0x0180)); |
| reg_temp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0039); |
| /* rx offset calibration start */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0039, (reg_temp | 0x2000)); |
| /* rx offset calibration end */ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0039, (reg_temp & (~0x2000))); |
| mdelay(10); /* mdelay for Hw calibration finish */ |
| reg_temp = (tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0171) & (~0x0180)); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0171, reg_temp); |
| |
| tc_mii_write(phyaddr, 0x0, reg0_temp); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x0100, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0145, dev1e_145_temp); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0x2000); |
| /* *** Rx offset Cal end *** */ |
| /*eye pic*/ |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x0, 0x018d); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x1, 0x01c7); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x2, 0x01c0); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3, 0x003a); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x4, 0x0206); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x5, 0x0000); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x6, 0x038a); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x7, 0x03c8); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x8, 0x03c0); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x9, 0x0235); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0xa, 0x0008); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0xb, 0x0000); |
| |
| /*tmp maybe changed*/ |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x27c, 0x1111); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x27b, 0x47); |
| tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0x2200); |
| |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3a8, 0x0810); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3aa, 0x0008); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3ab, 0x0810); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3ad, 0x0008); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3ae, 0x0106); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3b0, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3b1, 0x0106); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3b3, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x18c, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x18d, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x18e, 0x0001); |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x18f, 0x0001); |
| |
| /*da_tx_bias1_b_tx_standby = 5'b10 (dev1eh_reg3aah[12:8])*/ |
| reg_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x3aa); |
| reg_tmp = reg_tmp & ~(0x1f00); |
| reg_tmp = reg_tmp | 0x2 << 8; |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3aa, reg_tmp); |
| |
| /*da_tx_bias1_a_tx_standby = 5'b10 (dev1eh_reg3a9h[4:0])*/ |
| reg_tmp = tc_phy_read_dev_reg(phyaddr, 0x1e, 0x3a9); |
| reg_tmp = reg_tmp & ~(0x1f); |
| reg_tmp = reg_tmp | 0x2; |
| tc_phy_write_dev_reg(phyaddr, 0x1e, 0x3a9, reg_tmp); |
| } |
| |
| #if 0 |
| static void mt7622_ephy_cal(void) |
| { |
| int i; |
| unsigned long t_s, t_e; |
| |
| t_s = jiffies; |
| for (i = 0; i < 5; i++) |
| do_fe_phy_all_analog_cal(i); |
| t_e = jiffies; |
| if (show_time) |
| pr_info("cal time = %lu\n", (t_e - t_s) * 4); |
| } |
| |
| static void leopard_ephy_cal(void) |
| { |
| int i, dbg; |
| unsigned long t_s, t_e; |
| |
| dbg = 1; |
| if (dbg) { |
| t_s = jiffies; |
| for (i = 1; i < 5; i++) |
| do_fe_phy_all_analog_cal(i); |
| |
| do_ge_phy_all_analog_cal(0); |
| |
| t_e = jiffies; |
| } |
| if (show_time) |
| pr_info("cal time = %lu\n", (t_e - t_s) * 4); |
| } |
| #endif |
| static void wait_loop(void) |
| { |
| int i; |
| int read_data; |
| |
| for (i = 0; i < 320; i = i + 1) |
| read_data = sys_reg_read(RALINK_ETH_SW_BASE + 0x108); |
| } |
| |
| static void trgmii_calibration_7623(void) |
| { |
| /* minimum delay for all correct */ |
| unsigned int tap_a[5] = { |
| 0, 0, 0, 0, 0 |
| }; |
| /* maximum delay for all correct */ |
| unsigned int tap_b[5] = { |
| 0, 0, 0, 0, 0 |
| }; |
| unsigned int final_tap[5]; |
| unsigned int rxc_step_size; |
| unsigned int rxd_step_size; |
| unsigned int read_data; |
| unsigned int tmp; |
| unsigned int rd_wd; |
| int i; |
| unsigned int err_cnt[5]; |
| unsigned int init_toggle_data; |
| unsigned int err_flag[5]; |
| unsigned int err_total_flag; |
| unsigned int training_word; |
| unsigned int rd_tap; |
| |
| void __iomem *TRGMII_7623_base; |
| void __iomem *TRGMII_7623_RD_0; |
| void __iomem *temp_addr; |
| |
| TRGMII_7623_base = ETHDMASYS_ETH_SW_BASE + 0x0300; |
| TRGMII_7623_RD_0 = TRGMII_7623_base + 0x10; |
| rxd_step_size = 0x1; |
| rxc_step_size = 0x4; |
| init_toggle_data = 0x00000055; |
| training_word = 0x000000AC; |
| |
| /* RX clock gating in MT7623 */ |
| reg_bit_zero(TRGMII_7623_base + 0x04, 30, 2); |
| /* Assert RX reset in MT7623 */ |
| reg_bit_one(TRGMII_7623_base + 0x00, 31, 1); |
| /* Set TX OE edge in MT7623 */ |
| reg_bit_one(TRGMII_7623_base + 0x78, 13, 1); |
| /* Disable RX clock gating in MT7623 */ |
| reg_bit_one(TRGMII_7623_base + 0x04, 30, 2); |
| /* Release RX reset in MT7623 */ |
| reg_bit_zero(TRGMII_7623_base, 31, 1); |
| |
| for (i = 0; i < 5; i++) |
| /* Set bslip_en = 1 */ |
| reg_bit_one(TRGMII_7623_RD_0 + i * 8, 31, 1); |
| |
| /* Enable Training Mode in MT7530 */ |
| mii_mgr_read(0x1F, 0x7A40, &read_data); |
| read_data |= 0xc0000000; |
| mii_mgr_write(0x1F, 0x7A40, read_data); |
| |
| err_total_flag = 0; |
| read_data = 0x0; |
| while (err_total_flag == 0 && read_data != 0x68) { |
| /* Enable EDGE CHK in MT7623 */ |
| for (i = 0; i < 5; i++) { |
| reg_bit_zero(TRGMII_7623_RD_0 + i * 8, 28, 4); |
| reg_bit_one(TRGMII_7623_RD_0 + i * 8, 31, 1); |
| } |
| wait_loop(); |
| err_total_flag = 1; |
| for (i = 0; i < 5; i++) { |
| tmp = sys_reg_read(TRGMII_7623_RD_0 + i * 8); |
| err_cnt[i] = (tmp >> 8) & 0x0000000f; |
| |
| tmp = sys_reg_read(TRGMII_7623_RD_0 + i * 8); |
| rd_wd = (tmp >> 16) & 0x000000ff; |
| |
| if (err_cnt[i] != 0) |
| err_flag[i] = 1; |
| else if (rd_wd != 0x55) |
| err_flag[i] = 1; |
| else |
| err_flag[i] = 0; |
| err_total_flag = err_flag[i] & err_total_flag; |
| } |
| |
| /* Disable EDGE CHK in MT7623 */ |
| for (i = 0; i < 5; i++) { |
| reg_bit_one(TRGMII_7623_RD_0 + i * 8, 30, 1); |
| reg_bit_zero(TRGMII_7623_RD_0 + i * 8, 28, 2); |
| reg_bit_zero(TRGMII_7623_RD_0 + i * 8, 31, 1); |
| } |
| wait_loop(); |
| /* Adjust RXC delay */ |
| /* RX clock gating in MT7623 */ |
| reg_bit_zero(TRGMII_7623_base + 0x04, 30, 2); |
| read_data = sys_reg_read(TRGMII_7623_base); |
| if (err_total_flag == 0) { |
| tmp = (read_data & 0x0000007f) + rxc_step_size; |
| read_data >>= 8; |
| read_data &= 0xffffff80; |
| read_data |= tmp; |
| read_data <<= 8; |
| read_data &= 0xffffff80; |
| read_data |= tmp; |
| sys_reg_write(TRGMII_7623_base, read_data); |
| } else { |
| tmp = (read_data & 0x0000007f) + 16; |
| read_data >>= 8; |
| read_data &= 0xffffff80; |
| read_data |= tmp; |
| read_data <<= 8; |
| read_data &= 0xffffff80; |
| read_data |= tmp; |
| sys_reg_write(TRGMII_7623_base, read_data); |
| } |
| read_data &= 0x000000ff; |
| /* Disable RX clock gating in MT7623 */ |
| reg_bit_one(TRGMII_7623_base + 0x04, 30, 2); |
| for (i = 0; i < 5; i++) |
| reg_bit_one(TRGMII_7623_RD_0 + i * 8, 31, 1); |
| } |
| /* Read RD_WD MT7623 */ |
| for (i = 0; i < 5; i++) { |
| temp_addr = TRGMII_7623_RD_0 + i * 8; |
| rd_tap = 0; |
| while (err_flag[i] != 0 && rd_tap != 128) { |
| /* Enable EDGE CHK in MT7623 */ |
| tmp = sys_reg_read(temp_addr); |
| tmp |= 0x40000000; |
| reg_bit_zero(temp_addr, 28, 4); |
| reg_bit_one(temp_addr, 30, 1); |
| wait_loop(); |
| read_data = sys_reg_read(temp_addr); |
| /* Read MT7623 Errcnt */ |
| err_cnt[i] = (read_data >> 8) & 0x0000000f; |
| rd_wd = (read_data >> 16) & 0x000000ff; |
| if (err_cnt[i] != 0 || rd_wd != 0x55) |
| err_flag[i] = 1; |
| else |
| err_flag[i] = 0; |
| /* Disable EDGE CHK in MT7623 */ |
| reg_bit_zero(temp_addr, 28, 2); |
| reg_bit_zero(temp_addr, 31, 1); |
| tmp |= 0x40000000; |
| sys_reg_write(temp_addr, tmp & 0x4fffffff); |
| wait_loop(); |
| if (err_flag[i] != 0) { |
| /* Add RXD delay in MT7623 */ |
| rd_tap = (read_data & 0x7f) + rxd_step_size; |
| |
| read_data = (read_data & 0xffffff80) | rd_tap; |
| sys_reg_write(temp_addr, read_data); |
| tap_a[i] = rd_tap; |
| } else { |
| rd_tap = (read_data & 0x0000007f) + 48; |
| read_data = (read_data & 0xffffff80) | rd_tap; |
| sys_reg_write(temp_addr, read_data); |
| } |
| } |
| pr_info("MT7623 %dth bit Tap_a = %d\n", i, tap_a[i]); |
| } |
| for (i = 0; i < 5; i++) { |
| while ((err_flag[i] == 0) && (rd_tap != 128)) { |
| read_data = sys_reg_read(TRGMII_7623_RD_0 + i * 8); |
| /* Add RXD delay in MT7623 */ |
| rd_tap = (read_data & 0x7f) + rxd_step_size; |
| |
| read_data = (read_data & 0xffffff80) | rd_tap; |
| sys_reg_write(TRGMII_7623_RD_0 + i * 8, read_data); |
| |
| /* Enable EDGE CHK in MT7623 */ |
| tmp = sys_reg_read(TRGMII_7623_RD_0 + i * 8); |
| tmp |= 0x40000000; |
| sys_reg_write(TRGMII_7623_RD_0 + i * 8, |
| (tmp & 0x4fffffff)); |
| wait_loop(); |
| read_data = sys_reg_read(TRGMII_7623_RD_0 + i * 8); |
| /* Read MT7623 Errcnt */ |
| err_cnt[i] = (read_data >> 8) & 0xf; |
| rd_wd = (read_data >> 16) & 0x000000ff; |
| if (err_cnt[i] != 0 || rd_wd != 0x55) |
| err_flag[i] = 1; |
| else |
| err_flag[i] = 0; |
| |
| /* Disable EDGE CHK in MT7623 */ |
| tmp = sys_reg_read(TRGMII_7623_RD_0 + i * 8); |
| tmp |= 0x40000000; |
| sys_reg_write(TRGMII_7623_RD_0 + i * 8, |
| (tmp & 0x4fffffff)); |
| wait_loop(); |
| } |
| tap_b[i] = rd_tap; /* -rxd_step_size; */ |
| pr_info("MT7623 %dth bit Tap_b = %d\n", i, tap_b[i]); |
| /* Calculate RXD delay = (TAP_A + TAP_B)/2 */ |
| final_tap[i] = (tap_a[i] + tap_b[i]) / 2; |
| read_data = (read_data & 0xffffff80) | final_tap[i]; |
| sys_reg_write(TRGMII_7623_RD_0 + i * 8, read_data); |
| } |
| |
| mii_mgr_read(0x1F, 0x7A40, &read_data); |
| read_data &= 0x3fffffff; |
| mii_mgr_write(0x1F, 0x7A40, read_data); |
| } |
| |
| static void trgmii_calibration_7530(void) |
| { |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| unsigned int tap_a[5] = { |
| 0, 0, 0, 0, 0 |
| }; |
| unsigned int tap_b[5] = { |
| 0, 0, 0, 0, 0 |
| }; |
| unsigned int final_tap[5]; |
| unsigned int rxc_step_size; |
| unsigned int rxd_step_size; |
| unsigned int read_data; |
| unsigned int tmp = 0; |
| int i; |
| unsigned int err_cnt[5]; |
| unsigned int rd_wd; |
| unsigned int init_toggle_data; |
| unsigned int err_flag[5]; |
| unsigned int err_total_flag; |
| unsigned int training_word; |
| unsigned int rd_tap; |
| |
| void __iomem *TRGMII_7623_base; |
| u32 TRGMII_7530_RD_0; |
| u32 TRGMII_7530_base; |
| u32 TRGMII_7530_TX_base; |
| |
| TRGMII_7623_base = ETHDMASYS_ETH_SW_BASE + 0x0300; |
| TRGMII_7530_base = 0x7A00; |
| TRGMII_7530_RD_0 = TRGMII_7530_base + 0x10; |
| rxd_step_size = 0x1; |
| rxc_step_size = 0x8; |
| init_toggle_data = 0x00000055; |
| training_word = 0x000000AC; |
| |
| TRGMII_7530_TX_base = TRGMII_7530_base + 0x50; |
| |
| reg_bit_one(TRGMII_7623_base + 0x40, 31, 1); |
| mii_mgr_read(0x1F, 0x7a10, &read_data); |
| |
| /* RX clock gating in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base + 0x04, &read_data); |
| read_data &= 0x3fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_base + 0x04, read_data); |
| |
| /* Set TX OE edge in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base + 0x78, &read_data); |
| read_data |= 0x00002000; |
| mii_mgr_write(0x1F, TRGMII_7530_base + 0x78, read_data); |
| |
| /* Assert RX reset in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base, &read_data); |
| read_data |= 0x80000000; |
| mii_mgr_write(0x1F, TRGMII_7530_base, read_data); |
| |
| /* Release RX reset in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base, &read_data); |
| read_data &= 0x7fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_base, read_data); |
| |
| /* Disable RX clock gating in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base + 0x04, &read_data); |
| read_data |= 0xC0000000; |
| mii_mgr_write(0x1F, TRGMII_7530_base + 0x04, read_data); |
| |
| /*Enable Training Mode in MT7623 */ |
| reg_bit_zero(TRGMII_7623_base + 0x40, 30, 1); |
| if (ei_local->architecture & GE1_TRGMII_FORCE_2000) |
| reg_bit_one(TRGMII_7623_base + 0x40, 30, 2); |
| else |
| reg_bit_one(TRGMII_7623_base + 0x40, 31, 1); |
| reg_bit_zero(TRGMII_7623_base + 0x78, 8, 4); |
| reg_bit_zero(TRGMII_7623_base + 0x50, 8, 4); |
| reg_bit_zero(TRGMII_7623_base + 0x58, 8, 4); |
| reg_bit_zero(TRGMII_7623_base + 0x60, 8, 4); |
| reg_bit_zero(TRGMII_7623_base + 0x68, 8, 4); |
| reg_bit_zero(TRGMII_7623_base + 0x70, 8, 4); |
| reg_bit_one(TRGMII_7623_base + 0x78, 11, 1); |
| |
| err_total_flag = 0; |
| read_data = 0x0; |
| while (err_total_flag == 0 && (read_data != 0x68)) { |
| /* Enable EDGE CHK in MT7530 */ |
| for (i = 0; i < 5; i++) { |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &read_data); |
| read_data |= 0x40000000; |
| read_data &= 0x4fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| wait_loop(); |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &err_cnt[i]); |
| err_cnt[i] >>= 8; |
| err_cnt[i] &= 0x0000ff0f; |
| rd_wd = err_cnt[i] >> 8; |
| rd_wd &= 0x000000ff; |
| err_cnt[i] &= 0x0000000f; |
| if (err_cnt[i] != 0) |
| err_flag[i] = 1; |
| else if (rd_wd != 0x55) |
| err_flag[i] = 1; |
| else |
| err_flag[i] = 0; |
| |
| if (i == 0) |
| err_total_flag = err_flag[i]; |
| else |
| err_total_flag = err_flag[i] & err_total_flag; |
| /* Disable EDGE CHK in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &read_data); |
| read_data |= 0x40000000; |
| read_data &= 0x4fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| wait_loop(); |
| } |
| /*Adjust RXC delay */ |
| if (err_total_flag == 0) { |
| /* Assert RX reset in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base, &read_data); |
| read_data |= 0x80000000; |
| mii_mgr_write(0x1F, TRGMII_7530_base, read_data); |
| |
| /* RX clock gating in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base + 0x04, &read_data); |
| read_data &= 0x3fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_base + 0x04, read_data); |
| |
| mii_mgr_read(0x1F, TRGMII_7530_base, &read_data); |
| tmp = read_data; |
| tmp &= 0x0000007f; |
| tmp += rxc_step_size; |
| read_data &= 0xffffff80; |
| read_data |= tmp; |
| mii_mgr_write(0x1F, TRGMII_7530_base, read_data); |
| mii_mgr_read(0x1F, TRGMII_7530_base, &read_data); |
| |
| /* Release RX reset in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base, &read_data); |
| read_data &= 0x7fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_base, read_data); |
| |
| /* Disable RX clock gating in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_base + 0x04, &read_data); |
| read_data |= 0xc0000000; |
| mii_mgr_write(0x1F, TRGMII_7530_base + 0x04, read_data); |
| } |
| read_data = tmp; |
| } |
| /* Read RD_WD MT7530 */ |
| for (i = 0; i < 5; i++) { |
| rd_tap = 0; |
| while (err_flag[i] != 0 && rd_tap != 128) { |
| /* Enable EDGE CHK in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &read_data); |
| read_data |= 0x40000000; |
| read_data &= 0x4fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| wait_loop(); |
| err_cnt[i] = (read_data >> 8) & 0x0000000f; |
| rd_wd = (read_data >> 16) & 0x000000ff; |
| if (err_cnt[i] != 0 || rd_wd != 0x55) |
| err_flag[i] = 1; |
| else |
| err_flag[i] = 0; |
| |
| if (err_flag[i] != 0) { |
| /* Add RXD delay in MT7530 */ |
| rd_tap = (read_data & 0x7f) + rxd_step_size; |
| read_data = (read_data & 0xffffff80) | rd_tap; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| tap_a[i] = rd_tap; |
| } else { |
| /* Record the min delay TAP_A */ |
| tap_a[i] = (read_data & 0x0000007f); |
| rd_tap = tap_a[i] + 0x4; |
| read_data = (read_data & 0xffffff80) | rd_tap; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| } |
| |
| /* Disable EDGE CHK in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &read_data); |
| read_data |= 0x40000000; |
| read_data &= 0x4fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| wait_loop(); |
| } |
| pr_info("MT7530 %dth bit Tap_a = %d\n", i, tap_a[i]); |
| } |
| for (i = 0; i < 5; i++) { |
| rd_tap = 0; |
| while (err_flag[i] == 0 && (rd_tap != 128)) { |
| /* Enable EDGE CHK in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &read_data); |
| read_data |= 0x40000000; |
| read_data &= 0x4fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| wait_loop(); |
| err_cnt[i] = (read_data >> 8) & 0x0000000f; |
| rd_wd = (read_data >> 16) & 0x000000ff; |
| if (err_cnt[i] != 0 || rd_wd != 0x55) |
| err_flag[i] = 1; |
| else |
| err_flag[i] = 0; |
| |
| if (err_flag[i] == 0 && (rd_tap != 128)) { |
| /* Add RXD delay in MT7530 */ |
| rd_tap = (read_data & 0x7f) + rxd_step_size; |
| read_data = (read_data & 0xffffff80) | rd_tap; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| } |
| /* Disable EDGE CHK in MT7530 */ |
| mii_mgr_read(0x1F, TRGMII_7530_RD_0 + i * 8, |
| &read_data); |
| read_data |= 0x40000000; |
| read_data &= 0x4fffffff; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, |
| read_data); |
| wait_loop(); |
| } |
| tap_b[i] = rd_tap; /* - rxd_step_size; */ |
| pr_info("MT7530 %dth bit Tap_b = %d\n", i, tap_b[i]); |
| /* Calculate RXD delay = (TAP_A + TAP_B)/2 */ |
| final_tap[i] = (tap_a[i] + tap_b[i]) / 2; |
| read_data = (read_data & 0xffffff80) | final_tap[i]; |
| mii_mgr_write(0x1F, TRGMII_7530_RD_0 + i * 8, read_data); |
| } |
| if (ei_local->architecture & GE1_TRGMII_FORCE_2000) |
| reg_bit_zero(TRGMII_7623_base + 0x40, 31, 1); |
| else |
| reg_bit_zero(TRGMII_7623_base + 0x40, 30, 2); |
| } |
| |
| static void mt7530_trgmii_clock_setting(u32 xtal_mode) |
| { |
| u32 reg_value; |
| /* TRGMII Clock */ |
| mii_mgr_write_cl45(0, 0x1f, 0x410, 0x1); |
| if (xtal_mode == 1) { /* 25MHz */ |
| mii_mgr_write_cl45(0, 0x1f, 0x404, MT7530_TRGMII_PLL_25M); |
| } else if (xtal_mode == 2) { /* 40MHz */ |
| mii_mgr_write_cl45(0, 0x1f, 0x404, MT7530_TRGMII_PLL_40M); |
| } |
| mii_mgr_write_cl45(0, 0x1f, 0x405, 0); |
| if (xtal_mode == 1) /* 25MHz */ |
| mii_mgr_write_cl45(0, 0x1f, 0x409, 0x57); |
| else |
| mii_mgr_write_cl45(0, 0x1f, 0x409, 0x87); |
| |
| if (xtal_mode == 1) /* 25MHz */ |
| mii_mgr_write_cl45(0, 0x1f, 0x40a, 0x57); |
| else |
| mii_mgr_write_cl45(0, 0x1f, 0x40a, 0x87); |
| |
| mii_mgr_write_cl45(0, 0x1f, 0x403, 0x1800); |
| mii_mgr_write_cl45(0, 0x1f, 0x403, 0x1c00); |
| mii_mgr_write_cl45(0, 0x1f, 0x401, 0xc020); |
| mii_mgr_write_cl45(0, 0x1f, 0x406, 0xa030); |
| mii_mgr_write_cl45(0, 0x1f, 0x406, 0xa038); |
| usleep_range(120, 130); /* for MT7623 bring up test */ |
| mii_mgr_write_cl45(0, 0x1f, 0x410, 0x3); |
| |
| mii_mgr_read(31, 0x7830, ®_value); |
| reg_value &= 0xFFFFFFFC; |
| reg_value |= 0x00000001; |
| mii_mgr_write(31, 0x7830, reg_value); |
| |
| mii_mgr_read(31, 0x7a40, ®_value); |
| reg_value &= ~(0x1 << 30); |
| reg_value &= ~(0x1 << 28); |
| mii_mgr_write(31, 0x7a40, reg_value); |
| |
| mii_mgr_write(31, 0x7a78, 0x55); |
| usleep_range(100, 110); /* for mt7623 bring up test */ |
| |
| /* Release MT7623 RXC reset */ |
| reg_bit_zero(ETHDMASYS_ETH_SW_BASE + 0x0300, 31, 1); |
| |
| trgmii_calibration_7623(); |
| trgmii_calibration_7530(); |
| /* Assert RX reset in MT7623 */ |
| reg_bit_one(ETHDMASYS_ETH_SW_BASE + 0x0300, 31, 1); |
| /* Release RX reset in MT7623 */ |
| reg_bit_zero(ETHDMASYS_ETH_SW_BASE + 0x0300, 31, 1); |
| mii_mgr_read(31, 0x7a00, ®_value); |
| reg_value |= (0x1 << 31); |
| mii_mgr_write(31, 0x7a00, reg_value); |
| mdelay(1); |
| reg_value &= ~(0x1 << 31); |
| mii_mgr_write(31, 0x7a00, reg_value); |
| mdelay(100); |
| } |
| |
| void trgmii_set_7621(void) |
| { |
| u32 val = 0; |
| u32 val_0 = 0; |
| |
| val = sys_reg_read(RSTCTRL); |
| /* MT7621 need to reset GMAC and FE first */ |
| val = val | RALINK_FE_RST | RALINK_ETH_RST; |
| sys_reg_write(RSTCTRL, val); |
| |
| /* set TRGMII clock */ |
| val_0 = sys_reg_read(CLK_CFG_0); |
| val_0 &= 0xffffff9f; |
| val_0 |= (0x1 << 5); |
| sys_reg_write(CLK_CFG_0, val_0); |
| mdelay(1); |
| val_0 = sys_reg_read(CLK_CFG_0); |
| pr_info("set CLK_CFG_0 = 0x%x!!!!!!!!!!!!!!!!!!1\n", val_0); |
| val = val & ~(RALINK_FE_RST | RALINK_ETH_RST); |
| sys_reg_write(RSTCTRL, val); |
| pr_info("trgmii_set_7621 Completed!!\n"); |
| } |
| |
| void trgmii_set_7530(void) |
| { |
| u32 regValue; |
| |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x404); |
| mii_mgr_write(0, 13, 0x401f); |
| mii_mgr_read(31, 0x7800, ®Value); |
| regValue = (regValue >> 9) & 0x3; |
| if (regValue == 0x3) |
| mii_mgr_write(0, 14, 0x0C00);/*25Mhz XTAL for 150Mhz CLK */ |
| else if (regValue == 0x2) |
| mii_mgr_write(0, 14, 0x0780);/*40Mhz XTAL for 150Mhz CLK */ |
| |
| mdelay(1); |
| |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x409); |
| mii_mgr_write(0, 13, 0x401f); |
| if (regValue == 0x3) /* 25MHz */ |
| mii_mgr_write(0, 14, 0x57); |
| else |
| mii_mgr_write(0, 14, 0x87); |
| mdelay(1); |
| |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x40a); |
| mii_mgr_write(0, 13, 0x401f); |
| if (regValue == 0x3) /* 25MHz */ |
| mii_mgr_write(0, 14, 0x57); |
| else |
| mii_mgr_write(0, 14, 0x87); |
| |
| /* PLL BIAS en */ |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x403); |
| mii_mgr_write(0, 13, 0x401f); |
| mii_mgr_write(0, 14, 0x1800); |
| mdelay(1); |
| |
| /* BIAS LPF en */ |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x403); |
| mii_mgr_write(0, 13, 0x401f); |
| mii_mgr_write(0, 14, 0x1c00); |
| |
| /* sys PLL en */ |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x401); |
| mii_mgr_write(0, 13, 0x401f); |
| mii_mgr_write(0, 14, 0xc020); |
| |
| /* LCDDDS PWDS */ |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x406); |
| mii_mgr_write(0, 13, 0x401f); |
| mii_mgr_write(0, 14, 0xa030); |
| mdelay(1); |
| |
| /* GSW_2X_CLK */ |
| mii_mgr_write(0, 13, 0x1f); |
| mii_mgr_write(0, 14, 0x410); |
| mii_mgr_write(0, 13, 0x401f); |
| mii_mgr_write(0, 14, 0x0003); |
| mii_mgr_write_cl45(0, 0x1f, 0x410, 0x0003); |
| |
| /* enable P6 */ |
| mii_mgr_write(31, 0x3600, 0x5e33b); |
| |
| /* enable TRGMII */ |
| mii_mgr_write(31, 0x7830, 0x1); |
| |
| pr_info("trgmii_set_7530 Completed!!\n"); |
| } |
| |
| static void is_switch_vlan_table_busy(void) |
| { |
| int j = 0; |
| unsigned int value = 0; |
| |
| for (j = 0; j < 20; j++) { |
| mii_mgr_read(31, 0x90, &value); |
| if ((value & 0x80000000) == 0) { /* table busy */ |
| break; |
| } |
| mdelay(70); |
| } |
| if (j == 20) |
| pr_info("set vlan timeout value=0x%x.\n", value); |
| } |
| |
| static void lan_wan_partition(void) |
| { |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| /*Set MT7530 */ |
| if (ei_local->architecture & WAN_AT_P0) { |
| pr_info("set LAN/WAN WLLLL\n"); |
| /*WLLLL, wan at P0 */ |
| /*LAN/WAN ports as security mode */ |
| mii_mgr_write(31, 0x2004, 0xff0003); /* port0 */ |
| mii_mgr_write(31, 0x2104, 0xff0003); /* port1 */ |
| mii_mgr_write(31, 0x2204, 0xff0003); /* port2 */ |
| mii_mgr_write(31, 0x2304, 0xff0003); /* port3 */ |
| mii_mgr_write(31, 0x2404, 0xff0003); /* port4 */ |
| mii_mgr_write(31, 0x2504, 0xff0003); /* port5 */ |
| mii_mgr_write(31, 0x2604, 0xff0003); /* port6 */ |
| |
| /*set PVID */ |
| mii_mgr_write(31, 0x2014, 0x10002); /* port0 */ |
| mii_mgr_write(31, 0x2114, 0x10001); /* port1 */ |
| mii_mgr_write(31, 0x2214, 0x10001); /* port2 */ |
| mii_mgr_write(31, 0x2314, 0x10001); /* port3 */ |
| mii_mgr_write(31, 0x2414, 0x10001); /* port4 */ |
| mii_mgr_write(31, 0x2514, 0x10002); /* port5 */ |
| mii_mgr_write(31, 0x2614, 0x10001); /* port6 */ |
| /*port6 */ |
| /*VLAN member */ |
| is_switch_vlan_table_busy(); |
| mii_mgr_write(31, 0x94, 0x405e0001); /* VAWD1 */ |
| mii_mgr_write(31, 0x90, 0x80001001); /* VTCR, VID=1 */ |
| is_switch_vlan_table_busy(); |
| |
| mii_mgr_write(31, 0x94, 0x40210001); /* VAWD1 */ |
| mii_mgr_write(31, 0x90, 0x80001002); /* VTCR, VID=2 */ |
| is_switch_vlan_table_busy(); |
| } |
| if (ei_local->architecture & WAN_AT_P4) { |
| pr_info("set LAN/WAN LLLLW\n"); |
| /*LLLLW, wan at P4 */ |
| /*LAN/WAN ports as security mode */ |
| mii_mgr_write(31, 0x2004, 0xff0003); /* port0 */ |
| mii_mgr_write(31, 0x2104, 0xff0003); /* port1 */ |
| mii_mgr_write(31, 0x2204, 0xff0003); /* port2 */ |
| mii_mgr_write(31, 0x2304, 0xff0003); /* port3 */ |
| mii_mgr_write(31, 0x2404, 0xff0003); /* port4 */ |
| mii_mgr_write(31, 0x2504, 0xff0003); /* port5 */ |
| mii_mgr_write(31, 0x2604, 0xff0003); /* port6 */ |
| |
| /*set PVID */ |
| mii_mgr_write(31, 0x2014, 0x10001); /* port0 */ |
| mii_mgr_write(31, 0x2114, 0x10001); /* port1 */ |
| mii_mgr_write(31, 0x2214, 0x10001); /* port2 */ |
| mii_mgr_write(31, 0x2314, 0x10001); /* port3 */ |
| mii_mgr_write(31, 0x2414, 0x10002); /* port4 */ |
| mii_mgr_write(31, 0x2514, 0x10002); /* port5 */ |
| mii_mgr_write(31, 0x2614, 0x10001); /* port6 */ |
| |
| /*VLAN member */ |
| is_switch_vlan_table_busy(); |
| mii_mgr_write(31, 0x94, 0x404f0001); /* VAWD1 */ |
| mii_mgr_write(31, 0x90, 0x80001001); /* VTCR, VID=1 */ |
| is_switch_vlan_table_busy(); |
| mii_mgr_write(31, 0x94, 0x40300001); /* VAWD1 */ |
| mii_mgr_write(31, 0x90, 0x80001002); /* VTCR, VID=2 */ |
| is_switch_vlan_table_busy(); |
| } |
| } |
| |
| static void mt7530_phy_setting(void) |
| { |
| u32 i; |
| u32 reg_value; |
| |
| for (i = 0; i < 5; i++) { |
| /* Disable EEE */ |
| mii_mgr_write_cl45(i, 0x7, 0x3c, 0); |
| /* Enable HW auto downshift */ |
| mii_mgr_write(i, 31, 0x1); |
| mii_mgr_read(i, 0x14, ®_value); |
| reg_value |= (1 << 4); |
| mii_mgr_write(i, 0x14, reg_value); |
| /* Increase SlvDPSready time */ |
| mii_mgr_write(i, 31, 0x52b5); |
| mii_mgr_write(i, 16, 0xafae); |
| mii_mgr_write(i, 18, 0x2f); |
| mii_mgr_write(i, 16, 0x8fae); |
| /* Incease post_update_timer */ |
| mii_mgr_write(i, 31, 0x3); |
| mii_mgr_write(i, 17, 0x4b); |
| /* Adjust 100_mse_threshold */ |
| mii_mgr_write_cl45(i, 0x1e, 0x123, 0xffff); |
| /* Disable mcc */ |
| mii_mgr_write_cl45(i, 0x1e, 0xa6, 0x300); |
| } |
| } |
| |
| static void setup_internal_gsw(void) |
| { |
| void __iomem *gpio_base_virt = ioremap(ETH_GPIO_BASE, 0x1000); |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| u32 reg_value; |
| u32 xtal_mode; |
| u32 i; |
| |
| if (ei_local->architecture & |
| (GE1_TRGMII_FORCE_2000 | GE1_TRGMII_FORCE_2600)) |
| reg_bit_one(RALINK_SYSCTL_BASE + 0x2c, 11, 1); |
| else |
| reg_bit_zero(RALINK_SYSCTL_BASE + 0x2c, 11, 1); |
| reg_bit_one(ETHDMASYS_ETH_SW_BASE + 0x0390, 1, 1); /* TRGMII mode */ |
| |
| #if defined(CONFIG_GE1_RGMII_FORCE_1200) |
| |
| if (ei_local->chip_name == MT7621_FE) |
| trgmii_set_7621(); |
| |
| #endif |
| |
| /*Hardware reset Switch */ |
| |
| reg_bit_zero((void __iomem *)gpio_base_virt + 0x520, 1, 1); |
| mdelay(1); |
| reg_bit_one((void __iomem *)gpio_base_virt + 0x520, 1, 1); |
| mdelay(100); |
| |
| /* Assert MT7623 RXC reset */ |
| reg_bit_one(ETHDMASYS_ETH_SW_BASE + 0x0300, 31, 1); |
| /*For MT7623 reset MT7530 */ |
| reg_bit_one(RALINK_SYSCTL_BASE + 0x34, 2, 1); |
| mdelay(1); |
| reg_bit_zero(RALINK_SYSCTL_BASE + 0x34, 2, 1); |
| mdelay(100); |
| |
| /* Wait for Switch Reset Completed */ |
| for (i = 0; i < 100; i++) { |
| mdelay(10); |
| mii_mgr_read(31, 0x7800, ®_value); |
| if (reg_value != 0) { |
| pr_info("MT7530 Reset Completed!!\n"); |
| break; |
| } |
| if (i == 99) |
| pr_info("MT7530 Reset Timeout!!\n"); |
| } |
| |
| for (i = 0; i <= 4; i++) { |
| /*turn off PHY */ |
| mii_mgr_read(i, 0x0, ®_value); |
| reg_value |= (0x1 << 11); |
| mii_mgr_write(i, 0x0, reg_value); |
| } |
| mii_mgr_write(31, 0x7000, 0x3); /* reset switch */ |
| usleep_range(100, 110); |
| |
| #if defined(CONFIG_GE1_RGMII_FORCE_1200) |
| |
| if (ei_local->chip_name == MT7621_FE) { |
| trgmii_set_7530(); |
| /* enable MDIO to control MT7530 */ |
| reg_value = sys_reg_read(RALINK_SYSCTL_BASE + 0x60); |
| reg_value &= ~(0x3 << 12); |
| sys_reg_write(RALINK_SYSCTL_BASE + 0x60, reg_value); |
| } |
| |
| #endif |
| |
| /* (GE1, Force 1000M/FD, FC ON) */ |
| sys_reg_write(RALINK_ETH_SW_BASE + 0x100, 0x2105e33b); |
| mii_mgr_write(31, 0x3600, 0x5e33b); |
| mii_mgr_read(31, 0x3600, ®_value); |
| /* (GE2, Link down) */ |
| sys_reg_write(RALINK_ETH_SW_BASE + 0x200, 0x00008000); |
| |
| mii_mgr_read(31, 0x7804, ®_value); |
| reg_value &= ~(1 << 8); /* Enable Port 6 */ |
| reg_value |= (1 << 6); /* Disable Port 5 */ |
| reg_value |= (1 << 13); /* Port 5 as GMAC, no Internal PHY */ |
| |
| if (ei_local->architecture & GMAC2) { |
| /*RGMII2=Normal mode */ |
| reg_bit_zero(RALINK_SYSCTL_BASE + 0x60, 15, 1); |
| |
| /*GMAC2= RGMII mode */ |
| reg_bit_zero(SYSCFG1, 14, 2); |
| if (ei_local->architecture & GE2_RGMII_AN) { |
| mii_mgr_write(31, 0x3500, 0x56300); |
| /* (GE2, auto-polling) */ |
| sys_reg_write(RALINK_ETH_SW_BASE + 0x200, 0x21056300); |
| reg_value |= (1 << 6); /* disable MT7530 P5 */ |
| enable_auto_negotiate(ei_local); |
| |
| } else { |
| /* MT7530 P5 Force 1000 */ |
| mii_mgr_write(31, 0x3500, 0x5e33b); |
| /* (GE2, Force 1000) */ |
| sys_reg_write(RALINK_ETH_SW_BASE + 0x200, 0x2105e33b); |
| reg_value &= ~(1 << 6); /* enable MT7530 P5 */ |
| reg_value |= ((1 << 7) | (1 << 13) | (1 << 16)); |
| if (ei_local->architecture & WAN_AT_P0) |
| reg_value |= (1 << 20); |
| else |
| reg_value &= ~(1 << 20); |
| } |
| } |
| reg_value &= ~(1 << 5); |
| reg_value |= (1 << 16); /* change HW-TRAP */ |
| pr_info("change HW-TRAP to 0x%x\n", reg_value); |
| mii_mgr_write(31, 0x7804, reg_value); |
| mii_mgr_read(31, 0x7800, ®_value); |
| reg_value = (reg_value >> 9) & 0x3; |
| if (reg_value == 0x3) { /* 25Mhz Xtal */ |
| xtal_mode = 1; |
| /*Do Nothing */ |
| } else if (reg_value == 0x2) { /* 40Mhz */ |
| xtal_mode = 2; |
| /* disable MT7530 core clock */ |
| mii_mgr_write_cl45(0, 0x1f, 0x410, 0x0); |
| |
| mii_mgr_write_cl45(0, 0x1f, 0x40d, 0x2020); |
| mii_mgr_write_cl45(0, 0x1f, 0x40e, 0x119); |
| mii_mgr_write_cl45(0, 0x1f, 0x40d, 0x2820); |
| usleep_range(20, 30); /* suggest by CD */ |
| #if defined(CONFIG_GE1_RGMII_FORCE_1200) |
| mii_mgr_write_cl45(0, 0x1f, 0x410, 0x3); |
| #else |
| mii_mgr_write_cl45(0, 0x1f, 0x410, 0x1); |
| #endif |
| |
| } else { |
| xtal_mode = 3; |
| /* TODO */} |
| |
| /* set MT7530 central align */ |
| #if !defined(CONFIG_GE1_RGMII_FORCE_1200) /* for RGMII 1000HZ */ |
| mii_mgr_read(31, 0x7830, ®_value); |
| reg_value &= ~1; |
| reg_value |= 1 << 1; |
| mii_mgr_write(31, 0x7830, reg_value); |
| |
| mii_mgr_read(31, 0x7a40, ®_value); |
| reg_value &= ~(1 << 30); |
| mii_mgr_write(31, 0x7a40, reg_value); |
| |
| reg_value = 0x855; |
| mii_mgr_write(31, 0x7a78, reg_value); |
| #endif |
| |
| mii_mgr_write(31, 0x7b00, 0x104); /* delay setting for 10/1000M */ |
| mii_mgr_write(31, 0x7b04, 0x10); /* delay setting for 10/1000M */ |
| |
| /*Tx Driving */ |
| mii_mgr_write(31, 0x7a54, 0x88); /* lower GE1 driving */ |
| mii_mgr_write(31, 0x7a5c, 0x88); /* lower GE1 driving */ |
| mii_mgr_write(31, 0x7a64, 0x88); /* lower GE1 driving */ |
| mii_mgr_write(31, 0x7a6c, 0x88); /* lower GE1 driving */ |
| mii_mgr_write(31, 0x7a74, 0x88); /* lower GE1 driving */ |
| mii_mgr_write(31, 0x7a7c, 0x88); /* lower GE1 driving */ |
| mii_mgr_write(31, 0x7810, 0x11); /* lower GE2 driving */ |
| /*Set MT7623 TX Driving */ |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0354, 0x88); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x035c, 0x88); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0364, 0x88); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x036c, 0x88); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0374, 0x88); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x037c, 0x88); |
| |
| /* Set GE2 driving and slew rate */ |
| if (ei_local->architecture & GE2_RGMII_AN) |
| sys_reg_write((void __iomem *)gpio_base_virt + 0xf00, 0xe00); |
| else |
| sys_reg_write((void __iomem *)gpio_base_virt + 0xf00, 0xa00); |
| /* set GE2 TDSEL */ |
| sys_reg_write((void __iomem *)gpio_base_virt + 0x4c0, 0x5); |
| /* set GE2 TUNE */ |
| sys_reg_write((void __iomem *)gpio_base_virt + 0xed0, 0); |
| |
| if (ei_local->chip_name == MT7623_FE) |
| mt7530_trgmii_clock_setting(xtal_mode); |
| if (ei_local->architecture & GE1_RGMII_FORCE_1000) { |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0350, 0x55); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0358, 0x55); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0360, 0x55); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0368, 0x55); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0370, 0x55); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x0378, 0x855); |
| } |
| |
| lan_wan_partition(); |
| mt7530_phy_setting(); |
| for (i = 0; i <= 4; i++) { |
| /*turn on PHY */ |
| mii_mgr_read(i, 0x0, ®_value); |
| reg_value &= ~(0x1 << 11); |
| mii_mgr_write(i, 0x0, reg_value); |
| } |
| |
| mii_mgr_read(31, 0x7808, ®_value); |
| reg_value |= (3 << 16); /* Enable INTR */ |
| mii_mgr_write(31, 0x7808, reg_value); |
| |
| iounmap(gpio_base_virt); |
| } |
| |
| void setup_external_gsw(void) |
| { |
| /* reduce RGMII2 PAD driving strength */ |
| reg_bit_zero(PAD_RGMII2_MDIO_CFG, 4, 2); |
| /*enable MDIO */ |
| reg_bit_zero(RALINK_SYSCTL_BASE + 0x60, 12, 2); |
| |
| /*RGMII1=Normal mode */ |
| reg_bit_zero(RALINK_SYSCTL_BASE + 0x60, 14, 1); |
| /*GMAC1= RGMII mode */ |
| reg_bit_zero(SYSCFG1, 12, 2); |
| |
| /* (GE1, Link down) */ |
| sys_reg_write(RALINK_ETH_SW_BASE + 0x100, 0x00008000); |
| |
| /*RGMII2=Normal mode */ |
| reg_bit_zero(RALINK_SYSCTL_BASE + 0x60, 15, 1); |
| /*GMAC2= RGMII mode */ |
| reg_bit_zero(SYSCFG1, 14, 2); |
| |
| /* (GE2, Force 1000M/FD, FC ON) */ |
| sys_reg_write(RALINK_ETH_SW_BASE + 0x200, 0x2105e33b); |
| |
| } int is_marvell_gigaphy(int ge) |
| { |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| u32 phy_id0 = 0, phy_id1 = 0, phy_address; |
| |
| if (ei_local->architecture & GE1_RGMII_AN) |
| phy_address = mac_to_gigaphy_mode_addr; |
| else |
| phy_address = mac_to_gigaphy_mode_addr2; |
| |
| if (!mii_mgr_read(phy_address, 2, &phy_id0)) { |
| pr_info("\n Read PhyID 1 is Fail!!\n"); |
| phy_id0 = 0; |
| } |
| if (!mii_mgr_read(phy_address, 3, &phy_id1)) { |
| pr_info("\n Read PhyID 1 is Fail!!\n"); |
| phy_id1 = 0; |
| } |
| |
| if ((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1)) |
| return 1; |
| return 0; |
| } |
| |
| int is_vtss_gigaphy(int ge) |
| { |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| u32 phy_id0 = 0, phy_id1 = 0, phy_address; |
| |
| if (ei_local->architecture & GE1_RGMII_AN) |
| phy_address = mac_to_gigaphy_mode_addr; |
| else |
| phy_address = mac_to_gigaphy_mode_addr2; |
| |
| if (!mii_mgr_read(phy_address, 2, &phy_id0)) { |
| pr_info("\n Read PhyID 1 is Fail!!\n"); |
| phy_id0 = 0; |
| } |
| if (!mii_mgr_read(phy_address, 3, &phy_id1)) { |
| pr_info("\n Read PhyID 1 is Fail!!\n"); |
| phy_id1 = 0; |
| } |
| |
| if ((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1)) |
| return 1; |
| return 0; |
| } |
| |
| void fe_sw_preinit(struct END_DEVICE *ei_local) |
| { |
| struct device_node *np = ei_local->switch_np; |
| struct platform_device *pdev = of_find_device_by_node(np); |
| struct mtk_gsw *gsw; |
| int ret; |
| |
| gsw = platform_get_drvdata(pdev); |
| if (!gsw) { |
| pr_info("Failed to get gsw\n"); |
| return; |
| } |
| |
| regulator_set_voltage(gsw->supply, 1000000, 1000000); |
| ret = regulator_enable(gsw->supply); |
| if (ret) |
| pr_info("Failed to enable mt7530 power: %d\n", ret); |
| |
| if (gsw->mcm) { |
| regulator_set_voltage(gsw->b3v, 3300000, 3300000); |
| ret = regulator_enable(gsw->b3v); |
| if (ret) |
| dev_err(&pdev->dev, "Failed to enable b3v: %d\n", ret); |
| } else { |
| ret = devm_gpio_request(&pdev->dev, gsw->reset_pin, |
| "mediatek,reset-pin"); |
| if (ret) |
| pr_info("fail to devm_gpio_request\n"); |
| |
| gpio_direction_output(gsw->reset_pin, 0); |
| usleep_range(1000, 1100); |
| gpio_set_value(gsw->reset_pin, 1); |
| mdelay(100); |
| devm_gpio_free(&pdev->dev, gsw->reset_pin); |
| } |
| } |
| |
| void set_sgmii_force_link(int port_num, int speed) |
| { |
| void __iomem *virt_addr; |
| unsigned int reg_value; |
| unsigned int sgmii_reg_phya, sgmii_reg; |
| |
| virt_addr = ioremap(ETHSYS_BASE, 0x20); |
| reg_value = sys_reg_read(virt_addr + 0x14); |
| |
| if (port_num == 1) { |
| reg_value |= SGMII_CONFIG_0; |
| sgmii_reg_phya = SGMII_REG_PHYA_BASE0; |
| sgmii_reg = SGMII_REG_BASE0; |
| set_ge1_force_1000(); |
| } |
| if (port_num == 2) { |
| reg_value |= SGMII_CONFIG_1; |
| sgmii_reg_phya = SGMII_REG_PHYA_BASE1; |
| sgmii_reg = SGMII_REG_BASE1; |
| set_ge2_force_1000(); |
| } |
| |
| sys_reg_write(virt_addr + 0x14, reg_value); |
| reg_value = sys_reg_read(virt_addr + 0x14); |
| iounmap(virt_addr); |
| |
| /* Set SGMII GEN2 speed(2.5G) */ |
| virt_addr = ioremap(sgmii_reg_phya, 0x100); |
| reg_value = sys_reg_read(virt_addr + 0x28); |
| reg_value |= speed << 2; |
| sys_reg_write(virt_addr + 0x28, reg_value); |
| iounmap(virt_addr); |
| |
| virt_addr = ioremap(sgmii_reg, 0x100); |
| /* disable SGMII AN */ |
| reg_value = sys_reg_read(virt_addr); |
| reg_value &= ~(1 << 12); |
| sys_reg_write(virt_addr, reg_value); |
| /* SGMII force mode setting */ |
| reg_value = sys_reg_read(virt_addr + 0x20); |
| sys_reg_write(virt_addr + 0x20, 0x31120019); |
| reg_value = sys_reg_read(virt_addr + 0x20); |
| /* Release PHYA power down state */ |
| reg_value = sys_reg_read(virt_addr + 0xe8); |
| reg_value &= ~(1 << 4); |
| sys_reg_write(virt_addr + 0xe8, reg_value); |
| iounmap(virt_addr); |
| } |
| |
| void set_sgmii_an(int port_num) |
| { |
| void __iomem *virt_addr; |
| unsigned int reg_value; |
| unsigned int sgmii_reg, sgmii_reg_phya; |
| |
| virt_addr = ioremap(ETHSYS_BASE, 0x20); |
| reg_value = sys_reg_read(virt_addr + 0x14); |
| |
| if (port_num == 1) { |
| reg_value |= SGMII_CONFIG_0; |
| sgmii_reg_phya = SGMII_REG_PHYA_BASE0; |
| sgmii_reg = SGMII_REG_BASE0; |
| } |
| if (port_num == 2) { |
| reg_value |= SGMII_CONFIG_1; |
| sgmii_reg_phya = SGMII_REG_PHYA_BASE1; |
| sgmii_reg = SGMII_REG_BASE1; |
| } |
| |
| sys_reg_write(virt_addr + 0x14, reg_value); |
| iounmap(virt_addr); |
| |
| /* set auto polling */ |
| virt_addr = ioremap(ETHSYS_MAC_BASE, 0x300); |
| sys_reg_write(virt_addr + (0x100 * port_num), 0x21056300); |
| iounmap(virt_addr); |
| |
| virt_addr = ioremap(sgmii_reg, 0x100); |
| /* set link timer */ |
| sys_reg_write(virt_addr + 0x18, 0x186a0); |
| /* disable remote fault */ |
| reg_value = sys_reg_read(virt_addr + 0x20); |
| reg_value |= 1 << 8; |
| sys_reg_write(virt_addr + 0x20, reg_value); |
| /* restart an */ |
| reg_value = sys_reg_read(virt_addr); |
| reg_value |= 1 << 9; |
| sys_reg_write(virt_addr, reg_value); |
| /* Release PHYA power down state */ |
| reg_value = sys_reg_read(virt_addr + 0xe8); |
| reg_value &= ~(1 << 4); |
| sys_reg_write(virt_addr + 0xe8, reg_value); |
| iounmap(virt_addr); |
| } |
| |
| static void mt7622_esw_5port_gpio(void) |
| { |
| u32 ret, value, i; |
| |
| mii_mgr_write(0, 31, 0x2000); /* change G2 page */ |
| |
| ret = mii_mgr_read(0, 31, &value); |
| pr_debug("(%d) R31: %x!\n", ret, value); |
| |
| mii_mgr_read(0, 25, &value); |
| value = 0xf020; |
| mii_mgr_write(0, 25, value); |
| mii_mgr_read(0, 25, &value); |
| pr_debug("G2_R25: %x!\n", value); |
| |
| mii_mgr_write(0, 31, 0x7000); /* change G7 page */ |
| mii_mgr_read(0, 22, &value); |
| |
| if (value & 0x8000) { |
| pr_debug("G7_R22[15]: 1\n"); |
| } else { |
| mii_mgr_write(0, 22, (value | (1 << 15))); |
| pr_debug("G7_R22[15]: set to 1\n"); |
| } |
| |
| mii_mgr_write(0, 31, 0x3000); /* change G3 page */ |
| mii_mgr_read(0, 16, &value); |
| value |= (1 << 3); |
| mii_mgr_write(0, 16, value); |
| |
| mii_mgr_read(0, 16, &value); |
| pr_debug("G3_R16: %x!\n", value); |
| |
| mii_mgr_write(0, 31, 0x7000); /* change G7 page */ |
| mii_mgr_read(0, 22, &value); |
| value |= (1 << 5); |
| mii_mgr_write(0, 22, value); |
| |
| mii_mgr_read(0, 24, &value); |
| value &= 0xDFFF; |
| mii_mgr_write(0, 24, value); |
| |
| mii_mgr_read(0, 24, &value); |
| value |= (1 << 14); |
| mii_mgr_write(0, 24, value); |
| |
| mii_mgr_read(0, 22, &value); |
| pr_debug("G7_R22: %x!\n", value); |
| |
| mii_mgr_read(0, 24, &value); |
| pr_debug("G7_R24: %x!\n", value); |
| |
| for (i = 0; i <= 4; i++) { |
| mii_mgr_write(i, 31, 0x8000); /* change L0 page */ |
| |
| mii_mgr_read(i, 30, &value); |
| value |= 0x3FFF; |
| mii_mgr_write(i, 30, value); |
| mii_mgr_read(i, 30, &value); |
| pr_debug("port %d L0_R30: %x!\n", i, value); |
| |
| mii_mgr_write(i, 31, 0xB000); /* change L3 page */ |
| |
| mii_mgr_read(i, 26, &value); |
| value |= (1 << 12); |
| mii_mgr_write(i, 26, value); |
| |
| mii_mgr_read(i, 26, &value); |
| pr_debug("port %d L3_R26: %x!\n", i, value); |
| |
| mii_mgr_read(i, 25, &value); |
| value |= (1 << 8); |
| value |= (1 << 12); |
| mii_mgr_write(i, 25, value); |
| |
| mii_mgr_read(i, 25, &value); |
| pr_debug("port %d L3_R25: %x!\n", i, value); |
| } |
| |
| mii_mgr_write(0, 31, 0x2000); /* change G2 page */ |
| |
| mii_mgr_read(0, 25, &value); |
| |
| pr_debug("G2_R25 before: %x!\n", value); |
| /* value &= 0xFFFF3FFF; */ |
| /* G2_R25: 1020!-->0020 */ |
| /* value &= 0xFFFF2FFF; */ |
| value = 0x20; |
| mii_mgr_write(0, 25, value); |
| |
| mii_mgr_read(0, 25, &value); |
| pr_debug("G2_R25: %x!\n", value); |
| |
| /* LDO */ |
| mii_mgr_write(0, 31, 0x7000); /* change G7 page */ |
| |
| mii_mgr_read(0, 16, &value); |
| value |= (1 << 2); |
| mii_mgr_write(0, 16, value); |
| |
| mii_mgr_read(0, 16, &value); |
| pr_debug("G7_R16: %x!\n", value); |
| |
| /* BG */ |
| mii_mgr_write(0, 31, 0x2000); /* change G2 page */ |
| |
| mii_mgr_read(0, 22, &value); |
| value |= (1 << 12); |
| value |= (1 << 13); |
| value |= (1 << 14); |
| mii_mgr_write(0, 22, value); |
| |
| mii_mgr_read(0, 22, &value); |
| pr_debug("G2_R22: %x!\n", value); |
| |
| mii_mgr_read(0, 22, &value); |
| value &= 0x7FFF; |
| mii_mgr_write(0, 22, value); |
| |
| mii_mgr_read(0, 22, &value); |
| pr_debug("G2_R22: %x!\n", value); |
| } |
| |
| void leopard_gmii_config(u8 enable) |
| { |
| unsigned int reg_value = 0; |
| void __iomem *gpio_base_virt, *infra_base_virt; |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| |
| /*bit[1]: gphy connect GMAC0 or GMAC2 1:GMAC0. 0:GMAC2*/ |
| /*bit[0]: Co-QPHY path selection 0:U3path, 1:SGMII*/ |
| infra_base_virt = ioremap(INFRA_BASE, 0x10); |
| reg_value = sys_reg_read(infra_base_virt); |
| if (enable) { |
| reg_value = reg_value | 0x02; |
| sys_reg_write(infra_base_virt, reg_value); |
| |
| mac_to_gigaphy_mode_addr = 0; |
| enable_auto_negotiate(ei_local); |
| |
| /*port5 enable*/ |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x90, 0x00007f7f); |
| /*port5 an mode, port6 fix*/ |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0xc8, 0x20503bfa); |
| } else { |
| reg_value = reg_value & (~0x2); |
| sys_reg_write(infra_base_virt, reg_value); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x84, 0); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x90, 0x10007f7f); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0xc8, 0x05503f38); |
| } |
| /*10000710 GEPHY_CTRL0[9:6] = 0 */ |
| gpio_base_virt = ioremap(GPIO_GO_BASE, 0x10); |
| reg_value = sys_reg_read(gpio_base_virt); |
| /*reg_value = reg_value & ~(0xfffff3cf);*/ |
| reg_value = 0x10000820; |
| sys_reg_write(gpio_base_virt, reg_value); |
| iounmap(gpio_base_virt); |
| iounmap(infra_base_virt); |
| } |
| |
| void fe_sw_init(void) |
| { |
| struct END_DEVICE *ei_local = netdev_priv(dev_raether); |
| unsigned int reg_value = 0; |
| void __iomem *gpio_base_virt, *infra_base_virt, *ethsys_base_virt; |
| //int i; |
| //u16 r0_tmp; |
| |
| /* Case1: MT7623/MT7622 GE1 + GigaPhy */ |
| if (ei_local->architecture & GE1_RGMII_AN) { |
| //enable_auto_negotiate(ei_local); |
| if (is_marvell_gigaphy(1)) { |
| if (ei_local->features & FE_FPGA_MODE) { |
| mii_mgr_read(mac_to_gigaphy_mode_addr, 9, |
| ®_value); |
| /* turn off 1000Base-T Advertisement |
| * (9.9=1000Full, 9.8=1000Half) |
| */ |
| reg_value &= ~(3 << 8); |
| mii_mgr_write(mac_to_gigaphy_mode_addr, |
| 9, reg_value); |
| |
| /*10Mbps, debug */ |
| mii_mgr_write(mac_to_gigaphy_mode_addr, |
| 4, 0x461); |
| |
| mii_mgr_read(mac_to_gigaphy_mode_addr, 0, |
| ®_value); |
| reg_value |= 1 << 9; /* restart AN */ |
| mii_mgr_write(mac_to_gigaphy_mode_addr, |
| 0, reg_value); |
| } |
| } |
| if (is_vtss_gigaphy(1)) { |
| mii_mgr_write(mac_to_gigaphy_mode_addr, 31, 1); |
| mii_mgr_read(mac_to_gigaphy_mode_addr, 28, |
| ®_value); |
| pr_info("Vitesse phy skew: %x --> ", reg_value); |
| reg_value |= (0x3 << 12); |
| reg_value &= ~(0x3 << 14); |
| pr_info("%x\n", reg_value); |
| mii_mgr_write(mac_to_gigaphy_mode_addr, 28, |
| reg_value); |
| mii_mgr_write(mac_to_gigaphy_mode_addr, 31, 0); |
| } |
| } |
| |
| /* Case2: RT3883/MT7621 GE2 + GigaPhy */ |
| if (ei_local->architecture & GE2_RGMII_AN) { |
| #if(0) |
| leopard_gmii_config(0); |
| enable_auto_negotiate(ei_local); |
| set_ge2_an(); |
| set_ge2_gmii(); |
| if (ei_local->chip_name == LEOPARD_FE) { |
| for (i = 1; i < 5; i++) |
| do_fe_phy_all_analog_cal(i); |
| |
| do_ge_phy_all_analog_cal(0); |
| } |
| #endif |
| if (is_marvell_gigaphy(2)) { |
| mii_mgr_read(mac_to_gigaphy_mode_addr2, 9, |
| ®_value); |
| /* turn off 1000Base-T Advertisement |
| * (9.9=1000Full, 9.8=1000Half) |
| */ |
| reg_value &= ~(3 << 8); |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, 9, |
| reg_value); |
| |
| mii_mgr_read(mac_to_gigaphy_mode_addr2, 20, |
| ®_value); |
| /* Add delay to RX_CLK for RXD Outputs */ |
| reg_value |= 1 << 7; |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, 20, |
| reg_value); |
| |
| mii_mgr_read(mac_to_gigaphy_mode_addr2, 0, |
| ®_value); |
| reg_value |= 1 << 15; /* PHY Software Reset */ |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, 0, |
| reg_value); |
| if (ei_local->features & FE_FPGA_MODE) { |
| mii_mgr_read(mac_to_gigaphy_mode_addr2, |
| 9, ®_value); |
| /* turn off 1000Base-T Advertisement |
| * (9.9=1000Full, 9.8=1000Half) |
| */ |
| reg_value &= ~(3 << 8); |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, |
| 9, reg_value); |
| |
| /*10Mbps, debug */ |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, |
| 4, 0x461); |
| |
| mii_mgr_read(mac_to_gigaphy_mode_addr2, |
| 0, ®_value); |
| reg_value |= 1 << 9; /* restart AN */ |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, |
| 0, reg_value); |
| } |
| } |
| if (is_vtss_gigaphy(2)) { |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, 31, 1); |
| mii_mgr_read(mac_to_gigaphy_mode_addr2, 28, |
| ®_value); |
| pr_info("Vitesse phy skew: %x --> ", reg_value); |
| reg_value |= (0x3 << 12); |
| reg_value &= ~(0x3 << 14); |
| pr_info("%x\n", reg_value); |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, 28, |
| reg_value); |
| mii_mgr_write(mac_to_gigaphy_mode_addr2, 31, 0); |
| } |
| } |
| |
| /* Case3: MT7623 GE1 + Internal GigaSW */ |
| if (ei_local->architecture & |
| (GE1_RGMII_FORCE_1000 | GE1_TRGMII_FORCE_2000 | |
| GE1_TRGMII_FORCE_2600)) { |
| if ((ei_local->chip_name == MT7623_FE) || |
| (ei_local->chip_name == MT7621_FE)) |
| setup_internal_gsw(); |
| /* TODO |
| * else if (ei_local->features & FE_FPGA_MODE) |
| * setup_fpga_gsw(); |
| * else |
| * sys_reg_write(MDIO_CFG, INIT_VALUE_OF_FORCE_1000_FD); |
| */ |
| } |
| |
| /* Case4: MT7623 GE2 + GigaSW */ |
| if (ei_local->architecture & GE2_RGMII_FORCE_1000) { |
| set_ge2_force_1000(); |
| if (ei_local->chip_name == MT7623_FE) |
| setup_external_gsw(); |
| } |
| /*TODO |
| * else |
| * sys_reg_write(MDIO_CFG2, INIT_VALUE_OF_FORCE_1000_FD); |
| */ |
| |
| /* Case5: MT7622 embedded switch */ |
| if (ei_local->architecture & RAETH_ESW) { |
| reg_value = sys_reg_read(ETHDMASYS_ETH_MAC_BASE + 0xC); |
| reg_value = reg_value | 0x1; |
| sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0xC, reg_value); |
| |
| if (ei_local->architecture & MT7622_EPHY) { |
| gpio_base_virt = ioremap(GPIO_GO_BASE, 0x100); |
| sys_reg_write(gpio_base_virt + 0xF0, 0xE0FFFFFF); |
| iounmap(gpio_base_virt); |
| gpio_base_virt = ioremap(GPIO_MODE_BASE, 0x100); |
| reg_value = sys_reg_read(gpio_base_virt + 0x90); |
| reg_value &= 0x0000ffff; |
| reg_value |= 0x22220000; |
| sys_reg_write(gpio_base_virt + 0x90, reg_value); |
| iounmap(gpio_base_virt); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x84, 0); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x90, 0x10007f7f); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0xc8, 0x05503f38); |
| } else if (ei_local->architecture & LEOPARD_EPHY) { |
| set_ge1_an(); |
| /*port0 force link down*/ |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x84, 0x8000000); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x8c, 0x02404040); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x98, 0x00007f7f); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x04, 0xfbffffff); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x9c, 0x0008a041); |
| #if(0) |
| if (ei_local->architecture & LEOPARD_EPHY_GMII) { |
| leopard_gmii_config(1); |
| set_ge0_gmii(); |
| } else { |
| leopard_gmii_config(0); |
| } |
| #endif |
| } |
| } |
| |
| /* clear SGMII setting */ |
| if ((ei_local->chip_name == LEOPARD_FE) || (ei_local->chip_name == MT7622_FE)) { |
| ethsys_base_virt = ioremap(ETHSYS_BASE, 0x20); |
| reg_value = sys_reg_read(ethsys_base_virt + 0x14); |
| reg_value &= ~(3 << 8); |
| sys_reg_write(ethsys_base_virt + 0x14, reg_value); |
| } |
| |
| if (ei_local->architecture & GE1_SGMII_FORCE_2500) |
| set_sgmii_force_link(1, 1); |
| else if (ei_local->architecture & GE1_SGMII_AN) { |
| enable_auto_negotiate(ei_local); |
| set_sgmii_an(1); |
| } |
| if (ei_local->chip_name == LEOPARD_FE) { |
| if (ei_local->architecture & GE2_RAETH_SGMII) { |
| /*bit[1]: gphy connect GMAC0 or GMAC2 1:GMAC0. 0:GMAC2*/ |
| /*bit[0]: Co-QPHY path selection 0:U3path, 1:SGMII*/ |
| infra_base_virt = ioremap(INFRA_BASE, 0x10); |
| reg_value = sys_reg_read(infra_base_virt); |
| reg_value = reg_value | 0x01; |
| sys_reg_write(infra_base_virt, reg_value); |
| iounmap(infra_base_virt); |
| } |
| } |
| |
| if (ei_local->architecture & GE2_SGMII_FORCE_2500) |
| set_sgmii_force_link(2, 1); |
| else if (ei_local->architecture & GE2_SGMII_AN) { |
| enable_auto_negotiate(ei_local); |
| set_sgmii_an(2); |
| } |
| |
| if (ei_local->architecture & MT7622_EPHY) { |
| //mt7622_ephy_cal(); |
| } else if (ei_local->architecture & LEOPARD_EPHY) { |
| #if(0) |
| leopard_ephy_cal(); |
| tc_phy_write_l_reg(2, 1, 18, 0x21f); |
| tc_phy_write_l_reg(2, 1, 18, 0x22f); |
| tc_phy_write_l_reg(2, 1, 18, 0x23f); |
| tc_phy_write_l_reg(2, 1, 18, 0x24f); |
| tc_phy_write_l_reg(2, 1, 18, 0x4f); |
| tc_phy_write_l_reg(4, 1, 18, 0x21f); |
| tc_phy_write_l_reg(4, 1, 18, 0x22f); |
| tc_phy_write_l_reg(4, 1, 18, 0x2f); |
| r0_tmp = tc_phy_read_l_reg(3, 0, 0); |
| r0_tmp = r0_tmp | 0x200; |
| tc_phy_write_l_reg(3, 0, 0, r0_tmp); |
| #endif |
| } |
| |
| if (ei_local->chip_name == MT7621_FE) { |
| clk_prepare_enable(ei_local->clks[MTK_CLK_GP0]); |
| |
| /* switch to esw */ |
| sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0xC, 0x1); |
| |
| /* set agpio to 5-port ephy */ |
| gpio_base_virt = ioremap(GPIO_GO_BASE, 0x100); |
| reg_value = sys_reg_read(gpio_base_virt + 0xF0); |
| reg_value &= 0xE0FFFFFF; |
| sys_reg_write(gpio_base_virt + 0xF0, reg_value); |
| iounmap(gpio_base_virt); |
| |
| /* set ephy to 5-port gpio mode */ |
| mt7622_esw_5port_gpio(); |
| |
| /* set agpio to 0-port ephy */ |
| gpio_base_virt = ioremap(GPIO_GO_BASE, 0x100); |
| reg_value = sys_reg_read(gpio_base_virt + 0xF0); |
| reg_value |= BITS(24, 28); |
| sys_reg_write(gpio_base_virt + 0xF0, reg_value); |
| iounmap(gpio_base_virt); |
| |
| /* switch back to gmac1 */ |
| sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0xC, 0x0); |
| |
| clk_disable_unprepare(ei_local->clks[MTK_CLK_GP0]); |
| } |
| |
| if (ei_local->chip_name == MT7622_FE) { |
| if (ei_local->features & FE_GE2_SUPPORT) { |
| gpio_base_virt = ioremap(GPIO_GO_BASE + 0x100, 0x100); |
| reg_value = sys_reg_read(gpio_base_virt + 0x70); |
| reg_value = reg_value | (1 << 30); |
| sys_reg_write(gpio_base_virt + 0x70, reg_value); |
| reg_value = sys_reg_read(gpio_base_virt + 0x8c); |
| reg_value = reg_value | (1 << 24); |
| sys_reg_write(gpio_base_virt + 0x8c, reg_value); |
| iounmap(gpio_base_virt); |
| } |
| } |
| } |
| |
| void fe_sw_deinit(struct END_DEVICE *ei_local) |
| { |
| struct device_node *np = ei_local->switch_np; |
| struct platform_device *pdev = of_find_device_by_node(np); |
| void __iomem *gpio_base_virt; |
| unsigned int reg_value; |
| struct mtk_gsw *gsw; |
| int ret; |
| |
| gsw = platform_get_drvdata(pdev); |
| if (!gsw) |
| return; |
| |
| ret = regulator_disable(gsw->supply); |
| if (ret) |
| dev_err(&pdev->dev, "Failed to disable mt7530 power: %d\n", ret); |
| |
| if (gsw->mcm) { |
| ret = regulator_disable(gsw->b3v); |
| if (ret) |
| dev_err(&pdev->dev, "Failed to disable b3v: %d\n", ret); |
| } |
| |
| if (ei_local->architecture & MT7622_EPHY) { |
| /* set ephy to 5-port gpio mode */ |
| mt7622_esw_5port_gpio(); |
| |
| /* set agpio to 0-port ephy */ |
| gpio_base_virt = ioremap(GPIO_GO_BASE, 0x100); |
| reg_value = sys_reg_read(gpio_base_virt + 0xF0); |
| reg_value |= BITS(24, 28); |
| sys_reg_write(gpio_base_virt + 0xF0, reg_value); |
| iounmap(gpio_base_virt); |
| } else if (ei_local->architecture & LEOPARD_EPHY) { |
| mt7622_esw_5port_gpio(); |
| /*10000710 GEPHY_CTRL0[9:6] = 1 */ |
| gpio_base_virt = ioremap(GPIO_GO_BASE, 0x10); |
| reg_value = sys_reg_read(gpio_base_virt); |
| reg_value = reg_value | 0x3c0; |
| sys_reg_write(gpio_base_virt, reg_value); |
| iounmap(gpio_base_virt); |
| |
| gpio_base_virt = ioremap(GPIO_MODE_BASE, 0x100); |
| /*10217310 GPIO_MODE1 [31:16] = 0x0*/ |
| reg_value = sys_reg_read(gpio_base_virt + 0x10); |
| reg_value &= 0x0000ffff; |
| reg_value = reg_value & (~0xffff0000); |
| sys_reg_write(gpio_base_virt + 0x10, reg_value); |
| |
| /*10217320 GPIO_MODE2(gpio17/18/21/22/23)*/ |
| reg_value = sys_reg_read(gpio_base_virt + 0x20); |
| reg_value = reg_value & (~0xfff00fff); |
| sys_reg_write(gpio_base_virt + 0x20, reg_value); |
| iounmap(gpio_base_virt); |
| } |
| } |
| |
| static void esw_link_status_changed(int port_no, void *dev_id) |
| { |
| unsigned int reg_val; |
| |
| mii_mgr_read(31, (0x3008 + (port_no * 0x100)), ®_val); |
| if (reg_val & 0x1) |
| pr_info("ESW: Link Status Changed - Port%d Link UP\n", port_no); |
| else |
| pr_info("ESW: Link Status Changed - Port%d Link Down\n", |
| port_no); |
| } |
| |
| irqreturn_t gsw_interrupt(int irq, void *resv) |
| { |
| unsigned long flags; |
| unsigned int reg_int_val; |
| struct net_device *dev = dev_raether; |
| struct END_DEVICE *ei_local = netdev_priv(dev); |
| void *dev_id = NULL; |
| |
| spin_lock_irqsave(&ei_local->page_lock, flags); |
| mii_mgr_read(31, 0x700c, ®_int_val); |
| |
| if (reg_int_val & P4_LINK_CH) |
| esw_link_status_changed(4, dev_id); |
| |
| if (reg_int_val & P3_LINK_CH) |
| esw_link_status_changed(3, dev_id); |
| if (reg_int_val & P2_LINK_CH) |
| esw_link_status_changed(2, dev_id); |
| if (reg_int_val & P1_LINK_CH) |
| esw_link_status_changed(1, dev_id); |
| if (reg_int_val & P0_LINK_CH) |
| esw_link_status_changed(0, dev_id); |
| |
| mii_mgr_write(31, 0x700c, 0x1f); /* ack switch link change */ |
| spin_unlock_irqrestore(&ei_local->page_lock, flags); |
| |
| return IRQ_HANDLED; |
| } |
| |
| u32 phy_tr_dbg(u8 phyaddr, char *type, u32 data_addr, u8 ch_num) |
| { |
| u16 page_reg = 31; |
| u32 token_ring_debug_reg = 0x52B5; |
| u32 token_ring_control_reg = 0x10; |
| u32 token_ring_low_data_reg = 0x11; |
| u32 token_ring_high_data_reg = 0x12; |
| u16 ch_addr = 0; |
| u32 node_addr = 0; |
| u32 value = 0; |
| u32 value_high = 0; |
| u32 value_low = 0; |
| |
| if (strncmp(type, "DSPF", 4) == 0) { |
| /* DSP Filter Debug Node*/ |
| ch_addr = 0x02; |
| node_addr = 0x0D; |
| } else if (strncmp(type, "PMA", 3) == 0) { |
| /*PMA Debug Node*/ |
| ch_addr = 0x01; |
| node_addr = 0x0F; |
| } else if (strncmp(type, "TR", 2) == 0) { |
| /* Timing Recovery Debug Node */ |
| ch_addr = 0x01; |
| node_addr = 0x0D; |
| } else if (strncmp(type, "PCS", 3) == 0) { |
| /* R1000PCS Debug Node */ |
| ch_addr = 0x02; |
| node_addr = 0x0F; |
| } else if (strncmp(type, "FFE", 3) == 0) { |
| /* FFE Debug Node */ |
| ch_addr = ch_num; |
| node_addr = 0x04; |
| } else if (strncmp(type, "EC", 2) == 0) { |
| /* ECC Debug Node */ |
| ch_addr = ch_num; |
| node_addr = 0x00; |
| } else if (strncmp(type, "ECT", 3) == 0) { |
| /* EC/Tail Debug Node */ |
| ch_addr = ch_num; |
| node_addr = 0x01; |
| } else if (strncmp(type, "NC", 2) == 0) { |
| /* EC/NC Debug Node */ |
| ch_addr = ch_num; |
| node_addr = 0x01; |
| } else if (strncmp(type, "DFEDC", 5) == 0) { |
| /* DFETail/DC Debug Node */ |
| ch_addr = ch_num; |
| node_addr = 0x05; |
| } else if (strncmp(type, "DEC", 3) == 0) { |
| /* R1000DEC Debug Node */ |
| ch_addr = 0x00; |
| node_addr = 0x07; |
| } else if (strncmp(type, "CRC", 3) == 0) { |
| /* R1000CRC Debug Node */ |
| ch_addr = ch_num; |
| node_addr = 0x06; |
| } else if (strncmp(type, "AN", 2) == 0) { |
| /* Autoneg Debug Node */ |
| ch_addr = 0x00; |
| node_addr = 0x0F; |
| } else if (strncmp(type, "CMI", 3) == 0) { |
| /* CMI Debug Node */ |
| ch_addr = 0x03; |
| node_addr = 0x0F; |
| } else if (strncmp(type, "SUPV", 4) == 0) { |
| /* SUPV PHY Debug Node */ |
| ch_addr = 0x00; |
| node_addr = 0x0D; |
| } else { |
| pr_info("Wrong TR register Type !"); |
| return 0xFFFF; |
| } |
| data_addr = data_addr & 0x3F; |
| |
| tc_mii_write(phyaddr, page_reg, token_ring_debug_reg); |
| tc_mii_write(phyaddr, token_ring_control_reg, |
| (1 << 15) | (1 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1)); |
| |
| value_low = tc_mii_read(phyaddr, token_ring_low_data_reg); |
| value_high = tc_mii_read(phyaddr, token_ring_high_data_reg); |
| value = value_low + ((value_high & 0x00FF) << 16); |
| pr_info("*%s => Phyaddr=%d, ch_addr=%d, node_addr=0x%X, data_addr=0x%X , value=0x%X\r\n", |
| type, phyaddr, ch_addr, node_addr, data_addr, value); |
| tc_mii_write(phyaddr, page_reg, 0x00);/* V1.11 */ |
| |
| return value; |
| } |
| |
| void esw_show_debug_log(u32 phy_addr) |
| { |
| u32 val; |
| |
| val = phy_tr_dbg(phy_addr, "PMA", 0x38, 0); |
| pr_info("VgaStateA =0x%x\n", ((val >> 4) & 0x1F)); |
| pr_info("VgaStateB =0x%x\n", ((val >> 9) & 0x1F)); |
| pr_info("VgaStateC =0x%x\n", ((val >> 14) & 0x1F)); |
| pr_info("VgaStateD =0x%x\n", ((val >> 19) & 0x1F)); |
| |
| /* pairA */ |
| val = tc_phy_read_dev_reg(phy_addr, 0x1E, 0x9B); |
| pr_info("XX0 0x1E,0x9B =0x%x\n", val); |
| val = (val >> 8) & 0xFF; |
| pr_info("AA0 lch_mse_mdcA =0x%x\r\n", val); |
| |
| /* Pair B */ |
| val = tc_phy_read_dev_reg(phy_addr, 0x1E, 0x9B); |
| pr_info("XX1 0x1E,0x9B =0x%x\n", val); |
| val = (val) & 0xFF; /* V1.16 */ |
| pr_info("AA1 lch_mse_mdcB =0x%x\r\n", val); |
| /* Pair C */ |
| val = tc_phy_read_dev_reg(phy_addr, 0x1E, 0x9C); |
| pr_info("XX2 0x1E,0x9C =0x%x\n", val); |
| val = (val >> 8) & 0xFF; |
| pr_info("AA2 lch_mse_mdcC =0x%x\r\n", val); |
| |
| /* Pair D */ |
| val = tc_phy_read_dev_reg(phy_addr, 0x1E, 0x9C); |
| pr_info("XX3 0x1E,0x9C =0x%x\n", val); |
| val = (val) & 0xFF; /* V1.16 */ |
| pr_info("AA3 lch_mse_mdcD =0x%x\r\n", val); |
| } |
| |
| irqreturn_t esw_interrupt(int irq, void *resv) |
| { |
| unsigned long flags; |
| u32 phy_val; |
| int i; |
| static unsigned int port_status[5] = {0, 0, 0, 0, 0}; |
| struct net_device *dev = dev_raether; |
| struct END_DEVICE *ei_local = netdev_priv(dev); |
| |
| spin_lock_irqsave(&ei_local->page_lock, flags); |
| /* disable irq mask and ack irq status */ |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x4, 0xffffffff); |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE, 0x04000000); |
| spin_unlock_irqrestore(&ei_local->page_lock, flags); |
| for (i = 0; i < 5; i++) { |
| mii_mgr_read(i, 1, &phy_val); |
| if (port_status[i] != ((phy_val & 0x4) >> 2)) { |
| if (port_status[i] == 0) { |
| port_status[i] = 1; |
| pr_info("ESW: Link Status Changed - Port%d Link Up\n", i); |
| } else { |
| port_status[i] = 0; |
| pr_info("ESW: Link Status Changed - Port%d Link Down\n", i); |
| } |
| if (ei_local->architecture & LEOPARD_EPHY) { |
| if (i == 0) |
| esw_show_debug_log(i);/*port0 giga port*/ |
| } |
| } |
| } |
| /* enable irq mask */ |
| sys_reg_write(ETHDMASYS_ETH_SW_BASE + 0x4, 0xfbffffff); |
| return IRQ_HANDLED; |
| } |
| |
| int ephy_ioctl(struct net_device *dev, struct ifreq *ifr, |
| struct ephy_ioctl_data *ioctl_data) |
| { |
| int ret = 0; |
| unsigned int cmd; |
| u8 cnt = 0; |
| u8 port_num = 0; |
| |
| cmd = ioctl_data->cmd; |
| pr_info("%s : cmd =%x\n", __func__, cmd); |
| switch (cmd) { |
| case RAETH_VBG_IEXT_CALIBRATION: |
| cnt = 0; |
| fe_cal_vbg_flag = 0; /*restart calibration*/ |
| for (port_num = 0; port_num < 5; port_num++) { |
| while ((fe_cal_vbg_flag == 0) && (cnt < 0x3)) { |
| fe_cal_vbg(port_num, 1); |
| cnt++; |
| if (fe_cal_vbg_flag == 0) |
| pr_info(" VBG wait! (%d)\n", cnt); |
| } |
| } |
| break; |
| |
| case RAETH_TXG_R50_CALIBRATION: |
| cnt = 0; |
| fe_cal_r50_flag = 0; |
| for (port_num = 0; port_num < 5; port_num++) { |
| while ((fe_cal_r50_flag == 0) && (cnt < 0x3)) { |
| fe_cal_r50(port_num, 1); |
| cnt++; |
| if (fe_cal_r50_flag == 0) |
| pr_info(" FE R50 wait! (%d)\n", cnt); |
| } |
| } |
| break; |
| |
| case RAETH_TXG_OFFSET_CALIBRATION: |
| for (port_num = 0; port_num < 5; port_num++) { |
| cnt = 0; |
| fe_cal_tx_offset_flag = 0; |
| while ((fe_cal_tx_offset_flag == 0) && (cnt < 0x3)) { |
| fe_cal_tx_offset(port_num, 100); |
| cnt++; |
| if (fe_cal_tx_offset_flag == 0) |
| pr_info("FeTxOffsetAnaCal wait!(%d)\n", |
| cnt); |
| } |
| cnt = 0; |
| fe_cal_tx_offset_flag_mdix = 0; |
| while ((fe_cal_tx_offset_flag_mdix == 0) && (cnt < 0x3)) { |
| fe_cal_tx_offset_mdix(port_num, 100); |
| cnt++; |
| if (fe_cal_tx_offset_flag_mdix == 0) |
| pr_info |
| ("FeTxOffsetAnaCal mdix wait!(%d)\n", |
| cnt); |
| } |
| } |
| break; |
| |
| case RAETH_TXG_AMP_CALIBRATION: |
| for (port_num = 0; port_num < 5; port_num++) { |
| cnt = 0; |
| fe_cal_flag = 0; |
| while ((fe_cal_flag == 0) && (cnt < 0x3)) { |
| fe_cal_tx_amp(port_num, 300); |
| cnt++; |
| if (fe_cal_flag == 0) |
| pr_info("FETxAmpAnaCal wait!(%d)\n", |
| cnt); |
| } |
| cnt = 0; |
| fe_cal_flag_mdix = 0; |
| while ((fe_cal_flag_mdix == 0) && (cnt < 0x3)) { |
| fe_cal_tx_amp_mdix(port_num, 300); |
| cnt++; |
| if (fe_cal_flag_mdix == 0) |
| pr_info |
| ("FETxAmpAnaCal mdix wait!(%d)\n", |
| cnt); |
| } |
| } |
| break; |
| |
| case GE_TXG_R50_CALIBRATION: |
| cnt = 0; |
| ge_cal_r50_flag = 0; |
| while ((ge_cal_r50_flag == 0) && (cnt < 0x3)) { |
| ge_cal_r50(0, 20); |
| cnt++; |
| if (ge_cal_r50_flag == 0) |
| pr_info(" GE R50 wait! (%d)\n", cnt); |
| } |
| break; |
| |
| case GE_TXG_OFFSET_CALIBRATION: |
| cnt = 0; |
| ge_cal_tx_offset_flag = 0; |
| while ((ge_cal_tx_offset_flag == 0) && (cnt < 0x3)) { |
| ge_cal_tx_offset(port_num, 20); |
| cnt++; |
| if (ge_cal_tx_offset_flag == 0) |
| pr_info("GeTxOffsetAnaCal wait!(%d)\n", |
| cnt); |
| } |
| break; |
| |
| case GE_TXG_AMP_CALIBRATION: |
| cnt = 0; |
| ge_cal_flag = 0; |
| while ((ge_cal_flag == 0) && (cnt < 0x3)) { |
| ge_cal_tx_amp(port_num, 20); |
| cnt++; |
| if (ge_cal_flag == 0) |
| pr_info("GETxAmpAnaCal wait!(%d)\n", |
| cnt); |
| } |
| break; |
| default: |
| ret = 1; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| static const struct of_device_id mediatek_gsw_match[] = { |
| {.compatible = "mediatek,mt7623-gsw"}, |
| {.compatible = "mediatek,mt7621-gsw"}, |
| {}, |
| }; |
| |
| MODULE_DEVICE_TABLE(of, mediatek_gsw_match); |
| |
| static int mtk_gsw_probe(struct platform_device *pdev) |
| { |
| struct device_node *np = pdev->dev.of_node; |
| struct device_node *pctl; |
| struct mtk_gsw *gsw; |
| int err; |
| const char *pm; |
| |
| gsw = devm_kzalloc(&pdev->dev, sizeof(struct mtk_gsw), GFP_KERNEL); |
| if (!gsw) |
| return -ENOMEM; |
| |
| gsw->dev = &pdev->dev; |
| gsw->trgmii_force = 2000; |
| gsw->irq = irq_of_parse_and_map(np, 0); |
| if (gsw->irq < 0) |
| return -EINVAL; |
| |
| err = of_property_read_string(pdev->dev.of_node, "mcm", &pm); |
| if (!err && !strcasecmp(pm, "enable")) { |
| gsw->mcm = true; |
| pr_info("== MT7530 MCM ==\n"); |
| } |
| |
| gsw->ethsys = syscon_regmap_lookup_by_phandle(np, "mediatek,ethsys"); |
| if (IS_ERR(gsw->ethsys)) { |
| pr_err("fail at %s %d\n", __func__, __LINE__); |
| return PTR_ERR(gsw->ethsys); |
| } |
| |
| if (!gsw->mcm) { |
| gsw->reset_pin = of_get_named_gpio(np, "mediatek,reset-pin", 0); |
| if (gsw->reset_pin < 0) { |
| pr_err("fail at %s %d\n", __func__, __LINE__); |
| return -1; |
| } |
| pr_debug("reset_pin_port= %d\n", gsw->reset_pin); |
| |
| pctl = of_parse_phandle(np, "mediatek,pctl-regmap", 0); |
| if (IS_ERR(pctl)) { |
| pr_err("fail at %s %d\n", __func__, __LINE__); |
| return PTR_ERR(pctl); |
| } |
| |
| gsw->pctl = syscon_node_to_regmap(pctl); |
| if (IS_ERR(pctl)) { |
| pr_err("fail at %s %d\n", __func__, __LINE__); |
| return PTR_ERR(pctl); |
| } |
| |
| gsw->pins = pinctrl_get(&pdev->dev); |
| if (gsw->pins) { |
| gsw->ps_reset = |
| pinctrl_lookup_state(gsw->pins, "reset"); |
| |
| if (IS_ERR(gsw->ps_reset)) { |
| dev_err(&pdev->dev, |
| "failed to lookup the gsw_reset state\n"); |
| return PTR_ERR(gsw->ps_reset); |
| } |
| } else { |
| dev_err(&pdev->dev, "gsw get pinctrl fail\n"); |
| return PTR_ERR(gsw->pins); |
| } |
| } |
| |
| gsw->supply = devm_regulator_get(&pdev->dev, "mt7530"); |
| if (IS_ERR(gsw->supply)) { |
| pr_info("fail at %s %d\n", __func__, __LINE__); |
| return PTR_ERR(gsw->supply); |
| } |
| |
| if (gsw->mcm) { |
| gsw->b3v = devm_regulator_get(&pdev->dev, "b3v"); |
| if (IS_ERR(gsw->b3v)) |
| return PTR_ERR(gsw->b3v); |
| } |
| |
| gsw->wllll = of_property_read_bool(np, "mediatek,wllll"); |
| |
| platform_set_drvdata(pdev, gsw); |
| |
| return 0; |
| } |
| |
| static int mtk_gsw_remove(struct platform_device *pdev) |
| { |
| platform_set_drvdata(pdev, NULL); |
| |
| return 0; |
| } |
| |
| static struct platform_driver gsw_driver = { |
| .probe = mtk_gsw_probe, |
| .remove = mtk_gsw_remove, |
| .driver = { |
| .name = "mtk-gsw", |
| .owner = THIS_MODULE, |
| .of_match_table = mediatek_gsw_match, |
| }, |
| }; |
| |
| module_platform_driver(gsw_driver); |