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