1 /*
2  * Copyright (c) 2017, Linaro Ltd
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_msp432p4xx_uart
8 
9 /* See www.ti.com/lit/pdf/slau356f, Chapter 22, for MSP432P4XX UART info. */
10 
11 /* include driverlib/gpio.h (from the msp432p4xx SDK) before Z's uart.h so
12  * that the definition of BIT is not overridden */
13 #include <driverlib/gpio.h>
14 
15 #include <zephyr/drivers/uart.h>
16 
17 /* Driverlib includes */
18 #include <driverlib/rom.h>
19 #include <driverlib/rom_map.h>
20 #include <driverlib/uart.h>
21 #include <zephyr/irq.h>
22 
23 struct uart_msp432p4xx_config {
24 	unsigned long base;
25 };
26 
27 struct uart_msp432p4xx_dev_data_t {
28 	/* UART config structure */
29 	eUSCI_UART_Config uartConfig;
30 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
31 	uart_irq_callback_user_data_t cb; /**< Callback function pointer */
32 	void *cb_data;  /**< Callback function arg */
33 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
34 };
35 
36 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
37 static void uart_msp432p4xx_isr(const struct device *dev);
38 #endif
39 
40 static const struct uart_msp432p4xx_config uart_msp432p4xx_dev_cfg_0 = {
41 	.base = DT_INST_REG_ADDR(0),
42 };
43 
44 static struct uart_msp432p4xx_dev_data_t uart_msp432p4xx_dev_data_0 = {
45 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
46 	.cb = NULL,
47 #endif
48 };
49 
baudrate_set(eUSCI_UART_Config * config,uint32_t baudrate)50 static int baudrate_set(eUSCI_UART_Config *config, uint32_t baudrate)
51 {
52 	uint16_t prescalar;
53 	uint8_t first_mod_reg, second_mod_reg;
54 
55 	switch (baudrate) {
56 	case 1200:
57 		prescalar = 2500U;
58 		first_mod_reg = 0U;
59 		second_mod_reg = 0U;
60 		break;
61 	case 2400:
62 		prescalar = 1250U;
63 		first_mod_reg = 0U;
64 		second_mod_reg = 0U;
65 		break;
66 	case 4800:
67 		prescalar = 625U;
68 		first_mod_reg = 0U;
69 		second_mod_reg = 0U;
70 		break;
71 	case 9600:
72 		prescalar = 312U;
73 		first_mod_reg = 8U;
74 		second_mod_reg = 0U;
75 		break;
76 	case 19200:
77 		prescalar = 156U;
78 		first_mod_reg = 4U;
79 		second_mod_reg = 0U;
80 		break;
81 	case 38400:
82 		prescalar = 78U;
83 		first_mod_reg = 2U;
84 		second_mod_reg = 0U;
85 		break;
86 	case 57600:
87 		prescalar = 52U;
88 		first_mod_reg = 1U;
89 		second_mod_reg = 37U;
90 		break;
91 	case 115200:
92 		prescalar = 26U;
93 		first_mod_reg = 0U;
94 		second_mod_reg = 111U;
95 		break;
96 	case 230400:
97 		prescalar = 13U;
98 		first_mod_reg = 0U;
99 		second_mod_reg = 37U;
100 		break;
101 	case 460800:
102 		prescalar = 6U;
103 		first_mod_reg = 8U;
104 		second_mod_reg = 32U;
105 		break;
106 	default:
107 		return -EINVAL;
108 	}
109 
110 	config->clockPrescalar = prescalar;
111 	config->firstModReg = first_mod_reg;
112 	config->secondModReg = second_mod_reg;
113 
114 	return 0;
115 }
116 
uart_msp432p4xx_init(const struct device * dev)117 static int uart_msp432p4xx_init(const struct device *dev)
118 {
119 	int err;
120 	const struct uart_msp432p4xx_config *config = dev->config;
121 	eUSCI_UART_Config UartConfig;
122 
123 	/* Select P1.2 and P1.3 in UART mode */
124 	MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
125 		(GPIO_PIN2 | GPIO_PIN3), GPIO_PRIMARY_MODULE_FUNCTION);
126 
127 	UartConfig.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK;
128 	UartConfig.parity = EUSCI_A_UART_NO_PARITY;
129 	UartConfig.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
130 	UartConfig.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT;
131 	UartConfig.uartMode = EUSCI_A_UART_MODE;
132 	UartConfig.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
133 
134 	/* Baud rate settings calculated for 48MHz */
135 	err = baudrate_set(&UartConfig, DT_INST_PROP(0, current_speed));
136 	if (err) {
137 		return err;
138 	}
139 	/* Configure UART Module */
140 	MAP_UART_initModule(config->base, &UartConfig);
141 
142 	/* Enable UART module */
143 	MAP_UART_enableModule(config->base);
144 
145 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
146 	IRQ_CONNECT(DT_INST_IRQN(0),
147 			DT_INST_IRQ(0, priority),
148 			uart_msp432p4xx_isr, DEVICE_DT_INST_GET(0),
149 			0);
150 	irq_enable(DT_INST_IRQN(0));
151 
152 #endif
153 	return 0;
154 }
155 
uart_msp432p4xx_poll_in(const struct device * dev,unsigned char * c)156 static int uart_msp432p4xx_poll_in(const struct device *dev, unsigned char *c)
157 {
158 	const struct uart_msp432p4xx_config *config = dev->config;
159 
160 	*c = MAP_UART_receiveData(config->base);
161 
162 	return 0;
163 }
164 
uart_msp432p4xx_poll_out(const struct device * dev,unsigned char c)165 static void uart_msp432p4xx_poll_out(const struct device *dev,
166 				     unsigned char c)
167 {
168 	const struct uart_msp432p4xx_config *config = dev->config;
169 
170 	MAP_UART_transmitData(config->base, c);
171 }
172 
173 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_msp432p4xx_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)174 static int uart_msp432p4xx_fifo_fill(const struct device *dev,
175 						const uint8_t *tx_data, int size)
176 {
177 	const struct uart_msp432p4xx_config *config = dev->config;
178 	unsigned int num_tx = 0U;
179 
180 	while ((size - num_tx) > 0) {
181 		MAP_UART_transmitData(config->base, tx_data[num_tx]);
182 		if (MAP_UART_getInterruptStatus(config->base,
183 			EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG)) {
184 			num_tx++;
185 		} else {
186 			break;
187 		}
188 	}
189 
190 	return (int)num_tx;
191 }
192 
uart_msp432p4xx_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)193 static int uart_msp432p4xx_fifo_read(const struct device *dev,
194 							uint8_t *rx_data,
195 							const int size)
196 {
197 	const struct uart_msp432p4xx_config *config = dev->config;
198 	unsigned int num_rx = 0U;
199 
200 	while (((size - num_rx) > 0) &&
201 		MAP_UART_getInterruptStatus(
202 			config->base, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)) {
203 
204 		rx_data[num_rx++] = MAP_UART_receiveData(config->base);
205 	}
206 
207 	return num_rx;
208 }
209 
uart_msp432p4xx_irq_tx_enable(const struct device * dev)210 static void uart_msp432p4xx_irq_tx_enable(const struct device *dev)
211 {
212 	const struct uart_msp432p4xx_config *config = dev->config;
213 
214 	MAP_UART_enableInterrupt(config->base, EUSCI_A_UART_TRANSMIT_INTERRUPT);
215 }
216 
uart_msp432p4xx_irq_tx_disable(const struct device * dev)217 static void uart_msp432p4xx_irq_tx_disable(const struct device *dev)
218 {
219 	const struct uart_msp432p4xx_config *config = dev->config;
220 
221 	MAP_UART_disableInterrupt(config->base,
222 				  EUSCI_A_UART_TRANSMIT_INTERRUPT);
223 }
224 
uart_msp432p4xx_irq_tx_ready(const struct device * dev)225 static int uart_msp432p4xx_irq_tx_ready(const struct device *dev)
226 {
227 	const struct uart_msp432p4xx_config *config = dev->config;
228 	unsigned int int_status;
229 
230 	int_status =  MAP_UART_getInterruptStatus(
231 		config->base, EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG);
232 
233 	return (int_status & EUSCI_A_IE_TXIE);
234 }
235 
uart_msp432p4xx_irq_rx_enable(const struct device * dev)236 static void uart_msp432p4xx_irq_rx_enable(const struct device *dev)
237 {
238 	const struct uart_msp432p4xx_config *config = dev->config;
239 
240 	MAP_UART_enableInterrupt(config->base, EUSCI_A_UART_RECEIVE_INTERRUPT);
241 }
242 
uart_msp432p4xx_irq_rx_disable(const struct device * dev)243 static void uart_msp432p4xx_irq_rx_disable(const struct device *dev)
244 {
245 	const struct uart_msp432p4xx_config *config = dev->config;
246 
247 	MAP_UART_disableInterrupt(config->base, EUSCI_A_UART_RECEIVE_INTERRUPT);
248 }
249 
uart_msp432p4xx_irq_tx_complete(const struct device * dev)250 static int uart_msp432p4xx_irq_tx_complete(const struct device *dev)
251 {
252 	const struct uart_msp432p4xx_config *config = dev->config;
253 
254 	return MAP_UART_getInterruptStatus(
255 		config->base, EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG);
256 }
257 
uart_msp432p4xx_irq_rx_ready(const struct device * dev)258 static int uart_msp432p4xx_irq_rx_ready(const struct device *dev)
259 {
260 	const struct uart_msp432p4xx_config *config = dev->config;
261 	unsigned int int_status;
262 
263 	int_status = MAP_UART_getInterruptStatus(
264 		config->base, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG);
265 
266 	return (int_status & EUSCI_A_IE_RXIE);
267 }
268 
uart_msp432p4xx_irq_err_enable(const struct device * dev)269 static void uart_msp432p4xx_irq_err_enable(const struct device *dev)
270 {
271 	/* Not yet used in zephyr */
272 }
273 
uart_msp432p4xx_irq_err_disable(const struct device * dev)274 static void uart_msp432p4xx_irq_err_disable(const struct device *dev)
275 {
276 	/* Not yet used in zephyr */
277 }
278 
uart_msp432p4xx_irq_is_pending(const struct device * dev)279 static int uart_msp432p4xx_irq_is_pending(const struct device *dev)
280 {
281 	const struct uart_msp432p4xx_config *config = dev->config;
282 	unsigned int int_status;
283 
284 	int_status = MAP_UART_getEnabledInterruptStatus(config->base);
285 
286 	return (int_status & (EUSCI_A_IE_TXIE | EUSCI_A_IE_RXIE));
287 }
288 
uart_msp432p4xx_irq_update(const struct device * dev)289 static int uart_msp432p4xx_irq_update(const struct device *dev)
290 {
291 	return 1;
292 }
293 
uart_msp432p4xx_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)294 static void uart_msp432p4xx_irq_callback_set(const struct device *dev,
295 					     uart_irq_callback_user_data_t cb,
296 					     void *cb_data)
297 {
298 	struct uart_msp432p4xx_dev_data_t * const dev_data = dev->data;
299 
300 	dev_data->cb = cb;
301 	dev_data->cb_data = cb_data;
302 }
303 
304 /**
305  * @brief Interrupt service routine.
306  *
307  * This simply calls the callback function, if one exists.
308  *
309  * @param arg Argument to ISR.
310  */
uart_msp432p4xx_isr(const struct device * dev)311 static void uart_msp432p4xx_isr(const struct device *dev)
312 {
313 	const struct uart_msp432p4xx_config *config = dev->config;
314 	struct uart_msp432p4xx_dev_data_t * const dev_data = dev->data;
315 	unsigned int int_status;
316 
317 	int_status = MAP_UART_getEnabledInterruptStatus(config->base);
318 
319 	if (dev_data->cb) {
320 		dev_data->cb(dev, dev_data->cb_data);
321 	}
322 	/*
323 	 * Clear interrupts only after cb called, as Zephyr UART clients expect
324 	 * to check interrupt status during the callback.
325 	 */
326 	MAP_UART_disableInterrupt(config->base, int_status);
327 }
328 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
329 
330 static DEVICE_API(uart, uart_msp432p4xx_driver_api) = {
331 	.poll_in = uart_msp432p4xx_poll_in,
332 	.poll_out = uart_msp432p4xx_poll_out,
333 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
334 	.fifo_fill	  = uart_msp432p4xx_fifo_fill,
335 	.fifo_read	  = uart_msp432p4xx_fifo_read,
336 	.irq_tx_enable	  = uart_msp432p4xx_irq_tx_enable,
337 	.irq_tx_disable	  = uart_msp432p4xx_irq_tx_disable,
338 	.irq_tx_ready	  = uart_msp432p4xx_irq_tx_ready,
339 	.irq_rx_enable	  = uart_msp432p4xx_irq_rx_enable,
340 	.irq_rx_disable	  = uart_msp432p4xx_irq_rx_disable,
341 	.irq_tx_complete  = uart_msp432p4xx_irq_tx_complete,
342 	.irq_rx_ready	  = uart_msp432p4xx_irq_rx_ready,
343 	.irq_err_enable	  = uart_msp432p4xx_irq_err_enable,
344 	.irq_err_disable  = uart_msp432p4xx_irq_err_disable,
345 	.irq_is_pending	  = uart_msp432p4xx_irq_is_pending,
346 	.irq_update	  = uart_msp432p4xx_irq_update,
347 	.irq_callback_set = uart_msp432p4xx_irq_callback_set,
348 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
349 };
350 
351 DEVICE_DT_INST_DEFINE(0,
352 			uart_msp432p4xx_init, NULL,
353 			&uart_msp432p4xx_dev_data_0,
354 			&uart_msp432p4xx_dev_cfg_0,
355 			PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,
356 			(void *)&uart_msp432p4xx_driver_api);
357