More UART fixes, and test of all UARTS.
[dtplug] / drivers / serial.c
1 /****************************************************************************
2  *  drivers/serial.c
3  *
4  * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *************************************************************************** */
23 /***************************************************************************** */
24 /*                UARTs                                                        */
25 /***************************************************************************** */
26 /* UART driver for the integrated UARTs of the LPC176x.
27  * Refer to LPC176x documentation (UM10360.pdf) for more information.
28  */
30 /* Both UARTs are available, UART numbers are in the range 0 - 1 */
32 #include <stdint.h>
33 #include "core/lpc_regs_17xx.h"
34 #include "core/lpc_core_cm3.h"
35 #include "core/system.h"
36 #include "core/pio.h"
37 #include "lib/string.h"
38 #include "lib/bit_arithm.h"
39 #include "drivers/serial.h"
41 struct uart_device
42 {
43         uint32_t num;
44         struct lpc_uart* regs;
45         uint32_t baudrate;
46         uint32_t config;
47         uint32_t capabilities;
48         uint32_t current_mode;
50         /* Output buffer */
51         volatile char out_buff[SERIAL_OUT_BUFF_SIZE];
52         volatile uint32_t sending; /* Actual sending position in out buffer */
53         /* This lock only prevents multiple calls to serial_write() to execute simultaneously */
54         volatile uint32_t out_lock;
55         volatile uint32_t out_length; /* actual position to add in out buffer */
57         /* Input */
58         void (*rx_callback)(uint8_t); /* Possible RX callback */
59 };
61 #define NUM_UARTS 4
62 static struct uart_device uarts[NUM_UARTS] = {
63         {
64                 .num = 0,
65                 .regs = (struct lpc_uart*)LPC_UART_0,
66                 .baudrate = 0,
67                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
68                 .out_buff = {0},
69                 .sending = 0,
70                 .out_lock = 0,
71                 .rx_callback = NULL,
72                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_IRDA),
73                 .current_mode = SERIAL_MODE_UART,
74         },
75         {
76                 .num = 1,
77                 .regs = (struct lpc_uart*)LPC_UART_1,
78                 .baudrate = 0,
79                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
80                 .out_buff = {0},
81                 .sending = 0,
82                 .out_lock = 0,
83                 .rx_callback = NULL,
84                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_RS485 | SERIAL_CAP_FULL_MODEM),
85                 .current_mode = SERIAL_MODE_UART,
86         },
87         {
88                 .num = 2,
89                 .regs = (struct lpc_uart*)LPC_UART_2,
90                 .baudrate = 0,
91                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
92                 .out_buff = {0},
93                 .sending = 0,
94                 .out_lock = 0,
95                 .rx_callback = NULL,
96                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_IRDA),
97                 .current_mode = SERIAL_MODE_UART,
98         },
99         {
100                 .num = 3,
101                 .regs = (struct lpc_uart*)LPC_UART_3,
102                 .baudrate = 0,
103                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
104                 .out_buff = {0},
105                 .sending = 0,
106                 .out_lock = 0,
107                 .rx_callback = NULL,
108                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_IRDA),
109                 .current_mode = SERIAL_MODE_UART,
110         },
111 };
113 static void uart_check_rx(struct uart_device* uart, uint32_t intr)
115         if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_RX) {
116                 uint8_t data = uart->regs->func.buffer;
117                 if (uart->rx_callback != NULL) {
118                         /* Call the Rx callback */
119                         uart->rx_callback(data);
120                 } else {
121                         /* Echo */
122                         uart->regs->func.buffer = data;
123                 }
124         }
127 static void uart_check_tx(struct uart_device* uart, uint32_t intr)
129         /* We are currently sending, send next char */
130         if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_TX) {
131                 if (uart->out_buff && uart->sending && (uart->out_length > uart->sending)) {
132                         uart->regs->func.buffer = uart->out_buff[uart->sending];
133                         uart->sending++;
134                 } else {
135                         uart->sending = 0;
136                 }
137         }
140 /* Generic UART handler */
141 static void UART_Handler(struct uart_device* uart)
143         uint32_t intr = uart->regs->func.intr_pending;
145         uart_check_rx(uart, intr);
146         uart_check_tx(uart, intr);
150 /* Handlers */
151 void UART_0_Handler(void)
153         UART_Handler(&uarts[0]);
155 void UART_1_Handler(void)
157         UART_Handler(&uarts[1]);
159 void UART_2_Handler(void)
161         UART_Handler(&uarts[2]);
163 void UART_3_Handler(void)
165         UART_Handler(&uarts[3]);
169 /* Start sending buffer content */
170 static void uart_start_sending(uint32_t uart_num)
172         struct uart_device* uart = &uarts[uart_num];
174         if (uart->out_buff == NULL)
175                 return;
177         if (!uart->sending && (uart->out_length != 0)) {
178                 uart->sending++;
179                 uart->regs->func.buffer = uart->out_buff[0];
180         }
185 /***************************************************************************** */
186 /*    Serial Write
187  *
188  * Try to send at most "length" characters from "buf" on the requested uart.
189  * Returns -1 on error, or number of characters copied into output buffer, witch
190  * may be less than requested "length"
191  * Possible errors: requested uart does not exists or unable to acquire uart lock.
192  *
193  * Warning for Real Time : This implementation will block if there's already a
194  * transmission ongoing.
195  */
196 int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
198         struct uart_device* uart = NULL;
200         if (uart_num >= NUM_UARTS)
201                 return -1;
203         uart = &uarts[uart_num];
204         /* Lock acquire */
205         if (sync_lock_test_and_set(&uart->out_lock, 1) == 1) {
206                 return -1;
207         }
209         /* If UART is sending wait for buffer empty */
210         /* FIXME : be smart for OS, call scheduler or return */
211         while (uart->sending != 0) {
212                 if (get_priority_mask() == 0) {
213                         uart_check_tx(uart, uart->regs->func.intr_pending);
214                 }
215         }
217         if (length > SERIAL_OUT_BUFF_SIZE) {
218                 length = SERIAL_OUT_BUFF_SIZE;
219         }
220         memcpy((char*)uart->out_buff, buf, length);
221         uart->out_length = length;
223         /* Turn output on */
224         uart_start_sending(uart_num);
226         /* Release the lock */
227         sync_lock_release(&uart->out_lock);
229         return length;
233 /***************************************************************************** */
234 /*    Serial Flush
235  *
236  * Wait until all characters have been sent
237  * Returns -1 on error, 0 on success.
238  * Possible errors: requested uart does not exists or unable to acquire uart lock.
239  *
240  * Warning for Real Time : This implementation will block if there's already a
241  * transmission ongoing.
242  */
243 int serial_flush(uint32_t uart_num)
245         struct uart_device* uart = NULL;
247         if (uart_num >= NUM_UARTS)
248                 return -1;
250         uart = &uarts[uart_num];
252         /* Active wait for message to be sent. If interrupts are
253          * disabled, call the UART handler while waiting. */
254         while (uart->sending) {
255                 if (get_priority_mask() == 0) {
256                         uart_check_tx(uart, uart->regs->func.intr_pending);
257                 }
258         }
260         return 0;
264 /***************************************************************************** */
265 /*   UART Setup : private part : Clocks, Pins, Power and Mode   */
267 struct uart_def
269         uint8_t irq;
270         uint8_t clk_num;
271         uint32_t power_offset;
272 };
273 static struct uart_def uart_defs[NUM_UARTS] = {
274         { UART0_IRQ, LPC_UART0_PCLK, LPC_UART0_POWER_ON },
275         { UART1_IRQ, LPC_UART1_PCLK, LPC_UART1_POWER_ON },
276         { UART2_IRQ, LPC_UART2_PCLK, LPC_UART2_POWER_ON },
277         { UART3_IRQ, LPC_UART3_PCLK, LPC_UART3_POWER_ON },
278 };
280 /* FIXME : compute values for other Clock rates and add a pclk parameter or define
281  *    to select between pclk frequencies
282  */
283 struct uart_clk_cfg {
284         uint32_t baudrate;
285         uint8_t divisor_latch_lsb;
286         uint8_t div_add_val;
287         uint8_t mul_val;
288 };
289 static struct uart_clk_cfg uart_clk_table[] = {
290         { 1152000, 2, 4, 13},
291         { 0, 0, 0, 0, },
292 };
294 /* UART Clock Setup */
295 /* Note : for all modules, we use the default clock divider, which is CCLK/4.
296  *    With a minimum main clock of 48MHz, this gives 12MHz/16 = 750kbauds at least
297  *    for UARTs baudrates.
298  * Note : IRQ are off, whether called by system update or by UART on helper
299  */
300 static void uart_clk_on(uint32_t uart_num, uint32_t baudrate)
302         struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
303         uint32_t div = 0, pclk = 0;
304         /* Save baudrate value */
305         uarts[uart_num].baudrate = baudrate;
306         /* Configure UART clock */
307         set_subsystem_clk_divider(uart_defs[uart_num].clk_num, LPC_PCLK_CCLK_QUARTER);
308         pclk = (get_main_clock() / 4); /* See above note */
309         div = (pclk / (baudrate * 16));
310         /* The easy one : divider is an integer, or baudrate is low enought for the aproximation */
311         if ((baudrate <= 115200) || ((div * baudrate * 16) == pclk)) {
312                 uart->line_ctrl |= LPC_UART_ENABLE_DLAB;
313                 uart->ctrl.divisor_latch_lsb = (div & 0xff);
314                 uart->ctrl.divisor_latch_msb = ((div >> 8) & 0xFF);
315                 uart->line_ctrl &= ~LPC_UART_ENABLE_DLAB;
316         } else {
317                 int i = 0;
318                 /* Do not try to communicate at high speed with a low speed clock ... or compute the table
319                  * for your clock rate */
320                 if (pclk != (48 * 1000 * 1000)) {
321                         return;
322                 }
323                 while (uart_clk_table[i].baudrate != 0) {
324                         if (uart_clk_table[i].baudrate < baudrate) {
325                                 i++;
326                                 continue;
327                         }
328                         uart->line_ctrl |= LPC_UART_ENABLE_DLAB;
329                         uart->ctrl.divisor_latch_lsb = uart_clk_table[i].divisor_latch_lsb;
330                         uart->ctrl.divisor_latch_msb = 0;
331                         uart->fractional_div = (uart_clk_table[i].div_add_val | (uart_clk_table[i].mul_val << 4));
332                         uart->line_ctrl &= ~LPC_UART_ENABLE_DLAB;
333                         break;
334                 }
335         }
338 static uint32_t uart_setup(uint32_t uart_num)
340         struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
341         uint32_t status = 0;
342         /* Set up UART mode */
343         uart->line_ctrl = uarts[uart_num].config;;
344         /* Clear all fifo, reset and enable them */
345         /* Note : fifo trigger level is one bit */
346         uart->ctrl.fifo_ctrl = (LPC_UART_FIFO_EN | LPC_UART_TX_CLR | LPC_UART_RX_CLR);
347         /* Clear the Line Status Register, return it to prevent compiler from removing the read */
348         status = uart->line_status;
349         /* Enable UART Interrupt */
350         uart->func.intr_enable = (LPC_UART_RX_INT_EN | LPC_UART_TX_INT_EN);
352         return status;
355 /***************************************************************************** */
356 /*   Public access to UART setup   */
358 /* Allow any change to the main clock to be forwarded to us */
359 void uart_clk_update(void)
361         int i = 0;
362         for (i = 0; i < NUM_UARTS; i++) {
363                 if (uarts[i].baudrate != 0) {
364                         uart_clk_on(i, uarts[i].baudrate);
365                 }
366         }
369 /* Change uart mode to RS485
370  * return -ENODEV when the device does not support RS485 mode.
371  */
372 int uart_set_mode_rs485(uint32_t uart_num, uint32_t control, uint8_t addr, uint8_t delay)
374         struct uart_device* uart = NULL;
375         struct lpc_uart* uart_regs = NULL;
376         if (uart_num >= NUM_UARTS)
377                 return -EINVAL;
378         uart = &uarts[uart_num];
379         uart_regs = uart->regs; /* Get the right registers */
381         if (!(uart->capabilities & SERIAL_CAP_RS485)) {
382                 return -ENODEV;
383         }
384         /* Disable all other modes */
385         uart_regs->irda_ctrl = 0;
387         /* Set current mode */
388         uart->current_mode = SERIAL_MODE_RS485;
389         uart_regs->RS485_ctrl = (control & 0xFF);
390         uart_regs->RS485_addr_match = LPC_RS485_ADDR(addr);
391         uart_regs->RS485_dir_ctrl_delay = LPC_RS485_DIR_DELAY(delay);
392         return 0;
395 /* Change uart mode to IRDA
396  * pulse_width is the number of clock cycles for a pulse. Should dbe a power of 2.
397  * return -ENODEV when the device does not support IrDA mode.
398  */
399 int uart_set_mode_irda(uint32_t uart_num, uint32_t control, uint16_t pulse_width)
401         struct uart_device* uart = NULL;
402         struct lpc_uart* uart_regs = NULL;
403         uint8_t pulse_div = 0;
405         if (uart_num >= NUM_UARTS)
406                 return -EINVAL;
407         uart = &uarts[uart_num];
408         uart_regs = uart->regs; /* Get the right registers */
410         if (!(uart->capabilities & SERIAL_CAP_IRDA)) {
411                 return -ENODEV;
412         }
413         /* Disable all other modes */
414         uart_regs->RS485_ctrl = 0;
416         /* Set current mode */
417         uart->current_mode = SERIAL_MODE_IRDA;
418         /* Setup IrDA */
419         if (pulse_width < 2) {
420                 pulse_div = 0;
421         } else {
422                 pulse_div = (31 - clz(pulse_width & 0x1FF));
423         }
424         uart_regs->irda_ctrl = control | LPC_IRDA_PULSEDIV(pulse_div);
425         return 0;
429 /* Do we need to allow setting of other parameters ? (Other than 8n1) */
430 int uart_on(uint32_t uart_num, uint32_t baudrate, void (*rx_callback)(uint8_t))
432         struct uart_def* uart = NULL;
433         uint32_t status = 0;
435         if (uart_num >= NUM_UARTS)
436                 return -EINVAL;
437         uart = &uart_defs[uart_num];
438         uarts[uart_num].rx_callback = rx_callback;
440         NVIC_DisableIRQ( uart->irq );
441         /* Turn On power */
442         subsystem_power(uart->power_offset, 1);
443         /* Setup clock acording to baudrate */
444         uart_clk_on(uart_num, baudrate);
445         /* Setup mode, fifo, ... */
446         status = uart_setup(uart_num);
447         /* Enable interrupts back on */
448         NVIC_EnableIRQ( uart->irq );
450         return status;
453 void uart_off(uint32_t uart_num)
455         struct uart_def* uart = NULL;
456         if (uart_num >= NUM_UARTS)
457                 return;
458         uart = &uart_defs[uart_num];
460         NVIC_DisableIRQ( uart->irq );
461         /* Turn Off power */
462         subsystem_power(uart->power_offset, 0);
463         uarts[uart_num].baudrate = 0;
464         uarts[uart_num].rx_callback = NULL;