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

Last change on this file since f085957 was f085957, checked in by Kinsey Moore <kinsey.moore@…>, on Oct 26, 2020 at 3:26:49 PM

bsps: Move zynq-uart to bsps/shared

This moves the zynq-uart driver from bsps/arm/shared to bsps/shared to
accomodate use by AArch64 BSPs.

  • Property mode set to 100644
File size: 5.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#if 0
146  volatile zynq_uart *regs = zynq_uart_get_regs(minor);
147  uint32_t brgr = 0;
148  uint32_t bauddiv = 0;
149  int rc;
150
151  rc = zynq_cal_baud_rate(115200, &brgr, &bauddiv, regs->mode);
152  if (rc != 0)
153    return rc;
154
155  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
156  regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);
157  regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);
158  regs->control |= ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN;
159
160  return true;
161#else
162  return false;
163#endif
164}
165
166const rtems_termios_device_handler zynq_uart_handler = {
167  .first_open = zynq_uart_first_open,
168  .set_attributes = zynq_uart_set_attributes,
169  .write = zynq_uart_write_support,
170#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
171  .last_close = zynq_uart_last_close,
172  .mode = TERMIOS_IRQ_DRIVEN
173#else
174  .poll_read = zynq_uart_read_polled,
175  .mode = TERMIOS_POLLED
176#endif
177};
Note: See TracBrowser for help on using the repository browser.