Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
53
sdk/lib/net/ethphy/eth_mdio_bus.c
Normal file
53
sdk/lib/net/ethphy/eth_mdio_bus.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "errno.h"
|
||||
#include "dev.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/task.h"
|
||||
#include "hal/netdev.h"
|
||||
#include "lib/net/ethphy/eth_phy.h"
|
||||
#include "lib/net/ethphy/eth_mdio_bus.h"
|
||||
|
||||
__init int32 eth_mdio_bus_attach(uint32 dev_id, struct ethernet_mdio_bus *p_mdio_bus)
|
||||
{
|
||||
dev_register(dev_id, (struct dev_obj *)p_mdio_bus);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 eth_mdio_bus_open(struct ethernet_mdio_bus *p_mdio_bus, struct netdev *p_netdev)
|
||||
{
|
||||
struct netdev_hal_ops *ndev_ops = (struct netdev_hal_ops *)p_netdev->dev.ops;
|
||||
if(!(p_netdev && ndev_ops->mdio_read && ndev_ops->mdio_write && p_mdio_bus)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
p_mdio_bus->priv = p_netdev;
|
||||
p_mdio_bus->read = (int (*)(void *, uint16, uint16))ndev_ops->mdio_read;
|
||||
p_mdio_bus->write = (int (*)(void *, uint16, uint16, uint16))ndev_ops->mdio_write;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 eth_mdio_bus_close(struct ethernet_mdio_bus *p_mdio_bus)
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 eth_mdio_bus_write(struct ethernet_mdio_bus *p_mdio_bus, uint16 phy_addr, uint16 reg_addr, uint16 data)
|
||||
{
|
||||
if(p_mdio_bus && p_mdio_bus->write) {
|
||||
return p_mdio_bus->write(p_mdio_bus->priv, phy_addr, reg_addr, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 eth_mdio_bus_read(struct ethernet_mdio_bus *p_mdio_bus, uint16 phy_addr, uint16 reg_addr)
|
||||
{
|
||||
if(p_mdio_bus && p_mdio_bus->read) {
|
||||
return p_mdio_bus->read(p_mdio_bus->priv, phy_addr, reg_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
443
sdk/lib/net/ethphy/eth_phy.c
Normal file
443
sdk/lib/net/ethphy/eth_phy.c
Normal file
@@ -0,0 +1,443 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file sdk/lib/ethernet_phy/eth_phy.c
|
||||
* @author HUGE-IC Application Team
|
||||
* @version V1.0.0
|
||||
* @date 10-10-2018
|
||||
* @brief Framework for configuring and reading PHY devices
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2018 HUGE-IC</center></h2>
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "typesdef.h"
|
||||
#include "errno.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "osal/timer.h"
|
||||
#include "hal/netdev.h"
|
||||
|
||||
#include "lib/common/sysevt.h"
|
||||
#include "lib/net/ethphy/eth_phy.h"
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
#define MAX_NUM_SETTINGS ARRAY_SIZE(settings)
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief A structure for mapping a particular speed and duplex combination
|
||||
* to a particular SUPPORTED and ADVERTISED value
|
||||
*/
|
||||
struct __phy_setting {
|
||||
int16 speed;
|
||||
int16 duplex;
|
||||
uint32 setting;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A mapping of all SUPPORTED settings to speed/duplex
|
||||
*/
|
||||
static const struct __phy_setting settings[] = {
|
||||
{
|
||||
.speed = SPEED_1000,
|
||||
.duplex = DUPLEX_FULL,
|
||||
.setting = SUPPORTED_1000baseT_Full,
|
||||
},
|
||||
{
|
||||
.speed = SPEED_1000,
|
||||
.duplex = DUPLEX_HALF,
|
||||
.setting = SUPPORTED_1000baseT_Half,
|
||||
},
|
||||
{
|
||||
.speed = SPEED_100,
|
||||
.duplex = DUPLEX_FULL,
|
||||
.setting = SUPPORTED_100baseT_Full,
|
||||
},
|
||||
{
|
||||
.speed = SPEED_100,
|
||||
.duplex = DUPLEX_HALF,
|
||||
.setting = SUPPORTED_100baseT_Half,
|
||||
},
|
||||
{
|
||||
.speed = SPEED_10,
|
||||
.duplex = DUPLEX_FULL,
|
||||
.setting = SUPPORTED_10baseT_Full,
|
||||
},
|
||||
{
|
||||
.speed = SPEED_10,
|
||||
.duplex = DUPLEX_HALF,
|
||||
.setting = SUPPORTED_10baseT_Half,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
struct _eth_phy_wkq {
|
||||
struct os_work os_work_phy;
|
||||
struct ethernet_phy_device *eth_phy_dev;
|
||||
};
|
||||
|
||||
static struct _eth_phy_wkq eth_phy_wkq;
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup NETWORK
|
||||
* @{
|
||||
*/
|
||||
|
||||
static void eth_phy_event(struct ethernet_phy_device *phydev, uint32 event, uint32 param1, uint32 param2)
|
||||
{
|
||||
const struct netdev_hal_ops *ops = (const struct netdev_hal_ops *)phydev->ndev->dev.ops;
|
||||
if (ops->phy_event) {
|
||||
ops->phy_event(phydev, event, param1, param2);
|
||||
}
|
||||
}
|
||||
|
||||
/** @defgroup NETWORK_PHY PHY Framework
|
||||
* @brief Framework for finding and configuring PHYs.
|
||||
* Also contains generic PHY driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return auto-negotiation status
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval auto-negotiation status
|
||||
* @note Reads the status register and returns 0 either if
|
||||
* auto-negotiation is incomplete, or if there was an error.
|
||||
* Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
|
||||
*/
|
||||
static inline int eth_phy_aneg_done(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = phy_read(phydev, MII_BMSR);
|
||||
|
||||
return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief find a PHY settings array entry that matches speed & duplex
|
||||
* @param advertising :
|
||||
* @retval the index of that setting
|
||||
* @note Searches the settings array for the setting which matches the
|
||||
* desired speed and duplex, and returns the index of that setting.
|
||||
* Returns the index of the last setting if none of the others
|
||||
* match.
|
||||
*/
|
||||
static inline int eth_phy_find_setting(uint32 advertising)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
while (idx < ARRAY_SIZE(settings) && (!(advertising & settings[idx].setting))) {
|
||||
idx++;
|
||||
}
|
||||
return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief find a PHY setting that matches the requested features mask
|
||||
* @param idx : The first index in settings[] to search
|
||||
* @retval the index of the first valid setting
|
||||
* @note Returns the index of the first valid setting less than or equal
|
||||
* to the one pointed to by idx, as determined by the mask in
|
||||
* features. Returns the index of the last setting if nothing else
|
||||
* matches.
|
||||
*/
|
||||
static inline int eth_phy_find_valid(int idx, uint32 features)
|
||||
{
|
||||
while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features)) {
|
||||
idx++;
|
||||
}
|
||||
|
||||
return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief make sure the PHY is set to supported speed and duplex
|
||||
* @param phydev : the target phy_device struct
|
||||
* @retval None
|
||||
* @note Make sure the PHY is set to supported speeds and duplexes. Drop
|
||||
* down by one in this order:
|
||||
* 1000/FULL, 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF.
|
||||
*/
|
||||
static void eth_phy_sanitize_settings(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
uint32 features = phydev->supported;
|
||||
int idx;
|
||||
|
||||
/* Sanitize settings based on PHY capabilities */
|
||||
if ((features & SUPPORTED_Autoneg) == 0) {
|
||||
phydev->autoneg = AUTONEG_DISABLE;
|
||||
}
|
||||
idx = eth_phy_find_valid(eth_phy_find_setting(phydev->advertising), features);
|
||||
|
||||
phydev->speed = settings[idx].speed;
|
||||
phydev->duplex = settings[idx].duplex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief start auto-negotiation for this PHY device
|
||||
* @param phydev : the phy_device struct
|
||||
* @retval Returning 0 means that the PHY does not support
|
||||
* auto-negotiation.
|
||||
* @note Sanitizes the settings (if we're not autonegotiating them), and
|
||||
* then calls the driver's config_aneg function. If the PHYCONTROL
|
||||
* Layer is operating, we change the state to reflect the beginning
|
||||
* of Auto-negotiation or forcing.
|
||||
*/
|
||||
uint8 eth_phy_start_aneg(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (AUTONEG_DISABLE == phydev->autoneg) {
|
||||
eth_phy_sanitize_settings(phydev);
|
||||
}
|
||||
|
||||
err = phydev->drv->config_aneg(phydev);
|
||||
if (err < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (phydev->state != ETH_PHY_HALTED) {
|
||||
if (AUTONEG_ENABLE == phydev->autoneg) {
|
||||
phydev->state = ETH_PHY_AN;
|
||||
} else {
|
||||
phydev->state = ETH_PHY_FORCING;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief start PHY state machine tracking
|
||||
* @param phydev : the phy_device struct
|
||||
* @param handler : callback function for state change notifications
|
||||
* @retval None
|
||||
* @note The PHY infrastructure can run a state machine which tracks
|
||||
* whether the PHY is starting up, negotiating, etc. This function
|
||||
* starts the timer which tracks the state of the PHY. If you want
|
||||
* to be notified when the state changes, pass in the callback
|
||||
* @handler, otherwise, pass NULL. If you want to maintain your own
|
||||
* state machine, do not call this function.
|
||||
*/
|
||||
void eth_phy_start_machine(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
//phydev->adjust_state = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the state machine
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval None
|
||||
*/
|
||||
void eth_phy_state_machine(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int needs_aneg = 0;
|
||||
int err = 0;
|
||||
int16 link = phydev->link;
|
||||
int16 speed = phydev->speed;
|
||||
int16 duplex = phydev->duplex;
|
||||
|
||||
//if(phydev->adjust_state) {
|
||||
// phydev->adjust_state(phydev);
|
||||
//}
|
||||
switch (phydev->state) {
|
||||
case ETH_PHY_DOWN:
|
||||
case ETH_PHY_STARTING:
|
||||
case ETH_PHY_READY:
|
||||
case ETH_PHY_PENDING:
|
||||
break;
|
||||
|
||||
case ETH_PHY_UP:
|
||||
needs_aneg = 1;
|
||||
break;
|
||||
|
||||
case ETH_PHY_AN:
|
||||
err = phydev->drv->read_status(phydev);
|
||||
|
||||
if (err < 0) {
|
||||
break;
|
||||
}
|
||||
/* If the link is down, give up on
|
||||
* negotiation for now */
|
||||
if (!phydev->link) {
|
||||
phydev->state = ETH_PHY_NOLINK;
|
||||
eth_phy_event(phydev, NETDEV_PHY_EVENT_LINK_CHANGED, phydev->link, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if negotiation is done. Break
|
||||
* if there's an error */
|
||||
err = eth_phy_aneg_done(phydev);
|
||||
if (err < 0) {
|
||||
break;
|
||||
}
|
||||
/* If AN is done, we're running */
|
||||
if (err > 0) {
|
||||
phydev->state = ETH_PHY_RUNNING;
|
||||
eth_phy_event(phydev, NETDEV_PHY_EVENT_LINK_CHANGED, phydev->link, 0);
|
||||
} else if (0 == phydev->link_timeout--) {
|
||||
needs_aneg = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ETH_PHY_NOLINK:
|
||||
err = phydev->drv->read_status(phydev);
|
||||
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
if (phydev->link) {
|
||||
phydev->state = ETH_PHY_RUNNING;
|
||||
eth_phy_event(phydev, NETDEV_PHY_EVENT_LINK_CHANGED, phydev->link, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case ETH_PHY_FORCING:
|
||||
err = genphy_update_link(phydev);
|
||||
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
if (phydev->link) {
|
||||
phydev->state = ETH_PHY_RUNNING;
|
||||
} else {
|
||||
if (0 == phydev->link_timeout--) {
|
||||
needs_aneg = 1;
|
||||
}
|
||||
}
|
||||
|
||||
eth_phy_event(phydev, NETDEV_PHY_EVENT_LINK_CHANGED, phydev->link, 0);
|
||||
break;
|
||||
|
||||
case ETH_PHY_RUNNING:
|
||||
err = phydev->drv->read_status(phydev);
|
||||
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
if (phydev->link) {
|
||||
phydev->state = ETH_PHY_RUNNING;
|
||||
} else {
|
||||
phydev->state = ETH_PHY_NOLINK;
|
||||
}
|
||||
eth_phy_event(phydev, NETDEV_PHY_EVENT_LINK_CHANGED, phydev->link, 0);
|
||||
break;
|
||||
|
||||
case ETH_PHY_HALTED:
|
||||
if (phydev->link) {
|
||||
phydev->link = 0;
|
||||
eth_phy_event(phydev, NETDEV_PHY_EVENT_LINK_CHANGED, phydev->link, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(link != phydev->link || speed != phydev->speed || duplex != phydev->duplex){
|
||||
SYSEVT_NEW_NETWORK_EVT(phydev->link ? SYSEVT_GMAC_LINK_UP : SYSEVT_GMAC_LINK_DOWN, phydev->speed);
|
||||
}
|
||||
|
||||
if (needs_aneg) {
|
||||
err = eth_phy_start_aneg(phydev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the state machine thread
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval None
|
||||
*/
|
||||
static int32 eth_phy_state_machine_thread(struct os_work *work)
|
||||
{
|
||||
|
||||
struct _eth_phy_wkq *phydev = container_of(work, struct _eth_phy_wkq, os_work_phy);
|
||||
|
||||
eth_phy_state_machine(phydev->eth_phy_dev);
|
||||
os_run_work_delay(work, 200);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32 eth_phy_open(struct ethernet_phy_device *phydev, struct ethernet_mdio_bus *mdio_bus, struct netdev *ndev)
|
||||
{
|
||||
|
||||
eth_phy_wkq.eth_phy_dev = phydev;
|
||||
|
||||
uint32 feature_supproted = phydev->drv->features;
|
||||
|
||||
if (!phydev || !mdio_bus) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
phydev->ndev = ndev;
|
||||
ASSERT(ndev);
|
||||
phydev->bus = mdio_bus;
|
||||
ASSERT(mdio_bus);
|
||||
|
||||
if (eth_get_phy_device(phydev)) {
|
||||
phydev->state = ETH_PHY_READY;
|
||||
} else {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
/* attach the mac to the phy */
|
||||
if (eth_phy_connect_direct(phydev) == RET_ERR) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
/* Only support features that we can support */
|
||||
phydev->advertising &= feature_supproted;
|
||||
if (feature_supproted & SUPPORTED_Autoneg) {
|
||||
phydev->autoneg = AUTONEG_ENABLE;
|
||||
} else {
|
||||
phydev->autoneg = AUTONEG_DISABLE;
|
||||
}
|
||||
|
||||
/* Initial invalid value */
|
||||
phydev->last_link = 0;
|
||||
phydev->last_speed = 0;
|
||||
phydev->last_duplex = -1;
|
||||
|
||||
/* start */
|
||||
phydev->state = ETH_PHY_UP;
|
||||
|
||||
|
||||
OS_WORK_INIT(ð_phy_wkq.os_work_phy, eth_phy_state_machine_thread, 0);
|
||||
os_run_work_delay(ð_phy_wkq.os_work_phy, 1);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void eth_phy_close(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
os_work_cancle(ð_phy_wkq.os_work_phy, 1);
|
||||
}
|
||||
|
||||
__init void eth_phy_attach(uint32 dev_id, struct ethernet_phy_device *phydev)
|
||||
{
|
||||
dev_register(dev_id, (struct dev_obj *)phydev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*************************** (C) COPYRIGHT 2018 HUGE-IC ***** END OF FILE *****/
|
||||
580
sdk/lib/net/ethphy/eth_phy_device.c
Normal file
580
sdk/lib/net/ethphy/eth_phy_device.c
Normal file
@@ -0,0 +1,580 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file sdk/lib/ethernet_phy/eth_phy_device.c
|
||||
* @author HUGE-IC Application Team
|
||||
* @version V1.0.0
|
||||
* @date 10-10-2018
|
||||
* @brief Framework for finding and configuring PHYs.
|
||||
* Also contains generic PHY driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2018 HUGE-IC</center></h2>
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "typesdef.h"
|
||||
#include "errno.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "hal/netdev.h"
|
||||
|
||||
#include "lib/net/ethphy/eth_mdio_bus.h"
|
||||
#include "lib/net/ethphy/eth_phy.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup NETWORK_PHY
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct ethernet_phy_driver genphy_driver = {
|
||||
.features = PHY_BASIC_FEATURES,
|
||||
.config_init = genphy_config_init,
|
||||
.config_aneg = genphy_config_aneg,
|
||||
.read_status = genphy_read_status,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Convenience function for reading a given PHY register
|
||||
* @param phydev : the phy_device struct
|
||||
* @param reg : register number to read
|
||||
* @retval Returns the data in the PHY register
|
||||
*/
|
||||
uint16 phy_read(struct ethernet_phy_device *phydev, uint16 reg) {
|
||||
return phydev->bus->read(phydev->bus->priv, phydev->addr, reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convenience function for writing a given PHY register
|
||||
* @param phydev : the phy_device struct
|
||||
* @param reg : register number to write
|
||||
* @param val : value to write to @reg
|
||||
* @retval None
|
||||
*/
|
||||
void phy_write(struct ethernet_phy_device *phydev, uint16 reg, uint16 val) {
|
||||
phydev->bus->write(phydev->bus->priv, phydev->addr, reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A small helper function that translates ethtool advertisement
|
||||
* settings to phy autonegotiation advertisements for the
|
||||
* MII_ADVERTISE register.
|
||||
* @param ethadv: the ethtool advertisement settings
|
||||
* @retval MII_ADVERTISE register value
|
||||
*/
|
||||
static inline uint32 eth_phy_adv_to_mii_adv_t(uint32 ethadv) {
|
||||
uint32 result = 0;
|
||||
|
||||
if(ethadv & ADVERTISED_10baseT_Half) {
|
||||
result |= ADVERTISE_10HALF;
|
||||
}
|
||||
if(ethadv & ADVERTISED_10baseT_Full) {
|
||||
result |= ADVERTISE_10FULL;
|
||||
}
|
||||
if(ethadv & ADVERTISED_100baseT_Half) {
|
||||
result |= ADVERTISE_100HALF;
|
||||
}
|
||||
if(ethadv & ADVERTISED_100baseT_Full) {
|
||||
result |= ADVERTISE_100FULL;
|
||||
}
|
||||
if(ethadv & ADVERTISED_Pause) {
|
||||
result |= ADVERTISE_PAUSE_CAP;
|
||||
}
|
||||
if(ethadv & ADVERTISED_Asym_Pause) {
|
||||
result |= ADVERTISE_PAUSE_ASYM;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the phy_device structure.
|
||||
* @param dev : the phy_device struct
|
||||
* @retval None
|
||||
*/
|
||||
__init void eth_phy_device_create(struct ethernet_phy_device *dev)
|
||||
{
|
||||
dev->speed = 0;
|
||||
dev->duplex = -1;
|
||||
dev->pause = dev->asym_pause = 0;
|
||||
dev->link = 1;
|
||||
|
||||
dev->autoneg = AUTONEG_ENABLE;
|
||||
dev->state = ETH_PHY_DOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reads the specified addr for its ID.
|
||||
* @param bus : the target MII bus
|
||||
* @retval Returning 0 means success and returning other values means
|
||||
* failure.
|
||||
* @note In the case of a 802.3-c22 PHY, reads the ID registers of the
|
||||
* PHY at @addr on the @bus, stores it in @phy_id and returns zero
|
||||
* on success.
|
||||
*/
|
||||
__init static int eth_get_phy_id(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int phy_reg;
|
||||
|
||||
/* Grab the bits from PHYIR1, and put them
|
||||
* in the upper half */
|
||||
phy_reg = phy_read(phydev, MII_PHYSID1);
|
||||
|
||||
if(phy_reg < 0) {
|
||||
return -1;
|
||||
}
|
||||
phydev->phy_id = (phy_reg & 0xffff) << 16;
|
||||
|
||||
/* Grab the bits from PHYIR2, and put them in the lower half */
|
||||
phy_reg = phy_read(phydev, MII_PHYSID2);
|
||||
|
||||
if(phy_reg < 0) {
|
||||
return -1;
|
||||
}
|
||||
phydev->phy_id |= (phy_reg & 0xffff);
|
||||
|
||||
//unvaild ID
|
||||
switch(phydev->phy_id) {
|
||||
case 0xFFFFFFFF:
|
||||
case 0x00000000:
|
||||
case 0x0000FFFF:
|
||||
case 0xFFFF0000:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reads the specified PHY device
|
||||
* @param phydev : the phy_device struct
|
||||
* @retval Return 1 to successfully initialize phy_device.
|
||||
*/
|
||||
__init uint8 eth_get_phy_device(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
//判断是否需要自适应查找地址
|
||||
if(phydev->addr == PHY_ADAPTIVE_ADDR) {
|
||||
for(i=1; i<=PHY_MAX_ADDR; i++) {
|
||||
phydev->addr = i;
|
||||
if(!eth_get_phy_id(phydev)) {
|
||||
/* If the phy_id is mostly Fs, there is no device there */
|
||||
if((phydev->phy_id & 0x1fffffff) != 0x1fffffff) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//not found
|
||||
if(i > PHY_MAX_ADDR) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(eth_get_phy_id(phydev)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the phy_id is mostly Fs, there is no device there */
|
||||
if((phydev->phy_id & 0x1fffffff) == 0x1fffffff) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
os_printf("eth phy id:%x\r\n", phydev->phy_id);
|
||||
|
||||
eth_phy_device_create(phydev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__init int genphy_config_init(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
uint32 features;
|
||||
|
||||
/* For now, I'll claim that the generic driver supports
|
||||
* all possible port types */
|
||||
features = (SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
|
||||
SUPPORTED_FIBRE | SUPPORTED_BNC);
|
||||
|
||||
/* Do we support autonegotiation? */
|
||||
val = phy_read(phydev, MII_BMSR);
|
||||
|
||||
if(val < 0) {
|
||||
return val;
|
||||
}
|
||||
|
||||
if(val & BMSR_ANEGCAPABLE) {
|
||||
features |= SUPPORTED_Autoneg;
|
||||
}
|
||||
|
||||
if(val & BMSR_100FULL) {
|
||||
features |= SUPPORTED_100baseT_Full;
|
||||
}
|
||||
if(val & BMSR_100HALF) {
|
||||
features |= SUPPORTED_100baseT_Half;
|
||||
}
|
||||
if(val & BMSR_10FULL) {
|
||||
features |= SUPPORTED_10baseT_Full;
|
||||
}
|
||||
if(val & BMSR_10HALF) {
|
||||
features |= SUPPORTED_10baseT_Half;
|
||||
}
|
||||
if(val & BMSR_ESTATEN) {
|
||||
val = phy_read(phydev, MII_ESTATUS);
|
||||
|
||||
if(val < 0) {
|
||||
return val;
|
||||
}
|
||||
if(val & ESTATUS_1000_TFULL) {
|
||||
features |= SUPPORTED_1000baseT_Full;
|
||||
}
|
||||
if(val & ESTATUS_1000_THALF) {
|
||||
features |= SUPPORTED_1000baseT_Half;
|
||||
}
|
||||
}
|
||||
|
||||
phydev->supported = features;
|
||||
phydev->advertising = features;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief attach a network device to a given PHY device pointer
|
||||
* @param priv : PHY private structure pointer.
|
||||
* @param phydev : Pointer to phy_device to attach
|
||||
* @retval always return 1
|
||||
* @note Called by drivers to attach to a particular PHY device. The
|
||||
* phy_device is found, and properly hooked up to the phy_driver.
|
||||
* If no driver is attached, then the genphy_driver is used. The
|
||||
* phy_device is given a ptr to the attaching device, and given a
|
||||
* callback for link status change. The phy_device is returned to
|
||||
* the attaching driver.
|
||||
*/
|
||||
__init static int32 eth_phy_attach_direct(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
phydev->state = ETH_PHY_READY;
|
||||
|
||||
/* Do initial configuration here, now that
|
||||
* we have certain key parameters
|
||||
* (dev_flags and interface) */
|
||||
return phydev->drv->config_init(phydev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief connect an ethernet device to a specific phy_device
|
||||
* @param phydev : the pointer to the phy device
|
||||
* @param handler : callback function for state change notifications
|
||||
* @retval Returns RET_OK if the PHY connection is successful
|
||||
*/
|
||||
__init int32 eth_phy_connect_direct(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int32 flag;
|
||||
|
||||
flag = eth_phy_attach_direct(phydev);
|
||||
if(flag == RET_ERR) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
eth_phy_start_machine(phydev);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sanitize and advertise auto-negotiation parameters
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval Returns < 0 on error, 0 if the PHY's advertisement hasn't
|
||||
* changed, and > 0 if it has changed.
|
||||
* @note Writes MII_ADVERTISE with the appropriate values, after
|
||||
* sanitizing the values to make sure we only advertise what is
|
||||
* supported.
|
||||
*/
|
||||
static int genphy_config_advert(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
uint32 advertise;
|
||||
int oldadv, adv;
|
||||
int changed = 0;
|
||||
|
||||
/* Only allow advertising what
|
||||
* this PHY supports */
|
||||
phydev->advertising &= phydev->supported;
|
||||
advertise = phydev->advertising;
|
||||
|
||||
/* Setup standard advertisement */
|
||||
oldadv = adv = phy_read(phydev, MII_ADVERTISE);
|
||||
|
||||
if(adv < 0) {
|
||||
return adv;
|
||||
}
|
||||
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
|
||||
ADVERTISE_PAUSE_ASYM);
|
||||
adv |= eth_phy_adv_to_mii_adv_t(advertise);
|
||||
|
||||
if(adv != oldadv) {
|
||||
phy_write(phydev, MII_ADVERTISE, adv);
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
/* Configure gigabit if it's supported */
|
||||
// if (phydev->supported & (SUPPORTED_1000baseT_Half |
|
||||
// SUPPORTED_1000baseT_Full)) {
|
||||
// oldadv = adv = phy_read(phydev, MII_CTRL1000);
|
||||
|
||||
// if (adv < 0)
|
||||
// return adv;
|
||||
|
||||
// adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
|
||||
// adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
|
||||
|
||||
// if (adv != oldadv) {
|
||||
// err = phy_write(phydev, MII_CTRL1000, adv);
|
||||
|
||||
// if (err < 0)
|
||||
// return err;
|
||||
// changed = 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configures/forces speed/duplex from @phydev
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval None
|
||||
* @note Configures MII_BMCR to force speed/duplex to the values in
|
||||
* phydev. Assumes that the values are valid. Please see
|
||||
* eth_phy_sanitize_settings().
|
||||
*/
|
||||
static void genphy_setup_forced(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int ctl = 0;
|
||||
|
||||
phydev->pause = phydev->asym_pause = 0;
|
||||
|
||||
if(SPEED_1000 == phydev->speed) {
|
||||
ctl |= BMCR_SPEED1000;
|
||||
} else if(SPEED_100 == phydev->speed) {
|
||||
ctl |= BMCR_SPEED100;
|
||||
}
|
||||
if(DUPLEX_FULL == phydev->duplex) {
|
||||
ctl |= BMCR_FULLDPLX;
|
||||
}
|
||||
phy_write(phydev, MII_BMCR, ctl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable and Restart Autonegotiation
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval Returning 0 means the PHY supports auto-negotiation.
|
||||
*/
|
||||
int genphy_restart_aneg(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int ctl;
|
||||
|
||||
ctl = phy_read(phydev, MII_BMCR);
|
||||
|
||||
if(ctl < 0) {
|
||||
return ctl;
|
||||
}
|
||||
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
|
||||
|
||||
/* Don't isolate the PHY if we're negotiating */
|
||||
ctl &= ~(BMCR_ISOLATE);
|
||||
|
||||
phy_write(phydev, MII_BMCR, ctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief restart auto-negotiation or write BMCR
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval Returns the auto-negotiation configuration result.
|
||||
* @note If auto-negotiation is enabled, we configure the advertising,
|
||||
* and then restart auto-negotiation. If it is not enabled, then we
|
||||
* write the BMCR
|
||||
*/
|
||||
int genphy_config_aneg(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int result;
|
||||
|
||||
if(AUTONEG_ENABLE != phydev->autoneg) {
|
||||
genphy_setup_forced(phydev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = genphy_config_advert(phydev);
|
||||
|
||||
if(result < 0) { /* error */
|
||||
return result;
|
||||
}
|
||||
|
||||
if(result == 0) {
|
||||
/* Advertisement hasn't changed, but maybe aneg was never on to
|
||||
* begin with? Or maybe phy was isolated? */
|
||||
int ctl = phy_read(phydev, MII_BMCR);
|
||||
|
||||
if(ctl < 0) {
|
||||
return ctl;
|
||||
}
|
||||
if(!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) {
|
||||
result = 1; /* do restart aneg */
|
||||
}
|
||||
}
|
||||
|
||||
/* Only restart aneg if we are advertising something different
|
||||
* than we were before. */
|
||||
if(result > 0) {
|
||||
result = genphy_restart_aneg(phydev);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief update link status in @phydev
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval Returns the link status of the PHY.
|
||||
* @note Update the value in phydev->link to reflect the current link
|
||||
* value. In order to do this, we need to read the status register
|
||||
* twice, keeping the second value.
|
||||
*/
|
||||
int genphy_update_link(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int status;
|
||||
|
||||
/* Do a fake read */
|
||||
status = phy_read(phydev, MII_BMSR);
|
||||
|
||||
if(status < 0) {
|
||||
return status;
|
||||
}
|
||||
/* Read link and autonegotiation status */
|
||||
status = phy_read(phydev, MII_BMSR);
|
||||
|
||||
if(status < 0) {
|
||||
return status;
|
||||
}
|
||||
if((status & BMSR_LSTATUS) == 0) {
|
||||
phydev->link = 0;
|
||||
} else {
|
||||
phydev->link = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check the link status and update current link state
|
||||
* @param phydev : target phy_device struct
|
||||
* @retval Returns 0 when the PHY has no errors.
|
||||
* @note Check the link, then figure out the current state by comparing
|
||||
* what we advertise with what the link partner advertises. Start
|
||||
* by checking the gigabit possibilities, then move on to 10/100.
|
||||
*/
|
||||
int genphy_read_status(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
int adv;
|
||||
int err;
|
||||
int lpa;
|
||||
int lpagb = 0;
|
||||
|
||||
/* Update the link, but return if there
|
||||
* was an error */
|
||||
err = genphy_update_link(phydev);
|
||||
if(err) {
|
||||
return err;
|
||||
}
|
||||
if(AUTONEG_ENABLE == phydev->autoneg) {
|
||||
if(phydev->supported & (SUPPORTED_1000baseT_Half |
|
||||
SUPPORTED_1000baseT_Full)) {
|
||||
lpagb = phy_read(phydev, MII_STAT1000);
|
||||
|
||||
if(lpagb < 0) {
|
||||
return lpagb;
|
||||
}
|
||||
adv = phy_read(phydev, MII_CTRL1000);
|
||||
|
||||
if(adv < 0) {
|
||||
return adv;
|
||||
}
|
||||
lpagb &= adv << 2;
|
||||
}
|
||||
|
||||
lpa = phy_read(phydev, MII_LPA);
|
||||
|
||||
if(lpa < 0) {
|
||||
return lpa;
|
||||
}
|
||||
adv = phy_read(phydev, MII_ADVERTISE);
|
||||
|
||||
if(adv < 0) {
|
||||
return adv;
|
||||
}
|
||||
lpa &= adv;
|
||||
|
||||
phydev->speed = SPEED_10;
|
||||
phydev->duplex = DUPLEX_HALF;
|
||||
phydev->pause = phydev->asym_pause = 0;
|
||||
|
||||
if(lpagb & (LPA_1000FULL | LPA_1000HALF)) {
|
||||
phydev->speed = SPEED_1000;
|
||||
|
||||
if(lpagb & LPA_1000FULL) {
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
}
|
||||
} else if(lpa & (LPA_100FULL | LPA_100HALF)) {
|
||||
phydev->speed = SPEED_100;
|
||||
|
||||
if(lpa & LPA_100FULL) {
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
}
|
||||
} else {
|
||||
if(lpa & LPA_10FULL) {
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
}
|
||||
}
|
||||
if(phydev->duplex == DUPLEX_FULL){
|
||||
phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
|
||||
phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
|
||||
}
|
||||
} else {
|
||||
int bmcr = phy_read(phydev, MII_BMCR);
|
||||
if(bmcr < 0) {
|
||||
return bmcr;
|
||||
}
|
||||
if(bmcr & BMCR_FULLDPLX) {
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
} else {
|
||||
phydev->duplex = DUPLEX_HALF;
|
||||
}
|
||||
if(bmcr & BMCR_SPEED1000) {
|
||||
phydev->speed = SPEED_1000;
|
||||
} else if(bmcr & BMCR_SPEED100) {
|
||||
phydev->speed = SPEED_100;
|
||||
} else {
|
||||
phydev->speed = SPEED_10;
|
||||
}
|
||||
phydev->pause = phydev->asym_pause = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*************************** (C) COPYRIGHT 2018 HUGE-IC ***** END OF FILE *****/
|
||||
205
sdk/lib/net/ethphy/mii.h
Normal file
205
sdk/lib/net/ethphy/mii.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file Libraries/Protocol/net/include/uapi/linux/mii.h
|
||||
* @author HUGE-IC Application Team
|
||||
* @version V1.0.0
|
||||
* @date 10-10-2018
|
||||
* @brief definitions for MII-compatible transceivers
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2018 HUGE-IC</center></h2>
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __UAPI_LINUX_MII_H__
|
||||
#define __UAPI_LINUX_MII_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @weakgroup NETWORK
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NETWORK_MII MII Register
|
||||
* @brief definitions for MII-compatible transceivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup MII_Exported_Constants Exported Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Generic MII registers. */
|
||||
#define MII_BMCR 0x00 /*!< Basic mode control register */
|
||||
#define MII_BMSR 0x01 /*!< Basic mode status register */
|
||||
#define MII_PHYSID1 0x02 /*!< PHYS ID 1 */
|
||||
#define MII_PHYSID2 0x03 /*!< PHYS ID 2 */
|
||||
#define MII_ADVERTISE 0x04 /*!< Advertisement control reg */
|
||||
#define MII_LPA 0x05 /*!< Link partner ability reg */
|
||||
#define MII_EXPANSION 0x06 /*!< Expansion register */
|
||||
#define MII_CTRL1000 0x09 /*!< 1000BASE-T control */
|
||||
#define MII_STAT1000 0x0a /*!< 1000BASE-T status */
|
||||
#define MII_MMD_CTRL 0x0d /*!< MMD Access Control Register */
|
||||
#define MII_MMD_DATA 0x0e /*!< MMD Access Data Register */
|
||||
#define MII_ESTATUS 0x0f /*!< Extended Status */
|
||||
#define MII_DCOUNTER 0x12 /*!< Disconnect counter */
|
||||
#define MII_FCSCOUNTER 0x13 /*!< False carrier counter */
|
||||
#define MII_NWAYTEST 0x14 /*!< N-way auto-neg test reg */
|
||||
#define MII_RERRCOUNTER 0x15 /*!< Receive error counter */
|
||||
#define MII_SREVISION 0x16 /*!< Silicon revision */
|
||||
#define MII_RESV1 0x17 /*!< Reserved... */
|
||||
#define MII_LBRERROR 0x18 /*!< Lpback, rx, bypass error */
|
||||
#define MII_PHYADDR 0x19 /*!< PHY address */
|
||||
#define MII_RESV2 0x1a /*!< Reserved... */
|
||||
#define MII_TPISTATUS 0x1b /*!< TPI status for 10mbps */
|
||||
#define MII_NCONFIG 0x1c /*!< Network interface config */
|
||||
|
||||
/* Basic mode control register. */
|
||||
#define BMCR_RESV 0x003f /*!< Unused... */
|
||||
#define BMCR_SPEED1000 0x0040 /*!< MSB of Speed (1000) */
|
||||
#define BMCR_CTST 0x0080 /*!< Collision test */
|
||||
#define BMCR_FULLDPLX 0x0100 /*!< Full duplex */
|
||||
#define BMCR_ANRESTART 0x0200 /*!< Auto negotiation restart */
|
||||
#define BMCR_ISOLATE 0x0400 /*!< Isolate data paths from MII */
|
||||
#define BMCR_PDOWN 0x0800 /*!< Enable low power state */
|
||||
#define BMCR_ANENABLE 0x1000 /*!< Enable auto negotiation */
|
||||
#define BMCR_SPEED100 0x2000 /*!< Select 100Mbps */
|
||||
#define BMCR_LOOPBACK 0x4000 /*!< TXD loopback bits */
|
||||
#define BMCR_RESET 0x8000 /*!< Reset to default state */
|
||||
|
||||
/* Basic mode status register. */
|
||||
#define BMSR_ERCAP 0x0001 /*!< Ext-reg capability */
|
||||
#define BMSR_JCD 0x0002 /*!< Jabber detected */
|
||||
#define BMSR_LSTATUS 0x0004 /*!< Link status */
|
||||
#define BMSR_ANEGCAPABLE 0x0008 /*!< Able to do auto-negotiation */
|
||||
#define BMSR_RFAULT 0x0010 /*!< Remote fault detected */
|
||||
#define BMSR_ANEGCOMPLETE 0x0020 /*!< Auto-negotiation complete */
|
||||
#define BMSR_RESV 0x00c0 /*!< Unused... */
|
||||
#define BMSR_ESTATEN 0x0100 /*!< Extended Status in R15 */
|
||||
#define BMSR_100HALF2 0x0200 /*!< Can do 100BASE-T2 HDX */
|
||||
#define BMSR_100FULL2 0x0400 /*!< Can do 100BASE-T2 FDX */
|
||||
#define BMSR_10HALF 0x0800 /*!< Can do 10mbps, half-duplex */
|
||||
#define BMSR_10FULL 0x1000 /*!< Can do 10mbps, full-duplex */
|
||||
#define BMSR_100HALF 0x2000 /*!< Can do 100mbps, half-duplex */
|
||||
#define BMSR_100FULL 0x4000 /*!< Can do 100mbps, full-duplex */
|
||||
#define BMSR_100BASE4 0x8000 /*!< Can do 100mbps, 4k packets */
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_SLCT 0x001f /*!< Selector bits */
|
||||
#define ADVERTISE_CSMA 0x0001 /*!< Only selector supported */
|
||||
#define ADVERTISE_10HALF 0x0020 /*!< Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_1000XFULL 0x0020 /*!< Try for 1000BASE-X full-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /*!< Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_1000XHALF 0x0040 /*!< Try for 1000BASE-X half-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /*!< Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_1000XPAUSE 0x0080 /*!< Try for 1000BASE-X pause */
|
||||
#define ADVERTISE_100FULL 0x0100 /*!< Try for 100mbps full-duplex */
|
||||
#define ADVERTISE_1000XPSE_ASYM 0x0100 /*!< Try for 1000BASE-X asym pause */
|
||||
#define ADVERTISE_100BASE4 0x0200 /*!< Try for 100mbps 4k packets */
|
||||
#define ADVERTISE_PAUSE_CAP 0x0400 /*!< Try for pause */
|
||||
#define ADVERTISE_PAUSE_ASYM 0x0800 /*!< Try for asymetric pause */
|
||||
#define ADVERTISE_RESV 0x1000 /*!< Unused... */
|
||||
#define ADVERTISE_RFAULT 0x2000 /*!< Say we can detect faults */
|
||||
#define ADVERTISE_LPACK 0x4000 /*!< Ack link partners response */
|
||||
#define ADVERTISE_NPAGE 0x8000 /*!< Next page bit */
|
||||
|
||||
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
|
||||
ADVERTISE_CSMA)
|
||||
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
|
||||
ADVERTISE_100HALF | ADVERTISE_100FULL)
|
||||
|
||||
/* Link partner ability register. */
|
||||
#define LPA_SLCT 0x001f /*!< Same as advertise selector */
|
||||
#define LPA_10HALF 0x0020 /*!< Can do 10mbps half-duplex */
|
||||
#define LPA_1000XFULL 0x0020 /*!< Can do 1000BASE-X full-duplex */
|
||||
#define LPA_10FULL 0x0040 /*!< Can do 10mbps full-duplex */
|
||||
#define LPA_1000XHALF 0x0040 /*!< Can do 1000BASE-X half-duplex */
|
||||
#define LPA_100HALF 0x0080 /*!< Can do 100mbps half-duplex */
|
||||
#define LPA_1000XPAUSE 0x0080 /*!< Can do 1000BASE-X pause */
|
||||
#define LPA_100FULL 0x0100 /*!< Can do 100mbps full-duplex */
|
||||
#define LPA_1000XPAUSE_ASYM 0x0100 /*!< Can do 1000BASE-X pause asym */
|
||||
#define LPA_100BASE4 0x0200 /*!< Can do 100mbps 4k packets */
|
||||
#define LPA_PAUSE_CAP 0x0400 /*!< Can pause */
|
||||
#define LPA_PAUSE_ASYM 0x0800 /*!< Can pause asymetrically */
|
||||
#define LPA_RESV 0x1000 /*!< Unused... */
|
||||
#define LPA_RFAULT 0x2000 /*!< Link partner faulted */
|
||||
#define LPA_LPACK 0x4000 /*!< Link partner acked us */
|
||||
#define LPA_NPAGE 0x8000 /*!< Next page bit */
|
||||
|
||||
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
|
||||
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
|
||||
|
||||
/* Expansion register for auto-negotiation. */
|
||||
#define EXPANSION_NWAY 0x0001 /*!< Can do N-way auto-nego */
|
||||
#define EXPANSION_LCWP 0x0002 /*!< Got new RX page code word */
|
||||
#define EXPANSION_ENABLENPAGE 0x0004 /*!< This enables npage words */
|
||||
#define EXPANSION_NPCAPABLE 0x0008 /*!< Link partner supports npage */
|
||||
#define EXPANSION_MFAULTS 0x0010 /*!< Multiple faults detected */
|
||||
#define EXPANSION_RESV 0xffe0 /*!< Unused... */
|
||||
|
||||
#define ESTATUS_1000_TFULL 0x2000 /*!< Can do 1000BT Full */
|
||||
#define ESTATUS_1000_THALF 0x1000 /*!< Can do 1000BT Half */
|
||||
|
||||
/* N-way test register. */
|
||||
#define NWAYTEST_RESV1 0x00ff /*!< Unused... */
|
||||
#define NWAYTEST_LOOPBACK 0x0100 /*!< Enable loopback for N-way */
|
||||
#define NWAYTEST_RESV2 0xfe00 /*!< Unused... */
|
||||
|
||||
/* 1000BASE-T Control register */
|
||||
#define ADVERTISE_1000FULL 0x0200 /*!< Advertise 1000BASE-T full duplex */
|
||||
#define ADVERTISE_1000HALF 0x0100 /*!< Advertise 1000BASE-T half duplex */
|
||||
#define CTL1000_AS_MASTER 0x0800
|
||||
#define CTL1000_ENABLE_MASTER 0x1000
|
||||
|
||||
/* 1000BASE-T Status register */
|
||||
#define LPA_1000LOCALRXOK 0x2000 /*!< Link partner local receiver status */
|
||||
#define LPA_1000REMRXOK 0x1000 /*!< Link partner remote receiver status*/
|
||||
#define LPA_1000FULL 0x0800 /*!< Link partner 1000BASE-T full duplex*/
|
||||
#define LPA_1000HALF 0x0400 /*!< Link partner 1000BASE-T half duplex*/
|
||||
|
||||
/* Flow control flags */
|
||||
#define FLOW_CTRL_TX 0x01
|
||||
#define FLOW_CTRL_RX 0x02
|
||||
|
||||
/* MMD Access Control register fields */
|
||||
#define MII_MMD_CTRL_DEVAD_MASK 0x1f /*!< Mask MMD DEVAD */
|
||||
#define MII_MMD_CTRL_ADDR 0x0000 /*!< Address */
|
||||
#define MII_MMD_CTRL_NOINCR 0x4000 /*!< no post increment */
|
||||
#define MII_MMD_CTRL_INCR_RDWT 0x8000 /*!< post increment on reads & writes */
|
||||
#define MII_MMD_CTRL_INCR_ON_WT 0xC000 /*!< post increment on writes only */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__UAPI_LINUX_MII_H__
|
||||
|
||||
/*************************** (C) COPYRIGHT 2018 HUGE-IC ***** END OF FILE *****/
|
||||
|
||||
33
sdk/lib/net/ethphy/phy/ip101g.c
Normal file
33
sdk/lib/net/ethphy/phy/ip101g.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "errno.h"
|
||||
#include "dev.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/task.h"
|
||||
#include "hal/netdev.h"
|
||||
#include "lib/net/ethphy/eth_mdio_bus.h"
|
||||
#include "lib/net/ethphy/eth_phy.h"
|
||||
#include "lib/net/ethphy/phy/ip101g.h"
|
||||
|
||||
static int ip101g_config_init(struct ethernet_phy_device *phydev)
|
||||
{
|
||||
/* Disalbe 100BASE-TX EEE capability. Fix the problem of a large number of
|
||||
* symbol errors in the communication between IP101GRI and Realtek RTL8168
|
||||
* network card.
|
||||
*/
|
||||
phy_write(phydev, 13, 0x0007);
|
||||
phy_write(phydev, 14, 0x003C);
|
||||
phy_write(phydev, 13, 0x4007);
|
||||
phy_write(phydev, 14, 0x0000);
|
||||
|
||||
return genphy_config_init(phydev);
|
||||
}
|
||||
|
||||
struct ethernet_phy_driver ip101g_driver = {
|
||||
.features = PHY_BASIC_FEATURES,
|
||||
.config_init = ip101g_config_init,
|
||||
.config_aneg = genphy_config_aneg,
|
||||
.read_status = genphy_read_status,
|
||||
};
|
||||
Reference in New Issue
Block a user