📄 vsc8601_phy.c
字号:
/* vsc8601_phy.c * * History: * Jan 14, 2007 wclewis ready common BDI/ECOS/Linux * May 24, 2007 Tag before BSP resturcture * * * 1) Routine uses MII interface to query the specified device. * * 2) If the device is a VSC8201 or VSC8601 routine initializes * device using Vitesse specific routines. * * 3) If device is a IEEE complient device the device is * initialized in a generic fashion. * * 4) During query the PHY address is captured and used to * initialize the phy table. This has been tested for * the VSC8201, VSC8601 and ICPLUS. */#ifdef __BDI#include "bdi.h"#else#ifdef __ECOS#if defined(CYGNUM_USE_ENET_VERBOSE)# undef VERBOSE# define VERBOSE CYGNUM_USE_ENET_VERBOSE#else# define VERBOSE 0#endif #define printk DEBUG_PRINTF#define udelay A_UDELAY#else#include <linux/kernel.h>#include <asm/delay.h>#include "ar7100.h"#endif#endif#ifndef VERBOSE#define VERBOSE 0#endif#include "vsc8601_phy.h"#define MODULE_NAME "VSC8601"typedef struct { uint16_t is_enet_port; uint16_t mac_unit; uint16_t phy_addr; uint32_t id; uint16_t status;}vsc8601_phy_t;static uint16_t nmbr_phys = 0;static vsc8601_phy_t phy_info[] = { { is_enet_port: 0, mac_unit : 0, phy_addr : 0 }, { is_enet_port: 0, mac_unit : 0, phy_addr : 0 }, { is_enet_port: 0, mac_unit : 0, phy_addr : 0 }, { is_enet_port: 0, mac_unit : 0, phy_addr : 0 }, { is_enet_port: 0, mac_unit : 0, phy_addr : 0 }, { is_enet_port: 0, mac_unit : 0, phy_addr : 0 }};static vsc8601_phy_t *vsc8601_phy_find(int unit){ int i; vsc8601_phy_t *phy; for(i = 0; i < sizeof(phy_info)/sizeof(phy_info[0]); i++) { phy = &phy_info[i]; if (phy->is_enet_port && (phy->mac_unit == unit)) return phy; } printk(MODULE_NAME": did not find unit %d\n", unit); return NULL;}/* Base read/write routines built on ag7100_mii_ macros */static inline voidvsc8601_phy_mii_write_main(int unit, uint32_t phy_addr, uint8_t reg, uint16_t data){ ag7100_mii_write(unit, phy_addr, 31, 0); ag7100_mii_write(unit, phy_addr, reg, data);}static inline void vsc8601_phy_mii_write_ex(int unit, uint32_t phy_addr, uint8_t reg, uint16_t data){ ag7100_mii_write(unit, phy_addr, 31, 1); ag7100_mii_write(unit, phy_addr, reg, data);}static inline uint16_t vsc8601_phy_mii_read_main(int unit, uint32_t phy_addr, uint8_t reg){ ag7100_mii_write(unit, phy_addr, 31, 0); return ag7100_mii_read(unit, phy_addr, reg);}static inline uint16_t vsc8601_phy_mii_read_ex(int unit, uint32_t phy_addr, uint8_t reg){ uint16_t val; ag7100_mii_write(unit, phy_addr, 31, 1); val = ag7100_mii_read(unit, phy_addr, reg); ag7100_mii_write(unit, phy_addr, 31, 0); return val;}/* Super simple routine to make it easier to print bits */static voidvsc8601_phy_print_val_bit_desc (uint16_t val, char *fieldName, char *bit_descriptions[]) { int ii; char *p2; printk(MODULE_NAME": %s=%04x ", fieldName, val); for (ii=0;ii<16; ii++) { p2 = val & 1<<(15-ii) ? bit_descriptions[ii*2] : bit_descriptions[ii*2+1]; if (p2 && p2[0]) printk(MODULE_NAME": %s\n", p2); }}/* **************************************************************************** * * For each register of interest: * 1) register read * 2) register print if there are alot of fields or bits * 3) register write if there may be a need to write * 4) masked write if there is a write and there are bits. * * **************************************************************************** *//* mode control */CEXTERN uint16_t vsc8601_phy_mii_read_mode_ctrl(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 0);}static char *mode_ctrl_desc[16*2] = { "sreset","", /* 15 */ "loopback", "", /* 14 */ "f100","", /* 13 */ "auto-eg","", /* 12 */ "pwr-dwn","", /* 11 */ "isolate","", /* 10 */ "restar-auto-neg","", /* 9 */ "full-duplex","half-duplex", /* 8 */ "ctest","", /* 7 */ "f1000","", /* 6 */ "","", /* 5 */ "","", /* 4 */ "","", /* 3 */ "","", /* 2 */ "","", /* 1 */ "","", /* 0 */};CEXTERN void vsc8601_phy_mii_print_mode_ctrl(uint16_t val){ vsc8601_phy_print_val_bit_desc (val, "mode_ctr (00 )", mode_ctrl_desc);}CEXTERN void vsc8601_phy_mii_write_mode_ctrl(int unit, uint32_t phy_addr, uint16_t reg ){ vsc8601_phy_mii_write_main(unit, phy_addr, 0, reg);}CEXTERN void vsc8601_phy_mii_rmw_ctrl(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_mii_read_mode_ctrl(unit, phy_addr); reg &= ~mask; reg |= val; vsc8601_phy_mii_write_mode_ctrl(unit, phy_addr, reg);}/* mode status */CEXTERN uint16_t vsc8601_phy_mii_read_mode_status(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 1);}static char *mode_status_desc[16*2] = { "","", /* 15 */ "","", /* 14 */ "","", /* 13 */ "","", /* 12 */ "","", /* 11 */ "","", /* 10 */ "","", /* 9 */ "","", /* 8 */ "","", /* 7 */ "","", /* 6 */ "auto-neg-cmplt","", /* 5 */ "rem-fault","", /* 4 */ "auto-neg-cap","", /* 3 */ "link-up","", /* 2 */ "jabber","", /* 1 */ "ex-cap","", /* 0 */};CEXTERN void vsc8601_phy_mii_print_mode_status(uint16_t val){ vsc8601_phy_print_val_bit_desc (val, "mode_status (01 )", mode_status_desc);}/* phy identification */CEXTERN uint16_t vsc8601_phy_mii_read_id1(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 2);}CEXTERN uint16_t vsc8601_phy_mii_read_id2(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 3);}/* gige control R/W */CEXTERN uint16_t vsc8601_phy_mii_read_gige_ctrl(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 9);}static char *gige_ctrl_desc[16*2] = { "distortion-test","", /* 15 */ "jitter-test","", /* 14 */ "waveform-test","", /* 13 */ "man-cfg","", /* 12 */ "master","", /* 11 */ "","", /* 10 */ "","", /* 9 */ "","", /* 8 */ "","", /* 7 */ "","", /* 6 */ "","", /* 5 */ "","", /* 4 */ "","", /* 3 */ "","", /* 2 */ "","", /* 1 */ "","", /* 0 */};CEXTERN void vsc8601_phy_mii_print_gige_ctrl(uint16_t val){ vsc8601_phy_print_val_bit_desc (val, "gige_ctrl (09 )", gige_ctrl_desc);}CEXTERN void vsc8601_phy_mii_write_gige_ctrl(int unit, uint32_t phy_addr, uint16_t reg){ return vsc8601_phy_mii_write_main(unit, phy_addr, 9, reg);}CEXTERN void vsc8601_phy_rmw_gige_ctrl(int unit, uint32_t phy_addr, uint32_t mask, uint32_t val){ uint16_t reg = vsc8601_phy_mii_read_gige_ctrl(unit, phy_addr); if (reg == 0xffff) return; reg &= ~mask; reg |= val; vsc8601_phy_mii_write_gige_ctrl(unit, phy_addr, reg);}/* gige status RO */CEXTERN uint16_t vsc8601_phy_read_gige_status(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 10);}static char *gige_status_desc[16*2] = { "ms-fault","", /* 15 */ "is-master","", /* 14 */ "loc-rcv-ok","", /* 13 */ "rem-rcv-ok","", /* 12 */ "fdx-cap","", /* 11 */ "hdx-cap","", /* 10 */ "","", /* 9 */ "","", /* 8 */ "","", /* 7 */ "","", /* 6 */ "","", /* 5 */ "","", /* 4 */ "","", /* 3 */ "","", /* 2 */ "","", /* 1 */ "","", /* 0 */};CEXTERN void vsc8601_phy_mii_print_gige_status(uint16_t val){ vsc8601_phy_print_val_bit_desc (val, " gige_status (10 )", gige_status_desc); printk(MODULE_NAME": idle-err-cnt: %02x\n", val&0xff);}/* gige status extension 1 todo *//* 100 base_t status extension RO */CEXTERN uint16_t vsc8601_phy_read_100_status_ex(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 16);}static char *l00_status_ex_desc[16*2] = { "descram-lock","", /* 15 */ "descram-err","", /* 14 */ "disc","", /* 13 */ "link-act","", /* 12 */ "rcv-err","", /* 11 */ "xmt-err","", /* 10 */ "sos-err","", /* 9 */ "","", /* 8 */ "","", /* 7 */ "","", /* 6 */ "","", /* 5 */ "","", /* 4 */ "","", /* 3 */ "","", /* 2 */ "","", /* 1 */ "","", /* 0 */};CEXTERN void vsc8601_phy_mii_print_100_status_ex(uint16_t val){ vsc8601_phy_print_val_bit_desc (val, "100_status_ex (16 )", l00_status_ex_desc);}/* gige status extention 2 RO */CEXTERN uint16_t vsc8601_phy_read_gige_status_ex_2(int unit, uint32_t phy_addr){ return vsc8601_phy_mii_read_main(unit, phy_addr, 17);}static char *gige_status_ex_2_desc[16*2] = { "descram-lock","", /* 15 */ "descram-err","", /* 14 */ "disc","", /* 13 */ "link-up","", /* 12 */ "rcv-err","", /* 11 */ "xmt-err","", /* 10 */ "ssd-err","", /* 9 */ "esd-err","", /* 8 */ "ce-err","", /* 7 */ "bcm-det","", /* 6 */ "mdi-x-err","", /* 5 */ "","", /* 4 */ "","", /* 3 */ "","", /* 2 */ "","", /* 1 */ "","", /* 0 */};CEXTERN void vsc8601_phy_mii_print_gige_status_ex_2(uint16_t val)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -