📄 swport.c
字号:
/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
* This software is copyrighted by and is the sole property of
* VIA Networking Technologies, Inc. This software may only be used
* in accordance with the corresponding license agreement. Any unauthorized
* use, duplication, transmission, distribution, or disclosure of this
* software is expressly forbidden.
*
* This software is provided by VIA Networking Technologies, Inc. "as is"
* and any express or implied warranties, including, but not limited to, the
* implied warranties of merchantability and fitness for a particular purpose
* are disclaimed. In no event shall VIA Networking Technologies, Inc.
* be liable for any direct, indirect, incidental, special, exemplary, or
* consequential damages.
*
*
* File: swport.c
*
* Purpose: Port configuration and status hardware accessing functions
*
* Author: Tevin Chen
* Henry Lin
*
* Date: Jan 08, 2002
* Apr 26, 2005
*
* Functions:
*
* Revision History:
*
*/
#if !defined(__PLATFORM_H__)
#include "platform.h"
#endif
#if !defined(__SWCFG_H__)
#include "swcfg.h"
#endif
#if !defined(__SWITCH_H__)
#include "switch.h"
#endif
#if !defined(__SWMII_H__)
#include "swmii.h"
#endif
#if !defined(__SWMSG_H__)
#include "swmsg.h"
#endif
#if !defined(__SWPORT_H__)
#include "swport.h"
#endif
/*--------------------- Static Definitions ------------------------*/
// for N-way force only
static UINT16 sg_awSpdDpxPtn[] = {
ANAR_100TXF,
ANAR_100TXH,
ANAR_10TXF,
ANAR_10TXH,
GBTCR_1000TF,
GBTCR_1000TH,
};
// for force mode
static UINT16 sg_awFrcSpdDpxMiiVal[] = {
(BMCR_SPD1 | BMCR_SPD0 | BMCR_FDX | BMCR_AUTO), // bits
(BMCR_SPD0 | BMCR_FDX),
BMCR_SPD0,
BMCR_FDX,
0,
(BMCR_SPD1 | BMCR_FDX),
BMCR_SPD1
};
static UINT8 sg_abyFrcSpdDpxBitOn[] = {
(PORT_ABL_FULL_DPX | PORT_ABL_SPD100),
PORT_ABL_SPD100,
PORT_ABL_FULL_DPX,
0,
(PORT_ABL_FULL_DPX | PORT_ABL_SPD1000),
PORT_ABL_SPD1000
};
static UINT8 sg_abyFrcSpdDpxBitOff[] = {
PORT_ABL_SPD1000,
(PORT_ABL_FULL_DPX | PORT_ABL_SPD1000),
(PORT_ABL_SPD100 | PORT_ABL_SPD1000),
(PORT_ABL_FULL_DPX | PORT_ABL_SPD100| PORT_ABL_SPD1000),
PORT_ABL_SPD100,
(PORT_ABL_FULL_DPX | PORT_ABL_SPD100)
};
/*--------------------- Static Types ------------------------------*/
/*--------------------- Static Macros -----------------------------*/
/*--------------------- Static Classes ----------------------------*/
/*--------------------- Static Variables --------------------------*/
/*--------------------- Static Functions --------------------------*/
static void s_vTBIRestartAN(UINT8 byPortId);
/*--------------------- Export Variables --------------------------*/
BOOL SWPORT_bIsTbiPort(UINT8 byPortId)
{
UINT8 u8Data;
UINT16 u16GigaStrap;
// Get port mode
if ((SWITCH_PORT_NUM > byPortId) && (byPortId >= SWITCH_MEGA_PORT_NUM)) {
//Strapping override
SWREG_vReadU8(PHYCTL_PORT24_MODE_CFG + (byPortId - SWITCH_MEGA_PORT_NUM), &u8Data);
if (u8Data & MODE_CFG_STRAP_OVERRIDE ){
//by bit[0]
if (u8Data & MODE_CFG_TBI)
return TRUE;
return FALSE;
}
else
{
//by strapping
// Get giga port strapping value
SWREG_vReadU16(INITCTL_CHIP_STRAP_CFG, &u16GigaStrap);
if (u16GigaStrap & (CHIP_CFG_GIGA0_GMII >> (byPortId - SWITCH_MEGA_PORT_NUM)) )
return FALSE; //GMII
return TRUE; //TBI
}
}
else {
// Mega ports must not be TBI mode
return FALSE;
}
}
BOOL SWPORT_bGetPortEn(UINT8 byPortId)
{
if (SWPORT_bIsTbiPort(byPortId)) {
// Get port enable
if (SWREG_bIsBitsOnU8(PHYCTL_OPER_CFG_BASE + byPortId, PORT_ABL_ENABLE) )
return TRUE;
else
return FALSE;
}
else {
return SWMII_bIsRegBitsOff(byPortId, MII_REG_BMCR, BMCR_PD);
}
}
void SWPORT_vSetPortEn(UINT8 byPortId, BOOL bPortEn)
{
if (SWPORT_bIsTbiPort(byPortId)) {
// Set port enable
if (bPortEn) {
// Enable Auto-polling
SWREG_vSpecBitOn(PHYCTL_AUTO_POLLING_EN, byPortId);
}
else {
// Disable Auto-polling
SWREG_vSpecBitOff(PHYCTL_AUTO_POLLING_EN, byPortId);
// Disable MAC I/O
SWREG_vBitsOffU8(PHYCTL_OPER_CFG_BASE + byPortId, PORT_ABL_ENABLE);
}
}
else {
// Set port enable
if (bPortEn) {
SWMII_bRegBitsOff(byPortId, MII_REG_BMCR, BMCR_PD);
}
else {
if (SWMII_bIsRegBitsOff(byPortId, MII_REG_BMCR, BMCR_PD))
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, BMCR_PD);
}
}
}
UINT8 SWPORT_byGetSpdDpx (UINT8 byPortId)
{
UINT8 byData;
SWREG_vReadU8(PHYCTL_OPER_CFG_BASE + byPortId, &byData);
if (byData & PORT_ABL_FULL_DPX) {
if (byData & PORT_ABL_SPD1000)
return PORT_SPDPX_1000M_FULL;
else if (byData & PORT_ABL_SPD100)
return PORT_SPDPX_100M_FULL;
else
return PORT_SPDPX_10M_FULL;
}
else {
if (byData & PORT_ABL_SPD1000)
return PORT_SPDPX_1000M_HALF;
else if (byData & PORT_ABL_SPD100)
return PORT_SPDPX_100M_HALF;
else
return PORT_SPDPX_10M_HALF;
}
}
UINT8 SWPORT_bySetSpdDpx(UINT8 byPortId, BOOL bAuto, UINT8 byPortAbl)
{
BOOL bIsTBIPort = SWPORT_bIsTbiPort(byPortId);
if (bAuto == 0 && byPortAbl == PORT_SPDPX_AUTO)
return PORT_OP_WRONG_AUTO_ABY;
if (bIsTBIPort) {
// In TBI mode, MAC only supports auto and force-1000F.
if (byPortAbl == PORT_SPDPX_AUTO) {
SWREG_vBitsOnU8(PHYCTL_PORT24_MODE_CFG + byPortId - SWITCH_MEGA_PORT_NUM, MODE_CFG_TBI_ABL_NWAY);
//restart AN
s_vTBIRestartAN(byPortId);
return OP_OK;
}
// If TBI force mode, it must be 1000Full
if ((bAuto == 0) && (byPortAbl != PORT_SPDPX_1000M_FULL) )
return OP_OK;
SWREG_vBitsOffU8(PHYCTL_PORT24_MODE_CFG + byPortId - SWITCH_MEGA_PORT_NUM, MODE_CFG_TBI_ABL_NWAY);
//restart AN
s_vTBIRestartAN(byPortId);
// then goto force mode to set ability
}
// set special Nway ability for via octo-phy only
else if (PHYTYPE_VIA_MEGA == SWMII_byGetPhyType(byPortId) && byPortId < SWITCH_MEGA_PORT_NUM) {
// nway-force only
if ((bAuto) && (byPortAbl != PORT_SPDPX_AUTO))
SWMII_bRegBitsOn(byPortId, MII_REG_VIA_NWAYFRC, (0x0100 << ((byPortId % 8))));
else
SWMII_bRegBitsOff(byPortId, MII_REG_VIA_NWAYFRC, (0x0100 << ((byPortId % 8))));
}
// Set port auto port ability
if (byPortAbl == PORT_SPDPX_AUTO) {
SWMII_bRegBitsOn(byPortId, MII_REG_ANAR, ANAR_ABL_MEGA);
if (byPortId >= SWITCH_GIGA_PORT_ID_BASE)
SWMII_bRegBitsOn(byPortId, MII_REG_GBTCR, GBTCR_ABL_GIGA);
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, BMCR_AUTO | BMCR_REAUTO);
}
// Set Nway forced port ability
else if (bAuto) {
SWMII_bRegBitsOff(byPortId, MII_REG_ANAR, ANAR_ABL_MEGA);
if (byPortId >= SWITCH_GIGA_PORT_ID_BASE)
SWMII_bRegBitsOff(byPortId, MII_REG_GBTCR, GBTCR_ABL_GIGA);
if ((byPortId >= SWITCH_GIGA_PORT_ID_BASE) &&
(byPortAbl == PORT_SPDPX_1000M_FULL || byPortAbl == PORT_SPDPX_1000M_HALF))
SWMII_bRegBitsOn(byPortId, MII_REG_GBTCR, sg_awSpdDpxPtn[byPortAbl - 1]);
else
SWMII_bRegBitsOn(byPortId, MII_REG_ANAR, sg_awSpdDpxPtn[byPortAbl - 1]);
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, BMCR_AUTO|BMCR_REAUTO);
}
// force mode
else {
SWREG_vBitsOnU8((PHYCTL_OPER_CFG_BASE + byPortId), sg_abyFrcSpdDpxBitOn[byPortAbl - 1]);
SWREG_vBitsOffU8((PHYCTL_OPER_CFG_BASE + byPortId), sg_abyFrcSpdDpxBitOff[byPortAbl - 1]);
if (!bIsTBIPort) {
SWMII_bRegBitsOff(byPortId, MII_REG_BMCR, sg_awFrcSpdDpxMiiVal[0]);
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, sg_awFrcSpdDpxMiiVal[byPortAbl]);
// PATCH Braodcom phy: can not use Power-Down(bit11) to let phy link down
if ((byPortId >= SWITCH_GIGA_PORT_ID_BASE) && (PHYTYPE_BROADCOM_GIGA == SWMII_byGetPhyType(byPortId)) ) {
//BCM5421 can not use Power Down(bit11) to reach link down then link up.
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, BMCR_LBK);
// delay 200ms
PLAT_vDelayLoop(200);
SWMII_bRegBitsOff(byPortId, MII_REG_BMCR, BMCR_LBK);
}
else {
// link down then link up to trigger remote port to change mode
// note: some phy may not work or phy registers will be reset.
// if port enable
if (SWMII_bIsRegBitsOff(byPortId, MII_REG_BMCR, BMCR_PD)) {
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, BMCR_PD);
// delay 200ms
PLAT_vDelayLoop(200);
SWMII_bRegBitsOff(byPortId, MII_REG_BMCR, BMCR_PD);
}
}
}
}
return OP_OK;
}
void SWPORT_vSetFlowCtrlEn(UINT8 byPortId, BOOL bFC)
{
if (bFC) {
// Set flow control ability
SWREG_vSpecBitOn(PHYCTL_FLOW_CTRL_ABL, byPortId * 2);
SWREG_vSpecBitOn(PHYCTL_FLOW_CTRL_ABL, byPortId * 2 + 1);
// Set back pressure ability
SWREG_vSpecBitOn(PHYCTL_BACK_PRESSURE_EN, byPortId);
}
else {
// Set flow control ability
SWREG_vSpecBitOff(PHYCTL_FLOW_CTRL_ABL, byPortId * 2);
SWREG_vSpecBitOff(PHYCTL_FLOW_CTRL_ABL, byPortId * 2 + 1);
// Set back pressure ability
SWREG_vSpecBitOff(PHYCTL_BACK_PRESSURE_EN, byPortId);
}
// check if NWay ability is on
// If TBI mode port
if (SWPORT_bIsTbiPort(byPortId)) {
// if auto mode
if (SWREG_bIsBitsOnU8(PHYCTL_PORT24_MODE_CFG + byPortId - SWITCH_MEGA_PORT_NUM, MODE_CFG_TBI_ABL_NWAY)) {
//restart AN
s_vTBIRestartAN(byPortId);
}
return;
}
// If Auto/Nway-force mode
if (SWMII_bIsRegBitsOn(byPortId, MII_REG_BMCR, BMCR_AUTO))
SWMII_bRegBitsOn(byPortId, MII_REG_BMCR, BMCR_REAUTO);
}
static void s_vTBIRestartAN(UINT8 byPortId)
{
SWREG_vBitsOnU8(PHYCTL_PORT24_MODE_CFG + byPortId - SWITCH_MEGA_PORT_NUM, MODE_CFG_TBI_LNK_DOWN);
SWREG_vBitsOffU8(PHYCTL_PORT24_MODE_CFG + byPortId - SWITCH_MEGA_PORT_NUM, MODE_CFG_TBI_LNK_DOWN);
}
BOOL SWPORT_bGetLinkSts(UINT8 byPortId)
{
UINT32 u32LnkChgSts = 0, u32Msk = 0x01;
SWREG_vReadU32(PHYCTL_LINK_STATUS, &u32LnkChgSts);
if (u32LnkChgSts & (u32Msk << byPortId) )
return TRUE;
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -