source: rtems/bsps/shared/dev/serial/zynq-uart-polled.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: 5.4 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
31#include <bspopts.h>
32
33/*
34 * Make weak and let the user override.
35 */
36uint32_t zynq_uart_input_clock(void) __attribute__ ((weak));
37
38uint32_t zynq_uart_input_clock(void)
39{
40  return ZYNQ_CLOCK_UART;
41}
42
43int zynq_cal_baud_rate(uint32_t  baudrate,
44                              uint32_t* brgr,
45                              uint32_t* bauddiv,
46                              uint32_t  modereg)
47{
48  uint32_t brgr_value;    /* Calculated value for baud rate generator */
49  uint32_t calcbaudrate;  /* Calculated baud rate */
50  uint32_t bauderror;     /* Diff between calculated and requested baud rate */
51  uint32_t best_error = 0xFFFFFFFF;
52  uint32_t percenterror;
53  uint32_t bdiv;
54  uint32_t inputclk = zynq_uart_input_clock();
55
56  /*
57   * Make sure the baud rate is not impossilby large.
58   * Fastest possible baud rate is Input Clock / 2.
59   */
60  if ((baudrate * 2) > inputclk) {
61    return -1;
62  }
63  /*
64   * Check whether the input clock is divided by 8
65   */
66  if(modereg & ZYNQ_UART_MODE_CLKS) {
67    inputclk = inputclk / 8;
68  }
69
70  /*
71   * Determine the Baud divider. It can be 4to 254.
72   * Loop through all possible combinations
73   */
74  for (bdiv = 4; bdiv < 255; bdiv++) {
75
76    /*
77     * Calculate the value for BRGR register
78     */
79    brgr_value = inputclk / (baudrate * (bdiv + 1));
80
81    /*
82     * Calculate the baud rate from the BRGR value
83     */
84    calcbaudrate = inputclk/ (brgr_value * (bdiv + 1));
85
86    /*
87     * Avoid unsigned integer underflow
88     */
89    if (baudrate > calcbaudrate) {
90      bauderror = baudrate - calcbaudrate;
91    }
92    else {
93      bauderror = calcbaudrate - baudrate;
94    }
95
96    /*
97     * Find the calculated baud rate closest to requested baud rate.
98     */
99    if (best_error > bauderror) {
100      *brgr = brgr_value;
101      *bauddiv = bdiv;
102      best_error = bauderror;
103    }
104  }
105
106  /*
107   * Make sure the best error is not too large.
108   */
109  percenterror = (best_error * 100) / baudrate;
110#define XUARTPS_MAX_BAUD_ERROR_RATE              3      /* max % error allowed */
111  if (XUARTPS_MAX_BAUD_ERROR_RATE < percenterror) {
112    return -1;
113  }
114
115  return 0;
116}
117
118void zynq_uart_initialize(rtems_termios_device_context *base)
119{
120  zynq_uart_context *ctx = (zynq_uart_context *) base;
121  volatile zynq_uart *regs = ctx->regs;
122  uint32_t brgr = 0x3e;
123  uint32_t bauddiv = 0x6;
124
125  zynq_uart_reset_tx_flush(ctx);
126
127  zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode);
128
129  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
130  regs->control = ZYNQ_UART_CONTROL_RXDIS
131    | ZYNQ_UART_CONTROL_TXDIS
132    | ZYNQ_UART_CONTROL_RXRES
133    | ZYNQ_UART_CONTROL_TXRES;
134  regs->mode = ZYNQ_UART_MODE_CHMODE(ZYNQ_UART_MODE_CHMODE_NORMAL)
135    | ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_NONE)
136    | ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8);
137  regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);
138  regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);
139  regs->rx_fifo_trg_lvl = ZYNQ_UART_RX_FIFO_TRG_LVL_RTRIG(0);
140  regs->rx_timeout = ZYNQ_UART_RX_TIMEOUT_RTO(0);
141  regs->control = ZYNQ_UART_CONTROL_RXEN
142    | ZYNQ_UART_CONTROL_TXEN
143    | ZYNQ_UART_CONTROL_RSTTO;
144}
145
146int zynq_uart_read_polled(rtems_termios_device_context *base)
147{
148  zynq_uart_context *ctx = (zynq_uart_context *) base;
149  volatile zynq_uart *regs = ctx->regs;
150
151  if ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) != 0) {
152    return -1;
153  } else {
154    return ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo);
155  }
156}
157
158void zynq_uart_write_polled(
159  rtems_termios_device_context *base,
160  char c
161)
162{
163  zynq_uart_context *ctx = (zynq_uart_context *) base;
164  volatile zynq_uart *regs = ctx->regs;
165
166  while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TFUL) != 0) {
167    /* Wait */
168  }
169
170  regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(c);
171}
172
173void zynq_uart_reset_tx_flush(zynq_uart_context *ctx)
174{
175  volatile zynq_uart *regs = ctx->regs;
176  int                 c = 4;
177
178  while (c-- > 0)
179    zynq_uart_write_polled(&ctx->base, '\r');
180
181  while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) == 0) {
182    /* Wait */
183  }
184}
Note: See TracBrowser for help on using the repository browser.