1 /*
2  * Copyright (c) 2019 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT litex_eth0
8 
9 #define LOG_MODULE_NAME eth_liteeth
10 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
11 
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
14 
15 #include <zephyr/kernel.h>
16 #include <zephyr/device.h>
17 #include <soc.h>
18 #include <stdbool.h>
19 #include <zephyr/net/ethernet.h>
20 #include <zephyr/net/net_if.h>
21 #include <zephyr/net/net_pkt.h>
22 
23 #include <zephyr/sys/printk.h>
24 #include <zephyr/irq.h>
25 
26 #include "eth.h"
27 
28 /* flags */
29 #define LITEETH_EV_TX		0x1
30 #define LITEETH_EV_RX		0x1
31 
32 /* slots */
33 #define LITEETH_SLOT_BASE_ADDR		DT_INST_REG_ADDR_BY_NAME(0, buffers)
34 #define LITEETH_SLOT_RX0_ADDR		(LITEETH_SLOT_BASE_ADDR + 0x0000)
35 #define LITEETH_SLOT_RX1_ADDR		(LITEETH_SLOT_BASE_ADDR + 0x0800)
36 #define LITEETH_SLOT_TX0_ADDR		(LITEETH_SLOT_BASE_ADDR + 0x1000)
37 #define LITEETH_SLOT_TX1_ADDR		(LITEETH_SLOT_BASE_ADDR + 0x1800)
38 
39 /* sram - rx */
40 #define LITEETH_RX_SLOT_ADDR		DT_INST_REG_ADDR_BY_NAME(0, rx_slot)
41 #define LITEETH_RX_LENGTH_ADDR		DT_INST_REG_ADDR_BY_NAME(0, rx_length)
42 #define LITEETH_RX_EV_PENDING_ADDR	DT_INST_REG_ADDR_BY_NAME(0, rx_ev_pending)
43 #define LITEETH_RX_EV_ENABLE_ADDR	DT_INST_REG_ADDR_BY_NAME(0, rx_ev_enable)
44 
45 /* sram - tx */
46 #define LITEETH_TX_START_ADDR		DT_INST_REG_ADDR_BY_NAME(0, tx_start)
47 #define LITEETH_TX_READY_ADDR		DT_INST_REG_ADDR_BY_NAME(0, tx_ready)
48 #define LITEETH_TX_SLOT_ADDR		DT_INST_REG_ADDR_BY_NAME(0, tx_slot)
49 #define LITEETH_TX_LENGTH_ADDR		DT_INST_REG_ADDR_BY_NAME(0, tx_length)
50 #define LITEETH_TX_EV_PENDING_ADDR	DT_INST_REG_ADDR_BY_NAME(0, tx_ev_pending)
51 
52 /* irq */
53 #define LITEETH_IRQ			DT_INST_IRQN(0)
54 #define LITEETH_IRQ_PRIORITY		DT_INST_IRQ(0, priority)
55 
56 #define MAX_TX_FAILURE 100
57 
58 struct eth_liteeth_dev_data {
59 	struct net_if *iface;
60 	uint8_t mac_addr[6];
61 
62 	uint8_t txslot;
63 	uint8_t rxslot;
64 
65 	uint8_t *tx_buf[2];
66 	uint8_t *rx_buf[2];
67 };
68 
69 struct eth_liteeth_config {
70 	void (*config_func)(void);
71 };
72 
eth_initialize(const struct device * dev)73 static int eth_initialize(const struct device *dev)
74 {
75 	const struct eth_liteeth_config *config = dev->config;
76 
77 	config->config_func();
78 
79 	return 0;
80 }
81 
eth_tx(const struct device * dev,struct net_pkt * pkt)82 static int eth_tx(const struct device *dev, struct net_pkt *pkt)
83 {
84 	unsigned int key;
85 	uint16_t len;
86 	struct eth_liteeth_dev_data *context = dev->data;
87 
88 	key = irq_lock();
89 	int attempts = 0;
90 
91 	/* get data from packet and send it */
92 	len = net_pkt_get_len(pkt);
93 	net_pkt_read(pkt, context->tx_buf[context->txslot], len);
94 
95 	litex_write8(context->txslot, LITEETH_TX_SLOT_ADDR);
96 	litex_write16(len, LITEETH_TX_LENGTH_ADDR);
97 
98 	/* wait for the device to be ready to transmit */
99 	while (litex_read8(LITEETH_TX_READY_ADDR) == 0) {
100 		if (attempts++ == MAX_TX_FAILURE) {
101 			goto error;
102 		}
103 		k_sleep(K_MSEC(1));
104 	}
105 
106 	/* start transmitting */
107 	litex_write8(1, LITEETH_TX_START_ADDR);
108 
109 	/* change slot */
110 	context->txslot = (context->txslot + 1) % 2;
111 
112 	irq_unlock(key);
113 
114 	return 0;
115 error:
116 	irq_unlock(key);
117 	LOG_ERR("TX fifo failed");
118 	return -1;
119 }
120 
eth_rx(const struct device * port)121 static void eth_rx(const struct device *port)
122 {
123 	struct net_pkt *pkt;
124 	struct eth_liteeth_dev_data *context = port->data;
125 
126 	int r;
127 	unsigned int key;
128 	uint16_t len = 0;
129 
130 	key = irq_lock();
131 
132 	/* get frame's length */
133 	len = litex_read16(LITEETH_RX_LENGTH_ADDR);
134 
135 	/* which slot is the frame in */
136 	context->rxslot = litex_read8(LITEETH_RX_SLOT_ADDR);
137 
138 	/* obtain rx buffer */
139 	pkt = net_pkt_rx_alloc_with_buffer(context->iface, len, AF_UNSPEC, 0,
140 					   K_NO_WAIT);
141 	if (pkt == NULL) {
142 		LOG_ERR("Failed to obtain RX buffer");
143 		goto out;
144 	}
145 
146 	/* copy data to buffer */
147 	if (net_pkt_write(pkt, (void *)context->rx_buf[context->rxslot], len) != 0) {
148 		LOG_ERR("Failed to append RX buffer to context buffer");
149 		net_pkt_unref(pkt);
150 		goto out;
151 	}
152 
153 	/* receive data */
154 	r = net_recv_data(context->iface, pkt);
155 	if (r < 0) {
156 		LOG_ERR("Failed to enqueue frame into RX queue: %d", r);
157 		net_pkt_unref(pkt);
158 	}
159 
160 out:
161 	irq_unlock(key);
162 }
163 
eth_irq_handler(const struct device * port)164 static void eth_irq_handler(const struct device *port)
165 {
166 	/* check sram reader events (tx) */
167 	if (litex_read8(LITEETH_TX_EV_PENDING_ADDR) & LITEETH_EV_TX) {
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(LITEETH_EV_TX, LITEETH_TX_EV_PENDING_ADDR);
172 	}
173 
174 	/* check sram writer events (rx) */
175 	if (litex_read8(LITEETH_RX_EV_PENDING_ADDR) & LITEETH_EV_RX) {
176 		eth_rx(port);
177 
178 		/* ack writer irq */
179 		litex_write8(LITEETH_EV_RX, LITEETH_RX_EV_PENDING_ADDR);
180 	}
181 }
182 
183 #ifdef CONFIG_ETH_LITEETH_0
184 
185 static struct eth_liteeth_dev_data eth_data = {
186 	.mac_addr =  DT_INST_PROP(0, local_mac_address)
187 };
188 
189 static void eth_irq_config(void);
190 static const struct eth_liteeth_config eth_config = {
191 	.config_func = eth_irq_config,
192 };
193 
eth_iface_init(struct net_if * iface)194 static void eth_iface_init(struct net_if *iface)
195 {
196 	const struct device *port = net_if_get_device(iface);
197 	struct eth_liteeth_dev_data *context = port->data;
198 	static bool init_done;
199 
200 	/* initialize only once */
201 	if (init_done) {
202 		return;
203 	}
204 
205 	/* set interface */
206 	context->iface = iface;
207 
208 	/* initialize ethernet L2 */
209 	ethernet_init(iface);
210 
211 #if DT_INST_PROP(0, zephyr_random_mac_address)
212 	/* generate random MAC address */
213 	gen_random_mac(context->mac_addr, 0x10, 0xe2, 0xd5);
214 #endif
215 
216 	/* set MAC address */
217 	if (net_if_set_link_addr(iface, context->mac_addr, sizeof(context->mac_addr),
218 			     NET_LINK_ETHERNET) < 0) {
219 		LOG_ERR("setting mac failed");
220 		return;
221 	}
222 
223 	/* clear pending events */
224 	litex_write8(LITEETH_EV_TX, LITEETH_TX_EV_PENDING_ADDR);
225 	litex_write8(LITEETH_EV_RX, LITEETH_RX_EV_PENDING_ADDR);
226 
227 	/* setup tx slots */
228 	context->txslot = 0;
229 	context->tx_buf[0] = (uint8_t *)LITEETH_SLOT_TX0_ADDR;
230 	context->tx_buf[1] = (uint8_t *)LITEETH_SLOT_TX1_ADDR;
231 
232 	/* setup rx slots */
233 	context->rxslot = 0;
234 	context->rx_buf[0] = (uint8_t *)LITEETH_SLOT_RX0_ADDR;
235 	context->rx_buf[1] = (uint8_t *)LITEETH_SLOT_RX1_ADDR;
236 
237 	init_done = true;
238 }
239 
eth_caps(const struct device * dev)240 static enum ethernet_hw_caps eth_caps(const struct device *dev)
241 {
242 	ARG_UNUSED(dev);
243 	return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T |
244 	       ETHERNET_LINK_1000BASE_T;
245 }
246 
247 static const struct ethernet_api eth_api = {
248 	.iface_api.init = eth_iface_init,
249 	.get_capabilities = eth_caps,
250 	.send = eth_tx
251 };
252 
253 NET_DEVICE_DT_INST_DEFINE(0, eth_initialize, NULL,
254 		&eth_data, &eth_config, CONFIG_ETH_INIT_PRIORITY, &eth_api,
255 		ETHERNET_L2, NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);
256 
eth_irq_config(void)257 static void eth_irq_config(void)
258 {
259 	IRQ_CONNECT(LITEETH_IRQ, LITEETH_IRQ_PRIORITY, eth_irq_handler,
260 		    DEVICE_DT_INST_GET(0), 0);
261 	irq_enable(LITEETH_IRQ);
262 	litex_write8(1, LITEETH_RX_EV_ENABLE_ADDR);
263 }
264 
265 #endif /* CONFIG_ETH_LITEETH_0 */
266