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