1 /*
2  * Copyright 2022-2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_s32_netc_vsi
8 
9 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(nxp_s32_eth_vsi);
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	0
32 #define RX_RING_IDX	0
33 
nxp_s32_eth_iface_init(struct net_if * iface)34 static void nxp_s32_eth_iface_init(struct net_if *iface)
35 {
36 	const struct device *dev = net_if_get_device(iface);
37 	struct nxp_s32_eth_data *ctx = dev->data;
38 	const struct nxp_s32_eth_config *cfg = dev->config;
39 	const struct nxp_s32_eth_msix *msix;
40 
41 	/*
42 	 * For VLAN, this value is only used to get the correct L2 driver.
43 	 * The iface pointer in context should contain the main interface
44 	 * if the VLANs are enabled.
45 	 */
46 	if (ctx->iface == NULL) {
47 		ctx->iface = iface;
48 	}
49 
50 	Netc_Eth_Ip_SetMacAddr(cfg->si_idx, (const uint8_t *)ctx->mac_addr);
51 	net_if_set_link_addr(iface, ctx->mac_addr, sizeof(ctx->mac_addr), NET_LINK_ETHERNET);
52 
53 	LOG_INF("SI%d MAC: %02x:%02x:%02x:%02x:%02x:%02x", cfg->si_idx,
54 		ctx->mac_addr[0], ctx->mac_addr[1], ctx->mac_addr[2],
55 		ctx->mac_addr[3], ctx->mac_addr[4], ctx->mac_addr[5]);
56 
57 	ethernet_init(iface);
58 
59 	/* Assumes PSI is already started and link is up, iface will auto-start after init */
60 	net_eth_carrier_on(iface);
61 
62 	for (int i = 0; i < NETC_MSIX_EVENTS_COUNT; i++) {
63 		msix = &cfg->msix[i];
64 		if (mbox_is_ready_dt(&msix->mbox_spec)) {
65 			if (mbox_set_enabled_dt(&msix->mbox_spec, true)) {
66 				LOG_ERR("Failed to enable MRU channel %u",
67 					msix->mbox_spec.channel_id);
68 			}
69 		}
70 	}
71 }
72 
73 static const struct ethernet_api nxp_s32_eth_api = {
74 	.iface_api.init = nxp_s32_eth_iface_init,
75 	.get_capabilities = nxp_s32_eth_get_capabilities,
76 	.set_config = nxp_s32_eth_set_config,
77 	.send = nxp_s32_eth_tx
78 };
79 
80 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nxp_s32_netc_vsi) == 1, "Only one VSI enabled supported");
81 
82 #define NETC_VSI_INSTANCE_DEFINE(n)								\
83 	NETC_GENERATE_MAC_ADDRESS(n)								\
84 												\
85 	void nxp_s32_eth_vsi##n##_rx_event(uint8_t chan, const uint32 *buf, uint8_t buf_size)	\
86 	{											\
87 		Netc_Eth_Ip_MSIX_Rx(NETC_SI_NXP_S32_HW_INSTANCE(n));				\
88 	}											\
89 												\
90 	static void nxp_s32_eth##n##_rx_callback(const uint8_t unused, const uint8_t ring)	\
91 	{											\
92 		const struct device *dev = DEVICE_DT_INST_GET(n);				\
93 		const struct nxp_s32_eth_config *cfg = dev->config;				\
94 		struct nxp_s32_eth_data *ctx = dev->data;					\
95 												\
96 		if (ring == cfg->rx_ring_idx) {							\
97 			k_sem_give(&ctx->rx_sem);						\
98 		}										\
99 	}											\
100 												\
101 	static __nocache Netc_Eth_Ip_StateType nxp_s32_eth##n##_state;				\
102 	__nocache Netc_Eth_Ip_VsiToPsiMsgType nxp_s32_eth##n##_vsi2psi_msg			\
103 		__aligned(FEATURE_NETC_ETH_VSI_MSG_ALIGNMENT);					\
104 	static __nocache Netc_Eth_Ip_MACFilterHashTableEntryType				\
105 	nxp_s32_eth##n##_mac_filter_hash_table[CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE];	\
106 												\
107 	NETC_RX_RING(n, TX_RING_IDX, CONFIG_ETH_NXP_S32_RX_RING_LEN,				\
108 			 CONFIG_ETH_NXP_S32_RX_RING_BUF_SIZE);					\
109 	NETC_TX_RING(n, RX_RING_IDX, CONFIG_ETH_NXP_S32_TX_RING_LEN,				\
110 			 CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE);					\
111 												\
112 	static const Netc_Eth_Ip_RxRingConfigType nxp_s32_eth##n##_rxring_cfg[1] = {		\
113 		{										\
114 			.RingDesc = nxp_s32_eth##n##_rxring0_desc,				\
115 			.Buffer = nxp_s32_eth##n##_rxring0_buf,					\
116 			.ringSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,				\
117 			.maxRingSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,				\
118 			.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
119 			.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
120 			.TimerThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_TIMER_THRESHOLD,		\
121 			.PacketsThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_PACKET_THRESHOLD,		\
122 			.Callback = nxp_s32_eth##n##_rx_callback,				\
123 		}										\
124 	};											\
125 	static const Netc_Eth_Ip_TxRingConfigType nxp_s32_eth##n##_txring_cfg[1] = {		\
126 		{										\
127 			.RingDesc = nxp_s32_eth##n##_txring0_desc,				\
128 			.Buffer = nxp_s32_eth##n##_txring0_buf,					\
129 			.ringSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,				\
130 			.maxRingSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,				\
131 			.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
132 			.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
133 		}										\
134 	};											\
135 												\
136 	static const Netc_Eth_Ip_StationInterfaceConfigType nxp_s32_eth##n##_si_cfg = {		\
137 		.NumberOfRxBDR = 1,								\
138 		.NumberOfTxBDR = 1,								\
139 		.txMruMailboxAddr = NULL,							\
140 		.rxMruMailboxAddr = (uint32 *)MRU_MBOX_ADDR(DT_DRV_INST(n), rx),		\
141 		.EnableSIMsgInterrupt = true,							\
142 		.RxInterrupts = (uint32_t)true,							\
143 		.TxInterrupts = (uint32_t)false,						\
144 		.MACFilterTableMaxNumOfEntries = CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE,	\
145 		.VSItoPSIMsgCommand = &nxp_s32_eth##n##_vsi2psi_msg,				\
146 	};											\
147 												\
148 	static struct nxp_s32_eth_data nxp_s32_eth##n##_data = {				\
149 		.mac_addr = DT_INST_PROP_OR(n, local_mac_address, {0}),				\
150 	};											\
151 												\
152 	static const struct nxp_s32_eth_config nxp_s32_eth##n##_cfg = {				\
153 		.netc_cfg = {									\
154 			.SiType = NETC_ETH_IP_VIRTUAL_SI,					\
155 			.siConfig = &nxp_s32_eth##n##_si_cfg,					\
156 			.stateStructure = &nxp_s32_eth##n##_state,				\
157 			.paCtrlRxRingConfig = &nxp_s32_eth##n##_rxring_cfg,			\
158 			.paCtrlTxRingConfig = &nxp_s32_eth##n##_txring_cfg,			\
159 		},										\
160 		.si_idx = NETC_SI_NXP_S32_HW_INSTANCE(n),					\
161 		.tx_ring_idx = TX_RING_IDX,							\
162 		.rx_ring_idx = RX_RING_IDX,							\
163 		.msix = {									\
164 			NETC_MSIX(DT_DRV_INST(n), rx, nxp_s32_eth_vsi##n##_rx_event),		\
165 		},										\
166 		.mac_filter_hash_table = &nxp_s32_eth##n##_mac_filter_hash_table[0],		\
167 		.generate_mac = nxp_s32_eth##n##_generate_mac,					\
168 	};											\
169 												\
170 	ETH_NET_DEVICE_DT_INST_DEFINE(n,							\
171 				nxp_s32_eth_initialize_common,					\
172 				NULL,								\
173 				&nxp_s32_eth##n##_data,						\
174 				&nxp_s32_eth##n##_cfg,						\
175 				CONFIG_ETH_NXP_S32_VSI_INIT_PRIORITY,				\
176 				&nxp_s32_eth_api,						\
177 				NET_ETH_MTU);
178 
179 DT_INST_FOREACH_STATUS_OKAY(NETC_VSI_INSTANCE_DEFINE)
180