mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #7206 from mikaleppanen/k64f_async_powerup
K64f non-blocking poweruppull/7271/head
commit
e8005f6d72
|
|
@ -186,7 +186,6 @@ bool Kinetis_EMAC::low_level_init_successful()
|
||||||
phy_speed_t phy_speed;
|
phy_speed_t phy_speed;
|
||||||
phy_duplex_t phy_duplex;
|
phy_duplex_t phy_duplex;
|
||||||
uint32_t phyAddr = 0;
|
uint32_t phyAddr = 0;
|
||||||
bool link = false;
|
|
||||||
enet_config_t config;
|
enet_config_t config;
|
||||||
|
|
||||||
// Allocate RX descriptors
|
// Allocate RX descriptors
|
||||||
|
|
@ -231,16 +230,16 @@ bool Kinetis_EMAC::low_level_init_successful()
|
||||||
|
|
||||||
ENET_GetDefaultConfig(&config);
|
ENET_GetDefaultConfig(&config);
|
||||||
|
|
||||||
PHY_Init(ENET, 0, sysClock);
|
if (PHY_Init(ENET, phyAddr, sysClock) != kStatus_Success) {
|
||||||
PHY_GetLinkStatus(ENET, phyAddr, &link);
|
return false;
|
||||||
if (link) {
|
}
|
||||||
|
|
||||||
/* Get link information from PHY */
|
/* Get link information from PHY */
|
||||||
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex);
|
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex);
|
||||||
/* Change the MII speed and duplex for actual link status. */
|
/* Change the MII speed and duplex for actual link status. */
|
||||||
config.miiSpeed = (enet_mii_speed_t)phy_speed;
|
config.miiSpeed = (enet_mii_speed_t)phy_speed;
|
||||||
config.miiDuplex = (enet_mii_duplex_t)phy_duplex;
|
config.miiDuplex = (enet_mii_duplex_t)phy_duplex;
|
||||||
config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt;
|
config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt;
|
||||||
}
|
|
||||||
config.rxMaxFrameLen = ENET_ETH_MAX_FLEN;
|
config.rxMaxFrameLen = ENET_ETH_MAX_FLEN;
|
||||||
config.macSpecialConfig = kENET_ControlFlowControlEnable;
|
config.macSpecialConfig = kENET_ControlFlowControlEnable;
|
||||||
config.txAccelerConfig = 0;
|
config.txAccelerConfig = 0;
|
||||||
|
|
@ -262,7 +261,6 @@ bool Kinetis_EMAC::low_level_init_successful()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet.
|
/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet.
|
||||||
*
|
*
|
||||||
* \param[in] idx index of packet to be read
|
* \param[in] idx index of packet to be read
|
||||||
|
|
@ -413,8 +411,8 @@ bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf)
|
||||||
buf = copy_buf;
|
buf = copy_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if a descriptor is available for the transfer. */
|
/* Check if a descriptor is available for the transfer (wait 10ms before dropping the buffer) */
|
||||||
if (xTXDCountSem.wait(0) == 0) {
|
if (xTXDCountSem.wait(10) == 0) {
|
||||||
memory_manager->free(buf);
|
memory_manager->free(buf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -452,41 +450,42 @@ bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#define STATE_UNKNOWN (-1)
|
#define STATE_UNKNOWN (-1)
|
||||||
|
#define STATE_LINK_DOWN (0)
|
||||||
int phy_link_status(void) {
|
#define STATE_LINK_UP (1)
|
||||||
bool connection_status;
|
|
||||||
uint32_t phyAddr = 0;
|
|
||||||
|
|
||||||
PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
|
|
||||||
return (int)connection_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Kinetis_EMAC::phy_task()
|
void Kinetis_EMAC::phy_task()
|
||||||
{
|
{
|
||||||
static PHY_STATE prev_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
|
|
||||||
|
|
||||||
uint32_t phyAddr = 0;
|
uint32_t phyAddr = 0;
|
||||||
|
|
||||||
// Get current status
|
// Get current status
|
||||||
PHY_STATE crt_state;
|
PHY_STATE crt_state;
|
||||||
bool connection_status;
|
bool connection_status;
|
||||||
PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
|
PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
|
||||||
crt_state.connected = connection_status;
|
|
||||||
// Get the actual PHY link speed
|
if (connection_status) {
|
||||||
|
crt_state.connected = STATE_LINK_UP;
|
||||||
|
} else {
|
||||||
|
crt_state.connected = STATE_LINK_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crt_state.connected == STATE_LINK_UP) {
|
||||||
|
if (prev_state.connected != STATE_LINK_UP) {
|
||||||
|
PHY_AutoNegotiation(ENET, phyAddr);
|
||||||
|
}
|
||||||
|
|
||||||
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
|
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
|
||||||
|
|
||||||
|
if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed) {
|
||||||
|
/* Poke the registers*/
|
||||||
|
ENET_SetMII(ENET, (enet_mii_speed_t)crt_state.speed, (enet_mii_duplex_t)crt_state.duplex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compare with previous state
|
// Compare with previous state
|
||||||
if (crt_state.connected != prev_state.connected && emac_link_state_cb) {
|
if (crt_state.connected != prev_state.connected && emac_link_state_cb) {
|
||||||
emac_link_state_cb(crt_state.connected);
|
emac_link_state_cb(crt_state.connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crt_state.speed != prev_state.speed) {
|
|
||||||
uint32_t rcr = ENET->RCR;
|
|
||||||
rcr &= ~ENET_RCR_RMII_10T_MASK;
|
|
||||||
rcr |= ENET_RCR_RMII_10T(!crt_state.speed);
|
|
||||||
ENET->RCR = rcr;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_state = crt_state;
|
prev_state = crt_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -504,19 +503,20 @@ bool Kinetis_EMAC::power_up()
|
||||||
rx_isr();
|
rx_isr();
|
||||||
|
|
||||||
/* PHY monitoring task */
|
/* PHY monitoring task */
|
||||||
prev_state.connected = STATE_UNKNOWN;
|
prev_state.connected = STATE_LINK_DOWN;
|
||||||
prev_state.speed = (phy_speed_t)STATE_UNKNOWN;
|
prev_state.speed = (phy_speed_t)STATE_UNKNOWN;
|
||||||
prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN;
|
prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN;
|
||||||
|
|
||||||
phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &Kinetis_EMAC::phy_task));
|
mbed::mbed_event_queue()->call(mbed::callback(this, &Kinetis_EMAC::phy_task));
|
||||||
|
|
||||||
/* Allow the PHY task to detect the initial link state and set up the proper flags */
|
/* Allow the PHY task to detect the initial link state and set up the proper flags */
|
||||||
osDelay(10);
|
osDelay(10);
|
||||||
|
|
||||||
|
phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &Kinetis_EMAC::phy_task));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t Kinetis_EMAC::get_mtu_size() const
|
uint32_t Kinetis_EMAC::get_mtu_size() const
|
||||||
{
|
{
|
||||||
return KINETIS_ETH_MTU_SIZE;
|
return KINETIS_ETH_MTU_SIZE;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
|
||||||
|
|
||||||
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
||||||
{
|
{
|
||||||
uint32_t bssReg;
|
|
||||||
uint32_t counter = PHY_TIMEOUT_COUNT;
|
uint32_t counter = PHY_TIMEOUT_COUNT;
|
||||||
uint32_t idReg = 0;
|
uint32_t idReg = 0;
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
|
|
@ -89,10 +88,17 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset PHY. */
|
/* Reset PHY. */
|
||||||
counter = PHY_TIMEOUT_COUNT;
|
|
||||||
result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
|
result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
|
||||||
if (result == kStatus_Success)
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PHY_AutoNegotiation(ENET_Type *base, uint32_t phyAddr)
|
||||||
{
|
{
|
||||||
|
status_t result = kStatus_Success;
|
||||||
|
uint32_t bssReg;
|
||||||
|
uint32_t counter = PHY_TIMEOUT_COUNT;
|
||||||
|
|
||||||
/* Set the negotiation. */
|
/* Set the negotiation. */
|
||||||
result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
|
result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
|
||||||
(PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
|
(PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
|
||||||
|
|
@ -122,7 +128,6 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,10 +136,19 @@ extern "C" {
|
||||||
* @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI.
|
* @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI.
|
||||||
* @retval kStatus_Success PHY initialize success
|
* @retval kStatus_Success PHY initialize success
|
||||||
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
|
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
|
||||||
* @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail
|
|
||||||
*/
|
*/
|
||||||
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
|
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Initiates auto negotiation.
|
||||||
|
*
|
||||||
|
* @param base ENET peripheral base address.
|
||||||
|
* @param phyAddr The PHY address.
|
||||||
|
* @retval kStatus_Success PHY auto negotiation success
|
||||||
|
* @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail
|
||||||
|
*/
|
||||||
|
status_t PHY_AutoNegotiation(ENET_Type *base, uint32_t phyAddr);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief PHY Write function. This function write data over the SMI to
|
* @brief PHY Write function. This function write data over the SMI to
|
||||||
* the specified PHY register. This function is called by all PHY interfaces.
|
* the specified PHY register. This function is called by all PHY interfaces.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
|
@ -53,8 +53,10 @@ extern uint32_t ENET_GetInstance(ENET_Type *base);
|
||||||
* Variables
|
* Variables
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/*! @brief Pointers to enet clocks for each instance. */
|
/*! @brief Pointers to enet clocks for each instance. */
|
||||||
extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
|
extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Code
|
* Code
|
||||||
|
|
@ -62,19 +64,41 @@ extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
|
||||||
|
|
||||||
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
||||||
{
|
{
|
||||||
uint32_t bssReg;
|
|
||||||
uint32_t counter = PHY_TIMEOUT_COUNT;
|
uint32_t counter = PHY_TIMEOUT_COUNT;
|
||||||
|
uint32_t idReg = 0;
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint32_t instance = ENET_GetInstance(base);
|
uint32_t instance = ENET_GetInstance(base);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Set SMI first. */
|
/* Set SMI first. */
|
||||||
CLOCK_EnableClock(s_enetClock[instance]);
|
CLOCK_EnableClock(s_enetClock[instance]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
ENET_SetSMI(base, srcClock_Hz, false);
|
ENET_SetSMI(base, srcClock_Hz, false);
|
||||||
|
|
||||||
|
/* Initialization after PHY stars to work. */
|
||||||
|
while ((idReg != PHY_CONTROL_ID1) && (counter != 0))
|
||||||
|
{
|
||||||
|
PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg);
|
||||||
|
counter --;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!counter)
|
||||||
|
{
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset PHY. */
|
/* Reset PHY. */
|
||||||
result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
|
result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
|
||||||
if (result == kStatus_Success)
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PHY_AutoNegotiation(ENET_Type *base, uint32_t phyAddr)
|
||||||
{
|
{
|
||||||
|
status_t result = kStatus_Success;
|
||||||
|
uint32_t bssReg;
|
||||||
|
uint32_t counter = PHY_TIMEOUT_COUNT;
|
||||||
|
|
||||||
/* Set the negotiation. */
|
/* Set the negotiation. */
|
||||||
result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
|
result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
|
||||||
(PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
|
(PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
|
||||||
|
|
@ -104,7 +128,6 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,10 +136,19 @@ extern "C" {
|
||||||
* @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI.
|
* @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI.
|
||||||
* @retval kStatus_Success PHY initialize success
|
* @retval kStatus_Success PHY initialize success
|
||||||
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
|
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
|
||||||
* @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail
|
|
||||||
*/
|
*/
|
||||||
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
|
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Initiates auto negotiation.
|
||||||
|
*
|
||||||
|
* @param base ENET peripheral base address.
|
||||||
|
* @param phyAddr The PHY address.
|
||||||
|
* @retval kStatus_Success PHY auto negotiation success
|
||||||
|
* @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail
|
||||||
|
*/
|
||||||
|
status_t PHY_AutoNegotiation(ENET_Type *base, uint32_t phyAddr);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief PHY Write function. This function write data over the SMI to
|
* @brief PHY Write function. This function write data over the SMI to
|
||||||
* the specified PHY register. This function is called by all PHY interfaces.
|
* the specified PHY register. This function is called by all PHY interfaces.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue