Changeset a7cd4b73 in rtems


Ignore:
Timestamp:
Jul 31, 2018, 9:38:56 AM (16 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
56b0387
Parents:
8a78b784
git-author:
Sebastian Huber <sebastian.huber@…> (07/31/18 09:38:56)
git-committer:
Sebastian Huber <sebastian.huber@…> (08/01/18 09:13:58)
Message:

serial/ns16550: Precision clock synthesizer

Set the FIFO control register while DLAB == 1 in the line control
register. At least on the QorIQ T4240 the driver still works with the
re-ordered FIFO control register access.

Location:
bsps
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • bsps/include/libchip/ns16550.h

    r8a78b784 ra7cd4b73  
    7070  uint32_t initial_baud;
    7171  bool has_fractional_divider_register;
     72  bool has_precision_clock_synthesizer;
    7273  uint8_t modem_control;
    7374  uint8_t line_control;
  • bsps/shared/dev/serial/ns16550-context.c

    r8a78b784 ra7cd4b73  
    5454static uint32_t NS16550_GetBaudDivisor(ns16550_context *ctx, uint32_t baud)
    5555{
    56   uint32_t clock = ctx->clock;
    57   uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16);
    58 
    59   if (ctx->has_fractional_divider_register) {
     56  uint32_t clock;
     57  uint32_t baudDivisor;
     58  uint32_t err;
     59  uint32_t actual;
     60  uint32_t newErr;
     61
     62  if (ctx->clock != 0) {
     63    clock = ctx->clock;
     64  } else {
     65    clock = 115200;
     66  }
     67
     68  baudDivisor = clock / (baud * 16);
     69
     70  if (ctx->has_precision_clock_synthesizer) {
     71    uint32_t i;
     72
     73    err = baud;
     74    baudDivisor = 0x0001ffff;
     75
     76    for (i = 2; i <= 0x10000; i *= 2) {
     77      uint32_t fout;
     78      uint32_t fin;
     79
     80      fin = i - 1;
     81      fout = (baud * fin * 16) / clock;
     82      actual = (clock * fout) / (16 * fin);
     83      newErr = actual > baud ? actual - baud : baud - actual;
     84
     85      if (newErr < err) {
     86        err = newErr;
     87        baudDivisor = fin | (fout << 16);
     88      }
     89    }
     90  } else if (ctx->has_fractional_divider_register) {
    6091    uint32_t fractionalDivider = 0x10;
    61     uint32_t err = baud;
    6292    uint32_t mulVal;
    6393    uint32_t divAddVal;
    6494
     95    err = baud;
    6596    clock /= 16 * baudDivisor;
     97
    6698    for (mulVal = 1; mulVal < 16; ++mulVal) {
    6799      for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) {
    68         uint32_t actual = (mulVal * clock) / (mulVal + divAddVal);
    69         uint32_t newErr = actual > baud ? actual - baud : baud - actual;
     100        actual = (mulVal * clock) / (mulVal + divAddVal);
     101        newErr = actual > baud ? actual - baud : baud - actual;
    70102
    71103        if (newErr < err) {
     
    160192  );
    161193
     194  /* Enable and reset transmit and receive FIFOs. TJA     */
     195  ucDataByte = SP_FIFO_ENABLE;
     196  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
     197
     198  ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
     199
     200  if (ctx->has_precision_clock_synthesizer) {
     201    /*
     202     * Enable precision clock synthesizer.  This must be done with DLAB == 1 in
     203     * the line control register.
     204     */
     205    ucDataByte |= 0x10;
     206  }
     207
     208  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
     209
    162210  /* Clear the divisor latch and set the character size to eight bits */
    163211  /* with one stop bit and no parity checking. */
    164212  ucDataByte = EIGHT_BITS;
    165213  ctx->line_control = ucDataByte;
    166   (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
    167 
    168   /* Enable and reset transmit and receive FIFOs. TJA     */
    169   ucDataByte = SP_FIFO_ENABLE;
    170   (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
    171 
    172   ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
    173   (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
     214
     215  if (ctx->has_precision_clock_synthesizer) {
     216    (*setReg)(pNS16550, NS16550_SCRATCH_PAD, (uint8_t)(ulBaudDivisor >> 24));
     217    (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte );
     218    (*setReg)(pNS16550, NS16550_SCRATCH_PAD, (uint8_t)(ulBaudDivisor >> 16));
     219  } else {
     220    (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
     221  }
    174222
    175223  ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
     
    667715     *  Now write the line control
    668716     */
    669     (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
     717    if (ctx->has_precision_clock_synthesizer) {
     718      (*setReg)(pNS16550, NS16550_SCRATCH_PAD, (uint8_t)(ulBaudDivisor >> 24));
     719      (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
     720      (*setReg)(pNS16550, NS16550_SCRATCH_PAD, (uint8_t)(ulBaudDivisor >> 16));
     721    } else {
     722      (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
     723    }
    670724
    671725    rtems_termios_device_lock_release(base, &lock_context);
Note: See TracChangeset for help on using the changeset viewer.