1 /*
2 * Copyright (c) 2019 Antmicro <www.antmicro.com>
3 * Copyright (c) 2024 Vogl Electronic GmbH
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT litex_liteeth
9
10 #define LOG_MODULE_NAME eth_litex_liteeth
11 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
12
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
15
16 #include <zephyr/kernel.h>
17 #include <zephyr/device.h>
18 #include <soc.h>
19 #include <stdbool.h>
20 #include <zephyr/net/ethernet.h>
21 #include <zephyr/net/net_if.h>
22 #include <zephyr/net/net_pkt.h>
23 #include <zephyr/net/phy.h>
24
25 #include <zephyr/sys/printk.h>
26 #include <zephyr/irq.h>
27
28 #include "eth.h"
29
30 #define MAX_TX_FAILURE 100
31
32 struct eth_litex_dev_data {
33 struct net_if *iface;
34 uint8_t mac_addr[6];
35 uint8_t txslot;
36 };
37
38 struct eth_litex_config {
39 const struct device *phy_dev;
40 void (*config_func)(const struct device *dev);
41 bool random_mac_address;
42 uint32_t rx_slot_addr;
43 uint32_t rx_length_addr;
44 uint32_t rx_ev_pending_addr;
45 uint32_t rx_ev_enable_addr;
46 uint32_t tx_start_addr;
47 uint32_t tx_ready_addr;
48 uint32_t tx_slot_addr;
49 uint32_t tx_length_addr;
50 uint32_t tx_ev_pending_addr;
51 uint32_t tx_ev_enable_addr;
52 uint8_t *tx_buf[2];
53 uint8_t *rx_buf[2];
54 };
55
eth_initialize(const struct device * dev)56 static int eth_initialize(const struct device *dev)
57 {
58 const struct eth_litex_config *config = dev->config;
59 struct eth_litex_dev_data *context = dev->data;
60
61 config->config_func(dev);
62
63 /* TX event is disabled because it isn't used by this driver */
64 litex_write8(0, config->tx_ev_enable_addr);
65
66 if (config->random_mac_address) {
67 /* generate random MAC address */
68 gen_random_mac(context->mac_addr, 0x10, 0xe2, 0xd5);
69 }
70
71 return 0;
72 }
73
eth_tx(const struct device * dev,struct net_pkt * pkt)74 static int eth_tx(const struct device *dev, struct net_pkt *pkt)
75 {
76 unsigned int key;
77 uint16_t len;
78 struct eth_litex_dev_data *context = dev->data;
79 const struct eth_litex_config *config = dev->config;
80
81 key = irq_lock();
82 int attempts = 0;
83
84 /* get data from packet and send it */
85 len = net_pkt_get_len(pkt);
86 net_pkt_read(pkt, config->tx_buf[context->txslot], len);
87
88 litex_write8(context->txslot, config->tx_slot_addr);
89 litex_write16(len, config->tx_length_addr);
90
91 /* wait for the device to be ready to transmit */
92 while (litex_read8(config->tx_ready_addr) == 0) {
93 if (attempts++ == MAX_TX_FAILURE) {
94 goto error;
95 }
96 k_sleep(K_MSEC(1));
97 }
98
99 /* start transmitting */
100 litex_write8(1, config->tx_start_addr);
101
102 /* change slot */
103 context->txslot = (context->txslot + 1) % 2;
104
105 irq_unlock(key);
106
107 return 0;
108 error:
109 irq_unlock(key);
110 LOG_ERR("TX fifo failed");
111 return -1;
112 }
113
eth_rx(const struct device * port)114 static void eth_rx(const struct device *port)
115 {
116 struct net_pkt *pkt;
117 struct eth_litex_dev_data *context = port->data;
118 const struct eth_litex_config *config = port->config;
119
120 int r;
121 unsigned int key;
122 uint16_t len = 0;
123 uint8_t rxslot = 0;
124
125 if (!net_if_flag_is_set(context->iface, NET_IF_UP)) {
126 return;
127 }
128
129 key = irq_lock();
130
131 /* get frame's length */
132 len = litex_read16(config->rx_length_addr);
133
134 /* which slot is the frame in */
135 rxslot = litex_read8(config->rx_slot_addr);
136
137 /* obtain rx buffer */
138 pkt = net_pkt_rx_alloc_with_buffer(context->iface, len, AF_UNSPEC, 0,
139 K_NO_WAIT);
140 if (pkt == NULL) {
141 LOG_ERR("Failed to obtain RX buffer");
142 goto out;
143 }
144
145 /* copy data to buffer */
146 if (net_pkt_write(pkt, (void *)config->rx_buf[rxslot], len) != 0) {
147 LOG_ERR("Failed to append RX buffer to context buffer");
148 net_pkt_unref(pkt);
149 goto out;
150 }
151
152 /* receive data */
153 r = net_recv_data(context->iface, pkt);
154 if (r < 0) {
155 LOG_ERR("Failed to enqueue frame into RX queue: %d", r);
156 net_pkt_unref(pkt);
157 }
158
159 out:
160 irq_unlock(key);
161 }
162
eth_irq_handler(const struct device * port)163 static void eth_irq_handler(const struct device *port)
164 {
165 const struct eth_litex_config *config = port->config;
166 /* check sram reader events (tx) */
167 if (litex_read8(config->tx_ev_pending_addr) & BIT(0)) {
168 /* TX event is not enabled nor used by this driver; ack just
169 * in case if some rogue TX event appeared
170 */
171 litex_write8(BIT(0), config->tx_ev_pending_addr);
172 }
173
174 /* check sram writer events (rx) */
175 if (litex_read8(config->rx_ev_pending_addr) & BIT(0)) {
176 eth_rx(port);
177
178 /* ack writer irq */
179 litex_write8(BIT(0), config->rx_ev_pending_addr);
180 }
181 }
182
eth_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)183 static int eth_set_config(const struct device *dev, enum ethernet_config_type type,
184 const struct ethernet_config *config)
185 {
186 struct eth_litex_dev_data *context = dev->data;
187 int ret = -ENOTSUP;
188
189 switch (type) {
190 case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
191 memcpy(context->mac_addr, config->mac_address.addr, sizeof(context->mac_addr));
192 ret = net_if_set_link_addr(context->iface, context->mac_addr,
193 sizeof(context->mac_addr), NET_LINK_ETHERNET);
194 break;
195 default:
196 break;
197 }
198
199 return ret;
200 }
201
eth_start(const struct device * dev)202 static int eth_start(const struct device *dev)
203 {
204 const struct eth_litex_config *config = dev->config;
205
206 litex_write8(1, config->rx_ev_enable_addr);
207
208 litex_write8(BIT(0), config->tx_ev_pending_addr);
209 litex_write8(BIT(0), config->rx_ev_pending_addr);
210
211 return 0;
212 }
213
eth_stop(const struct device * dev)214 static int eth_stop(const struct device *dev)
215 {
216 const struct eth_litex_config *config = dev->config;
217
218 litex_write8(0, config->rx_ev_enable_addr);
219
220 return 0;
221 }
222
eth_get_phy(const struct device * dev)223 static const struct device *eth_get_phy(const struct device *dev)
224 {
225 const struct eth_litex_config *config = dev->config;
226
227 return config->phy_dev;
228 }
229
phy_link_state_changed(const struct device * phy_dev,struct phy_link_state * state,void * user_data)230 static void phy_link_state_changed(const struct device *phy_dev,
231 struct phy_link_state *state,
232 void *user_data)
233 {
234 const struct device *dev = (const struct device *)user_data;
235 struct eth_litex_dev_data *context = dev->data;
236
237 ARG_UNUSED(phy_dev);
238
239 if (state->is_up) {
240 net_eth_carrier_on(context->iface);
241 } else {
242 net_eth_carrier_off(context->iface);
243 }
244 }
245
eth_iface_init(struct net_if * iface)246 static void eth_iface_init(struct net_if *iface)
247 {
248 const struct device *port = net_if_get_device(iface);
249 const struct eth_litex_config *config = port->config;
250 struct eth_litex_dev_data *context = port->data;
251
252 /* set interface */
253 if (context->iface == NULL) {
254 context->iface = iface;
255 }
256
257 /* initialize ethernet L2 */
258 ethernet_init(iface);
259
260 /* set MAC address */
261 if (net_if_set_link_addr(iface, context->mac_addr, sizeof(context->mac_addr),
262 NET_LINK_ETHERNET) < 0) {
263 LOG_ERR("setting mac failed");
264 return;
265 }
266
267 if (config->phy_dev == NULL) {
268 LOG_WRN("No PHY device");
269 return;
270 }
271
272 net_if_carrier_off(iface);
273
274 if (device_is_ready(config->phy_dev)) {
275 phy_link_callback_set(config->phy_dev, phy_link_state_changed, (void *)port);
276 } else {
277 LOG_ERR("PHY device not ready");
278 }
279 }
280
eth_caps(const struct device * dev)281 static enum ethernet_hw_caps eth_caps(const struct device *dev)
282 {
283 ARG_UNUSED(dev);
284
285 return
286 #ifdef CONFIG_NET_VLAN
287 ETHERNET_HW_VLAN |
288 #endif
289 ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T | ETHERNET_LINK_1000BASE_T;
290 }
291
292 static const struct ethernet_api eth_api = {
293 .iface_api.init = eth_iface_init,
294 .start = eth_start,
295 .stop = eth_stop,
296 .get_capabilities = eth_caps,
297 .set_config = eth_set_config,
298 .get_phy = eth_get_phy,
299 .send = eth_tx
300 };
301
302 #define ETH_LITEX_SLOT_SIZE 0x0800
303
304 #define ETH_LITEX_SLOT_RX0_ADDR(n) \
305 DT_INST_REG_ADDR_BY_NAME_OR(n, rx_buffers, (DT_INST_REG_ADDR_BY_NAME(n, buffers)))
306 #define ETH_LITEX_SLOT_RX1_ADDR(n) (ETH_LITEX_SLOT_RX0_ADDR(n) + ETH_LITEX_SLOT_SIZE)
307 #define ETH_LITEX_SLOT_TX0_ADDR(n) \
308 DT_INST_REG_ADDR_BY_NAME_OR(n, tx_buffers, \
309 (DT_INST_REG_ADDR_BY_NAME(n, buffers) + \
310 (DT_INST_REG_SIZE_BY_NAME(n, buffers) / 2)))
311 #define ETH_LITEX_SLOT_TX1_ADDR(n) (ETH_LITEX_SLOT_TX0_ADDR(n) + ETH_LITEX_SLOT_SIZE)
312
313 #define ETH_LITEX_INIT(n) \
314 \
315 static void eth_irq_config##n(const struct device *dev) \
316 { \
317 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), eth_irq_handler, \
318 DEVICE_DT_INST_GET(n), 0); \
319 \
320 irq_enable(DT_INST_IRQN(n)); \
321 } \
322 \
323 static struct eth_litex_dev_data eth_data##n = { \
324 .mac_addr = DT_INST_PROP(n, local_mac_address)}; \
325 \
326 static const struct eth_litex_config eth_config##n = { \
327 IF_ENABLED(DT_INST_NODE_HAS_PROP(n, phy_handle), \
328 (.phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, phy_handle)),)) \
329 .config_func = eth_irq_config##n, \
330 .random_mac_address = DT_INST_PROP(n, zephyr_random_mac_address), \
331 .rx_slot_addr = DT_INST_REG_ADDR_BY_NAME(n, rx_slot), \
332 .rx_length_addr = DT_INST_REG_ADDR_BY_NAME(n, rx_length), \
333 .rx_ev_pending_addr = DT_INST_REG_ADDR_BY_NAME(n, rx_ev_pending), \
334 .rx_ev_enable_addr = DT_INST_REG_ADDR_BY_NAME(n, rx_ev_enable), \
335 .tx_start_addr = DT_INST_REG_ADDR_BY_NAME(n, tx_start), \
336 .tx_ready_addr = DT_INST_REG_ADDR_BY_NAME(n, tx_ready), \
337 .tx_slot_addr = DT_INST_REG_ADDR_BY_NAME(n, tx_slot), \
338 .tx_length_addr = DT_INST_REG_ADDR_BY_NAME(n, tx_length), \
339 .tx_ev_pending_addr = DT_INST_REG_ADDR_BY_NAME(n, tx_ev_pending), \
340 .tx_ev_enable_addr = DT_INST_REG_ADDR_BY_NAME(n, tx_ev_enable), \
341 .rx_buf = { \
342 (uint8_t *)ETH_LITEX_SLOT_RX0_ADDR(n), \
343 (uint8_t *)ETH_LITEX_SLOT_RX1_ADDR(n), \
344 \
345 }, \
346 .tx_buf = { \
347 (uint8_t *)ETH_LITEX_SLOT_TX0_ADDR(n), \
348 (uint8_t *)ETH_LITEX_SLOT_TX1_ADDR(n), \
349 }, \
350 \
351 }; \
352 \
353 ETH_NET_DEVICE_DT_INST_DEFINE(n, eth_initialize, NULL, ð_data##n, ð_config##n, \
354 CONFIG_ETH_INIT_PRIORITY, ð_api, NET_ETH_MTU);
355
356 DT_INST_FOREACH_STATUS_OKAY(ETH_LITEX_INIT);
357