📄 vsc73xx.c
字号:
udelay(10000); } while (1);}#endifstatic voidvsc73xx_print_val_bit_desc (unsigned int val, char *fieldName, char *bit_descriptions[]) { int ii; char *p2; printk(MODULE_NAME": %s=%04x\n", fieldName, val); for (ii=0;ii<32; ii++) { p2 = val & 1<<(31-ii) ? bit_descriptions[ii*2] : bit_descriptions[ii*2+1]; if (p2 && p2[0]) printk(MODULE_NAME": %s\n", p2); }}/* Port 0..4, 6 */static inline int vsc73xx_get_mac_cfg(int port, unsigned int *d){ return vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_MAC_CFG, d);}static char *mac_cfg_desc[32*2] = { "wexc_dis","", /* 31 */ "","", /* 30 */ "port_rst","", /* 29 */ "tx_en","", /* 28 */ "seed_load","", /* 27 */ "","", /* 26 */ "","", /* 25 */ "","", /* 24 */ "","", /* 23 */ "","", /* 22 */ "","", /* 21 */ "","", /* 20 */ "","", /* 19 */ "en-fdx","", /* 18 */ "gige","", /* 17 */ "rx_en","", /* 16 */ "vlan_dblawr","", /* 15 */ "vlan_awr","", /* 14 */ "100-base-T","", /* 13 */ "","", /* 12 */ "","", /* 11 */ "","", /* 10 */ "","", /* 9 */ "","", /* 8 */ "","", /* 7 */ "","", /* 6 */ "mac_rx_rst","", /* 5 */ "mac_tx_rst","", /* 4 */ "","", /* 3 */ "","", /* 2 */ "","", /* 1 */ "","", /* 0 */};static inline voidvsc73xx_print_mac_cfg_val(unsigned int val){ vsc73xx_print_val_bit_desc (val, "mac_cfg (01P00)", mac_cfg_desc); printk(MODULE_NAME": clk_sel: %02x\n", (val>>0)&0x3); printk(MODULE_NAME": tx_ipg: %02x\n", (val>>6)&0x1f);}static inline int vsc73xx_set_mac_cfg(int port, unsigned int value){ return vsc73xx_wr(VSC73XX_MAC, port, VSC73XX_MAC_CFG, value);}static inline int vsc73xx_get_clock_delay_reg(unsigned int *val){ return vsc73xx_rd(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CLOCK_DELAY, val);}static inline intvsc73xx_set_clock_delay_reg(unsigned int val){ return vsc73xx_wr(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CLOCK_DELAY, val);}static inline int vsc73xx_get_advportm(int port, unsigned int *val){ return vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_ADVPORTM, val);}static char *advportm_desc[32*2] = { "","", /* 31 */ "","", /* 30 */ "","", /* 29 */ "","", /* 28 */ "","", /* 27 */ "","", /* 26 */ "","", /* 25 */ "","", /* 24 */ "","", /* 23 */ "","", /* 22 */ "","", /* 21 */ "","", /* 20 */ "","", /* 19 */ "","", /* 18 */ "","", /* 17 */ "","", /* 16 */ "","", /* 15 */ "","", /* 14 */ "","", /* 13 */ "","", /* 12 */ "","", /* 11 */ "","", /* 10 */ "","", /* 9 */ "","", /* 8 */ "ifg_ppm","", /* 7 */ "exc_col","", /* 6 */ "ext_port","", /* 5 */ "inv_gtx","", /* 4 */ "ena_gtx","", /* 3 */ "ddr_mode","", /* 2 */ "io_loopback","", /* 1 */ "host_loopback","", /* 0 */};static inline voidvsc73xx_print_advportm_val(unsigned int val){ vsc73xx_print_val_bit_desc (val, "advportm (01P19)", advportm_desc);}static inline intvsc73xx_set_advportm(int port, unsigned int val){ return vsc73xx_wr(VSC73XX_MAC, port, VSC73XX_ADVPORTM, val);}/* HERE */static inline unsigned int vsc73xx_get_c_rx0(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_RX0, &d); return d;}static inline unsigned int vsc73xx_get_c_rx1(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_RX1, &d); return d;}static inline unsigned int vsc73xx_get_c_rx2(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_RX2, &d); return d;}static inline unsigned int vsc73xx_get_c_tx0(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_TX0, &d); return d;}static inline unsigned int vsc73xx_get_c_tx1(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_TX1, &d); return d;}static inline unsigned int vsc73xx_get_c_tx2(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_TX2, &d); return d;}static inline unsigned int vsc73xx_get_c_cfg(int port){ unsigned int d; vsc73xx_rd(VSC73XX_MAC, port, VSC73XX_C_CFG, &d); return d;}static inline voidvsc73xx_set_c_cfg(int port, unsigned int value){ vsc73xx_wr(VSC73XX_MAC, port, VSC73XX_C_CFG, value);}voidvsc73xx_print_counts(int port){ printk(MODULE_NAME":counters port %d\n", port); printk(MODULE_NAME": cfg: %8x\n", vsc73xx_get_c_cfg(port)); printk(MODULE_NAME": rx0: %9d\n", vsc73xx_get_c_rx0(port)); printk(MODULE_NAME": rx0: %9d\n", vsc73xx_get_c_rx1(port)); printk(MODULE_NAME": rx0: %9d\n", vsc73xx_get_c_tx2(port)); printk(MODULE_NAME": tx0: %9d\n", vsc73xx_get_c_tx0(port)); printk(MODULE_NAME": tx0: %9d\n", vsc73xx_get_c_tx1(port)); printk(MODULE_NAME": tx0: %9d\n", vsc73xx_get_c_tx2(port));}static inline voidvsc73xx_print_link_status_from_value(int port, int up, int fdx, int speed, unsigned int cfg){ printk(MODULE_NAME": STATUS Port: %d up: %d fdx: %d speed: %d mac cfg: %08x\n", port, up, fdx, speed, cfg); vsc73xx_print_mac_cfg_val(cfg);}#if 0/* WARNING: Do not use this if the switch application is running on the 8051. This * function may be used if the switch application is on the host and the * 8051 is in reset. */unsigned shortvsc73xx_rw_phy(int writeFlg, int unit, int phy_addr, int reg, uint16_t value){ /* unit 0 = mac0 and should not happen here * unit 1 = mac1, PHY we connect to using MAC 1 * unit 2-6 = ports on switch */ unsigned int request; unsigned int resp; int sublockA; int sublockB; /* This needs to be checked since we are at a new level of 8051 code */ sublockA = unit==1 ? 6:0; /* unit==1 is PHY tied to MAC using RGMII */ sublockB = unit==1 ? 1:0; /* unit>=1 is PHY on switch */ /* With the new 8051 code this has to be figured * out again ( that is sublock values ) */ request = (writeFlg ? 0 : 1)<<26 | (phy_addr<<21) | (reg<<16) | value; vsc73xx_wr(VSC73XX_MII, sublockA, VSC73XX_MII_CMD, request, 0); udelay(10); do { vsc73xx_rd(VSC73XX_MII, sublockB, VSC73XX_MII_STAT, &resp, 0); udelay(10); } while ( resp & 0xf ); if (writeFlg) return 0; udelay(1); vsc73xx_rd(VSC73XX_MII, sublockB, VSC73XX_MII_DATA, &resp, 0); if (resp & 1<<16) { return 0xffff; } return resp & 0xffff;}#endifstatic intvsc73xx_setup_raw(void){ int rc; int sVersion=0; int resetNeeded=0; unsigned int t_cfg; unsigned int t_clock_delay; unsigned int t_advportm;#ifdef CONFIG_AR9100 vsc73xx_wr(7,0,0x5,0x33);#endif rc = generic_spi_init(GENERIC_SPI_VSC73XX_CS); if (rc < 0) { printk(MODULE_NAME": could not initialize spi interface, err %d\n", rc); return rc; } vsc73xx_get_sVersion_resetNeeded(&sVersion, &resetNeeded); if ( (resetNeeded) || (sVersion < VSC73XX_SFTW_VERSION) ) { rc = vsc73xx_load_firmware(); if (rc < 0) return rc; } /* The VSC73XX does not work very well unless we setup 2 nsec delay */ vsc73xx_set_clock_delay_reg(VSC73XX_CLOCK_DELAY); vsc73xx_get_clock_delay_reg(&t_clock_delay); if ((t_clock_delay & VSC73XX_CLOCK_DELAY_MASK) != VSC73XX_CLOCK_DELAY) { printk(MODULE_NAME": unable to set clock_delay %08x %08x\n", VSC73XX_CLOCK_DELAY, VSC73XX_CLOCK_DELAY_MASK & t_clock_delay); return -1; } else printk(MODULE_NAME": clock_delay_reg %08x\n", t_clock_delay); /* We must tell the VSC73XX that it has an external interface */ vsc73xx_set_advportm(VSC73XX_PORT_MAC, VSC73XX_ADVPORTM_HYDRA); vsc73xx_get_advportm(VSC73XX_PORT_MAC, &t_advportm); if ((VSC73XX_ADVPORTM_HYDRA_MASK & t_advportm) != VSC73XX_ADVPORTM_HYDRA) { printk(MODULE_NAME": unable to set advanportm for MAC port (6) %08x %08x\n", VSC73XX_ADVPORTM_HYDRA, VSC73XX_ADVPORTM_HYDRA_MASK & t_advportm); } else vsc73xx_print_advportm_val(t_advportm); /* We must tell the VSC73XX that it can send/recieve data */#ifdef CONFIG_AR9100 vsc73xx_set_mac_cfg(VSC73XX_PORT_MAC, VSC73XX_MAC_CFG_PORT_RST | VSC73XX_MAC_CFG_MAC_RX_RST | VSC73XX_MAC_CFG_MAC_TX_RST); vsc73xx_set_mac_cfg(VSC73XX_PORT_MAC, VSC73XX_MAC_CFG_AR9100);#else vsc73xx_set_mac_cfg(VSC73XX_PORT_MAC, VSC73XX_MAC_CFG_HYDRA );#endif vsc73xx_get_mac_cfg(VSC73XX_PORT_MAC, &t_cfg);#ifndef CONFIG_AR9100 if ((VSC73XX_MAC_CFG_HYDRA_MASK & t_cfg) != VSC73XX_MAC_CFG_HYDRA) { printk(MODULE_NAME": unable to set mac_cfg for port 6 %08x %08x\n", VSC73XX_MAC_CFG_HYDRA, VSC73XX_MAC_CFG_HYDRA_MASK & t_cfg); } else#endif vsc73xx_print_mac_cfg_val(t_cfg); return rc;}static unsigned int mac_cfg_port[7] = { 0, 0, 0, 0, 0, 0, 0 };static unsigned intvsc73xx_get_link_status_raw(int port, int *up, int *fdx, ag7100_phy_speed_t *speed, unsigned int *cfg){ int rc; int t_up; int t_fdx; ag7100_phy_speed_t t_speed; unsigned int t_cfg; unsigned int t_chg; rc = vsc73xx_get_mac_cfg(port, &t_cfg); if (rc<0) return ~0; /* FIXME WCL * Occasionally the VSC73XX will return 0xffffffff for cfg status with no apparent error. */ if (t_cfg == 0xffffffff) return ~0; t_chg = mac_cfg_port[port] ^ t_cfg; mac_cfg_port[port] = t_cfg; t_up = (t_cfg & ( VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN )) == ( VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN ); t_fdx = (t_cfg & VSC73XX_MAC_CFG_FDX ) != 0; if ( t_cfg & VSC73XX_MAC_CFG_GIGA_MODE ) t_speed = AG7100_PHY_SPEED_1000T; else if ( t_cfg & VSC73XX_MAC_CFG_100_BASE_T ) t_speed = AG7100_PHY_SPEED_100TX; else t_speed = AG7100_PHY_SPEED_10T; if (up) *up = t_up; if (fdx) *fdx = t_fdx; if (speed) *speed = t_speed; if (cfg) *cfg = t_cfg; return t_chg;}#ifdef USE_TEST_CODEvoidvsc73xx_test_link_status(void){ int port; int ii; unsigned int t_up; unsigned int t_fdx; ag7100_phy_speed_t t_speed; unsigned int t_cfg; unsigned int t_chg; int rc; printk(MODULE_NAME": looping on load firmware / reset firmware\n" ); vsc73xx_setup_raw(); do { t_chg = vsc73xx_get_link_status_raw(port, &t_up, &t_fdx, &t_speed, &t_cfg); if (t_chg == ~0) { printk(MODULE_NAME": bad read from switch\n"); } else { if (t_chg) vsc73xx_print_link_status_from_value(port, t_up, t_fdx, t_speed, t_cfg); } } while (1);}#endifint vsc73xx_setup(int unit){ return vsc73xx_setup_raw();}intvsc73xx_get_link_status(int unit, int *up, int *fdx, ag7100_phy_speed_t *speed, unsigned int *cfg){ int port; unsigned int t_up; unsigned int t_fdx; ag7100_phy_speed_t t_speed; unsigned int t_cfg; unsigned int t_chg; /* The VSC73XX uses a fixed numbering scheme to get to ports - rather than using PHY Address. * * unit 0 == mac 0 * unit 1 == mac 1 * unit 2-6 == ports 0-4 */ switch (unit) { case 1: port=VSC73XX_PORT_MAC; break; case 2: port=VSC73XX_PORT_0; break; case 3: port=VSC73XX_PORT_1; break; case 4: port=VSC73XX_PORT_2; break; case 5: port=VSC73XX_PORT_3; break; case 6: port=VSC73XX_PORT_4; break; default: printk(MODULE_NAME": bad unit number %d\n", unit); return -1; } #ifdef CONFIG_AR9100 vsc73xx_wr(7,0,0x5,0x33);#endif t_chg = vsc73xx_get_link_status_raw(port, &t_up, &t_fdx, &t_speed, &t_cfg); if (t_chg == ~0) return -2; if (up) *up = t_up; if (fdx) *fdx = t_fdx; if (speed) *speed = t_speed; if (cfg) *cfg = t_cfg;#ifdef VSC73XX_DEBUG printk("\t==== vsc(%d) up:%d fdx:%d speed:%d cfg=0x%08x\n", unit, t_up, t_fdx, t_speed, t_cfg);#endif return 0;}#ifdef VSC73XX_DEBUGvoidvsc73xx_get_link_status_dbg(void){ printk("\n"); vsc73xx_get_link_status(1, 0, 0, 0, 0); vsc73xx_get_link_status(2, 0, 0, 0, 0); vsc73xx_get_link_status(3, 0, 0, 0, 0); vsc73xx_get_link_status(4, 0, 0, 0, 0); vsc73xx_get_link_status(5, 0, 0, 0, 0); vsc73xx_get_link_status(6, 0, 0, 0, 0);}#endif /* VSC73XX_DEBUG */intvsc73xx_phy_print_link_status(int unit){ int port; unsigned int t_up; unsigned int t_fdx; ag7100_phy_speed_t t_speed; unsigned int t_cfg; unsigned int t_chg; /* The VSC73XX uses a fixed numbering scheme to get to ports - rather than using PHY Address. * * unit 0 == mac 0 * unit 1 == mac 1 * unit 2-6 == ports 0-4 */ switch (unit) { case 1: port=VSC73XX_PORT_MAC; break; case 2: port=VSC73XX_PORT_0; break; case 3: port=VSC73XX_PORT_1; break; case 4: port=VSC73XX_PORT_2; break; case 5: port=VSC73XX_PORT_3; break; case 6: port=VSC73XX_PORT_4; break; default: printk(MODULE_NAME": bad unit number %d\n", unit); return -1; } t_chg = vsc73xx_get_link_status_raw(port, &t_up, &t_fdx, &t_speed, &t_cfg); if (t_chg == ~0) return -2; vsc73xx_print_link_status_from_value(port, t_up, t_fdx, t_speed, t_cfg); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -