📄 phydrv.c
字号:
phy_write(port_no, 23, VTSS_REG_23);
assert_reset(port_no);
init_seq_8224(port_no);
phy_receiver_init(port_no);
break;
#endif
#if VTSS_8204
case PHY_FAMILY_VTSS_8204:
phy_write(port_no, 23, VTSS_REG_23);
break;
#endif
#if VTSS_8201
case PHY_FAMILY_VTSS_8201:
break;
#endif
}
}
#if SFP_NUM
/* ************************************************************************ */
static void phy_sfp_init (uchar port_no)
/* ------------------------------------------------------------------------ --
* Purpose :
* Remarks :
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
ushort reg_val;
uchar sfp_no;
ushort mask;
uchar present;
for (sfp_no = 0; sfp_no < sizeof(sfp_ports); sfp_no++) {
if (sfp_ports[sfp_no] == port_no) {
break;
}
}
/* read GPIO inputs with sfp module detect signals */
phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0010);
reg_val = phy_read(SFP_MODULE_DETECT_GPIO_PORT, 15);
phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0000);
/* enable fiber if sfp module detected */
present = ((reg_val & bit_mask_16(sfp_module_detect_gpios[sfp_no])) == 0);
if (present) {
sfp_module_detect_status |= (1 << sfp_no);
if ((h2_read(SYSTEM, 0, SYS_CHIPID) & 0xF0000000) > 0x10000000) {
phy_write(port_no, 23, 0x0604);
}
else {
phy_write(port_no, 23, 0x0204); /* fiber only */
}
assert_reset(port_no);
}
else {
sfp_module_detect_status &= ~(1 << sfp_no);
phy_write(port_no, 23, 0x0004);
assert_reset(port_no);
}
/* set/reset TX disable signal */
mask = bit_mask_16(sfp_tx_disable_gpios[sfp_no]);
phy_write(SFP_TX_DISABLE_GPIO_PORT, 31, 0x0010);
phy_write_masked(SFP_TX_DISABLE_GPIO_PORT, 0x11, mask, mask); /* Enable GPIO as output */
if (present) {
phy_write_masked(SFP_TX_DISABLE_GPIO_PORT, 0x10, 0, mask); /* reset GPIO */
}
else {
phy_write_masked(SFP_TX_DISABLE_GPIO_PORT, 0x10, mask, mask); /* set GPIO */
}
phy_write(SFP_TX_DISABLE_GPIO_PORT, 31, 0x0000);
}
void phy_poll_sfp (void)
{
ushort reg_val;
uchar sfp_present_new;
uchar port_no;
uchar sfp_no;
/* read GPIO inputs with sfp module detect signals */
phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0010);
reg_val = phy_read(SFP_MODULE_DETECT_GPIO_PORT, 15);
phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0000);
sfp_present_new = 0;
for (sfp_no = 0; sfp_no < SFP_NUM; sfp_no++) {
if ((reg_val & bit_mask_16(sfp_module_detect_gpios[sfp_no])) == 0) {
sfp_present_new |= (1 << sfp_no);
}
}
if (sfp_present_new != sfp_module_detect_status) {
for (sfp_no = 0; sfp_no < SFP_NUM; sfp_no++) {
if ((sfp_present_new & (1 << sfp_no)) != (sfp_module_detect_status & (1 << sfp_no))) {
port_no = sfp_ports[sfp_no];
assert_reset(port_no);
phy_post_reset(port_no);
}
}
}
}
uchar phy_sfp_present (uchar port_no)
{
uchar sfp_no;
for (sfp_no = 0; sfp_no < sizeof(sfp_ports); sfp_no++) {
if (sfp_ports[sfp_no] == port_no) {
if (sfp_module_detect_status & (1 << sfp_no)) {
return TRUE;
}
break;
}
}
return FALSE;
}
#endif
/* ************************************************************************ */
ushort phy_read (uchar port_no, uchar reg_no) small
/* ------------------------------------------------------------------------ --
* Purpose : Read a PHY register.
* Remarks : port_no: The port number to which the PHY is attached.
* reg_no: the PHY register number (0-31).
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
ulong dat;
uchar miim_no;
uchar phy_no;
miim_no = phy_map_miim_no(port_no);
phy_no = phy_map_phy_no(port_no);
h2_write(MIIM, miim_no, MIIMCMD, ushorts2ulong(0, ((ushort) phy_no << 5) | MIIM_CMD_READ | reg_no));
phy_await_completed(miim_no);
dat = h2_read(MIIM, miim_no, MIIMDATA);
if (!(dat & MIIM_DATA_FAILURE_MASK)) {
return (ushort) dat;
}
else {
return 0;
}
}
/* ************************************************************************ */
void phy_write (uchar port_no, uchar reg_no, ushort value) small
/* ------------------------------------------------------------------------ --
* Purpose : Write to a PHY register.
* Remarks : port_no: The port number to which the PHY is attached.
* reg_no: the PHY register number (0-31).
* value: value to be written.
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
uchar miim_no;
uchar phy_no;
miim_no = phy_map_miim_no(port_no);
phy_no = phy_map_phy_no(port_no);
h2_write(MIIM, miim_no, MIIMCMD, build_phy_write_cmd(value, reg_no, phy_no));
phy_await_completed(miim_no);
}
/* ************************************************************************ */
void phy_write_masked (uchar port_no, uchar reg_no, ushort value, ushort mask) small
/* ------------------------------------------------------------------------ --
* Purpose : Update specified bit(s) of a PHY register.
* Remarks : port_no: The port number to which the PHY is attached.
* reg_no: the PHY register number (0-31).
* value: Holds bits (in right positions) to be written.
* mask: Bit mask specifying the bits to be updated.
* Restrictions:
* See also :
* Example : To set AN_EN and Restart_AN bits in register 0, write:
* phy_write_masked(miim_no, phy_no, 0, 0x1200, 0x1200);
* ************************************************************************ */
{
value |= (phy_read(port_no, reg_no) & ~mask);
phy_write(port_no, reg_no, value);
}
/* ************************************************************************ */
void phy_read_id (uchar port_no, phy_id_t *phy_id_p)
/* ------------------------------------------------------------------------ --
* Purpose : Read PHY id from register 2 and 3 and generate software ids.
* Remarks : port_no: The port number to which the PHY is attached.
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
ul_union_t phy_id_raw;
phy_id_raw.w[0] = phy_read(port_no, 2);
phy_id_raw.w[1] = phy_read(port_no, 3);
/* Generate vendor identification */
if (((phy_id_raw.l & 0xfffffc00) == PHY_OUI_VTSS_1) ||
((phy_id_raw.l & 0xfffffc00) == PHY_OUI_VTSS_2)) {
phy_id_p->vendor = PHY_VENDOR_VTSS;
}
else {
phy_id_p->vendor = PHY_VENDOR_UNKNOWN;
}
/* Retrieve revision number */
phy_id_p->revision = phy_id_raw.w[1] & 0x000f;
/* Generate family and model identifications */
switch (phy_id_raw.l & 0xfffffff0) { /* mask out revision */
#if VTSS_8201
case PHY_ID_VTSS_8201:
phy_id_p->family = PHY_FAMILY_VTSS_8201;
phy_id_p->model = PHY_MODEL_VTSS_8201;
break;
#endif
#if VTSS_8204
case PHY_ID_VTSS_8204:
phy_id_p->family = PHY_FAMILY_VTSS_8204;
phy_id_p->model = PHY_MODEL_VTSS_8204;
break;
#endif
#if VTSS_8224
case PHY_ID_VTSS_8224:
phy_id_p->family = PHY_FAMILY_VTSS_8224;
phy_id_p->model = PHY_MODEL_VTSS_8224;
break;
case PHY_ID_VTSS_8234:
phy_id_p->family = PHY_FAMILY_VTSS_8224;
phy_id_p->model = PHY_MODEL_VTSS_8234;
break;
case PHY_ID_VTSS_8244:
phy_id_p->family = PHY_FAMILY_VTSS_8224;
phy_id_p->model = PHY_MODEL_VTSS_8244;
break;
#endif
case PHY_ID_VTSS_7390:
phy_id_p->family = PHY_FAMILY_VTSS_7390;
phy_id_p->model = PHY_MODEL_VTSS_7390;
break;
case PHY_ID_VTSS_7389:
phy_id_p->family = PHY_FAMILY_VTSS_7390;
phy_id_p->model = PHY_MODEL_VTSS_7389;
break;
case PHY_ID_VTSS_7391:
phy_id_p->family = PHY_FAMILY_VTSS_7390;
phy_id_p->model = PHY_MODEL_VTSS_7391;
break;
#if VTSS_8538
case PHY_ID_VTSS_8538_A:
case PHY_ID_VTSS_8538:
phy_id_p->family = PHY_FAMILY_VTSS_8538;
phy_id_p->model = PHY_MODEL_VTSS_8538;
break;
case PHY_ID_VTSS_8558_A:
case PHY_ID_VTSS_8558:
phy_id_p->family = PHY_FAMILY_VTSS_8538;
phy_id_p->model = PHY_MODEL_VTSS_8558;
break;
#endif
default:
phy_id_p->family = PHY_FAMILY_UNKNOWN;
phy_id_p->model = PHY_MODEL_UNKNOWN;
break;
}
}
/* ************************************************************************ */
void phy_restart_aneg (uchar port_no)
/* ------------------------------------------------------------------------ --
* Purpose : Restart auto-negotiation on the PHY connected to the
* specified port.
* Remarks :
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
/* start autonegotiation by writing to register 0 */
phy_write_masked(port_no, 0, 0x1200, 0x1200);
}
#if LOOPBACK_TEST
/* ************************************************************************ */
void phy_set_forced_speed (uchar port_no, uchar link_mode)
/* ------------------------------------------------------------------------ --
* Purpose : Set forced speed.
* Remarks : link_mode specifies speed. See bit-map of link_mode in main.h.
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
ushort val;
if (link_mode & LINK_MODE_INT_LOOPBACK) {
phy_suspend_10_100_fix(port_no);
}
/* temporary */
phy_write(port_no, 0, 0);
/* temporary ends */
if ((link_mode & LINK_MODE_SPEED_MASK) == LINK_MODE_SPEED_10) {
val = 0x0000;
}
else if ((link_mode & LINK_MODE_SPEED_MASK) == LINK_MODE_SPEED_100) {
val = 0x2000;
}
else if ((link_mode & LINK_MODE_SPEED_MASK) == LINK_MODE_SPEED_1000) {
val = 0x0040;
}
if (link_mode & LINK_MODE_FDX_MASK) {
val |= 0x100;
}
if (link_mode & LINK_MODE_INT_LOOPBACK) {
val |= 0x4000;
}
phy_write(port_no, 0, val);
}
#endif
/* ************************************************************************ */
bool phy_link_status (uchar port_no) small
/* ------------------------------------------------------------------------ --
* Purpose : Read link status bit from PHY.
* Remarks :
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
return ((phy_read(port_no, 1) & 0x0004) != 0);
}
#define __PHY_RESET__
#if LOOPBACK_TEST
#define __PHY_RESET__
#endif
#ifdef __PHY_RESET__
/* ************************************************************************ */
void phy_reset (uchar port_no)
/* ------------------------------------------------------------------------ --
* Purpose : Perform a reset of the PHY attached to the specified port.
* Remarks :
* Restrictions:
* See also :
* Example :
* ************************************************************************ */
{
assert_reset(port_no);
phy_post_reset(port_no);
}
#endif
/* ************************************************************************ */
void phy_do_link_up_settings (uchar port_no, uchar link_mode)
/* ------------------------------------------------------------------------ --
* Purpose : Do any PHY settings after link transition to up.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -