1 | /* |
---|
2 | * Copyright (c) 2013 Eugeniy Meshcheryakov <eugen@debian.org> |
---|
3 | * |
---|
4 | * Copyright (c) 2011 Sebastian Huber. All rights reserved. |
---|
5 | * |
---|
6 | * embedded brains GmbH |
---|
7 | * Obere Lagerstr. 30 |
---|
8 | * 82178 Puchheim |
---|
9 | * Germany |
---|
10 | * <rtems@embedded-brains.de> |
---|
11 | * |
---|
12 | * The license and distribution terms for this file may be |
---|
13 | * found in the file LICENSE in this distribution or at |
---|
14 | * http://www.rtems.org/license/LICENSE. |
---|
15 | */ |
---|
16 | |
---|
17 | #include <bspopts.h> |
---|
18 | #include <bsp/uart.h> |
---|
19 | #include <libchip/sersupp.h> |
---|
20 | #include <bsp/syscon.h> |
---|
21 | #include <bsp/lm3s69xx.h> |
---|
22 | #include <rtems/irq-extension.h> |
---|
23 | #include <assert.h> |
---|
24 | |
---|
25 | #define LM3S69XX_UART_FIFO_DEPTH 16 |
---|
26 | |
---|
27 | static volatile lm3s69xx_uart *get_uart_regs(int minor) |
---|
28 | { |
---|
29 | console_tbl *ct = Console_Port_Tbl [minor]; |
---|
30 | |
---|
31 | return (lm3s69xx_uart *) ct->ulCtrlPort1; |
---|
32 | } |
---|
33 | |
---|
34 | static unsigned int get_uart_number(int minor) |
---|
35 | { |
---|
36 | console_tbl *ct = Console_Port_Tbl [minor]; |
---|
37 | |
---|
38 | return (unsigned int)ct->pDeviceParams; |
---|
39 | } |
---|
40 | |
---|
41 | /* |
---|
42 | * Returns both integer and fractional parts as one number. |
---|
43 | */ |
---|
44 | static uint32_t get_baud_div(uint32_t baud) |
---|
45 | { |
---|
46 | uint32_t clock4 = LM3S69XX_SYSTEM_CLOCK * 4; |
---|
47 | return (clock4 + baud - 1) / baud; |
---|
48 | } |
---|
49 | |
---|
50 | static void irq_handler(void *arg) |
---|
51 | { |
---|
52 | int minor = (int)arg; |
---|
53 | console_data *cd = &Console_Port_Data [minor]; |
---|
54 | volatile lm3s69xx_uart *uart = get_uart_regs(minor); |
---|
55 | |
---|
56 | do { |
---|
57 | char buf[LM3S69XX_UART_FIFO_DEPTH]; |
---|
58 | int i = 0; |
---|
59 | uint32_t status = uart->fr; |
---|
60 | |
---|
61 | while (((status & UARTFR_RXFE) == 0) && (i < LM3S69XX_UART_FIFO_DEPTH)) { |
---|
62 | uint32_t d = uart->dr; |
---|
63 | |
---|
64 | if ((d & UARTDR_ERROR_MSK) == 0) { |
---|
65 | buf[i] = UARTDR_DATA_GET(d); |
---|
66 | i++; |
---|
67 | } |
---|
68 | |
---|
69 | status = uart->fr; |
---|
70 | } |
---|
71 | |
---|
72 | if (i > 0) |
---|
73 | rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); |
---|
74 | } while (uart->mis != 0); |
---|
75 | } |
---|
76 | |
---|
77 | static void initialize(int minor) |
---|
78 | { |
---|
79 | const console_tbl *ct = Console_Port_Tbl[minor]; |
---|
80 | volatile lm3s69xx_uart *uart = get_uart_regs(minor); |
---|
81 | unsigned int num = get_uart_number(minor); |
---|
82 | |
---|
83 | lm3s69xx_syscon_enable_uart_clock(num, true); |
---|
84 | |
---|
85 | uart->ctl = 0; |
---|
86 | |
---|
87 | uint32_t brd = get_baud_div(LM3S69XX_UART_BAUD); |
---|
88 | uart->ibrd = brd / 64; |
---|
89 | uart->fbrd = brd % 64; |
---|
90 | |
---|
91 | uart->lcrh = UARTLCRH_WLEN(0x3) | UARTLCRH_FEN; |
---|
92 | uart->ctl = UARTCTL_RXE | UARTCTL_TXE | UARTCTL_UARTEN; |
---|
93 | |
---|
94 | int rv = rtems_interrupt_handler_install(ct->ulIntVector, "UART", |
---|
95 | RTEMS_INTERRUPT_UNIQUE, irq_handler, (void *)minor); |
---|
96 | assert(rv == RTEMS_SUCCESSFUL); |
---|
97 | } |
---|
98 | |
---|
99 | static int first_open(int major, int minor, void *arg) |
---|
100 | { |
---|
101 | rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; |
---|
102 | struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; |
---|
103 | console_data *cd = &Console_Port_Data [minor]; |
---|
104 | volatile lm3s69xx_uart *uart = get_uart_regs(minor); |
---|
105 | |
---|
106 | cd->termios_data = tty; |
---|
107 | rtems_termios_set_initial_baud(tty, LM3S69XX_UART_BAUD); |
---|
108 | |
---|
109 | /* Drain the RX FIFO. */ |
---|
110 | while ((uart->fr & UARTFR_RXFE) == 0) |
---|
111 | (void)uart->dr; |
---|
112 | |
---|
113 | uart->im = UARTI_RX | UARTI_RT; |
---|
114 | |
---|
115 | return 0; |
---|
116 | } |
---|
117 | |
---|
118 | static int last_close(int major, int minor, void *arg) |
---|
119 | { |
---|
120 | volatile lm3s69xx_uart *uart = get_uart_regs(minor); |
---|
121 | uart->im = 0; |
---|
122 | |
---|
123 | return 0; |
---|
124 | } |
---|
125 | |
---|
126 | static void write_polled(int minor, char c) |
---|
127 | { |
---|
128 | volatile lm3s69xx_uart *uart = get_uart_regs(minor); |
---|
129 | |
---|
130 | while ((uart->fr & UARTFR_TXFF) != 0) { |
---|
131 | /* Wait */ |
---|
132 | } |
---|
133 | |
---|
134 | uart->dr = UARTDR_DATA(c); |
---|
135 | } |
---|
136 | |
---|
137 | static ssize_t write_support_polled( |
---|
138 | int minor, |
---|
139 | const char *s, |
---|
140 | size_t n |
---|
141 | ) |
---|
142 | { |
---|
143 | ssize_t i = 0; |
---|
144 | |
---|
145 | for (i = 0; i < n; ++i) { |
---|
146 | write_polled(minor, s [i]); |
---|
147 | } |
---|
148 | |
---|
149 | return n; |
---|
150 | } |
---|
151 | |
---|
152 | static int set_attribues(int minor, const struct termios *term) |
---|
153 | { |
---|
154 | return -1; |
---|
155 | } |
---|
156 | |
---|
157 | const console_fns lm3s69xx_uart_fns = { |
---|
158 | .deviceProbe = libchip_serial_default_probe, |
---|
159 | .deviceFirstOpen = first_open, |
---|
160 | .deviceLastClose = last_close, |
---|
161 | .deviceRead = NULL, |
---|
162 | .deviceWrite = write_support_polled, |
---|
163 | .deviceInitialize = initialize, |
---|
164 | .deviceWritePolled = write_polled, |
---|
165 | .deviceSetAttributes = set_attribues, |
---|
166 | .deviceOutputUsesInterrupts = false |
---|
167 | }; |
---|