File indexing completed on 2025-05-11 08:24:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <dev/serial/zynq-uart-regs.h>
0038
0039 #include <bspopts.h>
0040
0041 #include <rtems/dev/io.h>
0042 #include <rtems/score/assert.h>
0043
0044 static uint32_t zync_uart_baud_error(
0045 uint32_t selected_clock,
0046 uint32_t desired_baud,
0047 uint32_t cd,
0048 uint32_t bdiv_plus_one
0049 )
0050 {
0051 uint32_t actual_baud = selected_clock / ( cd * bdiv_plus_one );
0052
0053 if ( actual_baud > desired_baud ) {
0054 return actual_baud - desired_baud;
0055 }
0056
0057 return desired_baud - actual_baud;
0058 }
0059
0060 uint32_t zynq_uart_calculate_baud(
0061 uint32_t desired_baud,
0062 uint32_t mode_clks,
0063 uint32_t *cd_ptr,
0064 uint32_t *bdiv_ptr
0065 )
0066 {
0067 uint32_t best_error = UINT32_MAX;
0068 uint32_t best_cd = 0x28b;
0069 uint32_t best_bdiv_plus_one = 16;
0070 uint32_t bdiv_plus_one;
0071 uint32_t selected_clock;
0072
0073 _Assert((mode_clks & ~ZYNQ_UART_MODE_CLKS) == 0);
0074 selected_clock = zynq_uart_input_clock() / (1U << (3 * mode_clks));
0075
0076 for (bdiv_plus_one = 5; bdiv_plus_one <= 256; ++bdiv_plus_one) {
0077 uint32_t cd = ( selected_clock / bdiv_plus_one ) / desired_baud;
0078 uint32_t error;
0079
0080 if (cd == 0 ) {
0081 cd = 1;
0082 } else if ( cd > 65535 ) {
0083 cd = 65535;
0084 }
0085
0086 error = zync_uart_baud_error(
0087 selected_clock,
0088 desired_baud,
0089 cd,
0090 bdiv_plus_one
0091 );
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 if (error < best_error || (bdiv_plus_one <= 20 && error <= best_error)) {
0103 best_error = error;
0104 best_cd = cd;
0105 best_bdiv_plus_one = bdiv_plus_one;
0106 }
0107 }
0108
0109 *cd_ptr = best_cd;
0110 *bdiv_ptr = best_bdiv_plus_one - 1;
0111 return best_error;
0112 }
0113
0114 void zynq_uart_initialize(volatile zynq_uart *regs)
0115 {
0116 uint32_t mode_clks = regs->mode & ZYNQ_UART_MODE_CLKS;
0117 uint32_t cd;
0118 uint32_t bdiv;
0119
0120 zynq_uart_reset_tx_flush(regs);
0121 (void) zynq_uart_calculate_baud(
0122 ZYNQ_UART_DEFAULT_BAUD,
0123 mode_clks,
0124 &cd,
0125 &bdiv
0126 );
0127
0128 regs->control = ZYNQ_UART_CONTROL_RXDIS | ZYNQ_UART_CONTROL_TXDIS;
0129 regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(cd);
0130 regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bdiv);
0131
0132 regs->control = ZYNQ_UART_CONTROL_RXRES | ZYNQ_UART_CONTROL_TXRES;
0133 regs->rx_fifo_trg_lvl = ZYNQ_UART_RX_FIFO_TRG_LVL_RTRIG(0);
0134 regs->rx_timeout = ZYNQ_UART_RX_TIMEOUT_RTO(0);
0135 regs->mode = ZYNQ_UART_MODE_CHMODE(ZYNQ_UART_MODE_CHMODE_NORMAL)
0136 | ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_NONE)
0137 | ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8)
0138 | mode_clks;
0139 regs->control = ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN;
0140 }
0141
0142 int zynq_uart_read_char_polled(volatile zynq_uart *regs)
0143 {
0144 if ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) != 0) {
0145 return -1;
0146 } else {
0147 return ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo);
0148 }
0149 }
0150
0151 void zynq_uart_write_char_polled(volatile zynq_uart *regs, char c)
0152 {
0153 while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TNFUL) != 0) {
0154 _IO_Relax();
0155 }
0156
0157 regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(c);
0158 }
0159
0160 void zynq_uart_reset_tx_flush(volatile zynq_uart *regs)
0161 {
0162 while (
0163 (regs->channel_sts &
0164 (ZYNQ_UART_CHANNEL_STS_TEMPTY | ZYNQ_UART_CHANNEL_STS_TACTIVE)) !=
0165 ZYNQ_UART_CHANNEL_STS_TEMPTY) {
0166 _IO_Relax();
0167 }
0168 }