📄 vsc8601_phy.c
字号:
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);}CEXTERN 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: printk(MODULE_NAME": unkown speed read!\n"); return 0; }}static void vsc8601_phy_setup_generic(uint16_t unit, uint16_t phy_addr){ vsc8601_phy_mii_set_duplex(unit, phy_addr, 1);#ifdef CONFIG_AR9100/* Temporary phy settings for 1000Mpbs mode */ 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 voidvsc8601_phy_setup_atheros_f1e(uint16_t unit, uint16_t phy_addr){ /* delay tx_clk */ ag7100_mii_write(unit, phy_addr, 0x1D, 0x5); ag7100_mii_write(unit, phy_addr, 0x1E, 0x100); /* what else????? */}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); /* Set Skew */ 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){ /* Set Skew */ vsc8601_phy_rmw_ex_crtl_set_1(unit, phy_addr, 1<<8, 1<<8);}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); printk(MODULE_NAME": 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: printk(MODULE_NAME": 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: printk(MODULE_NAME": 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: printk(MODULE_NAME": 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: printk(MODULE_NAME": PHY is ICPlus IP175B Switch\n"); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; case 0x004dd04e: printk(MODULE_NAME": PHY is an Atheros F1E\n"); vsc8601_phy_setup_atheros_f1e(unit, phy_addr); vsc8601_phy_setup_generic(unit, phy_addr); phy_info[nmbr_phys].is_enet_port=1; unit_cnt++; break; default: printk(MODULE_NAME": 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) { printk(MODULE_NAME": no PHY IDs found \n"); return 1; } if (unit_cnt == 0) { printk(MODULE_NAME": no PHY IDs assigned to unit\n"); return 1; } return 0;}CEXTERN intvsc8601_phy_print_status_raw(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); printk(MODULE_NAME": unit %d phy_addr %d\n", unit, phy_addr); vsc8601_phy_mii_print_mode_ctrl(mc); vsc8601_phy_mii_print_mode_status(ms); printk(MODULE_NAME": id1 (02 )=%02x\n", id1 & 0xff); printk(MODULE_NAME": id2 (03 )=%02x\n", id2 & 0xff); printk(MODULE_NAME": rcv-error (19 )=%04x\n", rec & 0xff); printk(MODULE_NAME": false-carrier (20 )=%04x\n", fcc & 0xff); printk(MODULE_NAME": disconnect_cnt (21 )=%04x\n", dc & 0xff); vsc8601_phy_mii_print_ex_ctrl_set_1(cs1); printk(MODULE_NAME": ex_crtl_set_2 (24 )=%04x\n", cs2); printk(MODULE_NAME": 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); printk(MODULE_NAME": crc_good (18E)=%04x\n", cgc); printk(MODULE_NAME": resistor (19E)=%04x\n", mcr); vsc8601_phy_mii_print_ex_crtl_set_5(cs5); vsc8601_phy_mii_print_skew_ctrl(skc); printk(MODULE_NAME": epg_1 (29E)=%04x\n", ep1); printk(MODULE_NAME": epg_2 (30E)=%04x\n", ep2); } break; } /* Speed specific */ switch(vsc8601_phy_get_speed(unit, phy_addr)) { case AG7100_PHY_SPEED_10T: printk(MODULE_NAME": * 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); printk(MODULE_NAME": * 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); printk(MODULE_NAME": * current speed gige\n"); } break; default: printk(MODULE_NAME": * current speed unknown\n"); break; } 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); printk(MODULE_NAME": unit %d phy_addr %d\n", unit, phy_addr); vsc8601_phy_mii_print_mode_ctrl(mc); vsc8601_phy_mii_print_mode_status(ms); printk(MODULE_NAME": rcv-error (19 )=%04x\n", rec & 0xff); printk(MODULE_NAME": false-carrier (20 )=%04x\n", fcc & 0xff); printk(MODULE_NAME": disconnect_cnt (21 )=%04x\n", dc & 0xff);#else uint16_t ms = vsc8601_phy_mii_read_mode_status (unit, phy_addr); printk(MODULE_NAME": unit %d phy_addr %d\n", unit, phy_addr);// vsc8601_phy_mii_print_mode_status(ms);#endif#endif return 0;}/* *********************************************************** * * 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; 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_raw(phy->mac_unit, phy->phy_addr); } return 0;}unsigned int vsc8601_phy_get_link_status(int unit, int *link, int *fdx, ag7100_phy_speed_t *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 (tc) vsc8601_phy_print_status_raw(unit, phy->phy_addr); if (cfg) *cfg=tc; return tc;}intvsc8601_phy_print_link_status(int unit){ vsc8601_phy_t *phy = vsc8601_phy_find(unit); if (!phy) { printk(MODULE_NAME": could not find mac\n"); return -1; } vsc8601_phy_print_status_raw(unit, phy->phy_addr); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -