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 - 2016, 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#define FRACTION_PART_SIZE_IN_BITS  6
24#define FRACTION_PART_MASK          ((1 << FRACTION_PART_SIZE_IN_BITS) - 1)
25
26//
27// EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE is the only
28// control bit that is not supported.
29//
30STATIC CONST UINT32 mInvalidControlBits = EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
31
32/**
33
34  Initialise the serial port to the specified settings.
35  The serial port is re-configured only if the specified settings
36  are different from the current settings.
37  All unspecified settings will be set to the default values.
38
39  @param  UartBase                The base address of the serial device.
40  @param  UartClkInHz             The clock in Hz for the serial device.
41                                  Ignored if the PCD PL011UartInteger is not 0
42  @param  BaudRate                The baud rate of the serial device. If the
43                                  baud rate is not supported, the speed will be
44                                  reduced to the nearest supported one and the
45                                  variable's value will be updated accordingly.
46  @param  ReceiveFifoDepth        The number of characters the device will
47                                  buffer on input.  Value of 0 will use the
48                                  device's default FIFO depth.
49  @param  Parity                  If applicable, this is the EFI_PARITY_TYPE
50                                  that is computed or checked as each character
51                                  is transmitted or received. If the device
52                                  does not support parity, the value is the
53                                  default parity value.
54  @param  DataBits                The number of data bits in each character.
55  @param  StopBits                If applicable, the EFI_STOP_BITS_TYPE number
56                                  of stop bits per character.
57                                  If the device does not support stop bits, the
58                                  value is the default stop bit value.
59
60  @retval RETURN_SUCCESS            All attributes were set correctly on the
61                                    serial device.
62  @retval RETURN_INVALID_PARAMETER  One or more of the attributes has an
63                                    unsupported value.
64
65**/
66RETURN_STATUS
67EFIAPI
68PL011UartInitializePort (
69  IN     UINTN               UartBase,
70  IN     UINT32              UartClkInHz,
71  IN OUT UINT64              *BaudRate,
72  IN OUT UINT32              *ReceiveFifoDepth,
73  IN OUT EFI_PARITY_TYPE     *Parity,
74  IN OUT UINT8               *DataBits,
75  IN OUT EFI_STOP_BITS_TYPE  *StopBits
76  )
77{
78  UINT32      LineControl;
79  UINT32      Divisor;
80  UINT32      Integer;
81  UINT32      Fractional;
82  UINT32      HardwareFifoDepth;
83
84  HardwareFifoDepth = (PL011_UARTPID2_VER (MmioRead32 (UartBase + UARTPID2)) \
85                       > PL011_VER_R1P4) \
86                      ? 32 : 16 ;
87  // The PL011 supports a buffer of 1, 16 or 32 chars. Therefore we can accept
88  // 1 char buffer as the minimum FIFO size. Because everything can be rounded
89  // down, there is no maximum FIFO size.
90  if ((*ReceiveFifoDepth == 0) || (*ReceiveFifoDepth >= HardwareFifoDepth)) {
91    // Enable FIFO
92    LineControl = PL011_UARTLCR_H_FEN;
93    *ReceiveFifoDepth = HardwareFifoDepth;
94  } else {
95    // Disable FIFO
96    LineControl = 0;
97    // Nothing else to do. 1 byte FIFO is default.
98    *ReceiveFifoDepth = 1;
99  }
100
101  //
102  // Parity
103  //
104  switch (*Parity) {
105  case DefaultParity:
106    *Parity = NoParity;
107  case NoParity:
108    // Nothing to do. Parity is disabled by default.
109    break;
110  case EvenParity:
111    LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_EPS);
112    break;
113  case OddParity:
114    LineControl |= PL011_UARTLCR_H_PEN;
115    break;
116  case MarkParity:
117    LineControl |= (  PL011_UARTLCR_H_PEN \
118                    | PL011_UARTLCR_H_SPS \
119                    | PL011_UARTLCR_H_EPS);
120    break;
121  case SpaceParity:
122    LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_SPS);
123    break;
124  default:
125    return RETURN_INVALID_PARAMETER;
126  }
127
128  //
129  // Data Bits
130  //
131  switch (*DataBits) {
132  case 0:
133    *DataBits = 8;
134  case 8:
135    LineControl |= PL011_UARTLCR_H_WLEN_8;
136    break;
137  case 7:
138    LineControl |= PL011_UARTLCR_H_WLEN_7;
139    break;
140  case 6:
141    LineControl |= PL011_UARTLCR_H_WLEN_6;
142    break;
143  case 5:
144    LineControl |= PL011_UARTLCR_H_WLEN_5;
145    break;
146  default:
147    return RETURN_INVALID_PARAMETER;
148  }
149
150  //
151  // Stop Bits
152  //
153  switch (*StopBits) {
154  case DefaultStopBits:
155    *StopBits = OneStopBit;
156  case OneStopBit:
157    // Nothing to do. One stop bit is enabled by default.
158    break;
159  case TwoStopBits:
160    LineControl |= PL011_UARTLCR_H_STP2;
161    break;
162  case OneFiveStopBits:
163    // Only 1 or 2 stop bits are supported
164  default:
165    return RETURN_INVALID_PARAMETER;
166  }
167
168  // Don't send the LineControl value to the PL011 yet,
169  // wait until after the Baud Rate setting.
170  // This ensures we do not mess up the UART settings halfway through
171  // in the rare case when there is an error with the Baud Rate.
172
173  //
174  // Baud Rate
175  //
176
177  // If PL011 Integer value has been defined then always ignore the BAUD rate
178  if (FixedPcdGet32 (PL011UartInteger) != 0) {
179    Integer = FixedPcdGet32 (PL011UartInteger);
180    Fractional = FixedPcdGet32 (PL011UartFractional);
181  } else {
182    // If BAUD rate is zero then replace it with the system default value
183    if (*BaudRate == 0) {
184      *BaudRate = FixedPcdGet32 (PcdSerialBaudRate);
185      if (*BaudRate == 0) {
186        return RETURN_INVALID_PARAMETER;
187      }
188    }
189    if (0 == UartClkInHz) {
190      return RETURN_INVALID_PARAMETER;
191    }
192
193    Divisor = (UartClkInHz * 4) / *BaudRate;
194    Integer = Divisor >> FRACTION_PART_SIZE_IN_BITS;
195    Fractional = Divisor & FRACTION_PART_MASK;
196  }
197
198  //
199  // If PL011 is already initialized, check the current settings
200  // and re-initialize only if the settings are different.
201  //
202  if (((MmioRead32 (UartBase + UARTCR) & PL011_UARTCR_UARTEN) != 0) &&
203       (MmioRead32 (UartBase + UARTLCR_H) == LineControl) &&
204       (MmioRead32 (UartBase + UARTIBRD) == Integer) &&
205       (MmioRead32 (UartBase + UARTFBRD) == Fractional)) {
206    // Nothing to do - already initialized with correct attributes
207    return RETURN_SUCCESS;
208  }
209
210  // Wait for the end of transmission
211  while ((MmioRead32 (UartBase + UARTFR) & PL011_UARTFR_TXFE) == 0);
212
213  // Disable UART: "The UARTLCR_H, UARTIBRD, and UARTFBRD registers must not be changed
214  // when the UART is enabled"
215  MmioWrite32 (UartBase + UARTCR, 0);
216
217  // Set Baud Rate Registers
218  MmioWrite32 (UartBase + UARTIBRD, Integer);
219  MmioWrite32 (UartBase + UARTFBRD, Fractional);
220
221  // No parity, 1 stop, no fifo, 8 data bits
222  MmioWrite32 (UartBase + UARTLCR_H, LineControl);
223
224  // Clear any pending errors
225  MmioWrite32 (UartBase + UARTECR, 0);
226
227  // Enable Tx, Rx, and UART overall
228  MmioWrite32 (UartBase + UARTCR,
229               PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN);
230
231  return RETURN_SUCCESS;
232}
233
234/**
235
236  Assert or deassert the control signals on a serial port.
237  The following control signals are set according their bit settings :
238  . Request to Send
239  . Data Terminal Ready
240
241  @param[in]  UartBase  UART registers base address
242  @param[in]  Control   The following bits are taken into account :
243                        . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
244                          "Request To Send" control signal if this bit is
245                          equal to one/zero.
246                        . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
247                          the "Data Terminal Ready" control signal if this
248                          bit is equal to one/zero.
249                        . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
250                          the hardware loopback if this bit is equal to
251                          one/zero.
252                        . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
253                        . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
254                          disable the hardware flow control based on CTS (Clear
255                          To Send) and RTS (Ready To Send) control signals.
256
257  @retval  RETURN_SUCCESS      The new control bits were set on the device.
258  @retval  RETURN_UNSUPPORTED  The device does not support this operation.
259
260**/
261RETURN_STATUS
262EFIAPI
263PL011UartSetControl (
264    IN UINTN   UartBase,
265    IN UINT32  Control
266  )
267{
268  UINT32  Bits;
269
270  if (Control & (mInvalidControlBits)) {
271    return RETURN_UNSUPPORTED;
272  }
273
274  Bits = MmioRead32 (UartBase + UARTCR);
275
276  if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
277    Bits |= PL011_UARTCR_RTS;
278  } else {
279    Bits &= ~PL011_UARTCR_RTS;
280  }
281
282  if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
283    Bits |= PL011_UARTCR_DTR;
284  } else {
285    Bits &= ~PL011_UARTCR_DTR;
286  }
287
288  if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
289    Bits |= PL011_UARTCR_LBE;
290  } else {
291    Bits &= ~PL011_UARTCR_LBE;
292  }
293
294  if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
295    Bits |= (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN);
296  } else {
297    Bits &= ~(PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN);
298  }
299
300  MmioWrite32 (UartBase + UARTCR, Bits);
301
302  return RETURN_SUCCESS;
303}
304
305/**
306
307  Retrieve the status of the control bits on a serial device.
308
309  @param[in]   UartBase  UART registers base address
310  @param[out]  Control   Status of the control bits on a serial device :
311
312                         . EFI_SERIAL_DATA_CLEAR_TO_SEND,
313                           EFI_SERIAL_DATA_SET_READY,
314                           EFI_SERIAL_RING_INDICATE,
315                           EFI_SERIAL_CARRIER_DETECT,
316                           EFI_SERIAL_REQUEST_TO_SEND,
317                           EFI_SERIAL_DATA_TERMINAL_READY
318                           are all related to the DTE (Data Terminal Equipment)
319                           and DCE (Data Communication Equipment) modes of
320                           operation of the serial device.
321                         . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
322                           receive buffer is empty, 0 otherwise.
323                         . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
324                           transmit buffer is empty, 0 otherwise.
325                         . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
326                           the hardware loopback is enabled (the ouput feeds the
327                           receive buffer), 0 otherwise.
328                         . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
329                           a loopback is accomplished by software, 0 otherwise.
330                         . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
331                           one if the hardware flow control based on CTS (Clear
332                           To Send) and RTS (Ready To Send) control signals is
333                           enabled, 0 otherwise.
334
335  @retval RETURN_SUCCESS  The control bits were read from the serial device.
336
337**/
338RETURN_STATUS
339EFIAPI
340PL011UartGetControl (
341    IN UINTN     UartBase,
342    OUT UINT32  *Control
343  )
344{
345  UINT32      FlagRegister;
346  UINT32      ControlRegister;
347
348
349  FlagRegister = MmioRead32 (UartBase + UARTFR);
350  ControlRegister = MmioRead32 (UartBase + UARTCR);
351
352  *Control = 0;
353
354  if ((FlagRegister & PL011_UARTFR_CTS) == PL011_UARTFR_CTS) {
355    *Control |= EFI_SERIAL_CLEAR_TO_SEND;
356  }
357
358  if ((FlagRegister & PL011_UARTFR_DSR) == PL011_UARTFR_DSR) {
359    *Control |= EFI_SERIAL_DATA_SET_READY;
360  }
361
362  if ((FlagRegister & PL011_UARTFR_RI) == PL011_UARTFR_RI) {
363    *Control |= EFI_SERIAL_RING_INDICATE;
364  }
365
366  if ((FlagRegister & PL011_UARTFR_DCD) == PL011_UARTFR_DCD) {
367    *Control |= EFI_SERIAL_CARRIER_DETECT;
368  }
369
370  if ((ControlRegister & PL011_UARTCR_RTS) == PL011_UARTCR_RTS) {
371    *Control |= EFI_SERIAL_REQUEST_TO_SEND;
372  }
373
374  if ((ControlRegister & PL011_UARTCR_DTR) == PL011_UARTCR_DTR) {
375    *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
376  }
377
378  if ((FlagRegister & PL011_UARTFR_RXFE) == PL011_UARTFR_RXFE) {
379    *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
380  }
381
382  if ((FlagRegister & PL011_UARTFR_TXFE) == PL011_UARTFR_TXFE) {
383    *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
384  }
385
386  if ((ControlRegister & (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN))
387       == (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN)) {
388    *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
389  }
390
391  if ((ControlRegister & PL011_UARTCR_LBE) == PL011_UARTCR_LBE) {
392    *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
393  }
394
395  return RETURN_SUCCESS;
396}
397
398/**
399  Write data to serial device.
400
401  @param  Buffer           Point of data buffer which need to be written.
402  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
403
404  @retval 0                Write data failed.
405  @retval !0               Actual number of bytes written to serial device.
406
407**/
408UINTN
409EFIAPI
410PL011UartWrite (
411  IN  UINTN    UartBase,
412  IN UINT8     *Buffer,
413  IN UINTN     NumberOfBytes
414  )
415{
416  UINT8* CONST Final = &Buffer[NumberOfBytes];
417
418  while (Buffer < Final) {
419    // Wait until UART able to accept another char
420    while ((MmioRead32 (UartBase + UARTFR) & UART_TX_FULL_FLAG_MASK));
421
422    MmioWrite8 (UartBase + UARTDR, *Buffer++);
423  }
424
425  return NumberOfBytes;
426}
427
428/**
429  Read data from serial device and save the data in buffer.
430
431  @param  Buffer           Point of data buffer which need to be written.
432  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
433
434  @retval 0                Read data failed.
435  @retval !0               Actual number of bytes read from serial device.
436
437**/
438UINTN
439EFIAPI
440PL011UartRead (
441  IN  UINTN     UartBase,
442  OUT UINT8     *Buffer,
443  IN  UINTN     NumberOfBytes
444  )
445{
446  UINTN   Count;
447
448  for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
449    while ((MmioRead32 (UartBase + UARTFR) & UART_RX_EMPTY_FLAG_MASK) != 0);
450    *Buffer = MmioRead8 (UartBase + UARTDR);
451  }
452
453  return NumberOfBytes;
454}
455
456/**
457  Check to see if any data is available to be read from the debug device.
458
459  @retval TRUE       At least one byte of data is available to be read
460  @retval FALSE      No data is available to be read
461
462**/
463BOOLEAN
464EFIAPI
465PL011UartPoll (
466  IN  UINTN     UartBase
467  )
468{
469  return ((MmioRead32 (UartBase + UARTFR) & UART_RX_EMPTY_FLAG_MASK) == 0);
470}
471