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 + -
显示快捷键?