435 lines
14 KiB
C
435 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 <soc.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);
|