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, &eth_data##n, &eth_config##n,       \
354 				      CONFIG_ETH_INIT_PRIORITY, &eth_api, NET_ETH_MTU);
355 
356 DT_INST_FOREACH_STATUS_OKAY(ETH_LITEX_INIT);
357