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