Remove the PIO config from the clkout_on() function.
[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 #define SERIAL_OUT_BUFF_SIZE 64
42 struct uart_device
43 {
44         uint32_t num;
45         struct lpc_uart* regs;
46         uint32_t baudrate;
47         uint32_t config;
48         uint32_t capabilities;
49         uint32_t current_mode;
51         /* Output buffer */
52         volatile char out_buff[SERIAL_OUT_BUFF_SIZE];
53         volatile uint32_t sending; /* Actual sending position in out buffer */
54         /* This lock only prevents multiple calls to serial_write() to execute simultaneously */
55         volatile uint32_t out_lock;
56         volatile uint32_t out_length; /* actual position to add in out buffer */
58         /* Input */
59         void (*rx_callback)(uint8_t); /* Possible RX callback */
60 };
62 #define NUM_UARTS 4
63 static struct uart_device uarts[NUM_UARTS] = {
64         {
65                 .num = 0,
66                 .regs = (struct lpc_uart*)LPC_UART_0,
67                 .baudrate = 0,
68                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
69                 .out_buff = {0},
70                 .sending = 0,
71                 .out_lock = 0,
72                 .rx_callback = NULL,
73                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_IRDA),
74                 .current_mode = SERIAL_MODE_UART,
75         },
76         {
77                 .num = 1,
78                 .regs = (struct lpc_uart*)LPC_UART_1,
79                 .baudrate = 0,
80                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
81                 .out_buff = {0},
82                 .sending = 0,
83                 .out_lock = 0,
84                 .rx_callback = NULL,
85                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_RS485 | SERIAL_CAP_FULL_MODEM),
86                 .current_mode = SERIAL_MODE_UART,
87         },
88         {
89                 .num = 2,
90                 .regs = (struct lpc_uart*)LPC_UART_2,
91                 .baudrate = 0,
92                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
93                 .out_buff = {0},
94                 .sending = 0,
95                 .out_lock = 0,
96                 .rx_callback = NULL,
97                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_IRDA),
98                 .current_mode = SERIAL_MODE_UART,
99         },
100         {
101                 .num = 3,
102                 .regs = (struct lpc_uart*)LPC_UART_3,
103                 .baudrate = 0,
104                 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
105                 .out_buff = {0},
106                 .sending = 0,
107                 .out_lock = 0,
108                 .rx_callback = NULL,
109                 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_IRDA),
110                 .current_mode = SERIAL_MODE_UART,
111         },
112 };
114 static void uart_check_rx(struct uart_device* uart, uint32_t intr)
116         if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_RX) {
117                 uint8_t data = uart->regs->func.buffer;
118                 if (uart->rx_callback != NULL) {
119                         /* Call the Rx callback */
120                         uart->rx_callback(data);
121                 } else {
122                         /* Echo */
123                         uart->regs->func.buffer = data;
124                 }
125         }
128 static void uart_check_tx(struct uart_device* uart, uint32_t intr)
130         /* We are currently sending, send next char */
131         if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_TX) {
132                 if (uart->out_buff && uart->sending && (uart->out_length > uart->sending)) {
133                         uart->regs->func.buffer = uart->out_buff[uart->sending];
134                         uart->sending++;
135                 } else {
136                         uart->sending = 0;
137                 }
138         }
141 /* Generic UART handler */
142 static void UART_Handler(struct uart_device* uart)
144         uint32_t intr = uart->regs->func.intr_pending;
146         uart_check_rx(uart, intr);
147         uart_check_tx(uart, intr);
151 /* Handlers */
152 void UART_0_Handler(void)
154         UART_Handler(&uarts[0]);
156 void UART_1_Handler(void)
158         UART_Handler(&uarts[1]);
162 /* Start sending buffer content */
163 static void uart_start_sending(uint32_t uart_num)
165         struct uart_device* uart = &uarts[uart_num];
167         if (uart->out_buff == NULL)
168                 return;
170         if (!uart->sending && (uart->out_length != 0)) {
171                 uart->sending++;
172                 uart->regs->func.buffer = uart->out_buff[0];
173         }
178 /***************************************************************************** */
179 /*    Serial Write
180  *
181  * Try to send at most "length" characters from "buf" on the requested uart.
182  * Returns -1 on error, or number of characters copied into output buffer, witch
183  * may be less than requested "length"
184  * Possible errors: requested uart does not exists or unable to acquire uart lock.
185  *
186  * Warning for Real Time : This implementation will block if there's already a
187  * transmission ongoing.
188  */
189 int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
191         struct uart_device* uart = NULL;
193         if (uart_num >= NUM_UARTS)
194                 return -1;
196         uart = &uarts[uart_num];
197         /* Lock acquire */
198         if (sync_lock_test_and_set(&uart->out_lock, 1) == 1) {
199                 return -1;
200         }
202         /* If UART is sending wait for buffer empty */
203         /* FIXME : be smart for OS, call scheduler or return */
204         while (uart->sending != 0) {
205                 if (get_priority_mask() == 0) {
206                         uart_check_tx(uart, uart->regs->func.intr_pending);
207                 }
208         }
210         if (length > SERIAL_OUT_BUFF_SIZE) {
211                 length = SERIAL_OUT_BUFF_SIZE;
212         }
213         memcpy((char*)uart->out_buff, buf, length);
214         uart->out_length = length;
216         /* Turn output on */
217         uart_start_sending(uart_num);
219         /* Release the lock */
220         sync_lock_release(&uart->out_lock);
222         return length;
226 /***************************************************************************** */
227 /*    Serial Flush
228  *
229  * Wait until all characters have been sent
230  * Returns -1 on error, 0 on success.
231  * Possible errors: requested uart does not exists or unable to acquire uart lock.
232  *
233  * Warning for Real Time : This implementation will block if there's already a
234  * transmission ongoing.
235  */
236 int serial_flush(uint32_t uart_num)
238         struct uart_device* uart = NULL;
240         if (uart_num >= NUM_UARTS)
241                 return -1;
243         uart = &uarts[uart_num];
245         /* Active wait for message to be sent. If interrupts are
246          * disabled, call the UART handler while waiting. */
247         while (uart->sending) {
248                 if (get_priority_mask() == 0) {
249                         uart_check_tx(uart, uart->regs->func.intr_pending);
250                 }
251         }
253         return 0;
257 /***************************************************************************** */
258 /*   UART Setup : private part : Clocks, Pins, Power and Mode   */
260 struct uart_def
262         uint8_t irq;
263         uint8_t clk_num;
264         uint32_t power_offset;
265 };
266 static struct uart_def uart_defs[NUM_UARTS] = {
267         { UART0_IRQ, LPC_UART0_PCLK, LPC_UART0_POWER_ON },
268         { UART1_IRQ, LPC_UART1_PCLK, LPC_UART1_POWER_ON },
269         { UART2_IRQ, LPC_UART2_PCLK, LPC_UART2_POWER_ON },
270         { UART3_IRQ, LPC_UART3_PCLK, LPC_UART3_POWER_ON },
271 };
273 /* FIXME : compute values for other Clock rates and add a pclk parameter or define
274  *    to select between pclk frequencies
275  */
276 struct uart_clk_cfg {
277         uint32_t baudrate;
278         uint8_t divisor_latch_lsb;
279         uint8_t div_add_val;
280         uint8_t mul_val;
281 };
282 static struct uart_clk_cfg uart_clk_table[] = {
283         { 1152000, 2, 4, 13},
284         { 0, 0, 0, 0, },
285 };
287 /* UART Clock Setup */
288 /* Note : for both uarts we use full peripheral clock.
289  *    With a minimum main clock of 12MHz, this gives 12MHz/16 = 750kbauds at least
290  *    for UARTs baudrates.
291  * Note : IRQ are off, whether called by system update or by UART on helper
292  */
293 static void uart_clk_on(uint32_t uart_num, uint32_t baudrate)
295         struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
296         uint32_t div = 0, pclk = 0;
297         /* Save baudrate value */
298         uarts[uart_num].baudrate = baudrate;
299         /* Configure UART clock */
300         set_subsystem_clk_divider(uart_defs[uart_num].clk_num, LPC_PCLK_CCLK);
301         pclk = get_main_clock(); /* See above note */
302         div = (pclk / (baudrate * 16));
303         /* The easy one : divider is an integer, or baudrate is low enought for the aproximation */
304         if ((baudrate <= 115200) || ((div * baudrate * 16) == pclk)) {
305                 uart->line_ctrl |= LPC_UART_ENABLE_DLAB;
306                 uart->ctrl.divisor_latch_lsb = (div & 0xff);
307                 uart->ctrl.divisor_latch_msb = ((div >> 8) & 0xFF);
308                 uart->line_ctrl &= ~LPC_UART_ENABLE_DLAB;
309         } else {
310                 int i = 0;
311                 /* Do not try to communicate at high speed with a low speed clock ... or compute the table
312                  * for your clock rate */
313                 if (pclk != (48 * 1000 * 1000)) {
314                         return;
315                 }
316                 while (uart_clk_table[i].baudrate != 0) {
317                         if (uart_clk_table[i].baudrate < baudrate) {
318                                 i++;
319                                 continue;
320                         }
321                         uart->line_ctrl |= LPC_UART_ENABLE_DLAB;
322                         uart->ctrl.divisor_latch_lsb = uart_clk_table[i].divisor_latch_lsb;
323                         uart->ctrl.divisor_latch_msb = 0;
324                         uart->fractional_div = (uart_clk_table[i].div_add_val | (uart_clk_table[i].mul_val << 4));
325                         uart->line_ctrl &= ~LPC_UART_ENABLE_DLAB;
326                         break;
327                 }
328         }
331 static uint32_t uart_setup(uint32_t uart_num)
333         struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
334         uint32_t status = 0;
335         /* Set up UART mode */
336         uart->line_ctrl = uarts[uart_num].config;;
337         /* Clear all fifo, reset and enable them */
338         /* Note : fifo trigger level is one bit */
339         uart->ctrl.fifo_ctrl = (LPC_UART_FIFO_EN | LPC_UART_TX_CLR | LPC_UART_RX_CLR);
340         /* Clear the Line Status Register, return it to prevent compiler from removing the read */
341         status = uart->line_status;
342         /* Enable UART Interrupt */
343         uart->func.intr_enable = (LPC_UART_RX_INT_EN | LPC_UART_TX_INT_EN);
345         return status;
348 /***************************************************************************** */
349 /*   Public access to UART setup   */
351 /* Allow any change to the main clock to be forwarded to us */
352 void uart_clk_update(void)
354         int i = 0;
355         for (i = 0; i < NUM_UARTS; i++) {
356                 if (uarts[i].baudrate != 0) {
357                         uart_clk_on(i, uarts[i].baudrate);
358                 }
359         }
362 /* Change uart mode to RS485
363  * return -ENODEV when the device does not support RS485 mode.
364  */
365 int uart_set_mode_rs485(uint32_t uart_num, uint32_t control, uint8_t addr, uint8_t delay)
367         struct uart_device* uart = NULL;
368         struct lpc_uart* uart_regs = NULL;
369         if (uart_num >= NUM_UARTS)
370                 return -EINVAL;
371         uart = &uarts[uart_num];
372         uart_regs = uart->regs; /* Get the right registers */
374         if (!(uart->capabilities & SERIAL_CAP_RS485)) {
375                 return -ENODEV;
376         }
377         /* Disable all other modes */
378         uart_regs->irda_ctrl = 0;
380         /* Set current mode */
381         uart->current_mode = SERIAL_MODE_RS485;
382         uart_regs->RS485_ctrl = (control & 0xFF);
383         uart_regs->RS485_addr_match = LPC_RS485_ADDR(addr);
384         uart_regs->RS485_dir_ctrl_delay = LPC_RS485_DIR_DELAY(delay);
385         return 0;
388 /* Change uart mode to IRDA
389  * pulse_width is the number of clock cycles for a pulse. Should dbe a power of 2.
390  * return -ENODEV when the device does not support IrDA mode.
391  */
392 int uart_set_mode_irda(uint32_t uart_num, uint32_t control, uint16_t pulse_width)
394         struct uart_device* uart = NULL;
395         struct lpc_uart* uart_regs = NULL;
396         uint8_t pulse_div = 0;
398         if (uart_num >= NUM_UARTS)
399                 return -EINVAL;
400         uart = &uarts[uart_num];
401         uart_regs = uart->regs; /* Get the right registers */
403         if (!(uart->capabilities & SERIAL_CAP_IRDA)) {
404                 return -ENODEV;
405         }
406         /* Disable all other modes */
407         uart_regs->RS485_ctrl = 0;
409         /* Set current mode */
410         uart->current_mode = SERIAL_MODE_IRDA;
411         /* Setup IrDA */
412         if (pulse_width < 2) {
413                 pulse_div = 0;
414         } else {
415                 pulse_div = (31 - clz(pulse_width & 0x1FF));
416         }
417         uart_regs->irda_ctrl = control | LPC_IRDA_PULSEDIV(pulse_div);
418         return 0;
422 /* Do we need to allow setting of other parameters ? (Other than 8n1) */
423 int uart_on(uint32_t uart_num, uint32_t baudrate, void (*rx_callback)(uint8_t))
425         struct uart_def* uart = NULL;
426         uint32_t status = 0;
428         if (uart_num >= NUM_UARTS)
429                 return -EINVAL;
430         uart = &uart_defs[uart_num];
431         uarts[uart_num].rx_callback = rx_callback;
433         NVIC_DisableIRQ( uart->irq );
434         /* Turn On power */
435         subsystem_power(uart->power_offset, 1);
436         /* Setup clock acording to baudrate */
437         uart_clk_on(uart_num, baudrate);
438         /* Setup mode, fifo, ... */
439         status = uart_setup(uart_num);
440         /* Enable interrupts back on */
441         NVIC_EnableIRQ( uart->irq );
443         return status;
446 void uart_off(uint32_t uart_num)
448         struct uart_def* uart = NULL;
449         if (uart_num >= NUM_UARTS)
450                 return;
451         uart = &uart_defs[uart_num];
453         NVIC_DisableIRQ( uart->irq );
454         /* Turn Off power */
455         subsystem_power(uart->power_offset, 0);
456         uarts[uart_num].baudrate = 0;
457         uarts[uart_num].rx_callback = NULL;