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