Initial commit, code based on LPC1224 support and LPC812-MAX CMSIS-DAP interface...
[lpc11u3x] / 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 /* Both UARTs are available, UART numbers are in the range 0 - 1 */
28 #include <stdint.h>
29 #include "core/lpc_regs_11u3x.h"
30 #include "core/lpc_core_cm0.h"
31 #include "core/system.h"
32 #include "core/pio.h"
33 #include "lib/string.h"
34 #include "lib/utils.h"
35 #include "drivers/serial.h"
37 struct uart_device
38 {
39         uint32_t num;
40         struct lpc_uart* regs;
41         uint32_t baudrate;
42         uint32_t config;
43         uint32_t capabilities;
44         uint32_t current_mode;
46         /* Output buffer */
47         volatile char out_buff[SERIAL_OUT_BUFF_SIZE];
48         volatile uint32_t sending; /* Actual sending position in out buffer */
49         /* This lock only prevents multiple calls to serial_write() to execute simultaneously */
50         volatile uint32_t out_lock;
51         volatile uint32_t out_length; /* actual position to add in out buffer */
53         /* Input */
54         void (*rx_callback)(uint8_t); /* Possible RX callback */
55 };
57 #define NUM_UARTS 1
58 static struct uart_device uarts[NUM_UARTS] = {
59         {
60                 .num = 0,
61                 .regs = (struct lpc_uart*)LPC_UART_0,
62                 .baudrate = 0,
63                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
64                 .out_buff = {0},
65                 .sending = 0,
66                 .out_lock = 0,
67                 .rx_callback = 0,
68                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_RS485 | SERIAL_CAP_IRDA | SERIAL_CAP_SMART_CARD),
69                 .current_mode = SERIAL_MODE_UART,
70         },
71 };
73 static void uart_check_rx(struct uart_device* uart, uint32_t intr)
74 {
75         if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_RX) {
76                 uint8_t data = uart->regs->func.buffer;
77                 if (uart->rx_callback != NULL) {
78                         /* Call the Rx callback */
79                         uart->rx_callback(data);
80                 } else {
81                         /* Echo */
82                         uart->regs->func.buffer = data;
83                 }
84         }
85 }
87 static void uart_check_tx(struct uart_device* uart, uint32_t intr)
88 {
89         /* We are currently sending, send next char */
90         if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_TX) {
91                 if (uart->out_buff && uart->sending && (uart->out_length > uart->sending)) {
92                         uart->regs->func.buffer = uart->out_buff[uart->sending];
93                         uart->sending++;
94                 } else {
95                         uart->sending = 0;
96                 }
97         }
98 }
100 /* Generic UART handler */
101 static void UART_Handler(struct uart_device* uart)
103         uint32_t intr = uart->regs->func.intr_pending;
105         uart_check_rx(uart, intr);
106         uart_check_tx(uart, intr);
110 /* Handlers */
111 void UART_0_Handler(void)
113         UART_Handler(&uarts[0]);
115 void UART_1_Handler(void)
117         UART_Handler(&uarts[1]);
121 /* Start sending buffer content */
122 static void uart_start_sending(uint32_t uart_num)
124         struct uart_device* uart = &uarts[uart_num];
126         if (uart->out_buff == NULL)
127                 return;
129         if (!uart->sending && (uart->out_length != 0)) {
130                 uart->sending++;
131                 uart->regs->func.buffer = uart->out_buff[0];
132         }
137 /***************************************************************************** */
138 /*    Serial Write
139  *
140  * Try to send at most "length" characters from "buf" on the requested uart.
141  * Returns -1 on error, or number of characters copied into output buffer, witch
142  * may be less than requested "length"
143  * Possible errors: requested uart does not exists or unable to acquire uart lock.
144  *
145  * Warning for Real Time : This implementation will block if there's already a
146  * transmission ongoing.
147  */
148 int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
150         struct uart_device* uart = NULL;
152         if (uart_num >= NUM_UARTS)
153                 return -1;
155         uart = &uarts[uart_num];
156         /* Lock acquire */
157         if (sync_lock_test_and_set(&uart->out_lock, 1) == 1) {
158                 return -1;
159         }
161         /* If UART is sending wait for buffer empty */
162         /* FIXME : be smart for OS, call scheduler or return */
163         while (uart->sending != 0) {
164                 if (get_priority_mask() == 0) {
165                         uart_check_tx(uart, uart->regs->func.intr_pending);
166                 }
167         }
169         if (length > SERIAL_OUT_BUFF_SIZE) {
170                 length = SERIAL_OUT_BUFF_SIZE;
171         }
172         memcpy((char*)uart->out_buff, buf, length);
173         uart->out_length = length;
175         /* Turn output on */
176         uart_start_sending(uart_num);
178         /* Release the lock */
179         sync_lock_release(&uart->out_lock);
181         return length;
185 /***************************************************************************** */
186 /*      Serial Flush
187  *
188  * Wait until all characters have been sent
189  * Returns -1 on error, 0 on success.
190  * Possible errors: requested uart does not exists or unable to acquire uart lock.
191  *
192  * Warning for Real Time : This implementation will block if there's already a
193  * transmission ongoing.
194  */
195 int serial_flush(uint32_t uart_num)
197         struct uart_device* uart = NULL;
199         if (uart_num >= NUM_UARTS)
200            return -1;
202         uart = &uarts[uart_num];
204         /* Active wait for message to be sent. If interrupts are
205         * disabled, call the UART handler while waiting. */
206         while (uart->sending) {
207            if (get_priority_mask() == 0) {
208                    uart_check_tx(uart, uart->regs->func.intr_pending);
209                 }
210         }
212         return 0;
216 /***************************************************************************** */
217 /*   UART Setup : private part : Clocks, Pins, Power and Mode   */
219 struct uart_clk_cfg {
220         uint32_t baudrate;
221         uint8_t divisor_latch_lsb;
222         uint8_t div_add_val;
223         uint8_t mul_val;
224 };
225 static struct uart_clk_cfg uart_clk_table[] = {
226         { 1152000, 2, 4, 13},
227         { 0, 0, 0, 0, },
228 };
230 /* UART Clock Setup */
231 /* Note : for both uarts we use full peripheral clock.
232  *    With a minimum main clock of 12MHz, this gives 12MHz/16 = 750kbauds at least
233  *    for UARTs baudrates.
234  * Note : IRQ are off, whether called by system update or by UART on helper
235  */
236 static void uart_clk_on(uint32_t uart_num, uint32_t baudrate)
238         struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
239         struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
240         uint32_t div = 0, pclk = 0;
241         /* Save baudrate value */
242         uarts[uart_num].baudrate = baudrate;
243         /* Configure UART clock */
244         pclk = get_main_clock(); /* See above note */
245         sys_ctrl->uart_clk_div = 0x01;
246         /* The easy one : divider is an integer, or baudrate is low enought for the aproximation */
247         if ((baudrate <= 115200) || ((div * baudrate * 16) == pclk)) {
248                 div = (pclk / (baudrate * 16));
249                 uart->line_ctrl |= LPC_UART_ENABLE_DLAB;
250                 uart->ctrl.divisor_latch_lsb = (div & 0xff);
251                 uart->ctrl.divisor_latch_msb = ((div >> 8) & 0xFF);
252                 uart->line_ctrl &= ~LPC_UART_ENABLE_DLAB;
253         } else {
254                 int i = 0;
255                 /* Do not try to communicate at high speed with a low speed clock ... or compute the table
256                  * for your clock rate */
257                 if (pclk != (48 * 1000 * 1000)) {
258                         return;
259                 }
260                 while (uart_clk_table[i].baudrate != 0) {
261                         if (uart_clk_table[i].baudrate < baudrate) {
262                                 i++;
263                                 continue;
264                         }
265                         uart->line_ctrl |= LPC_UART_ENABLE_DLAB;
266                         uart->ctrl.divisor_latch_lsb = uart_clk_table[i].divisor_latch_lsb;
267                         uart->ctrl.divisor_latch_msb = 0;
268                         uart->fractional_div = (uart_clk_table[i].div_add_val | (uart_clk_table[i].mul_val << 4));
269                         uart->line_ctrl &= ~LPC_UART_ENABLE_DLAB;
270                         break;
271                 }
272         }
274 static void uart_clk_off(uint32_t uart_num)
276         struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
277         /* Erase saved baudrate */
278         uarts[uart_num].baudrate = 0;
279         sys_ctrl->uart_clk_div = 0;
282 static uint32_t uart_setup(uint32_t uart_num)
284         struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
285         uint32_t status = 0;
286         /* Set up UART mode */
287         uart->line_ctrl = uarts[uart_num].config;;
288         /* Clear all fifo, reset and enable them */
289         /* Note : fifo trigger level is one bit */
290         uart->ctrl.fifo_ctrl = (LPC_UART_FIFO_EN | LPC_UART_TX_CLR | LPC_UART_RX_CLR);
291         /* Clear the Line Status Register, return it to prevent compiler from removing the read */
292         status = uart->line_status;
293         /* Enable UART Interrupt */
294         uart->func.intr_enable = (LPC_UART_RX_INT_EN | LPC_UART_TX_INT_EN);
296         return status;
299 struct uart_def
301         uint32_t irq;
302         uint32_t power_offset;
303 };
304 static struct uart_def uart_defs[NUM_UARTS] = {
305         { UART0_IRQ, LPC_SYS_ABH_CLK_CTRL_UART0 },
306 };
308 /***************************************************************************** */
309 /*   Public access to UART setup   */
311 /* Allow any change to the main clock to be forwarded to us */
312 void uart_clk_update(void)
314         int i = 0;
315         for (i = 0; i < NUM_UARTS; i++) {
316                 if (uarts[i].baudrate != 0) {
317                         uart_clk_on(i, uarts[i].baudrate);
318                 }
319         }
322 /* Change uart mode to RS485
323  * return -ENODEV when the device does not support RS485 mode.
324  */
325 int uart_set_mode_rs485(uint32_t uart_num, uint32_t control, uint8_t addr, uint8_t delay)
327         struct uart_device* uart = NULL;
328         struct lpc_uart* uart_regs = NULL;
329         if (uart_num >= NUM_UARTS)
330                 return -EINVAL;
331         uart = &uarts[uart_num];
332         uart_regs = uart->regs; /* Get the right registers */
334         if (!(uart->capabilities & SERIAL_CAP_RS485)) {
335                 return -ENODEV;
336         }
337         /* Disable all other modes */
338         uart_regs->irda_ctrl = 0;
340         /* Set current mode */
341         uart->current_mode = SERIAL_MODE_RS485;
342         uart_regs->RS485_ctrl = (control & 0xFF);
343         uart_regs->RS485_addr_match = LPC_RS485_ADDR(addr);
344         uart_regs->RS485_dir_ctrl_delay = LPC_RS485_DIR_DELAY(delay);
345         return 0;
348 /* Change uart mode to IRDA
349  * pulse_width is the number of clock cycles for a pulse. Should dbe a power of 2.
350  * return -ENODEV when the device does not support IrDA mode.
351  */
352 int uart_set_mode_irda(uint32_t uart_num, uint32_t control, uint16_t pulse_width)
354         struct uart_device* uart = NULL;
355         struct lpc_uart* uart_regs = NULL;
356         uint8_t pulse_div = 0;
358         if (uart_num >= NUM_UARTS)
359                 return -EINVAL;
360         uart = &uarts[uart_num];
361         uart_regs = uart->regs; /* Get the right registers */
363         if (!(uart->capabilities & SERIAL_CAP_IRDA)) {
364                 return -ENODEV;
365         }
366         /* Disable all other modes */
367         uart_regs->RS485_ctrl = 0;
369         /* Set current mode */
370         uart->current_mode = SERIAL_MODE_IRDA;
371         /* Setup IrDA */
372         if (pulse_width < 2) {
373                 pulse_div = 0;
374         } else {
375                 pulse_div = (31 - clz(pulse_width & 0x1FF));
376         }
377         uart_regs->irda_ctrl = control | LPC_IRDA_PULSEDIV(pulse_div);
378         return 0;
382 /* Do we need to allow setting of other parameters ? (Other than 8n1) */
383 int uart_on(uint32_t uart_num, uint32_t baudrate, void (*rx_callback)(uint8_t))
385         struct uart_def* uart = NULL;
386         uint32_t status = 0;
388         if (uart_num >= NUM_UARTS)
389                 return -EINVAL;
390         uart = &uart_defs[uart_num];
391         uarts[uart_num].rx_callback = rx_callback;
393         NVIC_DisableIRQ( uart->irq );
394         /* Setup pins, must be done before clock setup and with uart powered off. */
395         uart_clk_off(uart_num);
396         subsystem_power(uart->power_offset, 0);
397         /* Turn On power */
398         subsystem_power(uart->power_offset, 1);
399         /* Setup clock acording to baudrate */
400         uart_clk_on(uart_num, baudrate);
401         /* Setup mode, fifo, ... */
402         status = uart_setup(uart_num);
403         /* Enable interrupts back on */
404         NVIC_EnableIRQ( uart->irq );
406         return status;
409 void uart_off(uint32_t uart_num)
411         struct uart_def* uart = NULL;
412         if (uart_num >= NUM_UARTS)
413                 return;
414         uart = &uart_defs[uart_num];
416         NVIC_DisableIRQ( uart->irq );
417         uart_clk_off(uart_num);
418         /* Turn Off power */
419         subsystem_power(uart->power_offset, 0);
420         uarts[uart_num].rx_callback = NULL;