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