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