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