vsc8601_phy.c
来自「TP-LINK公司TL-WR941N无线路由器的Bootloader U_BOO」· C语言 代码 · 共 1,217 行 · 第 1/2 页
C
1,217 行
generic_printk(" pair d delay: %02x\n", (val>> 0)&7);}/* Extended registers - specific to chips? */CEXTERN uint16_t vsc8601_phy_read_crc_good_counter(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_ex(unit, phy_addr, 18);}/* Resistor calibration */CEXTERN uint16_t vsc8601_phy_read_mac_resistor_calibration(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_ex(unit, phy_addr, 19);}CEXTERN void vsc8601_phy_write_mac_resistor_calibration(int unit, uint32_t phy_addr, uint16_t val){ vsc8601_phy_mii_write_ex(unit, phy_addr, 19, val);}CEXTERN void vsc8601_phy_rmw_mac_resistor_calibration(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_read_mac_resistor_calibration(unit, phy_addr); reg &= ~mask; reg |= val; vsc8601_phy_write_mac_resistor_calibration(unit, phy_addr, reg);}CEXTERN uint16_t vsc8601_phy_read_ex_crtl_set_5(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_ex(unit, phy_addr, 27);}CEXTERN void vsc8601_phy_mii_print_ex_crtl_set_5(uint16_t val){ generic_printk(" ex_crtl_set_5 (27E)=%04x\n", val); generic_printk(" crs: %x\n", (val>>12)&7); generic_printk(" 100 tx amp: %x\n", (val>> 6)&7); generic_printk(" gige tx amp: %x\n", (val>> 3)&7); generic_printk(" gige edge: %x\n", (val>> 0)&7); if (val & 1<<10) generic_printk(" FAR-END-LOOPBACK\n");}CEXTERN void vsc8601_phy_write_ex_crtl_set_5(int unit, uint32_t phy_addr, uint16_t reg){ return vsc8601_phy_mii_write_ex(unit, phy_addr, 27, reg);}CEXTERN void vsc8601_phy_rmw_ex_crtl_set_5(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_read_ex_crtl_set_5(unit, phy_addr); if (reg == 0xffff) return; reg &= ~mask; reg |= val; vsc8601_phy_write_ex_crtl_set_5(unit, phy_addr, reg);}CEXTERN uint16_t vsc8601_phy_read_skew_ctrl(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_ex(unit, phy_addr, 28);}CEXTERN void vsc8601_phy_mii_print_skew_ctrl(uint16_t val){ generic_printk(" skew_ctrl (28E)=%04x\n", val); generic_printk(" tx cmp: %x\n", (val>>14)&3); generic_printk(" rx cmp: %x\n", (val>>12)&7); generic_printk(" jumbo: %x\n", (val>>10)&7); }CEXTERN void vsc8601_phy_write_skew_ctrl(int unit, uint32_t phy_addr, uint16_t reg){ return vsc8601_phy_mii_write_ex(unit, phy_addr, 28, reg);}CEXTERN void vsc8601_phy_rmw_skew_ctrl(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_read_skew_ctrl(unit, phy_addr); if (reg == 0xffff) return; reg &= ~mask; reg |= val; vsc8601_phy_write_skew_ctrl(unit, phy_addr, reg);}CEXTERN uint16_t vsc8601_phy_read_epg_1(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_ex(unit, phy_addr, 29);}CEXTERN void vsc8601_phy_write_epg_1(int unit, uint32_t phy_addr, uint16_t reg){ return vsc8601_phy_mii_write_ex(unit, phy_addr, 29, reg);}CEXTERN void vsc8601_phy_rmw_epg_1(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_read_epg_1(unit, phy_addr); if (reg == 0xffff) return; reg &= ~mask; reg |= val; vsc8601_phy_write_epg_1(unit, phy_addr, reg);}CEXTERN uint16_t vsc8601_phy_read_epg_2(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_ex(unit, phy_addr, 20);}CEXTERN void vsc8601_phy_write_epg_2(int unit, uint32_t phy_addr, uint16_t reg){ return vsc8601_phy_mii_write_ex(unit, phy_addr, 30, reg);}CEXTERN void vsc8601_phy_rmw_epg_2(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_read_epg_2(unit, phy_addr); if (reg == 0xffff) return; reg &= ~mask; reg |= val; vsc8601_phy_write_epg_2(unit, phy_addr, reg);}#endif/* Functions */CEXTERN void vsc8601_phy_mii_soft_reset(int unit, uint32_t phy_addr) { vsc8601_phy_mii_rmw_ctrl(unit, phy_addr, 1<<15, 1<<15); generic_udelay(10);}CEXTERN void vsc8601_phy_mii_set_loopback(int unit, uint32_t phy_addr, int onOff) { uint32_t val = onOff ? 1<<14 : 0; vsc8601_phy_mii_rmw_ctrl(unit, phy_addr, 1<<14, val);}CEXTERN void vsc8601_phy_mii_set_auto(int unit, uint32_t phy_addr, int onOff) { uint32_t val = onOff ? 1<<12 : 0; vsc8601_phy_mii_rmw_ctrl(unit, phy_addr, 1<<12, val);}CEXTERN void vsc8601_phy_mii_force_speed(int unit, uint32_t phy_addr, int speed) { uint32_t val=0; if (speed & 1<<0) val |= 1<<6; if (speed & 2<<0) val |= 1<<13; vsc8601_phy_mii_rmw_ctrl(unit, phy_addr, 1<<6 | 1<<13 , val);}CEXTERN void vsc8601_phy_mii_restart_auto(int unit, uint32_t phy_addr, int onOff) { uint32_t val = onOff ? 1<<9 : 0; vsc8601_phy_mii_rmw_ctrl(unit, phy_addr, 1<<9, val);}CEXTERN void vsc8601_phy_mii_set_duplex(int unit, uint32_t phy_addr, int onOff) { uint32_t val = onOff ? 1<<8 : 0; vsc8601_phy_mii_rmw_ctrl(unit, phy_addr, 1<<8, val);}/* IEEE GIGE extended control */CEXTERN void vsc8601_phy_set_gige_test_normal(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 7<<13, 0<<13);}CEXTERN void vsc8601_phy_set_gige_test_waveform(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 7<<13, 1<<13);}CEXTERN void vsc8601_phy_set_gige_test_jitter_master(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 7<<13, 2<<13);}CEXTERN void vsc8601_phy_set_gige_test_jitter_slave(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 7<<13, 3<<13);}CEXTERN void vsc8601_phy_set_gige_test_distortion(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 7<<13, 4<<13);}CEXTERN void vsc8601_phy_set_gige_test_master(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 3<<11, 3<<11);}CEXTERN void vsc8601_phy_set_gige_test_slave(int unit, uint32_t phy_addr) { vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 3<<11, 2<<11);}CEXTERN void vsc8601_phy_set_gige_multiport(int unit, uint32_t phy_addr, int onOff) { uint32_t val = onOff ? 1<<10 : 0; vsc8601_phy_rmw_gige_ctrl(unit, phy_addr, 1<<10, val);}#if 0CEXTERN uint16_tvsc8601_phy_get_speed(uint16_t unit, uint16_t phy_addr){ uint16_t speed = (vsc8601_phy_read_aux_ctrl_status(unit, phy_addr) >> 3) & 3; switch(speed) { case 0: return AG7100_PHY_SPEED_10T; case 1: return AG7100_PHY_SPEED_100TX; case 2: return AG7100_PHY_SPEED_1000T; default: generic_printk("ERROR: Unkown speed read!\n"); return 0; }}#endifstatic void vsc8601_phy_setup_generic(uint16_t unit, uint16_t phy_addr){ vsc8601_phy_mii_set_duplex(unit, phy_addr, 1);#ifdef CONFIG_AR9100 ag7100_mii_write(unit, phy_addr, 0x1f, 0x1); ag7100_mii_write(unit, phy_addr, 0x1c, 0x3000); ag7100_mii_write(unit, phy_addr, 0x1f, 0x0);#endif}static void vsc8601_phy_setup_vsc8601_Rev_A(uint16_t unit, uint16_t phy_addr){ uint16_t uu; /* Weird patch in vsc86-1 datasheet Errata */ ag7100_mii_write(unit, phy_addr, 31, 0x52b5); ag7100_mii_write(unit, phy_addr, 16, 0xaf8a); uu=ag7100_mii_read(unit, phy_addr, 18); ag7100_mii_write(unit, phy_addr, 18, uu); uu=ag7100_mii_read(unit, phy_addr, 17); uu&=~0x000c; uu|= 0x0008; ag7100_mii_write(unit, phy_addr, 17, uu); ag7100_mii_write(unit, phy_addr, 16, 0x8f8a); ag7100_mii_write(unit, phy_addr, 16, 0xaf86); uu=ag7100_mii_read(unit, phy_addr, 18); uu&=~0x000c; uu|= 0x0008; ag7100_mii_write(unit, phy_addr, 18, uu); uu=ag7100_mii_read(unit, phy_addr, 17); ag7100_mii_write(unit, phy_addr, 17, uu); ag7100_mii_write(unit, phy_addr, 16, 0x8f86); ag7100_mii_write(unit, phy_addr, 16, 0xaf82); uu=ag7100_mii_read(unit, phy_addr, 18); ag7100_mii_write(unit, phy_addr, 18, uu); uu=ag7100_mii_read(unit, phy_addr, 17); uu&=~0x0180; uu|= 0x0100; ag7100_mii_write(unit, phy_addr, 17, uu); ag7100_mii_write(unit, phy_addr, 16, 0x8f82); ag7100_mii_write(unit, phy_addr, 31, 0); /* Skew stuff */ vsc8601_phy_rmw_ex_crtl_set_1(unit, phy_addr, 1<<8, 1<<8);}static void vsc8601_phy_setup_vsc8601_Rev_B(uint16_t unit, uint16_t phy_addr){ vsc8601_phy_mii_set_duplex(unit, phy_addr, 1);#ifdef CONFIG_AR9100 vsc8601_phy_rmw_ex_crtl_set_1(unit, phy_addr, 1<<8, 1<<8);#endif}CEXTERN intvsc8601_phy_discover_and_setup_phy(int unit){ uint16_t phy_addr; uint16_t unit_cnt; unit_cnt=0; nmbr_phys=0; for (phy_addr=0; phy_addr<31; phy_addr++) { uint16_t id1 = vsc8601_phy_mii_read_id1(unit, phy_addr); uint32_t id2 = vsc8601_phy_mii_read_id2(unit, phy_addr); uint32_t id = id1<<16 | id2; uint32_t id_sav = 0; uint16_t phy_status = 0; if (id1 > 0 && id1 < 0x7ff) { vsc8601_phy_mii_soft_reset( unit, phy_addr ); phy_status=vsc8601_phy_mii_read_mode_status(unit, phy_addr); generic_printk(" VSCXXX Found %d unit %d:%d phy_addr: %d id: %08x\n", nmbr_phys, unit, unit_cnt, phy_addr, id); phy_info[nmbr_phys].id=id; phy_info[nmbr_phys].phy_addr=phy_addr; phy_info[nmbr_phys].mac_unit=unit_cnt; phy_info[nmbr_phys].is_enet_port=0; if (id != id_sav) { switch(id) { case 0x00070420: generic_printk(" PHY is Vitesse VSC8601 Rev A\n"); vsc8601_phy_setup_vsc8601_Rev_A(unit, phy_addr); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; case 0x00070421: generic_printk(" PHY is Vitesse VSC8601 Rev B\n"); vsc8601_phy_setup_vsc8601_Rev_B(unit, phy_addr); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; case 0x000fc413: generic_printk(" PHY is Vitesse VSC8201 Phy\n"); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; case 0x02430d80: generic_printk(" PHY is ICPlus IP175B Switch\n"); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; default: generic_printk(" PHY is unknown, using generic IEEE interface\n"); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; } id_sav=id; } nmbr_phys++; } } if (nmbr_phys == 0) { generic_printk(" ERROR: No PHY IDs found \n"); return 1; } if (unit_cnt == 0) { generic_printk(" ERROR: No PHY IDs assigned to unit\n"); return 1; } return 0;}#if 0CEXTERN intvsc8601_phy_print_status(uint16_t unit, uint16_t phy_addr){ #if ( VERBOSE > 1 ) /* Generic IEEE */ uint16_t mc = vsc8601_phy_mii_read_mode_ctrl (unit, phy_addr); uint16_t ms = vsc8601_phy_mii_read_mode_status (unit, phy_addr); uint16_t id1 = vsc8601_phy_mii_read_id1 (unit, phy_addr); uint32_t id2 = vsc8601_phy_mii_read_id2 (unit, phy_addr); uint32_t id = id1<<16 | id2; uint16_t rec = vsc8601_phy_read_rx_error_count (unit, phy_addr); uint16_t fcc = vsc8601_phy_read_false_carrier_count (unit, phy_addr); uint16_t dc = vsc8601_phy_read_disconnect_count (unit, phy_addr); uint16_t cs1 = vsc8601_phy_read_ex_crtl_set_1 (unit, phy_addr); uint16_t cs2 = vsc8601_phy_read_ex_crtl_set_2 (unit, phy_addr); uint16_t im = vsc8601_phy_read_irq_msk (unit, phy_addr); uint16_t is = vsc8601_phy_read_irq_status (unit, phy_addr); uint16_t acs = vsc8601_phy_read_aux_ctrl_status (unit, phy_addr); uint16_t dss = vsc8601_phy_read_delay_skew_status (unit, phy_addr); generic_printk("VSCXXX unit %d phy_addr %d\n", unit, phy_addr); vsc8601_phy_mii_print_mode_ctrl(mc); vsc8601_phy_mii_print_mode_status(ms); generic_printk(" id1 (02 )=%02x\n", id1 & 0xff); generic_printk(" id2 (03 )=%02x\n", id2 & 0xff); generic_printk(" rcv-error (19 )=%04x\n", rec & 0xff); generic_printk(" false-carrier (20 )=%04x\n", fcc & 0xff); generic_printk(" disconnect_cnt (21 )=%04x\n", dc & 0xff); vsc8601_phy_mii_print_ex_ctrl_set_1(cs1); generic_printk(" ex_crtl_set_2 (24 )=%04x\n", cs2); generic_printk(" irq_msk (25 )=%04x\n", im); vsc8601_phy_mii_print_irq_status(is); vsc8601_phy_mii_print_aux_ctrl_status(acs); vsc8601_phy_mii_print_delay_skew_status(dss); /* Chip specific */ switch( id ) { case 0x00070420: { uint16_t cgc = vsc8601_phy_read_crc_good_counter (unit, phy_addr); uint16_t mcr = vsc8601_phy_read_mac_resistor_calibration (unit, phy_addr); uint16_t cs5 = vsc8601_phy_read_ex_crtl_set_5 (unit, phy_addr); uint16_t skc = vsc8601_phy_read_skew_ctrl (unit, phy_addr); uint16_t ep1 = vsc8601_phy_read_epg_1 (unit, phy_addr); uint16_t ep2 = vsc8601_phy_read_epg_1 (unit, phy_addr); generic_printk(" crc_good (18E)=%04x\n", cgc); generic_printk(" resistor (19E)=%04x\n", mcr); vsc8601_phy_mii_print_ex_crtl_set_5(cs5); vsc8601_phy_mii_print_skew_ctrl(skc); generic_printk(" epg_1 (29E)=%04x\n", ep1); generic_printk(" epg_2 (30E)=%04x\n", ep2); } break; } /* Speed specific */ switch(vsc8601_phy_get_speed(unit, phy_addr)) { case AG7100_PHY_SPEED_10T: generic_printk(" * current speed 10 base-t\n"); break; case AG7100_PHY_SPEED_100TX: { uint16_t es = vsc8601_phy_read_100_status_ex (unit, phy_addr); vsc8601_phy_mii_print_100_status_ex(es); generic_printk(" * current speed 100 base-t\n"); } break; case AG7100_PHY_SPEED_1000T: { uint16_t gc = vsc8601_phy_mii_read_gige_ctrl (unit, phy_addr); uint16_t gs = vsc8601_phy_read_gige_status (unit, phy_addr); uint16_t gs2 = vsc8601_phy_read_gige_status_ex_2 (unit, phy_addr); vsc8601_phy_mii_print_gige_ctrl(gc); vsc8601_phy_mii_print_gige_status(gs); vsc8601_phy_mii_print_gige_status_ex_2(gs2); generic_printk(" * current speed gige\n"); } break; default: generic_printk(" * current speed unknown\n"); break; } generic_printk("\n");#else#if ( VERBOSE > 0 ) uint16_t ms = vsc8601_phy_mii_read_mode_status (unit, phy_addr); uint16_t mc = vsc8601_phy_mii_read_mode_ctrl (unit, phy_addr); uint16_t rec = vsc8601_phy_read_rx_error_count (unit, phy_addr); uint16_t fcc = vsc8601_phy_read_false_carrier_count (unit, phy_addr); uint16_t dc = vsc8601_phy_read_disconnect_count (unit, phy_addr); generic_printk("VSCXXX unit %d phy_addr %d\n", unit, phy_addr); vsc8601_phy_mii_print_mode_ctrl(mc); vsc8601_phy_mii_print_mode_status(ms); generic_printk(" rcv-error (19 )=%04x\n", rec & 0xff); generic_printk(" false-carrier (20 )=%04x\n", fcc & 0xff); generic_printk(" disconnect_cnt (21 )=%04x\n", dc & 0xff);#else uint16_t ms = vsc8601_phy_mii_read_mode_status (unit, phy_addr); generic_printk("VSCXXX unit %d phy_addr %d\n", unit, phy_addr); vsc8601_phy_mii_print_mode_status(ms);#endif#endif return 0;}#endif/* *********************************************************** * * These are exported for use by ag7100_phy.h * * *********************************************************** */int vsc8601_phy_setup(int unit){ int ii; vsc8601_phy_t *phy; if (vsc8601_phy_discover_and_setup_phy(unit)) return -1;#if 0 for (ii = 0; ii < sizeof(phy_info)/sizeof(phy_info[0]); ii++) { phy = &phy_info[ii]; if (phy->is_enet_port && (phy->mac_unit == unit)) vsc8601_phy_print_status(phy->mac_unit, phy->phy_addr); }#endif return 0;}#if 0unsigned int vsc8601_phy_get_link_status(int unit, int *link, int *fdx, int *speed, unsigned int *cfg){ unsigned short ms; unsigned short acs; unsigned int tc; vsc8601_phy_t *phy = vsc8601_phy_find(unit); if (!phy) return 0; ms = vsc8601_phy_mii_read_mode_status (unit, phy->phy_addr); if (link) *link = (ms & 1<<2) > 0; if (speed) *speed = vsc8601_phy_get_speed(unit, phy->phy_addr); if (fdx) { acs = vsc8601_phy_read_aux_ctrl_status(unit, phy->phy_addr); *fdx = (acs & 1<<5) > 0; } tc = phy->status != ms; phy->status = ms; #if VERBOSE > 0 if (tc) vsc8601_phy_print_status(unit, phy->phy_addr);#endif if (cfg) *cfg=tc; return tc;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?