Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: ethernet: eth_mcux: support multiple ethernet interfaces at once #60073

10 changes: 10 additions & 0 deletions drivers/ethernet/Kconfig.mcux
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ config ETH_MCUX_USE_DTCM_FOR_DMA_BUFFER

config ETH_MCUX_PROMISCUOUS_MODE
bool "Promiscuous mode"
default y if NET_IPV6
default n
help
Place the Ethernet receiver in promiscuous mode. This may be useful
for debugging and not needed for normal work.
Expand All @@ -36,6 +38,14 @@ config ETH_MCUX_RMII_EXT_CLK
Setting this option will configure MCUX clock block to feed RMII
reference clock from external source (ENET_1588_CLKIN)

config ETH_MCUX_REFCLK_50MHZ
bool "Configure PHY Refclk Crystal is 50MHz (else 25MHz)"
default n if ETH_MCUX_RMII_EXT_CLK
default y
help
Setting this option will configure the PHY for a 50MHz refclk.
Comment on lines +41 to +46
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This belongs in device tree instead of kconfig IMO, and ETH_MCUX_RMII_EXT_CLK probably as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, but as a property for a phy, not the ethernet block, which this driver does not support right now



config ETH_MCUX_NO_PHY_SMI
bool "Do not use SMI for PHY communication"
help
Expand Down
60 changes: 49 additions & 11 deletions drivers/ethernet/eth_mcux.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include "fsl_iomuxc.h"
#define DT_DRV_COMPAT nxp_kinetis_ethernet

/* Driver Limitations:
Expand Down Expand Up @@ -65,6 +66,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define PHY_OMS_FACTORY_MODE_MASK 0x8000U /* The factory mode Override/Status mask. */

/* Defines the PHY KSZ8081 vendor defined registers. */
#define PHY_INTCTL_REG 0x1BU /* The PHY interrupt control / status register */
#define PHY_CONTROL1_REG 0x1EU /* The PHY control one register. */
#define PHY_CONTROL2_REG 0x1FU /* The PHY control two register. */

Expand All @@ -83,6 +85,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define PHY_CTL1_LINKUP_MASK 0x100U /* The PHY link up. */
#define PHY_LINK_READY_MASK (PHY_CTL1_ENERGYDETECT_MASK | PHY_CTL1_LINKUP_MASK)

#define PHY_INTCTL_LINKUP_IE_MASK 0x0100
#define PHY_INTCTL_LINKDOWN_IE_MASK 0x0400

/* Defines the timeout macro. */
#define PHY_READID_TIMEOUT_COUNT 1000U

Expand Down Expand Up @@ -472,11 +477,18 @@ static void eth_mcux_phy_event(struct eth_context *context)
LOG_WRN("Reading PHY reg failed (status 0x%x)", res);
k_work_submit(&context->phy_work);
} else {
ctrl2 |= PHY_CTL2_REFCLK_SELECT_MASK;
if(IS_ENABLED(CONFIG_ETH_MCUX_REFCLK_50MHZ)) {
ctrl2 |= PHY_CTL2_REFCLK_SELECT_MASK;
ENET_StartSMIWrite(context->base, context->phy_addr,
PHY_CONTROL2_REG,
kENET_MiiWriteValidFrame,
ctrl2);
}
uint16_t int_ctrl = PHY_INTCTL_LINKDOWN_IE_MASK | PHY_INTCTL_LINKUP_IE_MASK;
ENET_StartSMIWrite(context->base, context->phy_addr,
PHY_CONTROL2_REG,
kENET_MiiWriteValidFrame,
ctrl2);
PHY_INTCTL_REG,
kENET_MiiWriteValidFrame,
int_ctrl);
}
context->phy_state = eth_mcux_phy_state_reset;
#endif /* CONFIG_SOC_SERIES_IMX_RT */
Expand Down Expand Up @@ -1026,7 +1038,9 @@ static void eth_mcux_init(const struct device *dev)
sys_clock = CLOCK_GetFreq(kCLOCK_IpgClk);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(enet2), okay)
sys_clock = CLOCK_GetFreq(kCLOCK_EnetPll1Clk);
if(context->base == ENET2) {
sys_clock = CLOCK_GetFreq(kCLOCK_EnetPll1Clk);
}
#endif
#elif defined(CONFIG_SOC_SERIES_IMX_RT11XX)
sys_clock = CLOCK_GetRootClockFreq(kCLOCK_Root_Bus);
Expand Down Expand Up @@ -1059,6 +1073,16 @@ static void eth_mcux_init(const struct device *dev)
kENET_RxAccelProtoCheckEnabled;
}

#ifdef CONFIG_ETH_MCUX_RMII_EXT_CLK
if(context->base == ENET) {
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1RefClkMode, true);
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, false);
} else {
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET2RefClkMode, true);
jameswalmsley marked this conversation as resolved.
Show resolved Hide resolved
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET2TxClkOutputDir, false);
}
#endif

ENET_Init(context->base,
&context->enet_handle,
&enet_config,
Expand Down Expand Up @@ -1227,6 +1251,9 @@ static enum ethernet_hw_caps eth_mcux_get_capabilities(const struct device *dev)
#if defined(CONFIG_NET_DSA)
ETHERNET_DSA_MASTER_PORT |
#endif
#if defined(CONFIG_ETH_MCUX_PROMISCUOUS_MODE)
ETHERNET_PROMISC_MODE |
#endif
#if defined(CONFIG_ETH_MCUX_HW_ACCELERATION)
ETHERNET_HW_TX_CHKSUM_OFFLOAD |
ETHERNET_HW_RX_CHKSUM_OFFLOAD |
Expand Down Expand Up @@ -1256,6 +1283,8 @@ static int eth_mcux_set_config(const struct device *dev,
context->mac_addr[2], context->mac_addr[3],
context->mac_addr[4], context->mac_addr[5]);
return 0;
case ETHERNET_CONFIG_TYPE_PROMISC_MODE:
return 0;
default:
break;
}
Expand Down Expand Up @@ -1512,6 +1541,12 @@ static void eth_mcux_err_isr(const struct device *dev)
#endif
#define ETH_MCUX_MAC_ADDR_TO_BOOL(n) ETH_MCUX_MAC_ADDR_TO_BOOL_##n

#if (NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(1))) == 0
#define ETH_MCUX_MAC_ADDR_TO_BOOL_1 0
#else
#define ETH_MCUX_MAC_ADDR_TO_BOOL_1 1
#endif

#if defined(CONFIG_PINCTRL)
#define ETH_MCUX_PINCTRL_DEFINE(n) PINCTRL_DT_INST_DEFINE(n);
#define ETH_MCUX_PINCTRL_INIT(n) .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),
Expand All @@ -1526,14 +1561,17 @@ static void eth_mcux_err_isr(const struct device *dev)
#define _mcux_dma_desc __dtcm_bss_section
#define _mcux_dma_buffer __dtcm_noinit_section
#define _mcux_driver_buffer __dtcm_noinit_section
#define MCUX_CACHED_BUF 0
#elif defined(CONFIG_NOCACHE_MEMORY)
#define _mcux_dma_desc __nocache
#define _mcux_dma_buffer __nocache
#define _mcux_driver_buffer
#define MCUX_CACHED_BUF 1
#else
#define _mcux_dma_desc
#define _mcux_dma_buffer
#define _mcux_driver_buffer
#define MCUX_CACHED_BUF 1
#endif

#if defined(CONFIG_ETH_MCUX_PHY_RESET)
Expand All @@ -1554,19 +1592,19 @@ static void eth_mcux_err_isr(const struct device *dev)
tx_enet_frame_##n##_buf[NET_ETH_MAX_FRAME_SIZE]; \
static _mcux_driver_buffer uint8_t \
rx_enet_frame_##n##_buf[NET_ETH_MAX_FRAME_SIZE]; \
static status_t _MDIO_Write(uint8_t phyAddr, uint8_t regAddr, uint16_t data) \
static status_t _MDIO_##n##_Write(uint8_t phyAddr, uint8_t regAddr, uint16_t data) \
{ \
return ENET_MDIOWrite((ENET_Type *)DT_INST_REG_ADDR(n), phyAddr, regAddr, data);\
}; \
\
static status_t _MDIO_Read(uint8_t phyAddr, uint8_t regAddr, uint16_t *pData) \
static status_t _MDIO_##n##_Read(uint8_t phyAddr, uint8_t regAddr, uint16_t *pData) \
{ \
return ENET_MDIORead((ENET_Type *)DT_INST_REG_ADDR(n), phyAddr, regAddr, pData); \
}; \
\
static struct _phy_resource eth##n##_phy_resource = { \
.read = _MDIO_Read, \
.write = _MDIO_Write \
.read = _MDIO_##n##_Read, \
.write = _MDIO_##n##_Write \
}; \
static phy_handle_t eth##n##_phy_handle = { \
.resource = (void *)&eth##n##_phy_resource \
Expand Down Expand Up @@ -1620,8 +1658,8 @@ static void eth_mcux_err_isr(const struct device *dev)
.txBdStartAddrAlign = eth##n##_tx_buffer_desc, \
.rxBufferAlign = eth##n##_rx_buffer[0], \
.txBufferAlign = eth##n##_tx_buffer[0], \
.rxMaintainEnable = true, \
.txMaintainEnable = true, \
.rxMaintainEnable = (MCUX_CACHED_BUF == 1 ? true : false), \
.txMaintainEnable = (MCUX_CACHED_BUF == 1 ? true : false), \
ETH_MCUX_PTP_FRAMEINFO(n) \
}; \
\
Expand Down