Changeset 6e4255d in rtems


Ignore:
Timestamp:
12/10/13 02:41:16 (10 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.11, 5, master
Children:
c59f668
Parents:
37df715
Message:

arm/xilinxzynq: Support application based clock freq.

Provide a weak call to a clock freq routine to allow the application
to supply the freq defined in the Xilinx generated source.

Add code to calculate the baud rate.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/arm/xilinx-zynq/console/zynq-uart.c

    r37df715 r6e4255d  
    2626}
    2727
     28/*
     29 * Make weak and let the user override.
     30 */
     31uint32_t zynq_uart_input_clock(void) __attribute__ ((weak));
     32
     33uint32_t zynq_uart_input_clock(void)
     34{
     35  return 100000000UL;
     36}
     37
     38static int zynq_cal_baud_rate(uint32_t  baudrate,
     39                              uint32_t* brgr,
     40                              uint32_t* bauddiv,
     41                              uint32_t  modereg)
     42{
     43  uint32_t brgr_value;    /* Calculated value for baud rate generator */
     44  uint32_t calcbaudrate;  /* Calculated baud rate */
     45  uint32_t bauderror;     /* Diff between calculated and requested baud rate */
     46  uint32_t best_error = 0xFFFFFFFF;
     47  uint32_t percenterror;
     48  uint32_t bdiv;
     49  uint32_t inputclk = zynq_uart_input_clock();
     50
     51  /*
     52   * Make sure the baud rate is not impossilby large.
     53   * Fastest possible baud rate is Input Clock / 2.
     54   */
     55  if ((baudrate * 2) > inputclk) {
     56    return -1;
     57  }
     58  /*
     59   * Check whether the input clock is divided by 8
     60   */
     61  if(modereg & ZYNQ_UART_MODE_CLKS) {
     62    inputclk = inputclk / 8;
     63  }
     64
     65  /*
     66   * Determine the Baud divider. It can be 4to 254.
     67   * Loop through all possible combinations
     68   */
     69  for (bdiv = 4; bdiv < 255; bdiv++) {
     70
     71    /*
     72     * Calculate the value for BRGR register
     73     */
     74    brgr_value = inputclk / (baudrate * (bdiv + 1));
     75
     76    /*
     77     * Calculate the baud rate from the BRGR value
     78     */
     79    calcbaudrate = inputclk/ (brgr_value * (bdiv + 1));
     80
     81    /*
     82     * Avoid unsigned integer underflow
     83     */
     84    if (baudrate > calcbaudrate) {
     85      bauderror = baudrate - calcbaudrate;
     86    }
     87    else {
     88      bauderror = calcbaudrate - baudrate;
     89    }
     90
     91    /*
     92     * Find the calculated baud rate closest to requested baud rate.
     93     */
     94    if (best_error > bauderror) {
     95      *brgr = brgr_value;
     96      *bauddiv = bdiv;
     97      best_error = bauderror;
     98    }
     99  }
     100
     101  /*
     102   * Make sure the best error is not too large.
     103   */
     104  percenterror = (best_error * 100) / baudrate;
     105#define XUARTPS_MAX_BAUD_ERROR_RATE              3      /* max % error allowed */
     106  if (XUARTPS_MAX_BAUD_ERROR_RATE < percenterror) {
     107    return -1;
     108  }
     109
     110  return 0;
     111}
     112
    28113static void zynq_uart_initialize(int minor)
    29114{
    30115  volatile zynq_uart *regs = zynq_uart_get_regs(minor);
    31 
     116  uint32_t brgr = 0x3e;
     117  uint32_t bauddiv = 0x6;
     118
     119  zynq_cal_baud_rate(115200, &brgr, &bauddiv, regs->mode);
     120
     121  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
    32122  regs->control = ZYNQ_UART_CONTROL_RXDIS
    33123    | ZYNQ_UART_CONTROL_TXDIS
     
    37127    | ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_NONE)
    38128    | ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8);
    39   regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(0x3e);
    40   regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(0x6);
     129  regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);
     130  regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);
    41131  regs->rx_fifo_trg_lvl = ZYNQ_UART_RX_FIFO_TRG_LVL_RTRIG(0);
    42132  regs->rx_timeout = ZYNQ_UART_RX_TIMEOUT_RTO(0);
     
    103193static int zynq_uart_set_attribues(int minor, const struct termios *term)
    104194{
     195#if 0
     196  volatile zynq_uart *regs = zynq_uart_get_regs(minor);
     197  uint32_t brgr = 0;
     198  uint32_t bauddiv = 0;
     199  int rc;
     200
     201  rc = zynq_cal_baud_rate(115200, &brgr, &bauddiv, regs->mode);
     202  if (rc != 0)
     203    return rc;
     204
     205  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
     206  regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);
     207  regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);
     208  regs->control |= ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN;
     209
     210  return 0;
     211#else
    105212  return -1;
     213#endif
    106214}
    107215
Note: See TracChangeset for help on using the changeset viewer.