2 * Copyright (c) 2005-2015, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <ucg_cirbuf.h>
34 /* Send the next char, or disable tx interruptions if tx fifo is
35 * empty. Must be called with intrp locked and uart data register
37 static void ucg_uart_send_next_char(struct ucg_uart *uart)
41 if (ucg_cirbuf_is_empty(uart->tx_fifo)) {
42 uart->ops->disable_tx_irq(uart);
46 c = ucg_cirbuf_get_tail(uart->tx_fifo);
47 ucg_cirbuf_del_tail(uart->tx_fifo);
48 uart->ops->set_udr(uart, c);
49 if (uart->tx_cb != NULL)
52 uart->ops->enable_tx_irq(uart);
56 /* Receive char and put it in the fifo. If the rx fifo is full, the char
57 * is dropped. Must be called with intrp locked and uart data register
59 static void ucg_uart_recv_next_char(struct ucg_uart *uart)
63 c = uart->ops->get_udr(uart);
65 if (!ucg_cirbuf_is_full(uart->rx_fifo))
66 ucg_cirbuf_add_head(uart->rx_fifo, c);
68 if (uart->rx_cb != NULL)
72 /* called by user to handle the "tx register empty" interrupt */
73 void ucg_uart_tx_intr(struct ucg_uart *uart)
75 ucg_uart_send_next_char(uart);
78 /* called by user to handle the "rx register non empty" interrupt */
79 void ucg_uart_rx_intr(struct ucg_uart *uart)
81 ucg_uart_recv_next_char(uart);
85 /* get a char from the receive fifo */
86 static int ucg_uart_recv_nowait(struct ucg_uart *uart)
91 flags = ucg_irq_lock_save();
92 if (ucg_cirbuf_is_empty(uart->rx_fifo)) {
93 ucg_irq_unlock_restore(flags);
97 c = ucg_cirbuf_get_tail(uart->rx_fifo);
98 ucg_cirbuf_del_tail(uart->rx_fifo);
99 ucg_irq_unlock_restore(flags);
104 /* get a char from the receive fifo */
105 int ucg_uart_recv(struct ucg_uart *uart, enum ucg_uart_wait wait)
109 c = ucg_uart_recv_nowait(uart);
116 if (ucg_irq_locked()) {
117 /* if irq are masked we have to poll uart register */
118 while (!uart->ops->rx_ready(uart))
121 /* then receive the data, and return it */
122 ucg_uart_recv_next_char(uart);
123 c = ucg_uart_recv_nowait(uart);
125 while ((c = ucg_uart_recv_nowait(uart)) == -1)
132 /* send a char, or put it in the fifo if uart is not ready. Return -1
134 static int ucg_uart_send_nowait(struct ucg_uart *uart, char c)
136 ucg_irqflags_t flags;
138 flags = ucg_irq_lock_save();
140 if (ucg_cirbuf_is_full(uart->tx_fifo)) {
141 ucg_irq_unlock_restore(flags);
145 /* uart is ready to send */
146 if (ucg_cirbuf_is_empty(uart->tx_fifo) && uart->ops->tx_ready(uart)) {
147 uart->ops->set_udr(uart, c);
148 if (uart->tx_cb != NULL)
150 uart->ops->enable_tx_irq(uart);
153 else { /* not ready, put char in fifo */
154 ucg_cirbuf_add_head(uart->tx_fifo, c);
157 ucg_irq_unlock_restore(flags);
162 int ucg_uart_send(struct ucg_uart *uart, char c, enum ucg_uart_wait wait)
164 /* try to send the char */
165 if (ucg_uart_send_nowait(uart, c) == 0)
171 if (ucg_irq_locked()) {
172 /* if irq are masked we have to poll uart register */
173 while (!uart->ops->tx_ready(uart))
176 /* then send a data to free a room in the fifo */
177 ucg_uart_send_next_char(uart);
178 ucg_cirbuf_add_head(uart->tx_fifo, c);
180 /* if irq are not locked, we can loop to emit */
181 while (ucg_uart_send_nowait(uart, c) != 0)
187 /* flush the tx fifo */
188 void ucg_uart_flush(struct ucg_uart *uart)
190 ucg_irqflags_t flags;
192 if (ucg_irq_locked()) {
193 /* poll uart register, and send next byte until tx fifo
196 if (ucg_cirbuf_is_empty(uart->tx_fifo))
198 while (!uart->ops->tx_ready(uart))
200 ucg_uart_send_next_char(uart);
203 /* just wait that tx fifo is empty */
205 flags = ucg_irq_lock_save();
206 if (ucg_cirbuf_is_empty(uart->tx_fifo)) {
207 ucg_irq_unlock_restore(flags);
210 ucg_irq_unlock_restore(flags);
215 /* read the current running configuration */
216 void ucg_uart_getconf(struct ucg_uart *uart, struct ucg_uart_config *conf)
218 memcpy(conf, &uart->conf, sizeof(*conf));
221 /* set a new uart config */
222 int ucg_uart_setconf(struct ucg_uart *uart, const struct ucg_uart_config *conf)
226 ret = uart->ops->set_conf(uart, conf);
230 memcpy(&uart->conf, conf, sizeof(*conf));
234 /* register the function that will be executed at each byte transmission */
235 void ucg_uart_register_tx_cb(struct ucg_uart *uart, void (*f)(char))
237 ucg_irqflags_t flags;
239 flags = ucg_irq_lock_save();
241 ucg_irq_unlock_restore(flags);
244 /* register the function that will be executed at each byte reception */
245 void ucg_uart_register_rx_cb(struct ucg_uart *uart, void (*f)(char))
247 ucg_irqflags_t flags;
249 flags = ucg_irq_lock_save();
251 ucg_irq_unlock_restore(flags);
254 /* init uart and fifos, call the per-arch initialization and set a default
255 * configuration (9600 bauds) */
256 int ucg_uart_init(struct ucg_uart *uart,
257 const struct ucg_uart_driver_ops *ops, void *driver_data,
258 struct ucg_cirbuf *rx_cbuf, char *rx_buf, unsigned rx_bufsize,
259 struct ucg_cirbuf *tx_cbuf, char *tx_buf, unsigned tx_bufsize)
263 const struct ucg_uart_config def_conf = {
272 memset(uart, 0, sizeof(*uart));
273 ucg_cirbuf_init(rx_cbuf, rx_buf, 0, rx_bufsize);
274 ucg_cirbuf_init(tx_cbuf, tx_buf, 0, tx_bufsize);
275 uart->rx_fifo = rx_cbuf;
276 uart->tx_fifo = tx_cbuf;
278 uart->driver_data = driver_data;
279 ret = ucg_uart_setconf(uart, &def_conf);