Home | History | Annotate | Download | only in PL011Uart
      1 /** @file
      2   Serial I/O Port library functions with no library constructor/destructor
      3 
      4   Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
      5   Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
      6 
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include <Library/DebugLib.h>
     18 #include <Library/IoLib.h>
     19 #include <Library/PcdLib.h>
     20 
     21 #include <Drivers/PL011Uart.h>
     22 
     23 //
     24 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE is the only
     25 // control bit that is not supported.
     26 //
     27 STATIC CONST UINT32 mInvalidControlBits = EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
     28 
     29 /*
     30 
     31   Initialise the serial port to the specified settings.
     32   All unspecified settings will be set to the default values.
     33 
     34   @return    Always return EFI_SUCCESS or EFI_INVALID_PARAMETER.
     35 
     36 **/
     37 RETURN_STATUS
     38 EFIAPI
     39 PL011UartInitializePort (
     40   IN OUT UINTN               UartBase,
     41   IN OUT UINT64              *BaudRate,
     42   IN OUT UINT32              *ReceiveFifoDepth,
     43   IN OUT EFI_PARITY_TYPE     *Parity,
     44   IN OUT UINT8               *DataBits,
     45   IN OUT EFI_STOP_BITS_TYPE  *StopBits
     46   )
     47 {
     48   UINT32      LineControl;
     49   UINT32      Divisor;
     50 
     51   LineControl = 0;
     52 
     53   // The PL011 supports a buffer of 1, 16 or 32 chars. Therefore we can accept
     54   // 1 char buffer as the minimum fifo size. Because everything can be rounded down,
     55   // there is no maximum fifo size.
     56   if ((*ReceiveFifoDepth == 0) || (*ReceiveFifoDepth >= 32)) {
     57     LineControl |= PL011_UARTLCR_H_FEN;
     58     if (PL011_UARTPID2_VER (MmioRead32 (UartBase + UARTPID2)) > PL011_VER_R1P4)
     59       *ReceiveFifoDepth = 32;
     60     else
     61       *ReceiveFifoDepth = 16;
     62   } else {
     63     ASSERT (*ReceiveFifoDepth < 32);
     64     // Nothing else to do. 1 byte fifo is default.
     65     *ReceiveFifoDepth = 1;
     66   }
     67 
     68   //
     69   // Parity
     70   //
     71   switch (*Parity) {
     72   case DefaultParity:
     73     *Parity = NoParity;
     74   case NoParity:
     75     // Nothing to do. Parity is disabled by default.
     76     break;
     77   case EvenParity:
     78     LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_EPS);
     79     break;
     80   case OddParity:
     81     LineControl |= PL011_UARTLCR_H_PEN;
     82     break;
     83   case MarkParity:
     84     LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_SPS | PL011_UARTLCR_H_EPS);
     85     break;
     86   case SpaceParity:
     87     LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_SPS);
     88     break;
     89   default:
     90     return RETURN_INVALID_PARAMETER;
     91   }
     92 
     93   //
     94   // Data Bits
     95   //
     96   switch (*DataBits) {
     97   case 0:
     98     *DataBits = 8;
     99   case 8:
    100     LineControl |= PL011_UARTLCR_H_WLEN_8;
    101     break;
    102   case 7:
    103     LineControl |= PL011_UARTLCR_H_WLEN_7;
    104     break;
    105   case 6:
    106     LineControl |= PL011_UARTLCR_H_WLEN_6;
    107     break;
    108   case 5:
    109     LineControl |= PL011_UARTLCR_H_WLEN_5;
    110     break;
    111   default:
    112     return RETURN_INVALID_PARAMETER;
    113   }
    114 
    115   //
    116   // Stop Bits
    117   //
    118   switch (*StopBits) {
    119   case DefaultStopBits:
    120     *StopBits = OneStopBit;
    121   case OneStopBit:
    122     // Nothing to do. One stop bit is enabled by default.
    123     break;
    124   case TwoStopBits:
    125     LineControl |= PL011_UARTLCR_H_STP2;
    126     break;
    127   case OneFiveStopBits:
    128     // Only 1 or 2 stops bits are supported
    129   default:
    130     return RETURN_INVALID_PARAMETER;
    131   }
    132 
    133   // Don't send the LineControl value to the PL011 yet,
    134   // wait until after the Baud Rate setting.
    135   // This ensures we do not mess up the UART settings halfway through
    136   // in the rare case when there is an error with the Baud Rate.
    137 
    138   //
    139   // Baud Rate
    140   //
    141 
    142   // If PL011 Integral value has been defined then always ignore the BAUD rate
    143   if (PcdGet32 (PL011UartInteger) != 0) {
    144       MmioWrite32 (UartBase + UARTIBRD, PcdGet32 (PL011UartInteger));
    145       MmioWrite32 (UartBase + UARTFBRD, PcdGet32 (PL011UartFractional));
    146   } else {
    147     // If BAUD rate is zero then replace it with the system default value
    148     if (*BaudRate == 0) {
    149       *BaudRate = PcdGet32 (PcdSerialBaudRate);
    150       ASSERT (*BaudRate != 0);
    151     }
    152 
    153     Divisor = (PcdGet32 (PL011UartClkInHz) * 4) / *BaudRate;
    154     MmioWrite32 (UartBase + UARTIBRD, Divisor >> 6);
    155     MmioWrite32 (UartBase + UARTFBRD, Divisor & 0x3F);
    156   }
    157 
    158   // No parity, 1 stop, no fifo, 8 data bits
    159   MmioWrite32 (UartBase + UARTLCR_H, LineControl);
    160 
    161   // Clear any pending errors
    162   MmioWrite32 (UartBase + UARTECR, 0);
    163 
    164   // Enable tx, rx, and uart overall
    165   MmioWrite32 (UartBase + UARTCR, PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN);
    166 
    167   return RETURN_SUCCESS;
    168 }
    169 
    170 /**
    171 
    172   Assert or deassert the control signals on a serial port.
    173   The following control signals are set according their bit settings :
    174   . Request to Send
    175   . Data Terminal Ready
    176 
    177   @param[in]  UartBase  UART registers base address
    178   @param[in]  Control   The following bits are taken into account :
    179                         . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
    180                           "Request To Send" control signal if this bit is
    181                           equal to one/zero.
    182                         . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
    183                           the "Data Terminal Ready" control signal if this
    184                           bit is equal to one/zero.
    185                         . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
    186                           the hardware loopback if this bit is equal to
    187                           one/zero.
    188                         . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
    189                         . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
    190                           disable the hardware flow control based on CTS (Clear
    191                           To Send) and RTS (Ready To Send) control signals.
    192 
    193   @retval  RETURN_SUCCESS      The new control bits were set on the serial device.
    194   @retval  RETURN_UNSUPPORTED  The serial device does not support this operation.
    195 
    196 **/
    197 RETURN_STATUS
    198 EFIAPI
    199 PL011UartSetControl (
    200     IN UINTN   UartBase,
    201     IN UINT32  Control
    202   )
    203 {
    204   UINT32  Bits;
    205 
    206   if (Control & (mInvalidControlBits)) {
    207     return RETURN_UNSUPPORTED;
    208   }
    209 
    210   Bits = MmioRead32 (UartBase + UARTCR);
    211 
    212   if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
    213     Bits |= PL011_UARTCR_RTS;
    214   } else {
    215     Bits &= ~PL011_UARTCR_RTS;
    216   }
    217 
    218   if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
    219     Bits |= PL011_UARTCR_DTR;
    220   } else {
    221     Bits &= ~PL011_UARTCR_DTR;
    222   }
    223 
    224   if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
    225     Bits |= PL011_UARTCR_LBE;
    226   } else {
    227     Bits &= ~PL011_UARTCR_LBE;
    228   }
    229 
    230   if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
    231     Bits |= (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN);
    232   } else {
    233     Bits &= ~(PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN);
    234   }
    235 
    236   MmioWrite32 (UartBase + UARTCR, Bits);
    237 
    238   return RETURN_SUCCESS;
    239 }
    240 
    241 /**
    242 
    243   Retrieve the status of the control bits on a serial device.
    244 
    245   @param[in]   UartBase  UART registers base address
    246   @param[out]  Control   Status of the control bits on a serial device :
    247 
    248                          . EFI_SERIAL_DATA_CLEAR_TO_SEND, EFI_SERIAL_DATA_SET_READY,
    249                            EFI_SERIAL_RING_INDICATE, EFI_SERIAL_CARRIER_DETECT,
    250                            EFI_SERIAL_REQUEST_TO_SEND, EFI_SERIAL_DATA_TERMINAL_READY
    251                            are all related to the DTE (Data Terminal Equipment) and
    252                            DCE (Data Communication Equipment) modes of operation of
    253                            the serial device.
    254                          . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the receive
    255                            buffer is empty, 0 otherwise.
    256                          . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the transmit
    257                            buffer is empty, 0 otherwise.
    258                          . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if the
    259                            hardware loopback is enabled (the ouput feeds the receive
    260                            buffer), 0 otherwise.
    261                          . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if a
    262                            loopback is accomplished by software, 0 otherwise.
    263                          . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to one if the
    264                            hardware flow control based on CTS (Clear To Send) and RTS
    265                            (Ready To Send) control signals is enabled, 0 otherwise.
    266 
    267   @retval RETURN_SUCCESS  The control bits were read from the serial device.
    268 
    269 **/
    270 RETURN_STATUS
    271 EFIAPI
    272 PL011UartGetControl (
    273     IN UINTN     UartBase,
    274     OUT UINT32  *Control
    275   )
    276 {
    277   UINT32      FlagRegister;
    278   UINT32      ControlRegister;
    279 
    280 
    281   FlagRegister = MmioRead32 (UartBase + UARTFR);
    282   ControlRegister = MmioRead32 (UartBase + UARTCR);
    283 
    284   *Control = 0;
    285 
    286   if ((FlagRegister & PL011_UARTFR_CTS) == PL011_UARTFR_CTS) {
    287     *Control |= EFI_SERIAL_CLEAR_TO_SEND;
    288   }
    289 
    290   if ((FlagRegister & PL011_UARTFR_DSR) == PL011_UARTFR_DSR) {
    291     *Control |= EFI_SERIAL_DATA_SET_READY;
    292   }
    293 
    294   if ((FlagRegister & PL011_UARTFR_RI) == PL011_UARTFR_RI) {
    295     *Control |= EFI_SERIAL_RING_INDICATE;
    296   }
    297 
    298   if ((FlagRegister & PL011_UARTFR_DCD) == PL011_UARTFR_DCD) {
    299     *Control |= EFI_SERIAL_CARRIER_DETECT;
    300   }
    301 
    302   if ((ControlRegister & PL011_UARTCR_RTS) == PL011_UARTCR_RTS) {
    303     *Control |= EFI_SERIAL_REQUEST_TO_SEND;
    304   }
    305 
    306   if ((ControlRegister & PL011_UARTCR_DTR) == PL011_UARTCR_DTR) {
    307     *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
    308   }
    309 
    310   if ((FlagRegister & PL011_UARTFR_RXFE) == PL011_UARTFR_RXFE) {
    311     *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
    312   }
    313 
    314   if ((FlagRegister & PL011_UARTFR_TXFE) == PL011_UARTFR_TXFE) {
    315     *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
    316   }
    317 
    318   if ((ControlRegister & (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN))
    319        == (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN)) {
    320     *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
    321   }
    322 
    323   if ((ControlRegister & PL011_UARTCR_LBE) == PL011_UARTCR_LBE) {
    324     *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
    325   }
    326 
    327   return RETURN_SUCCESS;
    328 }
    329 
    330 /**
    331   Write data to serial device.
    332 
    333   @param  Buffer           Point of data buffer which need to be written.
    334   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
    335 
    336   @retval 0                Write data failed.
    337   @retval !0               Actual number of bytes written to serial device.
    338 
    339 **/
    340 UINTN
    341 EFIAPI
    342 PL011UartWrite (
    343   IN  UINTN    UartBase,
    344   IN UINT8     *Buffer,
    345   IN UINTN     NumberOfBytes
    346   )
    347 {
    348   UINT8* CONST Final = &Buffer[NumberOfBytes];
    349 
    350   while (Buffer < Final) {
    351     // Wait until UART able to accept another char
    352     while ((MmioRead32 (UartBase + UARTFR) & UART_TX_FULL_FLAG_MASK));
    353 
    354     MmioWrite8 (UartBase + UARTDR, *Buffer++);
    355   }
    356 
    357   return NumberOfBytes;
    358 }
    359 
    360 /**
    361   Read data from serial device and save the data in buffer.
    362 
    363   @param  Buffer           Point of data buffer which need to be written.
    364   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
    365 
    366   @retval 0                Read data failed.
    367   @retval !0               Actual number of bytes read from serial device.
    368 
    369 **/
    370 UINTN
    371 EFIAPI
    372 PL011UartRead (
    373   IN  UINTN     UartBase,
    374   OUT UINT8     *Buffer,
    375   IN  UINTN     NumberOfBytes
    376   )
    377 {
    378   UINTN   Count;
    379 
    380   for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
    381     while ((MmioRead32 (UartBase + UARTFR) & UART_RX_EMPTY_FLAG_MASK) != 0);
    382     *Buffer = MmioRead8 (UartBase + UARTDR);
    383   }
    384 
    385   return NumberOfBytes;
    386 }
    387 
    388 /**
    389   Check to see if any data is available to be read from the debug device.
    390 
    391   @retval EFI_SUCCESS       At least one byte of data is available to be read
    392   @retval EFI_NOT_READY     No data is available to be read
    393   @retval EFI_DEVICE_ERROR  The serial device is not functioning properly
    394 
    395 **/
    396 BOOLEAN
    397 EFIAPI
    398 PL011UartPoll (
    399   IN  UINTN     UartBase
    400   )
    401 {
    402   return ((MmioRead32 (UartBase + UARTFR) & UART_RX_EMPTY_FLAG_MASK) == 0);
    403 }
    404