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