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