1 /*
2 * Copyright (c) 2016-2017, Texas Instruments Incorporated
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ti_cc32xx_uart
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/arch/cpu.h>
11 #include <zephyr/drivers/uart.h>
12 #include <zephyr/drivers/pinctrl.h>
13
14 /* Driverlib includes */
15 #include <inc/hw_types.h>
16 #include <driverlib/rom.h>
17 #include <driverlib/rom_map.h>
18 #include <driverlib/prcm.h>
19 #include <driverlib/uart.h>
20 #include <zephyr/irq.h>
21
22 struct uart_cc32xx_dev_config {
23 unsigned long base;
24 uint32_t sys_clk_freq;
25 const struct pinctrl_dev_config *pcfg;
26 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
27 uart_irq_config_func_t irq_config_func;
28 #endif
29 };
30
31 struct uart_cc32xx_dev_data_t {
32 uint32_t prcm;
33 uint32_t baud_rate;
34 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
35 uart_irq_callback_user_data_t cb; /**< Callback function pointer */
36 void *cb_data; /**< Callback function arg */
37 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
38 };
39
40 #define PRIME_CHAR '\r'
41
42 /* Forward decls: */
43 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
44 static void uart_cc32xx_isr(const struct device *dev);
45 #endif
46
47 /*
48 * CC32XX UART has a configurable FIFO length, from 1 to 8 characters.
49 * However, the Zephyr console driver, and the Zephyr uart sample test, assume
50 * a RX FIFO depth of one: meaning, one interrupt == one character received.
51 * Keeping with this assumption, this driver leaves the FIFOs disabled,
52 * and at depth 1.
53 */
uart_cc32xx_init(const struct device * dev)54 static int uart_cc32xx_init(const struct device *dev)
55 {
56 const struct uart_cc32xx_dev_config *config = dev->config;
57 const struct uart_cc32xx_dev_data_t *data = dev->data;
58 int ret;
59
60 MAP_PRCMPeripheralClkEnable(data->prcm,
61 PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
62
63 MAP_PRCMPeripheralReset(data->prcm);
64
65 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
66 if (ret < 0) {
67 return ret;
68 }
69
70 /* This also calls MAP_UARTEnable() to enable the FIFOs: */
71 MAP_UARTConfigSetExpClk(config->base,
72 MAP_PRCMPeripheralClockGet(data->prcm),
73 data->baud_rate,
74 (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE
75 | UART_CONFIG_PAR_NONE));
76 MAP_UARTFlowControlSet(config->base, UART_FLOWCONTROL_NONE);
77 /* Re-disable the FIFOs: */
78 MAP_UARTFIFODisable(config->base);
79
80 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
81 /* Clear any pending UART RX interrupts: */
82 MAP_UARTIntClear(config->base, UART_INT_RX);
83
84 config->irq_config_func(dev);
85
86 /* Fill the tx fifo, so Zephyr console & shell subsystems get "primed"
87 * with first tx fifo empty interrupt when they first call
88 * uart_irq_tx_enable().
89 */
90 MAP_UARTCharPutNonBlocking(config->base, PRIME_CHAR);
91 #endif
92 return 0;
93 }
94
uart_cc32xx_poll_in(const struct device * dev,unsigned char * c)95 static int uart_cc32xx_poll_in(const struct device *dev, unsigned char *c)
96 {
97 const struct uart_cc32xx_dev_config *config = dev->config;
98
99 if (MAP_UARTCharsAvail(config->base)) {
100 *c = MAP_UARTCharGetNonBlocking(config->base);
101 } else {
102 return (-1);
103 }
104 return 0;
105 }
106
uart_cc32xx_poll_out(const struct device * dev,unsigned char c)107 static void uart_cc32xx_poll_out(const struct device *dev, unsigned char c)
108 {
109 const struct uart_cc32xx_dev_config *config = dev->config;
110
111 MAP_UARTCharPut(config->base, c);
112 }
113
uart_cc32xx_err_check(const struct device * dev)114 static int uart_cc32xx_err_check(const struct device *dev)
115 {
116 const struct uart_cc32xx_dev_config *config = dev->config;
117 unsigned long cc32xx_errs = 0L;
118 unsigned int z_err = 0U;
119
120 cc32xx_errs = MAP_UARTRxErrorGet(config->base);
121
122 /* Map cc32xx SDK uart.h defines to zephyr uart.h defines */
123 z_err = ((cc32xx_errs & UART_RXERROR_OVERRUN) ?
124 UART_ERROR_OVERRUN : 0) |
125 ((cc32xx_errs & UART_RXERROR_BREAK) ? UART_BREAK : 0) |
126 ((cc32xx_errs & UART_RXERROR_PARITY) ? UART_ERROR_PARITY : 0) |
127 ((cc32xx_errs & UART_RXERROR_FRAMING) ? UART_ERROR_FRAMING : 0);
128
129 MAP_UARTRxErrorClear(config->base);
130
131 return (int)z_err;
132 }
133
134 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
135
uart_cc32xx_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)136 static int uart_cc32xx_fifo_fill(const struct device *dev,
137 const uint8_t *tx_data,
138 int size)
139 {
140 const struct uart_cc32xx_dev_config *config = dev->config;
141 unsigned int num_tx = 0U;
142
143 while ((size - num_tx) > 0) {
144 /* Send a character */
145 if (MAP_UARTCharPutNonBlocking(config->base, tx_data[num_tx])) {
146 num_tx++;
147 } else {
148 break;
149 }
150 }
151
152 return (int)num_tx;
153 }
154
uart_cc32xx_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)155 static int uart_cc32xx_fifo_read(const struct device *dev, uint8_t *rx_data,
156 const int size)
157 {
158 const struct uart_cc32xx_dev_config *config = dev->config;
159 unsigned int num_rx = 0U;
160
161 while (((size - num_rx) > 0) &&
162 MAP_UARTCharsAvail(config->base)) {
163
164 /* Receive a character */
165 rx_data[num_rx++] =
166 MAP_UARTCharGetNonBlocking(config->base);
167 }
168
169 return num_rx;
170 }
171
uart_cc32xx_irq_tx_enable(const struct device * dev)172 static void uart_cc32xx_irq_tx_enable(const struct device *dev)
173 {
174 const struct uart_cc32xx_dev_config *config = dev->config;
175
176 MAP_UARTIntEnable(config->base, UART_INT_TX);
177 }
178
uart_cc32xx_irq_tx_disable(const struct device * dev)179 static void uart_cc32xx_irq_tx_disable(const struct device *dev)
180 {
181 const struct uart_cc32xx_dev_config *config = dev->config;
182
183 MAP_UARTIntDisable(config->base, UART_INT_TX);
184 }
185
uart_cc32xx_irq_tx_ready(const struct device * dev)186 static int uart_cc32xx_irq_tx_ready(const struct device *dev)
187 {
188 const struct uart_cc32xx_dev_config *config = dev->config;
189 unsigned int int_status;
190
191 int_status = MAP_UARTIntStatus(config->base, 1);
192
193 return (int_status & UART_INT_TX);
194 }
195
uart_cc32xx_irq_rx_enable(const struct device * dev)196 static void uart_cc32xx_irq_rx_enable(const struct device *dev)
197 {
198 const struct uart_cc32xx_dev_config *config = dev->config;
199
200 /* FIFOs are left disabled from reset, so UART_INT_RT flag not used. */
201 MAP_UARTIntEnable(config->base, UART_INT_RX);
202 }
203
uart_cc32xx_irq_rx_disable(const struct device * dev)204 static void uart_cc32xx_irq_rx_disable(const struct device *dev)
205 {
206 const struct uart_cc32xx_dev_config *config = dev->config;
207
208 MAP_UARTIntDisable(config->base, UART_INT_RX);
209 }
210
uart_cc32xx_irq_tx_complete(const struct device * dev)211 static int uart_cc32xx_irq_tx_complete(const struct device *dev)
212 {
213 const struct uart_cc32xx_dev_config *config = dev->config;
214
215 return (!MAP_UARTBusy(config->base));
216 }
217
uart_cc32xx_irq_rx_ready(const struct device * dev)218 static int uart_cc32xx_irq_rx_ready(const struct device *dev)
219 {
220 const struct uart_cc32xx_dev_config *config = dev->config;
221 unsigned int int_status;
222
223 int_status = MAP_UARTIntStatus(config->base, 1);
224
225 return (int_status & UART_INT_RX);
226 }
227
uart_cc32xx_irq_err_enable(const struct device * dev)228 static void uart_cc32xx_irq_err_enable(const struct device *dev)
229 {
230 /* Not yet used in zephyr */
231 }
232
uart_cc32xx_irq_err_disable(const struct device * dev)233 static void uart_cc32xx_irq_err_disable(const struct device *dev)
234 {
235 /* Not yet used in zephyr */
236 }
237
uart_cc32xx_irq_is_pending(const struct device * dev)238 static int uart_cc32xx_irq_is_pending(const struct device *dev)
239 {
240 const struct uart_cc32xx_dev_config *config = dev->config;
241 unsigned int int_status;
242
243 int_status = MAP_UARTIntStatus(config->base, 1);
244
245 return (int_status & (UART_INT_TX | UART_INT_RX));
246 }
247
uart_cc32xx_irq_update(const struct device * dev)248 static int uart_cc32xx_irq_update(const struct device *dev)
249 {
250 return 1;
251 }
252
uart_cc32xx_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)253 static void uart_cc32xx_irq_callback_set(const struct device *dev,
254 uart_irq_callback_user_data_t cb,
255 void *cb_data)
256 {
257 struct uart_cc32xx_dev_data_t * const dev_data = dev->data;
258
259 dev_data->cb = cb;
260 dev_data->cb_data = cb_data;
261 }
262
263 /**
264 * @brief Interrupt service routine.
265 *
266 * This simply calls the callback function, if one exists.
267 *
268 * Note: CC32XX UART Tx interrupts when ready to send; Rx interrupts when char
269 * received.
270 *
271 * @param arg Argument to ISR.
272 */
uart_cc32xx_isr(const struct device * dev)273 static void uart_cc32xx_isr(const struct device *dev)
274 {
275 const struct uart_cc32xx_dev_config *config = dev->config;
276 struct uart_cc32xx_dev_data_t * const dev_data = dev->data;
277
278 unsigned long intStatus = MAP_UARTIntStatus(config->base, 1);
279
280 if (dev_data->cb) {
281 dev_data->cb(dev, dev_data->cb_data);
282 }
283 /*
284 * RX/TX interrupt should have been implicitly cleared by Zephyr UART
285 * clients calling uart_fifo_read() or uart_fifo_write().
286 * Still, clear any error interrupts here, as they're not yet handled.
287 */
288 MAP_UARTIntClear(config->base,
289 intStatus & ~(UART_INT_RX | UART_INT_TX));
290 }
291 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
292
293 static DEVICE_API(uart, uart_cc32xx_driver_api) = {
294 .poll_in = uart_cc32xx_poll_in,
295 .poll_out = uart_cc32xx_poll_out,
296 .err_check = uart_cc32xx_err_check,
297 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
298 .fifo_fill = uart_cc32xx_fifo_fill,
299 .fifo_read = uart_cc32xx_fifo_read,
300 .irq_tx_enable = uart_cc32xx_irq_tx_enable,
301 .irq_tx_disable = uart_cc32xx_irq_tx_disable,
302 .irq_tx_ready = uart_cc32xx_irq_tx_ready,
303 .irq_rx_enable = uart_cc32xx_irq_rx_enable,
304 .irq_rx_disable = uart_cc32xx_irq_rx_disable,
305 .irq_tx_complete = uart_cc32xx_irq_tx_complete,
306 .irq_rx_ready = uart_cc32xx_irq_rx_ready,
307 .irq_err_enable = uart_cc32xx_irq_err_enable,
308 .irq_err_disable = uart_cc32xx_irq_err_disable,
309 .irq_is_pending = uart_cc32xx_irq_is_pending,
310 .irq_update = uart_cc32xx_irq_update,
311 .irq_callback_set = uart_cc32xx_irq_callback_set,
312 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
313 };
314
315 #define UART_32XX_DEVICE(idx) \
316 PINCTRL_DT_INST_DEFINE(idx); \
317 IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
318 (static void uart_cc32xx_cfg_func_##idx(const struct device *dev) \
319 { \
320 IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, ( \
321 IRQ_CONNECT(DT_INST_IRQN(idx), \
322 DT_INST_IRQ(idx, priority), \
323 uart_cc32xx_isr, DEVICE_DT_INST_GET(idx), \
324 0); \
325 irq_enable(DT_INST_IRQN(idx))) \
326 ); \
327 })); \
328 static const struct uart_cc32xx_dev_config uart_cc32xx_dev_cfg_##idx = { \
329 .base = DT_INST_REG_ADDR(idx), \
330 .sys_clk_freq = DT_INST_PROP_BY_PHANDLE(idx, clocks, clock_frequency),\
331 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
332 IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
333 (.irq_config_func = uart_cc32xx_cfg_func_##idx,)) \
334 }; \
335 static struct uart_cc32xx_dev_data_t uart_cc32xx_dev_data_##idx = { \
336 .prcm = PRCM_UARTA##idx, \
337 .baud_rate = DT_INST_PROP(idx, current_speed), \
338 IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, (.cb = NULL,)) \
339 }; \
340 DEVICE_DT_INST_DEFINE(idx, uart_cc32xx_init, \
341 NULL, &uart_cc32xx_dev_data_##idx, \
342 &uart_cc32xx_dev_cfg_##idx, \
343 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
344 (void *)&uart_cc32xx_driver_api); \
345
346 DT_INST_FOREACH_STATUS_OKAY(UART_32XX_DEVICE);
347