1 /*
2  * Copyright 2022 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_REGISTER(nxp_s32_eth_vsi);
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/mbox.h>
14 #include <zephyr/drivers/pinctrl.h>
15 #include <zephyr/net/ethernet.h>
16 #include <zephyr/net/net_if.h>
17 #include <zephyr/net/net_pkt.h>
18 #include <zephyr/net/phy.h>
19 #include <ethernet/eth_stats.h>
20 
21 #include <S32Z2.h>
22 #include <Netc_Eth_Ip.h>
23 #include <Netc_Eth_Ip_Irq.h>
24 #include <Netc_EthSwt_Ip.h>
25 
26 #include "eth.h"
27 #include "eth_nxp_s32_netc_priv.h"
28 
29 #define VSI_NODE(n)	DT_NODELABEL(enetc_vsi##n)
30 #define TX_RING_IDX	0
31 #define RX_RING_IDX	0
32 
nxp_s32_eth_iface_init(struct net_if * iface)33 static void nxp_s32_eth_iface_init(struct net_if *iface)
34 {
35 	const struct device *dev = net_if_get_device(iface);
36 	struct nxp_s32_eth_data *ctx = dev->data;
37 	const struct nxp_s32_eth_config *cfg = dev->config;
38 	const struct nxp_s32_eth_msix *msix;
39 #if defined(CONFIG_NET_IPV6)
40 	static struct net_if_mcast_monitor mon;
41 
42 	net_if_mcast_mon_register(&mon, iface, nxp_s32_eth_mcast_cb);
43 #endif /* CONFIG_NET_IPV6 */
44 
45 	/*
46 	 * For VLAN, this value is only used to get the correct L2 driver.
47 	 * The iface pointer in context should contain the main interface
48 	 * if the VLANs are enabled.
49 	 */
50 	if (ctx->iface == NULL) {
51 		ctx->iface = iface;
52 	}
53 
54 	Netc_Eth_Ip_SetMacAddr(cfg->si_idx, (const uint8_t *)ctx->mac_addr);
55 	net_if_set_link_addr(iface, ctx->mac_addr, sizeof(ctx->mac_addr), NET_LINK_ETHERNET);
56 
57 	LOG_INF("SI%d MAC: %02x:%02x:%02x:%02x:%02x:%02x", cfg->si_idx,
58 		ctx->mac_addr[0], ctx->mac_addr[1], ctx->mac_addr[2],
59 		ctx->mac_addr[3], ctx->mac_addr[4], ctx->mac_addr[5]);
60 
61 	ethernet_init(iface);
62 
63 	/* Assumes PSI is already started and link is up, iface will auto-start after init */
64 	net_eth_carrier_on(iface);
65 
66 	for (int i = 0; i < NETC_MSIX_EVENTS_COUNT; i++) {
67 		msix = &cfg->msix[i];
68 		if (msix->mbox_channel.dev != NULL) {
69 			if (mbox_set_enabled(&msix->mbox_channel, true)) {
70 				LOG_ERR("Failed to enable MRU channel %u", msix->mbox_channel.id);
71 			}
72 		}
73 	}
74 }
75 
76 static const struct ethernet_api nxp_s32_eth_api = {
77 	.iface_api.init = nxp_s32_eth_iface_init,
78 	.get_capabilities = nxp_s32_eth_get_capabilities,
79 	.set_config = nxp_s32_eth_set_config,
80 	.send = nxp_s32_eth_tx
81 };
82 
83 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nxp_s32_netc_vsi) == 1, "Only one VSI enabled supported");
84 
85 #define NETC_VSI_INSTANCE_DEFINE(n)								\
86 	NETC_GENERATE_MAC_ADDRESS(VSI_NODE(n), n)						\
87 												\
88 	static void nxp_s32_eth##n##_rx_callback(const uint8_t unused, const uint8_t ring)	\
89 	{											\
90 		const struct device *dev = DEVICE_DT_GET(VSI_NODE(n));				\
91 		const struct nxp_s32_eth_config *cfg = dev->config;				\
92 		struct nxp_s32_eth_data *ctx = dev->data;					\
93 												\
94 		if (ring == cfg->rx_ring_idx) {							\
95 			k_sem_give(&ctx->rx_sem);						\
96 		}										\
97 	}											\
98 												\
99 	static Netc_Eth_Ip_StateType nxp_s32_eth##n##_state;					\
100 	Netc_Eth_Ip_VsiToPsiMsgType nxp_s32_eth##n##_vsi2psi_msg				\
101 		__aligned(FEATURE_NETC_ETH_VSI_MSG_ALIGNMENT);					\
102 	static Netc_Eth_Ip_MACFilterHashTableEntryType						\
103 	nxp_s32_eth##n##_mac_filter_hash_table[CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE];	\
104 												\
105 	NETC_RX_RING(n, TX_RING_IDX, CONFIG_ETH_NXP_S32_RX_RING_LEN,				\
106 			 CONFIG_ETH_NXP_S32_RX_RING_BUF_SIZE);					\
107 	NETC_TX_RING(n, RX_RING_IDX, CONFIG_ETH_NXP_S32_TX_RING_LEN,				\
108 			 CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE);					\
109 												\
110 	static const Netc_Eth_Ip_RxRingConfigType nxp_s32_eth##n##_rxring_cfg[1] = {		\
111 		{										\
112 			.RingDesc = nxp_s32_eth##n##_rxring0_desc,				\
113 			.Buffer = nxp_s32_eth##n##_rxring0_buf,					\
114 			.ringSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,				\
115 			.maxRingSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,				\
116 			.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
117 			.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
118 			.TimerThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_TIMER_THRESHOLD,		\
119 			.PacketsThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_PACKET_THRESHOLD,		\
120 			.Callback = nxp_s32_eth##n##_rx_callback,				\
121 		}										\
122 	};											\
123 	static const Netc_Eth_Ip_TxRingConfigType nxp_s32_eth##n##_txring_cfg[1] = {		\
124 		{										\
125 			.RingDesc = nxp_s32_eth##n##_txring0_desc,				\
126 			.Buffer = nxp_s32_eth##n##_txring0_buf,					\
127 			.ringSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,				\
128 			.maxRingSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,				\
129 			.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
130 			.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,			\
131 		}										\
132 	};											\
133 												\
134 	static const Netc_Eth_Ip_StationInterfaceConfigType nxp_s32_eth##n##_si_cfg = {		\
135 		.NumberOfRxBDR = 1,								\
136 		.NumberOfTxBDR = 1,								\
137 		.txMruMailboxAddr = NULL,							\
138 		.rxMruMailboxAddr = (uint32_t *)MRU_MBOX_ADDR(VSI_NODE(n), rx),			\
139 		.RxInterrupts = (uint32_t)true,							\
140 		.TxInterrupts = (uint32_t)false,						\
141 		.MACFilterTableMaxNumOfEntries = CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE,	\
142 		.VSItoPSIMsgCommand = &nxp_s32_eth##n##_vsi2psi_msg,				\
143 	};											\
144 												\
145 	static struct nxp_s32_eth_data nxp_s32_eth##n##_data = {				\
146 		.mac_addr = DT_PROP_OR(VSI_NODE(n), local_mac_address, {0}),			\
147 	};											\
148 												\
149 	static const struct nxp_s32_eth_config nxp_s32_eth##n##_cfg = {				\
150 		.netc_cfg = {									\
151 			.SiType = NETC_ETH_IP_VIRTUAL_SI,					\
152 			.siConfig = &nxp_s32_eth##n##_si_cfg,					\
153 			.stateStructure = &nxp_s32_eth##n##_state,				\
154 			.paCtrlRxRingConfig = &nxp_s32_eth##n##_rxring_cfg,			\
155 			.paCtrlTxRingConfig = &nxp_s32_eth##n##_txring_cfg,			\
156 		},										\
157 		.si_idx = n,									\
158 		.tx_ring_idx = TX_RING_IDX,							\
159 		.rx_ring_idx = RX_RING_IDX,							\
160 		.msix = {									\
161 			NETC_MSIX(VSI_NODE(n), rx, Netc_Eth_Ip_##n##_MSIX_RxEvent),		\
162 		},										\
163 		.mac_filter_hash_table = &nxp_s32_eth##n##_mac_filter_hash_table[0],		\
164 		.generate_mac = nxp_s32_eth##n##_generate_mac,					\
165 	};											\
166 												\
167 	ETH_NET_DEVICE_DT_DEFINE(VSI_NODE(n),							\
168 				nxp_s32_eth_initialize_common,					\
169 				NULL,								\
170 				&nxp_s32_eth##n##_data,						\
171 				&nxp_s32_eth##n##_cfg,						\
172 				CONFIG_ETH_NXP_S32_VSI_INIT_PRIORITY,				\
173 				&nxp_s32_eth_api,						\
174 				NET_ETH_MTU)
175 
176 #if DT_NODE_HAS_STATUS(VSI_NODE(1), okay)
177 NETC_VSI_INSTANCE_DEFINE(1);
178 #endif
179 
180 #if DT_NODE_HAS_STATUS(VSI_NODE(2), okay)
181 NETC_VSI_INSTANCE_DEFINE(2);
182 #endif
183 
184 #if DT_NODE_HAS_STATUS(VSI_NODE(3), okay)
185 NETC_VSI_INSTANCE_DEFINE(3);
186 #endif
187 
188 #if DT_NODE_HAS_STATUS(VSI_NODE(4), okay)
189 NETC_VSI_INSTANCE_DEFINE(4);
190 #endif
191 
192 #if DT_NODE_HAS_STATUS(VSI_NODE(5), okay)
193 NETC_VSI_INSTANCE_DEFINE(5);
194 #endif
195 
196 #if DT_NODE_HAS_STATUS(VSI_NODE(6), okay)
197 NETC_VSI_INSTANCE_DEFINE(6);
198 #endif
199 
200 #if DT_NODE_HAS_STATUS(VSI_NODE(7), okay)
201 NETC_VSI_INSTANCE_DEFINE(7);
202 #endif
203