So far the init priories were: enetc_psi0=60 < enetc_vsin=61 < emdio=70 < ethernet-phy=80 because the Ethernet PSI driver was doing global initialization for the whole NETC complex, including enabling MDIO function (due to the way the HAL works). Change to use the default init priorities: mdio=60 < phy=70 < eth=enetc_psi0=80 < enetc_vsin=81 by executing at an early stage the NETC global initialization. This also allows to match the DT hierarchy representation of NETC with the effective priorities assigned. Signed-off-by: Manuel Argüelles <manuel.arguelles@nxp.com>
434 lines
14 KiB
C
434 lines
14 KiB
C
/*
|
|
* Copyright 2022 NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(nxp_s32_eth_psi);
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/drivers/mbox.h>
|
|
#include <zephyr/drivers/pinctrl.h>
|
|
#include <zephyr/net/ethernet.h>
|
|
#include <zephyr/net/net_if.h>
|
|
#include <zephyr/net/net_pkt.h>
|
|
#include <zephyr/net/phy.h>
|
|
#include <ethernet/eth_stats.h>
|
|
|
|
#include <S32Z2.h>
|
|
#include <Netc_Eth_Ip.h>
|
|
#include <Netc_Eth_Ip_Irq.h>
|
|
#include <Netc_EthSwt_Ip.h>
|
|
|
|
#include "eth.h"
|
|
#include "eth_nxp_s32_netc_priv.h"
|
|
|
|
#define PSI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_psi)
|
|
#define PHY_NODE DT_PHANDLE(PSI_NODE, phy_handle)
|
|
#define INIT_VSIS DT_NODE_HAS_PROP(PSI_NODE, vsis)
|
|
#define TX_RING_IDX 1
|
|
#define RX_RING_IDX 0
|
|
|
|
static void nxp_s32_eth_configure_port(uint8_t port_idx, enum phy_link_speed speed)
|
|
{
|
|
EthTrcv_BaudRateType baudrate;
|
|
Netc_EthSwt_Ip_PortDuplexType duplex;
|
|
Std_ReturnType status;
|
|
|
|
(void)Netc_EthSwt_Ip_SetPortMode(NETC_SWITCH_IDX, port_idx, false);
|
|
|
|
baudrate = PHY_TO_NETC_SPEED(speed);
|
|
status = Netc_EthSwt_Ip_SetPortSpeed(NETC_SWITCH_IDX, port_idx, baudrate);
|
|
if (status != E_OK) {
|
|
LOG_ERR("Failed to set port %d speed: %d", port_idx, status);
|
|
return;
|
|
}
|
|
|
|
duplex = PHY_TO_NETC_DUPLEX_MODE(speed);
|
|
status = Netc_EthSwt_Ip_SetPortMacLayerDuplexMode(NETC_SWITCH_IDX, port_idx, duplex);
|
|
if (status != E_OK) {
|
|
LOG_ERR("Failed to set port %d duplex mode: %d", port_idx, status);
|
|
return;
|
|
}
|
|
|
|
(void)Netc_EthSwt_Ip_SetPortMode(NETC_SWITCH_IDX, port_idx, true);
|
|
}
|
|
|
|
static void phy_link_state_changed(const struct device *pdev,
|
|
struct phy_link_state *state,
|
|
void *user_data)
|
|
{
|
|
const struct device *dev = (struct device *)user_data;
|
|
const struct nxp_s32_eth_config *cfg = dev->config;
|
|
const struct nxp_s32_eth_data *ctx = dev->data;
|
|
|
|
ARG_UNUSED(pdev);
|
|
|
|
if (state->is_up) {
|
|
LOG_DBG("Link up");
|
|
nxp_s32_eth_configure_port(cfg->port_idx, state->speed);
|
|
net_eth_carrier_on(ctx->iface);
|
|
} else {
|
|
LOG_DBG("Link down");
|
|
net_eth_carrier_off(ctx->iface);
|
|
}
|
|
}
|
|
|
|
/* Configure ETHx_EXT_RX_CLK @ 125 MHz as source of ETH_x_RGMII_RX_CLK */
|
|
static int nxp_s32_eth_configure_cgm(uint8_t port_idx)
|
|
{
|
|
uint32_t tout = 0xFFFFFFFF;
|
|
|
|
if (port_idx == 0) {
|
|
IP_MC_CGM_1->MUX_7_CSC = (IP_MC_CGM_1->MUX_7_CSC & ~MC_CGM_MUX_7_CSC_SELCTL_MASK)
|
|
| MC_CGM_MUX_7_CSC_SELCTL(NETC_ETH_0_RX_CLK_IDX);
|
|
IP_MC_CGM_1->MUX_7_CSC = (IP_MC_CGM_1->MUX_7_CSC & ~MC_CGM_MUX_7_CSC_CLK_SW_MASK)
|
|
| MC_CGM_MUX_7_CSC_CLK_SW(1);
|
|
|
|
while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_CLK_SW_MASK) == 0)
|
|
&& (tout > 0)) {
|
|
tout--;
|
|
}
|
|
while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
|
|
&& (tout > 0)) {
|
|
tout--;
|
|
}
|
|
while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWTRG_MASK)
|
|
>> MC_CGM_MUX_7_CSS_SWTRG_SHIFT != 1) && (tout > 0)) {
|
|
tout--;
|
|
}
|
|
|
|
__ASSERT_NO_MSG(((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SELSTAT_MASK)
|
|
>> MC_CGM_MUX_7_CSS_SELSTAT_SHIFT) == NETC_ETH_0_RX_CLK_IDX);
|
|
|
|
} else if (port_idx == 1) {
|
|
IP_MC_CGM_1->MUX_9_CSC = (IP_MC_CGM_1->MUX_9_CSC & ~MC_CGM_MUX_9_CSC_SELCTL_MASK)
|
|
| MC_CGM_MUX_9_CSC_SELCTL(NETC_ETH_1_RX_CLK_IDX);
|
|
IP_MC_CGM_1->MUX_9_CSC = (IP_MC_CGM_1->MUX_9_CSC & ~MC_CGM_MUX_9_CSC_CLK_SW_MASK)
|
|
| MC_CGM_MUX_9_CSC_CLK_SW(1);
|
|
|
|
while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_CLK_SW_MASK) == 0)
|
|
&& (tout > 0)) {
|
|
tout--;
|
|
}
|
|
while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
|
|
&& (tout > 0)) {
|
|
tout--;
|
|
}
|
|
while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWTRG_MASK)
|
|
>> MC_CGM_MUX_9_CSS_SWTRG_SHIFT != 1) && (tout > 0)) {
|
|
tout--;
|
|
}
|
|
|
|
__ASSERT_NO_MSG(((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SELSTAT_MASK)
|
|
>> MC_CGM_MUX_9_CSS_SELSTAT_SHIFT) == NETC_ETH_1_RX_CLK_IDX);
|
|
} else {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nxp_s32_eth_initialize(const struct device *dev)
|
|
{
|
|
const struct nxp_s32_eth_config *cfg = dev->config;
|
|
int err;
|
|
|
|
err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
|
|
if (err != 0) {
|
|
return err;
|
|
}
|
|
|
|
err = nxp_s32_eth_configure_cgm(cfg->port_idx);
|
|
if (err != 0) {
|
|
LOG_ERR("Failed to configure NETC Switch CGM");
|
|
return -EIO;
|
|
}
|
|
|
|
return nxp_s32_eth_initialize_common(dev);
|
|
}
|
|
|
|
static void nxp_s32_eth_iface_init(struct net_if *iface)
|
|
{
|
|
const struct device *dev = net_if_get_device(iface);
|
|
struct nxp_s32_eth_data *ctx = dev->data;
|
|
const struct nxp_s32_eth_config *cfg = dev->config;
|
|
const struct nxp_s32_eth_msix *msix;
|
|
#if defined(CONFIG_NET_IPV6)
|
|
static struct net_if_mcast_monitor mon;
|
|
|
|
net_if_mcast_mon_register(&mon, iface, nxp_s32_eth_mcast_cb);
|
|
#endif /* CONFIG_NET_IPV6 */
|
|
|
|
/*
|
|
* For VLAN, this value is only used to get the correct L2 driver.
|
|
* The iface pointer in context should contain the main interface
|
|
* if the VLANs are enabled.
|
|
*/
|
|
if (ctx->iface == NULL) {
|
|
ctx->iface = iface;
|
|
}
|
|
|
|
Netc_Eth_Ip_SetMacAddr(cfg->si_idx, (const uint8_t *)ctx->mac_addr);
|
|
net_if_set_link_addr(iface, ctx->mac_addr, sizeof(ctx->mac_addr), NET_LINK_ETHERNET);
|
|
|
|
LOG_INF("SI%d MAC: %02x:%02x:%02x:%02x:%02x:%02x", cfg->si_idx,
|
|
ctx->mac_addr[0], ctx->mac_addr[1], ctx->mac_addr[2],
|
|
ctx->mac_addr[3], ctx->mac_addr[4], ctx->mac_addr[5]);
|
|
|
|
ethernet_init(iface);
|
|
|
|
/*
|
|
* PSI controls the PHY. If PHY is configured either as fixed
|
|
* link or autoneg, the callback is executed at least once
|
|
* immediately after setting it.
|
|
*/
|
|
if (!device_is_ready(cfg->phy_dev)) {
|
|
LOG_ERR("PHY device (%p) is not ready, cannot init iface",
|
|
cfg->phy_dev);
|
|
return;
|
|
}
|
|
phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev);
|
|
|
|
/* Do not start the interface until PHY link is up */
|
|
net_if_carrier_off(iface);
|
|
|
|
for (int i = 0; i < NETC_MSIX_EVENTS_COUNT; i++) {
|
|
msix = &cfg->msix[i];
|
|
if (msix->mbox_channel.dev != NULL) {
|
|
if (mbox_set_enabled(&msix->mbox_channel, true)) {
|
|
LOG_ERR("Failed to enable MRU channel %u", msix->mbox_channel.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void nxp_s32_eth0_rx_callback(const uint8_t unused, const uint8_t ring)
|
|
{
|
|
const struct device *dev = DEVICE_DT_GET(PSI_NODE);
|
|
const struct nxp_s32_eth_config *cfg = dev->config;
|
|
struct nxp_s32_eth_data *ctx = dev->data;
|
|
|
|
ARG_UNUSED(unused);
|
|
|
|
if (ring == cfg->rx_ring_idx) {
|
|
k_sem_give(&ctx->rx_sem);
|
|
}
|
|
}
|
|
|
|
static const struct ethernet_api nxp_s32_eth_api = {
|
|
.iface_api.init = nxp_s32_eth_iface_init,
|
|
.get_capabilities = nxp_s32_eth_get_capabilities,
|
|
.set_config = nxp_s32_eth_set_config,
|
|
.send = nxp_s32_eth_tx
|
|
};
|
|
|
|
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nxp_s32_netc_psi) == 1, "Only one PSI enabled supported");
|
|
|
|
#define NETC_VSI_GENERAL_CFG(node, prop, idx) \
|
|
[DT_PROP_BY_IDX(node, prop, idx)] = { \
|
|
.siId = DT_PROP_BY_IDX(node, prop, idx), \
|
|
.enableSi = true, \
|
|
.NumberOfRxBDR = 1, \
|
|
.NumberOfTxBDR = 1, \
|
|
.SIVlanControl = (NETC_F3_PSICFGR0_SIVC_CVLAN_BIT \
|
|
| NETC_F3_PSICFGR0_SIVC_SVLAN_BIT), \
|
|
}
|
|
|
|
#define NETC_VSI_RX_MSG_BUF(node, prop, idx) \
|
|
BUILD_ASSERT((DT_PROP_BY_IDX(node, prop, idx) > NETC_ETH_IP_PSI_INDEX) \
|
|
&& (DT_PROP_BY_IDX(node, prop, idx) <= FEATURE_NETC_ETH_NUM_OF_VIRTUAL_CTRLS), \
|
|
"Invalid VSI index"); \
|
|
static Netc_Eth_Ip_VsiToPsiMsgType \
|
|
_CONCAT3(nxp_s32_eth0_vsi, DT_PROP_BY_IDX(node, prop, idx), _rx_msg_buf) \
|
|
__aligned(FEATURE_NETC_ETH_VSI_MSG_ALIGNMENT)
|
|
|
|
#define NETC_VSI_RX_MSG_BUF_ARRAY(node, prop, idx) \
|
|
[DT_PROP_BY_IDX(node, prop, idx) - 1] = \
|
|
&_CONCAT3(nxp_s32_eth0_vsi, DT_PROP_BY_IDX(node, prop, idx), _rx_msg_buf)
|
|
|
|
#define NETC_SWITCH_PORT_CFG(_, __) \
|
|
{ \
|
|
.ePort = &nxp_s32_eth0_switch_port_egress_cfg, \
|
|
.iPort = &nxp_s32_eth0_switch_port_ingress_cfg, \
|
|
.EthSwtPortMacLayerPortEnable = true, \
|
|
.EthSwtPortMacLayerSpeed = ETHTRCV_BAUD_RATE_1000MBIT, \
|
|
.EthSwtPortMacLayerDuplexMode = NETC_ETHSWT_PORT_FULL_DUPLEX, \
|
|
.EthSwtPortPhysicalLayerType = NETC_ETHSWT_RGMII_MODE, \
|
|
.EthSwtPortPruningEnable = true, \
|
|
}
|
|
|
|
static Netc_Eth_Ip_StateType nxp_s32_eth0_state;
|
|
|
|
static Netc_Eth_Ip_MACFilterHashTableEntryType
|
|
nxp_s32_eth0_mac_filter_hash_table[CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE];
|
|
|
|
NETC_TX_RING(0, 0, NETC_MIN_RING_LEN, NETC_MIN_RING_BUF_SIZE);
|
|
NETC_TX_RING(0, TX_RING_IDX,
|
|
CONFIG_ETH_NXP_S32_TX_RING_LEN, CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE);
|
|
NETC_RX_RING(0, RX_RING_IDX,
|
|
CONFIG_ETH_NXP_S32_RX_RING_LEN, CONFIG_ETH_NXP_S32_RX_RING_BUF_SIZE);
|
|
|
|
static const Netc_Eth_Ip_RxRingConfigType nxp_s32_eth0_rxring_cfg[1] = {
|
|
{
|
|
.RingDesc = nxp_s32_eth0_rxring0_desc,
|
|
.Buffer = nxp_s32_eth0_rxring0_buf,
|
|
.ringSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,
|
|
.maxRingSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,
|
|
.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
|
|
.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
|
|
.TimerThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_TIMER_THRESHOLD,
|
|
.PacketsThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_PACKET_THRESHOLD,
|
|
.Callback = nxp_s32_eth0_rx_callback,
|
|
}
|
|
};
|
|
|
|
static const Netc_Eth_Ip_TxRingConfigType nxp_s32_eth0_txring_cfg[2] = {
|
|
{
|
|
.RingDesc = nxp_s32_eth0_txring0_desc,
|
|
.Buffer = nxp_s32_eth0_txring0_buf,
|
|
.ringSize = NETC_MIN_RING_LEN,
|
|
.maxRingSize = NETC_MIN_RING_LEN,
|
|
.bufferLen = NETC_MIN_RING_BUF_SIZE,
|
|
.maxBuffLen = NETC_MIN_RING_BUF_SIZE,
|
|
},
|
|
{
|
|
.RingDesc = nxp_s32_eth0_txring1_desc,
|
|
.Buffer = nxp_s32_eth0_txring1_buf,
|
|
.ringSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,
|
|
.maxRingSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,
|
|
.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
|
|
.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
|
|
}
|
|
};
|
|
|
|
static const Netc_Eth_Ip_GeneralSIConfigType
|
|
nxp_s32_eth0_psi_cfg[FEATURE_NETC_ETH_NUMBER_OF_CTRLS] = {
|
|
[NETC_ETH_IP_PSI_INDEX] = {
|
|
.siId = NETC_ETH_IP_PSI_INDEX,
|
|
.enableSi = true,
|
|
.NumberOfRxBDR = 1,
|
|
.NumberOfTxBDR = 2,
|
|
.SIVlanControl = (NETC_F3_PSICFGR0_SIVC_CVLAN_BIT
|
|
| NETC_F3_PSICFGR0_SIVC_SVLAN_BIT),
|
|
},
|
|
COND_CODE_1(INIT_VSIS,
|
|
(DT_FOREACH_PROP_ELEM_SEP(PSI_NODE, vsis, NETC_VSI_GENERAL_CFG, (,))),
|
|
(EMPTY))
|
|
};
|
|
|
|
COND_CODE_1(INIT_VSIS,
|
|
(DT_FOREACH_PROP_ELEM_SEP(PSI_NODE, vsis, NETC_VSI_RX_MSG_BUF, (;))),
|
|
(EMPTY));
|
|
|
|
static const Netc_Eth_Ip_EnetcGeneralConfigType nxp_s32_eth0_enetc_general_cfg = {
|
|
.numberOfConfiguredSis = FEATURE_NETC_ETH_NUMBER_OF_CTRLS,
|
|
.stationInterfaceGeneralConfig = &nxp_s32_eth0_psi_cfg,
|
|
#if defined(CONFIG_NET_PROMISCUOUS_MODE)
|
|
.maskMACPromiscuousMulticastEnable = (uint16_t)true,
|
|
.maskMACPromiscuousUnicastEnable = (uint16_t)true,
|
|
#endif
|
|
.RxVsiMsgCmdToPsi = {
|
|
COND_CODE_1(INIT_VSIS,
|
|
(DT_FOREACH_PROP_ELEM_SEP(PSI_NODE, vsis,
|
|
NETC_VSI_RX_MSG_BUF_ARRAY, (,))),
|
|
(EMPTY))
|
|
},
|
|
};
|
|
|
|
static const Netc_Eth_Ip_StationInterfaceConfigType nxp_s32_eth0_si_cfg = {
|
|
.NumberOfRxBDR = 1,
|
|
.NumberOfTxBDR = 2,
|
|
.txMruMailboxAddr = NULL,
|
|
.rxMruMailboxAddr = (uint32_t *)MRU_MBOX_ADDR(PSI_NODE, rx),
|
|
.siMsgMruMailboxAddr = COND_CODE_1(INIT_VSIS,
|
|
((uint32_t *)MRU_MBOX_ADDR(PSI_NODE, vsi_msg)), (NULL)),
|
|
.RxInterrupts = (uint32_t)true,
|
|
.TxInterrupts = (uint32_t)false,
|
|
.MACFilterTableMaxNumOfEntries = CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE,
|
|
};
|
|
|
|
static uint8_t nxp_s32_eth0_switch_vlandr2dei_cfg[NETC_ETHSWT_NUMBER_OF_DR];
|
|
static Netc_EthSwt_Ip_PortIngressType nxp_s32_eth0_switch_port_ingress_cfg;
|
|
static Netc_EthSwt_Ip_PortEgressType nxp_s32_eth0_switch_port_egress_cfg = {
|
|
.vlanDrToDei = &nxp_s32_eth0_switch_vlandr2dei_cfg,
|
|
};
|
|
static Netc_EthSwt_Ip_PortType nxp_s32_eth0_switch_ports_cfg[NETC_ETHSWT_NUMBER_OF_PORTS] = {
|
|
LISTIFY(NETC_ETHSWT_NUMBER_OF_PORTS, NETC_SWITCH_PORT_CFG, (,))
|
|
};
|
|
|
|
static const Netc_EthSwt_Ip_ConfigType nxp_s32_eth0_switch_cfg = {
|
|
.port = &nxp_s32_eth0_switch_ports_cfg,
|
|
.EthSwtArlTableEntryTimeout = NETC_SWITCH_PORT_AGING,
|
|
.netcClockFrequency = DT_PROP(PSI_NODE, clock_frequency),
|
|
.MacLearningOption = ETHSWT_MACLEARNINGOPTION_HWDISABLED,
|
|
.MacForwardingOption = ETHSWT_NO_FDB_LOOKUP_FLOOD_FRAME,
|
|
.Timer1588ClkSrc = ETHSWT_REFERENCE_CLOCK_DISABLED,
|
|
};
|
|
|
|
PINCTRL_DT_DEFINE(PSI_NODE);
|
|
|
|
NETC_GENERATE_MAC_ADDRESS(PSI_NODE, 0)
|
|
|
|
static const struct nxp_s32_eth_config nxp_s32_eth0_config = {
|
|
.netc_cfg = {
|
|
.SiType = NETC_ETH_IP_PHYSICAL_SI,
|
|
.siConfig = &nxp_s32_eth0_si_cfg,
|
|
.generalConfig = &nxp_s32_eth0_enetc_general_cfg,
|
|
.stateStructure = &nxp_s32_eth0_state,
|
|
.paCtrlRxRingConfig = &nxp_s32_eth0_rxring_cfg,
|
|
.paCtrlTxRingConfig = &nxp_s32_eth0_txring_cfg,
|
|
},
|
|
.si_idx = NETC_ETH_IP_PSI_INDEX,
|
|
.port_idx = NETC_SWITCH_PORT_IDX,
|
|
.tx_ring_idx = TX_RING_IDX,
|
|
.rx_ring_idx = RX_RING_IDX,
|
|
.msix = {
|
|
NETC_MSIX(PSI_NODE, rx, Netc_Eth_Ip_0_MSIX_RxEvent),
|
|
COND_CODE_1(INIT_VSIS,
|
|
(NETC_MSIX(PSI_NODE, vsi_msg, Netc_Eth_Ip_MSIX_SIMsgEvent)),
|
|
(EMPTY))
|
|
},
|
|
.mac_filter_hash_table = &nxp_s32_eth0_mac_filter_hash_table[0],
|
|
.generate_mac = nxp_s32_eth0_generate_mac,
|
|
.phy_dev = DEVICE_DT_GET(PHY_NODE),
|
|
.pincfg = PINCTRL_DT_DEV_CONFIG_GET(PSI_NODE),
|
|
};
|
|
|
|
static struct nxp_s32_eth_data nxp_s32_eth0_data = {
|
|
.mac_addr = DT_PROP_OR(PSI_NODE, local_mac_address, {0}),
|
|
};
|
|
|
|
ETH_NET_DEVICE_DT_DEFINE(PSI_NODE,
|
|
nxp_s32_eth_initialize,
|
|
NULL,
|
|
&nxp_s32_eth0_data,
|
|
&nxp_s32_eth0_config,
|
|
CONFIG_ETH_INIT_PRIORITY,
|
|
&nxp_s32_eth_api,
|
|
NET_ETH_MTU);
|
|
|
|
static int nxp_s32_eth_switch_init(void)
|
|
{
|
|
Std_ReturnType swt_status;
|
|
|
|
swt_status = Netc_EthSwt_Ip_Init(NETC_SWITCH_IDX, &nxp_s32_eth0_switch_cfg);
|
|
if (swt_status != E_OK) {
|
|
LOG_ERR("Failed to initialize NETC Switch %d (%d)",
|
|
NETC_SWITCH_IDX, swt_status);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NETC Switch driver must be initialized before any other NETC component.
|
|
* This is because Netc_EthSwt_Ip_Init() will not only initialize the Switch,
|
|
* but also perform global initialization, enable the PCIe functions for MDIO
|
|
* and ENETC, and initialize MDIO with a fixed configuration.
|
|
*/
|
|
SYS_INIT(nxp_s32_eth_switch_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|