1 /*
2  * Copyright (c) 2022 Libre Solar Technologies GmbH
3  * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT espressif_esp32_usb_serial
9 
10 #include <hal/usb_serial_jtag_ll.h>
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/device.h>
14 #include <errno.h>
15 #include <soc.h>
16 #include <zephyr/drivers/uart.h>
17 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
18 #include <zephyr/drivers/clock_control.h>
19 #include <zephyr/sys/util.h>
20 #include <esp_attr.h>
21 
22 /*
23  * Timeout after which the poll_out function stops waiting for space in the tx fifo.
24  *
25  * Without this timeout, the function would get stuck forever and block the processor if no host is
26  * connected to the USB port.
27  *
28  * USB full-speed uses a frame rate of 1 ms. Thus, a timeout of 50 ms provides plenty of safety
29  * margin even for a loaded bus. This is the same value as used in the ESP-IDF.
30  */
31 #define USBSERIAL_POLL_OUT_TIMEOUT_MS (50U)
32 
33 struct serial_esp32_usb_config {
34 	const struct device *clock_dev;
35 	const clock_control_subsys_t clock_subsys;
36 	int irq_source;
37 	int irq_priority;
38 	int irq_flags;
39 };
40 
41 struct serial_esp32_usb_data {
42 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
43 	uart_irq_callback_user_data_t irq_cb;
44 	void *irq_cb_data;
45 #endif
46 	int64_t last_tx_time;
47 };
48 
49 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
50 static void serial_esp32_usb_isr(void *arg);
51 #endif
52 
serial_esp32_usb_poll_in(const struct device * dev,unsigned char * p_char)53 static int serial_esp32_usb_poll_in(const struct device *dev, unsigned char *p_char)
54 {
55 	if (!usb_serial_jtag_ll_rxfifo_data_available()) {
56 		return -1;
57 	}
58 
59 	usb_serial_jtag_ll_read_rxfifo(p_char, 1);
60 
61 	return 0;
62 }
63 
serial_esp32_usb_poll_out(const struct device * dev,unsigned char c)64 static void serial_esp32_usb_poll_out(const struct device *dev, unsigned char c)
65 {
66 	struct serial_esp32_usb_data *data = dev->data;
67 
68 	/*
69 	 * If there is no USB host connected, this function will busy-wait once for the timeout
70 	 * period, but return immediately for subsequent calls.
71 	 */
72 	do {
73 		if (usb_serial_jtag_ll_txfifo_writable()) {
74 			usb_serial_jtag_ll_write_txfifo(&c, 1);
75 			usb_serial_jtag_ll_txfifo_flush();
76 			data->last_tx_time = k_uptime_get();
77 			return;
78 		}
79 	} while ((k_uptime_get() - data->last_tx_time) < USBSERIAL_POLL_OUT_TIMEOUT_MS);
80 }
81 
serial_esp32_usb_err_check(const struct device * dev)82 static int serial_esp32_usb_err_check(const struct device *dev)
83 {
84 	ARG_UNUSED(dev);
85 
86 	return 0;
87 }
88 
serial_esp32_usb_init(const struct device * dev)89 static int serial_esp32_usb_init(const struct device *dev)
90 {
91 	const struct serial_esp32_usb_config *config = dev->config;
92 
93 	if (!device_is_ready(config->clock_dev)) {
94 		return -ENODEV;
95 	}
96 
97 	int ret = clock_control_on(config->clock_dev, config->clock_subsys);
98 
99 	if (ret != 0) {
100 		return ret;
101 	}
102 
103 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
104 	ret = esp_intr_alloc(config->irq_source,
105 			ESP_PRIO_TO_FLAGS(config->irq_priority) |
106 			ESP_INT_FLAGS_CHECK(config->irq_flags),
107 			(intr_handler_t)serial_esp32_usb_isr,
108 			(void *)dev, NULL);
109 #endif
110 	return ret;
111 }
112 
113 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
114 
serial_esp32_usb_fifo_fill(const struct device * dev,const uint8_t * tx_data,int len)115 static int serial_esp32_usb_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
116 {
117 	ARG_UNUSED(dev);
118 
119 	int ret = usb_serial_jtag_ll_write_txfifo(tx_data, len);
120 
121 	usb_serial_jtag_ll_txfifo_flush();
122 
123 	return ret;
124 }
125 
serial_esp32_usb_fifo_read(const struct device * dev,uint8_t * rx_data,const int len)126 static int serial_esp32_usb_fifo_read(const struct device *dev, uint8_t *rx_data, const int len)
127 {
128 	ARG_UNUSED(dev);
129 
130 	return usb_serial_jtag_ll_read_rxfifo(rx_data, len);
131 }
132 
serial_esp32_usb_irq_tx_enable(const struct device * dev)133 static void serial_esp32_usb_irq_tx_enable(const struct device *dev)
134 {
135 	struct serial_esp32_usb_data *data = dev->data;
136 
137 	usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
138 	usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
139 
140 	if (data->irq_cb != NULL) {
141 		unsigned int key = irq_lock();
142 		data->irq_cb(dev, data->irq_cb_data);
143 		arch_irq_unlock(key);
144 	}
145 }
146 
serial_esp32_usb_irq_tx_disable(const struct device * dev)147 static void serial_esp32_usb_irq_tx_disable(const struct device *dev)
148 {
149 	ARG_UNUSED(dev);
150 
151 	usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
152 }
153 
serial_esp32_usb_irq_tx_ready(const struct device * dev)154 static int serial_esp32_usb_irq_tx_ready(const struct device *dev)
155 {
156 	ARG_UNUSED(dev);
157 
158 	return (usb_serial_jtag_ll_txfifo_writable() &&
159 		usb_serial_jtag_ll_get_intr_ena_status() & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
160 }
161 
serial_esp32_usb_irq_rx_enable(const struct device * dev)162 static void serial_esp32_usb_irq_rx_enable(const struct device *dev)
163 {
164 	ARG_UNUSED(dev);
165 
166 	usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
167 	usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
168 }
169 
serial_esp32_usb_irq_rx_disable(const struct device * dev)170 static void serial_esp32_usb_irq_rx_disable(const struct device *dev)
171 {
172 	ARG_UNUSED(dev);
173 
174 	usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
175 }
176 
serial_esp32_usb_irq_tx_complete(const struct device * dev)177 static int serial_esp32_usb_irq_tx_complete(const struct device *dev)
178 {
179 	ARG_UNUSED(dev);
180 
181 	return usb_serial_jtag_ll_txfifo_writable();
182 }
183 
serial_esp32_usb_irq_rx_ready(const struct device * dev)184 static int serial_esp32_usb_irq_rx_ready(const struct device *dev)
185 {
186 	ARG_UNUSED(dev);
187 
188 	return usb_serial_jtag_ll_rxfifo_data_available();
189 }
190 
serial_esp32_usb_irq_err_enable(const struct device * dev)191 static void serial_esp32_usb_irq_err_enable(const struct device *dev)
192 {
193 	ARG_UNUSED(dev);
194 }
195 
serial_esp32_usb_irq_err_disable(const struct device * dev)196 static void serial_esp32_usb_irq_err_disable(const struct device *dev)
197 {
198 	ARG_UNUSED(dev);
199 }
200 
serial_esp32_usb_irq_is_pending(const struct device * dev)201 static int serial_esp32_usb_irq_is_pending(const struct device *dev)
202 {
203 	return serial_esp32_usb_irq_rx_ready(dev) || serial_esp32_usb_irq_tx_ready(dev);
204 }
205 
serial_esp32_usb_irq_update(const struct device * dev)206 static int serial_esp32_usb_irq_update(const struct device *dev)
207 {
208 	ARG_UNUSED(dev);
209 
210 	usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
211 	usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
212 
213 	return 1;
214 }
215 
serial_esp32_usb_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)216 static void serial_esp32_usb_irq_callback_set(const struct device *dev,
217 					      uart_irq_callback_user_data_t cb, void *cb_data)
218 {
219 	struct serial_esp32_usb_data *data = dev->data;
220 
221 	data->irq_cb_data = cb_data;
222 	data->irq_cb = cb;
223 }
224 
serial_esp32_usb_isr(void * arg)225 static void serial_esp32_usb_isr(void *arg)
226 {
227 	const struct device *dev = (const struct device *)arg;
228 	struct serial_esp32_usb_data *data = dev->data;
229 	uint32_t uart_intr_status = usb_serial_jtag_ll_get_intsts_mask();
230 
231 	if (uart_intr_status == 0) {
232 		return;
233 	}
234 	usb_serial_jtag_ll_clr_intsts_mask(uart_intr_status);
235 
236 	if (data->irq_cb != NULL) {
237 		data->irq_cb(dev, data->irq_cb_data);
238 	}
239 }
240 
241 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
242 
243 static DEVICE_API(uart, serial_esp32_usb_api) = {
244 	.poll_in = serial_esp32_usb_poll_in,
245 	.poll_out = serial_esp32_usb_poll_out,
246 	.err_check = serial_esp32_usb_err_check,
247 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
248 	.fifo_fill = serial_esp32_usb_fifo_fill,
249 	.fifo_read = serial_esp32_usb_fifo_read,
250 	.irq_tx_enable = serial_esp32_usb_irq_tx_enable,
251 	.irq_tx_disable = serial_esp32_usb_irq_tx_disable,
252 	.irq_tx_ready = serial_esp32_usb_irq_tx_ready,
253 	.irq_rx_enable = serial_esp32_usb_irq_rx_enable,
254 	.irq_rx_disable = serial_esp32_usb_irq_rx_disable,
255 	.irq_tx_complete = serial_esp32_usb_irq_tx_complete,
256 	.irq_rx_ready = serial_esp32_usb_irq_rx_ready,
257 	.irq_err_enable = serial_esp32_usb_irq_err_enable,
258 	.irq_err_disable = serial_esp32_usb_irq_err_disable,
259 	.irq_is_pending = serial_esp32_usb_irq_is_pending,
260 	.irq_update = serial_esp32_usb_irq_update,
261 	.irq_callback_set = serial_esp32_usb_irq_callback_set,
262 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
263 };
264 
265 static const DRAM_ATTR struct serial_esp32_usb_config serial_esp32_usb_cfg = {
266 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
267 	.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset),
268 	.irq_source = DT_INST_IRQ_BY_IDX(0, 0, irq),
269 	.irq_priority = DT_INST_IRQ_BY_IDX(0, 0, priority),
270 	.irq_flags = DT_INST_IRQ_BY_IDX(0, 0, flags)
271 };
272 
273 static struct serial_esp32_usb_data serial_esp32_usb_data_0;
274 
275 DEVICE_DT_INST_DEFINE(0, serial_esp32_usb_init, NULL, &serial_esp32_usb_data_0,
276 		      &serial_esp32_usb_cfg, PRE_KERNEL_1,
277 		      CONFIG_SERIAL_INIT_PRIORITY, &serial_esp32_usb_api);
278