1 /*
2 * Copyright 2022-2023 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_s32_netc_psi
8
9 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(nxp_s32_eth_psi);
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/mbox.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <zephyr/net/ethernet.h>
18 #include <zephyr/net/net_if.h>
19 #include <zephyr/net/net_pkt.h>
20 #include <zephyr/net/phy.h>
21 #include <ethernet/eth_stats.h>
22
23 #include <soc.h>
24 #include <Netc_Eth_Ip.h>
25 #include <Netc_Eth_Ip_Irq.h>
26 #include <Netc_EthSwt_Ip.h>
27
28 #include "eth.h"
29 #include "eth_nxp_s32_netc_priv.h"
30
31 #define TX_RING_IDX 1
32 #define RX_RING_IDX 0
33
nxp_s32_eth_configure_port(uint8_t port_idx,enum phy_link_speed speed)34 static void nxp_s32_eth_configure_port(uint8_t port_idx, enum phy_link_speed speed)
35 {
36 EthTrcv_BaudRateType baudrate;
37 Netc_EthSwt_Ip_PortDuplexType duplex;
38 Std_ReturnType status;
39
40 (void)Netc_EthSwt_Ip_SetPortMode(NETC_SWITCH_IDX, port_idx, false);
41
42 baudrate = PHY_TO_NETC_SPEED(speed);
43 status = Netc_EthSwt_Ip_SetPortSpeed(NETC_SWITCH_IDX, port_idx, baudrate);
44 if (status != E_OK) {
45 LOG_ERR("Failed to set port %d speed: %d", port_idx, status);
46 return;
47 }
48
49 duplex = PHY_TO_NETC_DUPLEX_MODE(speed);
50 status = Netc_EthSwt_Ip_SetPortMacLayerDuplexMode(NETC_SWITCH_IDX, port_idx, duplex);
51 if (status != E_OK) {
52 LOG_ERR("Failed to set port %d duplex mode: %d", port_idx, status);
53 return;
54 }
55
56 (void)Netc_EthSwt_Ip_SetPortMode(NETC_SWITCH_IDX, port_idx, true);
57 }
58
phy_link_state_changed(const struct device * pdev,struct phy_link_state * state,void * user_data)59 static void phy_link_state_changed(const struct device *pdev,
60 struct phy_link_state *state,
61 void *user_data)
62 {
63 const struct device *dev = (struct device *)user_data;
64 const struct nxp_s32_eth_config *cfg = dev->config;
65 const struct nxp_s32_eth_data *ctx = dev->data;
66
67 ARG_UNUSED(pdev);
68
69 if (state->is_up) {
70 LOG_DBG("Link up");
71 nxp_s32_eth_configure_port(cfg->port_idx, state->speed);
72 net_eth_carrier_on(ctx->iface);
73 } else {
74 LOG_DBG("Link down");
75 net_eth_carrier_off(ctx->iface);
76 }
77 }
78
79 /* Configure ETHx_EXT_RX_CLK @ 125 MHz as source of ETH_x_RGMII_RX_CLK */
nxp_s32_eth_configure_cgm(uint8_t port_idx)80 static int nxp_s32_eth_configure_cgm(uint8_t port_idx)
81 {
82 uint32_t tout = 0xFFFFFFFF;
83
84 if (port_idx == 0) {
85 IP_MC_CGM_1->MUX_7_CSC = (IP_MC_CGM_1->MUX_7_CSC & ~MC_CGM_MUX_7_CSC_SELCTL_MASK)
86 | MC_CGM_MUX_7_CSC_SELCTL(NETC_ETH_0_RX_CLK_IDX);
87 IP_MC_CGM_1->MUX_7_CSC = (IP_MC_CGM_1->MUX_7_CSC & ~MC_CGM_MUX_7_CSC_CLK_SW_MASK)
88 | MC_CGM_MUX_7_CSC_CLK_SW(1);
89
90 while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_CLK_SW_MASK) == 0)
91 && (tout > 0)) {
92 tout--;
93 }
94 while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
95 && (tout > 0)) {
96 tout--;
97 }
98 while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWTRG_MASK)
99 >> MC_CGM_MUX_7_CSS_SWTRG_SHIFT != 1) && (tout > 0)) {
100 tout--;
101 }
102
103 __ASSERT_NO_MSG(((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SELSTAT_MASK)
104 >> MC_CGM_MUX_7_CSS_SELSTAT_SHIFT) == NETC_ETH_0_RX_CLK_IDX);
105
106 } else if (port_idx == 1) {
107 IP_MC_CGM_1->MUX_9_CSC = (IP_MC_CGM_1->MUX_9_CSC & ~MC_CGM_MUX_9_CSC_SELCTL_MASK)
108 | MC_CGM_MUX_9_CSC_SELCTL(NETC_ETH_1_RX_CLK_IDX);
109 IP_MC_CGM_1->MUX_9_CSC = (IP_MC_CGM_1->MUX_9_CSC & ~MC_CGM_MUX_9_CSC_CLK_SW_MASK)
110 | MC_CGM_MUX_9_CSC_CLK_SW(1);
111
112 while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_CLK_SW_MASK) == 0)
113 && (tout > 0)) {
114 tout--;
115 }
116 while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
117 && (tout > 0)) {
118 tout--;
119 }
120 while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWTRG_MASK)
121 >> MC_CGM_MUX_9_CSS_SWTRG_SHIFT != 1) && (tout > 0)) {
122 tout--;
123 }
124
125 __ASSERT_NO_MSG(((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SELSTAT_MASK)
126 >> MC_CGM_MUX_9_CSS_SELSTAT_SHIFT) == NETC_ETH_1_RX_CLK_IDX);
127 } else {
128 return -EINVAL;
129 }
130
131 return 0;
132 }
133
nxp_s32_eth_initialize(const struct device * dev)134 static int nxp_s32_eth_initialize(const struct device *dev)
135 {
136 const struct nxp_s32_eth_config *cfg = dev->config;
137 int err;
138
139 err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
140 if (err != 0) {
141 return err;
142 }
143
144 err = nxp_s32_eth_configure_cgm(cfg->port_idx);
145 if (err != 0) {
146 LOG_ERR("Failed to configure NETC Switch CGM");
147 return -EIO;
148 }
149
150 return nxp_s32_eth_initialize_common(dev);
151 }
152
nxp_s32_eth_iface_init(struct net_if * iface)153 static void nxp_s32_eth_iface_init(struct net_if *iface)
154 {
155 const struct device *dev = net_if_get_device(iface);
156 struct nxp_s32_eth_data *ctx = dev->data;
157 const struct nxp_s32_eth_config *cfg = dev->config;
158 const struct nxp_s32_eth_msix *msix;
159 #if defined(CONFIG_NET_IPV6)
160 static struct net_if_mcast_monitor mon;
161
162 net_if_mcast_mon_register(&mon, iface, nxp_s32_eth_mcast_cb);
163 #endif /* CONFIG_NET_IPV6 */
164
165 /*
166 * For VLAN, this value is only used to get the correct L2 driver.
167 * The iface pointer in context should contain the main interface
168 * if the VLANs are enabled.
169 */
170 if (ctx->iface == NULL) {
171 ctx->iface = iface;
172 }
173
174 Netc_Eth_Ip_SetMacAddr(cfg->si_idx, (const uint8_t *)ctx->mac_addr);
175 net_if_set_link_addr(iface, ctx->mac_addr, sizeof(ctx->mac_addr), NET_LINK_ETHERNET);
176
177 LOG_INF("SI%d MAC: %02x:%02x:%02x:%02x:%02x:%02x", cfg->si_idx,
178 ctx->mac_addr[0], ctx->mac_addr[1], ctx->mac_addr[2],
179 ctx->mac_addr[3], ctx->mac_addr[4], ctx->mac_addr[5]);
180
181 ethernet_init(iface);
182
183 /*
184 * PSI controls the PHY. If PHY is configured either as fixed
185 * link or autoneg, the callback is executed at least once
186 * immediately after setting it.
187 */
188 if (!device_is_ready(cfg->phy_dev)) {
189 LOG_ERR("PHY device (%p) is not ready, cannot init iface",
190 cfg->phy_dev);
191 return;
192 }
193 phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev);
194
195 /* Do not start the interface until PHY link is up */
196 net_if_carrier_off(iface);
197
198 for (int i = 0; i < NETC_MSIX_EVENTS_COUNT; i++) {
199 msix = &cfg->msix[i];
200 if (msix->mbox_channel.dev != NULL) {
201 if (mbox_set_enabled(&msix->mbox_channel, true)) {
202 LOG_ERR("Failed to enable MRU channel %u", msix->mbox_channel.id);
203 }
204 }
205 }
206 }
207
208 static const struct ethernet_api nxp_s32_eth_api = {
209 .iface_api.init = nxp_s32_eth_iface_init,
210 .get_capabilities = nxp_s32_eth_get_capabilities,
211 .set_config = nxp_s32_eth_set_config,
212 .send = nxp_s32_eth_tx
213 };
214
215 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nxp_s32_netc_psi) == 1, "Only one PSI enabled supported");
216
217 #define NETC_VSI_GENERAL_CFG(node, prop, idx) \
218 [DT_PROP_BY_IDX(node, prop, idx)] = { \
219 .siId = DT_PROP_BY_IDX(node, prop, idx), \
220 .enableSi = true, \
221 .NumberOfRxBDR = 1, \
222 .NumberOfTxBDR = 1, \
223 .SIVlanControl = (NETC_F3_PSICFGR0_SIVC_CVLAN_BIT \
224 | NETC_F3_PSICFGR0_SIVC_SVLAN_BIT), \
225 .changeMACAllowed = true, \
226 .hashFilterUpdateAllowed = true, \
227 IF_ENABLED(CONFIG_NET_PROMISCUOUS_MODE, \
228 (.multicastPromiscuousChangeAllowed = true,)) \
229 }
230
231 #define NETC_VSI_RX_MSG_BUF(node, prop, idx, n) \
232 BUILD_ASSERT((DT_PROP_BY_IDX(node, prop, idx) > NETC_ETH_IP_PSI_INDEX) \
233 && (DT_PROP_BY_IDX(node, prop, idx) <= FEATURE_NETC_ETH_NUM_OF_VIRTUAL_CTRLS), \
234 "Invalid VSI index"); \
235 static Netc_Eth_Ip_VsiToPsiMsgType \
236 _CONCAT3(nxp_s32_eth##n##_vsi, DT_PROP_BY_IDX(node, prop, idx), _rx_msg_buf) \
237 __aligned(FEATURE_NETC_ETH_VSI_MSG_ALIGNMENT)
238
239 #define NETC_VSI_RX_MSG_BUF_ARRAY(node, prop, idx, n) \
240 [DT_PROP_BY_IDX(node, prop, idx) - 1] = \
241 &_CONCAT3(nxp_s32_eth##n##_vsi, DT_PROP_BY_IDX(node, prop, idx), _rx_msg_buf)
242
243 #define NETC_SWITCH_PORT_CFG(_, n) \
244 { \
245 .ePort = &nxp_s32_eth##n##_switch_port_egress_cfg, \
246 .iPort = &nxp_s32_eth##n##_switch_port_ingress_cfg, \
247 .EthSwtPortMacLayerPortEnable = true, \
248 .EthSwtPortMacLayerSpeed = ETHTRCV_BAUD_RATE_1000MBIT, \
249 .EthSwtPortMacLayerDuplexMode = NETC_ETHSWT_PORT_FULL_DUPLEX, \
250 .EthSwtPortPhysicalLayerType = NETC_ETHSWT_RGMII_MODE, \
251 .EthSwtPortPruningEnable = true, \
252 }
253
254 #define PHY_NODE(n) DT_INST_PHANDLE(n, phy_handle)
255 #define INIT_VSIS(n) DT_INST_NODE_HAS_PROP(n, vsis)
256
257 #define NETC_PSI_INSTANCE_DEFINE(n) \
258 void nxp_s32_eth_psi##n##_rx_event(uint8_t chan, const uint32_t *buf, uint8_t buf_size) \
259 { \
260 ARG_UNUSED(chan); \
261 ARG_UNUSED(buf); \
262 ARG_UNUSED(buf_size); \
263 \
264 Netc_Eth_Ip_MSIX_Rx(NETC_SI_NXP_S32_HW_INSTANCE(n)); \
265 } \
266 \
267 static void nxp_s32_eth##n##_rx_callback(const uint8_t unused, const uint8_t ring) \
268 { \
269 const struct device *dev = DEVICE_DT_INST_GET(n); \
270 const struct nxp_s32_eth_config *cfg = dev->config; \
271 struct nxp_s32_eth_data *ctx = dev->data; \
272 \
273 ARG_UNUSED(unused); \
274 \
275 if (ring == cfg->rx_ring_idx) { \
276 k_sem_give(&ctx->rx_sem); \
277 } \
278 } \
279 \
280 static Netc_Eth_Ip_StateType nxp_s32_eth##n##_state; \
281 static Netc_Eth_Ip_MACFilterHashTableEntryType \
282 nxp_s32_eth##n##_mac_filter_hash_table[CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE]; \
283 \
284 NETC_TX_RING(n, 0, NETC_MIN_RING_LEN, NETC_MIN_RING_BUF_SIZE); \
285 NETC_TX_RING(n, TX_RING_IDX, \
286 CONFIG_ETH_NXP_S32_TX_RING_LEN, CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE); \
287 NETC_RX_RING(n, RX_RING_IDX, \
288 CONFIG_ETH_NXP_S32_RX_RING_LEN, CONFIG_ETH_NXP_S32_RX_RING_BUF_SIZE); \
289 \
290 static const Netc_Eth_Ip_RxRingConfigType nxp_s32_eth##n##_rxring_cfg[1] = { \
291 { \
292 .RingDesc = nxp_s32_eth##n##_rxring0_desc, \
293 .Buffer = nxp_s32_eth##n##_rxring0_buf, \
294 .ringSize = CONFIG_ETH_NXP_S32_RX_RING_LEN, \
295 .maxRingSize = CONFIG_ETH_NXP_S32_RX_RING_LEN, \
296 .bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE, \
297 .maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE, \
298 .TimerThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_TIMER_THRESHOLD, \
299 .PacketsThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_PACKET_THRESHOLD, \
300 .Callback = nxp_s32_eth##n##_rx_callback, \
301 } \
302 }; \
303 \
304 static const Netc_Eth_Ip_TxRingConfigType nxp_s32_eth##n##_txring_cfg[2] = { \
305 { \
306 .RingDesc = nxp_s32_eth##n##_txring0_desc, \
307 .Buffer = nxp_s32_eth##n##_txring0_buf, \
308 .ringSize = NETC_MIN_RING_LEN, \
309 .maxRingSize = NETC_MIN_RING_LEN, \
310 .bufferLen = NETC_MIN_RING_BUF_SIZE, \
311 .maxBuffLen = NETC_MIN_RING_BUF_SIZE, \
312 }, \
313 { \
314 .RingDesc = nxp_s32_eth##n##_txring1_desc, \
315 .Buffer = nxp_s32_eth##n##_txring1_buf, \
316 .ringSize = CONFIG_ETH_NXP_S32_TX_RING_LEN, \
317 .maxRingSize = CONFIG_ETH_NXP_S32_TX_RING_LEN, \
318 .bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE, \
319 .maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE, \
320 } \
321 }; \
322 \
323 static const Netc_Eth_Ip_GeneralSIConfigType \
324 nxp_s32_eth##n##_psi_cfg[FEATURE_NETC_ETH_NUMBER_OF_CTRLS] = { \
325 [NETC_SI_NXP_S32_HW_INSTANCE(n)] = { \
326 .siId = NETC_SI_NXP_S32_HW_INSTANCE(n), \
327 .enableSi = true, \
328 .NumberOfRxBDR = 1, \
329 .NumberOfTxBDR = 2, \
330 .SIVlanControl = (NETC_F3_PSICFGR0_SIVC_CVLAN_BIT \
331 | NETC_F3_PSICFGR0_SIVC_SVLAN_BIT), \
332 .changeMACAllowed = true, \
333 .hashFilterUpdateAllowed = true, \
334 IF_ENABLED(CONFIG_NET_PROMISCUOUS_MODE, \
335 (.multicastPromiscuousChangeAllowed = true,)) \
336 }, \
337 COND_CODE_1(INIT_VSIS(n), \
338 (DT_INST_FOREACH_PROP_ELEM_SEP(n, vsis, NETC_VSI_GENERAL_CFG, (,))), \
339 (EMPTY)) \
340 }; \
341 \
342 COND_CODE_1(INIT_VSIS(n), \
343 (DT_INST_FOREACH_PROP_ELEM_SEP_VARGS(n, vsis, NETC_VSI_RX_MSG_BUF, (;), n)), \
344 (EMPTY)); \
345 \
346 static const Netc_Eth_Ip_EnetcGeneralConfigType nxp_s32_eth##n##_enetc_general_cfg = { \
347 .numberOfConfiguredSis = FEATURE_NETC_ETH_NUMBER_OF_CTRLS, \
348 .stationInterfaceGeneralConfig = &nxp_s32_eth##n##_psi_cfg, \
349 IF_ENABLED(CONFIG_NET_PROMISCUOUS_MODE, \
350 (.maskMACPromiscuousMulticastEnable = (uint16_t)true, \
351 .maskMACPromiscuousUnicastEnable = (uint16_t)true,)) \
352 .RxVsiMsgCmdToPsi = { \
353 COND_CODE_1(INIT_VSIS(n), \
354 (DT_INST_FOREACH_PROP_ELEM_SEP_VARGS(n, vsis, \
355 NETC_VSI_RX_MSG_BUF_ARRAY, (,), n)), \
356 (EMPTY)) \
357 }, \
358 }; \
359 \
360 static const Netc_Eth_Ip_StationInterfaceConfigType nxp_s32_eth##n##_si_cfg = { \
361 .NumberOfRxBDR = 1, \
362 .NumberOfTxBDR = 2, \
363 .txMruMailboxAddr = NULL, \
364 .rxMruMailboxAddr = (uint32_t *)MRU_MBOX_ADDR(DT_DRV_INST(n), rx), \
365 .siMsgMruMailboxAddr = COND_CODE_1(INIT_VSIS(n), \
366 ((uint32_t *)MRU_MBOX_ADDR(DT_DRV_INST(n), vsi_msg)), (NULL)), \
367 .RxInterrupts = (uint32_t)true, \
368 .TxInterrupts = (uint32_t)false, \
369 .MACFilterTableMaxNumOfEntries = CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE, \
370 }; \
371 \
372 static uint8_t nxp_s32_eth##n##_switch_vlandr2dei_cfg[NETC_ETHSWT_NUMBER_OF_DR]; \
373 static Netc_EthSwt_Ip_PortIngressType nxp_s32_eth##n##_switch_port_ingress_cfg; \
374 static Netc_EthSwt_Ip_PortEgressType nxp_s32_eth##n##_switch_port_egress_cfg = { \
375 .vlanDrToDei = &nxp_s32_eth##n##_switch_vlandr2dei_cfg, \
376 }; \
377 static Netc_EthSwt_Ip_PortType nxp_s32_eth##n##_switch_ports_cfg[NETC_ETHSWT_NUMBER_OF_PORTS] = {\
378 LISTIFY(NETC_ETHSWT_NUMBER_OF_PORTS, NETC_SWITCH_PORT_CFG, (,), n) \
379 }; \
380 \
381 static const Netc_EthSwt_Ip_ConfigType nxp_s32_eth##n##_switch_cfg = { \
382 .port = &nxp_s32_eth##n##_switch_ports_cfg, \
383 .EthSwtArlTableEntryTimeout = NETC_SWITCH_PORT_AGING, \
384 .netcClockFrequency = DT_INST_PROP(n, clock_frequency), \
385 .MacLearningOption = ETHSWT_MACLEARNINGOPTION_HWDISABLED, \
386 .MacForwardingOption = ETHSWT_NO_FDB_LOOKUP_FLOOD_FRAME, \
387 .Timer1588ClkSrc = ETHSWT_REFERENCE_CLOCK_DISABLED, \
388 }; \
389 \
390 PINCTRL_DT_INST_DEFINE(n); \
391 \
392 NETC_GENERATE_MAC_ADDRESS(n) \
393 \
394 static const struct nxp_s32_eth_config nxp_s32_eth##n##_config = { \
395 .netc_cfg = { \
396 .SiType = NETC_ETH_IP_PHYSICAL_SI, \
397 .siConfig = &nxp_s32_eth##n##_si_cfg, \
398 .generalConfig = &nxp_s32_eth##n##_enetc_general_cfg, \
399 .stateStructure = &nxp_s32_eth##n##_state, \
400 .paCtrlRxRingConfig = &nxp_s32_eth##n##_rxring_cfg, \
401 .paCtrlTxRingConfig = &nxp_s32_eth##n##_txring_cfg, \
402 }, \
403 .si_idx = NETC_SI_NXP_S32_HW_INSTANCE(n), \
404 .port_idx = NETC_SWITCH_PORT_IDX, \
405 .tx_ring_idx = TX_RING_IDX, \
406 .rx_ring_idx = RX_RING_IDX, \
407 .msix = { \
408 NETC_MSIX(DT_DRV_INST(n), rx, nxp_s32_eth_psi##n##_rx_event), \
409 COND_CODE_1(INIT_VSIS(n), \
410 (NETC_MSIX(DT_DRV_INST(n), vsi_msg, Netc_Eth_Ip_MSIX_SIMsgEvent)),\
411 (EMPTY)) \
412 }, \
413 .mac_filter_hash_table = &nxp_s32_eth##n##_mac_filter_hash_table[0], \
414 .generate_mac = nxp_s32_eth##n##_generate_mac, \
415 .phy_dev = DEVICE_DT_GET(PHY_NODE(n)), \
416 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
417 }; \
418 \
419 static struct nxp_s32_eth_data nxp_s32_eth##n##_data = { \
420 .mac_addr = DT_INST_PROP_OR(n, local_mac_address, {0}), \
421 }; \
422 \
423 ETH_NET_DEVICE_DT_INST_DEFINE(n, \
424 nxp_s32_eth_initialize, \
425 NULL, \
426 &nxp_s32_eth##n##_data, \
427 &nxp_s32_eth##n##_config, \
428 CONFIG_ETH_INIT_PRIORITY, \
429 &nxp_s32_eth_api, \
430 NET_ETH_MTU); \
431
DT_INST_FOREACH_STATUS_OKAY(NETC_PSI_INSTANCE_DEFINE)432 DT_INST_FOREACH_STATUS_OKAY(NETC_PSI_INSTANCE_DEFINE)
433
434 static int nxp_s32_eth_switch_init(void)
435 {
436 Std_ReturnType swt_status;
437
438 swt_status = Netc_EthSwt_Ip_Init(NETC_SWITCH_IDX, &nxp_s32_eth0_switch_cfg);
439 if (swt_status != E_OK) {
440 LOG_ERR("Failed to initialize NETC Switch %d (%d)",
441 NETC_SWITCH_IDX, swt_status);
442 return -EIO;
443 }
444
445 return 0;
446 }
447
448 /*
449 * NETC Switch driver must be initialized before any other NETC component.
450 * This is because Netc_EthSwt_Ip_Init() will not only initialize the Switch,
451 * but also perform global initialization, enable the PCIe functions for MDIO
452 * and ENETC, and initialize MDIO with a fixed configuration.
453 */
454 SYS_INIT(nxp_s32_eth_switch_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
455