source: rtems/bsps/shared/dev/serial/zynq-uart.c @ 5686b44d

Last change on this file since 5686b44d was 5686b44d, checked in by Kinsey Moore <kinsey.moore@…>, on Dec 2, 2020 at 7:20:36 PM

zynq-uart: Fix set_attributes implementation

The zynq-uart set_attributes implementation was configured to always
return false which causes spconsole01 to fail. This restores the
disabled implementation which sets the baud rate registers
appropriately and allows spconsole01 to pass. This also expands the
set_attributes functionality to allow setting of the stop bits,
character width, and parity.

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (C) 2013, 2017 embedded brains GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <dev/serial/zynq-uart.h>
29#include <dev/serial/zynq-uart-regs.h>
30#include <bsp/irq.h>
31
32#include <bspopts.h>
33
34#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
35static void zynq_uart_interrupt(void *arg)
36{
37  rtems_termios_tty *tty = arg;
38  zynq_uart_context *ctx = rtems_termios_get_device_context(tty);
39  volatile zynq_uart *regs = ctx->regs;
40  uint32_t channel_sts;
41
42  if ((regs->irq_sts & (ZYNQ_UART_TIMEOUT | ZYNQ_UART_RTRIG)) != 0) {
43    regs->irq_sts = ZYNQ_UART_TIMEOUT | ZYNQ_UART_RTRIG;
44
45    do {
46      char c = (char) ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo);
47
48      rtems_termios_enqueue_raw_characters(tty, &c, 1);
49
50      channel_sts = regs->channel_sts;
51    } while ((channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) == 0);
52  } else {
53    channel_sts = regs->channel_sts;
54  }
55
56  if (ctx->transmitting && (channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) != 0) {
57    rtems_termios_dequeue_characters(tty, 1);
58  }
59}
60#endif
61
62static bool zynq_uart_first_open(
63  rtems_termios_tty *tty,
64  rtems_termios_device_context *base,
65  struct termios *term,
66  rtems_libio_open_close_args_t *args
67)
68{
69#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
70  zynq_uart_context *ctx = (zynq_uart_context *) base;
71  volatile zynq_uart *regs = ctx->regs;
72  rtems_status_code sc;
73#endif
74
75  rtems_termios_set_initial_baud(tty, ZYNQ_UART_DEFAULT_BAUD);
76  zynq_uart_initialize(base);
77
78#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
79  regs->rx_timeout = 32;
80  regs->rx_fifo_trg_lvl = ZYNQ_UART_FIFO_DEPTH / 2;
81  regs->irq_dis = 0xffffffff;
82  regs->irq_sts = 0xffffffff;
83  regs->irq_en = ZYNQ_UART_RTRIG | ZYNQ_UART_TIMEOUT;
84  sc = rtems_interrupt_handler_install(
85    ctx->irq,
86    "UART",
87    RTEMS_INTERRUPT_SHARED,
88    zynq_uart_interrupt,
89    tty
90  );
91  if (sc != RTEMS_SUCCESSFUL) {
92    return false;
93  }
94#endif
95
96  return true;
97}
98
99#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
100static void zynq_uart_last_close(
101  rtems_termios_tty *tty,
102  rtems_termios_device_context *base,
103  rtems_libio_open_close_args_t *args
104)
105{
106  zynq_uart_context *ctx = (zynq_uart_context *) base;
107
108  rtems_interrupt_handler_remove(ctx->irq, zynq_uart_interrupt, tty);
109}
110#endif
111
112static void zynq_uart_write_support(
113  rtems_termios_device_context *base,
114  const char *buf,
115  size_t len
116)
117{
118#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
119  zynq_uart_context *ctx = (zynq_uart_context *) base;
120  volatile zynq_uart *regs = ctx->regs;
121
122  if (len > 0) {
123    ctx->transmitting = true;
124    regs->irq_sts = ZYNQ_UART_TEMPTY;
125    regs->irq_en = ZYNQ_UART_TEMPTY;
126    regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(buf[0]);
127  } else {
128    ctx->transmitting = false;
129    regs->irq_dis = ZYNQ_UART_TEMPTY;
130  }
131#else
132  ssize_t i;
133
134  for (i = 0; i < len; ++i) {
135    zynq_uart_write_polled(base, buf[i]);
136  }
137#endif
138}
139
140static bool zynq_uart_set_attributes(
141  rtems_termios_device_context *context,
142  const struct termios *term
143)
144{
145  zynq_uart_context *ctx = (zynq_uart_context *) context;
146  volatile zynq_uart *regs = ctx->regs;
147  uint32_t brgr = 0;
148  uint32_t bauddiv = 0;
149  uint32_t mode = 0;
150  int rc;
151
152  rc = zynq_cal_baud_rate(115200, &brgr, &bauddiv, regs->mode);
153  if (rc != 0)
154    return rc;
155
156  /*
157   * Configure the mode register
158   */
159  mode |= ZYNQ_UART_MODE_CHMODE(ZYNQ_UART_MODE_CHMODE_NORMAL);
160
161  /*
162   * Parity
163   */
164  mode |= ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_NONE);
165  if (term->c_cflag & PARENB) {
166    if (!(term->c_cflag & PARODD)) {
167      mode |= ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_ODD);
168    } else {
169      mode |= ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_EVEN);
170    }
171  }
172
173  /*
174   * Character Size
175   */
176  switch (term->c_cflag & CSIZE)
177  {
178  case CS5:
179    return false;
180  case CS6:
181    mode |= ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_6);
182    break;
183  case CS7:
184    mode |= ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_7);
185    break;
186  case CS8:
187  default:
188    mode |= ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8);
189    break;
190  }
191
192  /*
193   * Stop Bits
194   */
195  if (term->c_cflag & CSTOPB) {
196    /* 2 stop bits */
197    mode |= ZYNQ_UART_MODE_NBSTOP(ZYNQ_UART_MODE_NBSTOP_STOP_2);
198  } else {
199    /* 1 stop bit */
200    mode |= ZYNQ_UART_MODE_NBSTOP(ZYNQ_UART_MODE_NBSTOP_STOP_1);
201  }
202
203  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
204  regs->mode = mode;
205  regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);
206  regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);
207  regs->control |= ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN;
208
209  return true;
210}
211
212const rtems_termios_device_handler zynq_uart_handler = {
213  .first_open = zynq_uart_first_open,
214  .set_attributes = zynq_uart_set_attributes,
215  .write = zynq_uart_write_support,
216#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
217  .last_close = zynq_uart_last_close,
218  .mode = TERMIOS_IRQ_DRIVEN
219#else
220  .poll_read = zynq_uart_read_polled,
221  .mode = TERMIOS_POLLED
222#endif
223};
Note: See TracBrowser for help on using the repository browser.