2 Serial I/O Port library functions with no library constructor/destructor
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5 Copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.<BR>
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
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.
17 #include <Library/DebugLib.h>
18 #include <Library/IoLib.h>
19 #include <Library/PcdLib.h>
21 #include <Drivers/PL011Uart.h>
23 #define FRACTION_PART_SIZE_IN_BITS 6
24 #define FRACTION_PART_MASK ((1 << FRACTION_PART_SIZE_IN_BITS) - 1)
27 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE is the only
28 // control bit that is not supported.
30 STATIC CONST UINT32 mInvalidControlBits
= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
34 Initialise the serial port to the specified settings.
35 All unspecified settings will be set to the default values.
37 @param UartBase The base address of the serial device.
38 @param BaudRate The baud rate of the serial device. If the
39 baud rate is not supported, the speed will be
40 reduced to the nearest supported one and the
41 variable's value will be updated accordingly.
42 @param ReceiveFifoDepth The number of characters the device will
43 buffer on input. Value of 0 will use the
44 device's default FIFO depth.
45 @param Parity If applicable, this is the EFI_PARITY_TYPE
46 that is computed or checked as each character
47 is transmitted or received. If the device
48 does not support parity, the value is the
50 @param DataBits The number of data bits in each character.
51 @param StopBits If applicable, the EFI_STOP_BITS_TYPE number
52 of stop bits per character.
53 If the device does not support stop bits, the
54 value is the default stop bit value.
56 @retval RETURN_SUCCESS All attributes were set correctly on the
58 @retval RETURN_INVALID_PARAMETER One or more of the attributes has an
64 PL011UartInitializePort (
66 IN OUT UINT64
*BaudRate
,
67 IN OUT UINT32
*ReceiveFifoDepth
,
68 IN OUT EFI_PARITY_TYPE
*Parity
,
69 IN OUT UINT8
*DataBits
,
70 IN OUT EFI_STOP_BITS_TYPE
*StopBits
78 // The PL011 supports a buffer of 1, 16 or 32 chars. Therefore we can accept
79 // 1 char buffer as the minimum FIFO size. Because everything can be rounded
80 // down, there is no maximum FIFO size.
81 if ((*ReceiveFifoDepth
== 0) || (*ReceiveFifoDepth
>= 32)) {
83 LineControl
|= PL011_UARTLCR_H_FEN
;
84 if (PL011_UARTPID2_VER (MmioRead32 (UartBase
+ UARTPID2
)) > PL011_VER_R1P4
)
85 *ReceiveFifoDepth
= 32;
87 *ReceiveFifoDepth
= 16;
89 ASSERT (*ReceiveFifoDepth
< 32);
90 // Nothing else to do. 1 byte FIFO is default.
91 *ReceiveFifoDepth
= 1;
101 // Nothing to do. Parity is disabled by default.
104 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_EPS
);
107 LineControl
|= PL011_UARTLCR_H_PEN
;
110 LineControl
|= ( PL011_UARTLCR_H_PEN \
111 | PL011_UARTLCR_H_SPS \
112 | PL011_UARTLCR_H_EPS
);
115 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_SPS
);
118 return RETURN_INVALID_PARAMETER
;
128 LineControl
|= PL011_UARTLCR_H_WLEN_8
;
131 LineControl
|= PL011_UARTLCR_H_WLEN_7
;
134 LineControl
|= PL011_UARTLCR_H_WLEN_6
;
137 LineControl
|= PL011_UARTLCR_H_WLEN_5
;
140 return RETURN_INVALID_PARAMETER
;
147 case DefaultStopBits
:
148 *StopBits
= OneStopBit
;
150 // Nothing to do. One stop bit is enabled by default.
153 LineControl
|= PL011_UARTLCR_H_STP2
;
155 case OneFiveStopBits
:
156 // Only 1 or 2 stop bits are supported
158 return RETURN_INVALID_PARAMETER
;
161 // Don't send the LineControl value to the PL011 yet,
162 // wait until after the Baud Rate setting.
163 // This ensures we do not mess up the UART settings halfway through
164 // in the rare case when there is an error with the Baud Rate.
170 // If PL011 Integer value has been defined then always ignore the BAUD rate
171 if (FixedPcdGet32 (PL011UartInteger
) != 0) {
172 MmioWrite32 (UartBase
+ UARTIBRD
, FixedPcdGet32 (PL011UartInteger
));
173 MmioWrite32 (UartBase
+ UARTFBRD
, FixedPcdGet32 (PL011UartFractional
));
175 // If BAUD rate is zero then replace it with the system default value
176 if (*BaudRate
== 0) {
177 *BaudRate
= FixedPcdGet32 (PcdSerialBaudRate
);
178 ASSERT (*BaudRate
!= 0);
181 Divisor
= (FixedPcdGet32 (PL011UartClkInHz
) * 4) / *BaudRate
;
182 MmioWrite32 (UartBase
+ UARTIBRD
, Divisor
>> FRACTION_PART_SIZE_IN_BITS
);
183 MmioWrite32 (UartBase
+ UARTFBRD
, Divisor
& FRACTION_PART_MASK
);
186 // No parity, 1 stop, no fifo, 8 data bits
187 MmioWrite32 (UartBase
+ UARTLCR_H
, LineControl
);
189 // Clear any pending errors
190 MmioWrite32 (UartBase
+ UARTECR
, 0);
192 // Enable Tx, Rx, and UART overall
193 MmioWrite32 (UartBase
+ UARTCR
,
194 PL011_UARTCR_RXE
| PL011_UARTCR_TXE
| PL011_UARTCR_UARTEN
);
196 return RETURN_SUCCESS
;
201 Assert or deassert the control signals on a serial port.
202 The following control signals are set according their bit settings :
204 . Data Terminal Ready
206 @param[in] UartBase UART registers base address
207 @param[in] Control The following bits are taken into account :
208 . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
209 "Request To Send" control signal if this bit is
211 . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
212 the "Data Terminal Ready" control signal if this
213 bit is equal to one/zero.
214 . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
215 the hardware loopback if this bit is equal to
217 . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
218 . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
219 disable the hardware flow control based on CTS (Clear
220 To Send) and RTS (Ready To Send) control signals.
222 @retval RETURN_SUCCESS The new control bits were set on the device.
223 @retval RETURN_UNSUPPORTED The device does not support this operation.
228 PL011UartSetControl (
235 if (Control
& (mInvalidControlBits
)) {
236 return RETURN_UNSUPPORTED
;
239 Bits
= MmioRead32 (UartBase
+ UARTCR
);
241 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
242 Bits
|= PL011_UARTCR_RTS
;
244 Bits
&= ~PL011_UARTCR_RTS
;
247 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
248 Bits
|= PL011_UARTCR_DTR
;
250 Bits
&= ~PL011_UARTCR_DTR
;
253 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
254 Bits
|= PL011_UARTCR_LBE
;
256 Bits
&= ~PL011_UARTCR_LBE
;
259 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
260 Bits
|= (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
);
262 Bits
&= ~(PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
);
265 MmioWrite32 (UartBase
+ UARTCR
, Bits
);
267 return RETURN_SUCCESS
;
272 Retrieve the status of the control bits on a serial device.
274 @param[in] UartBase UART registers base address
275 @param[out] Control Status of the control bits on a serial device :
277 . EFI_SERIAL_DATA_CLEAR_TO_SEND,
278 EFI_SERIAL_DATA_SET_READY,
279 EFI_SERIAL_RING_INDICATE,
280 EFI_SERIAL_CARRIER_DETECT,
281 EFI_SERIAL_REQUEST_TO_SEND,
282 EFI_SERIAL_DATA_TERMINAL_READY
283 are all related to the DTE (Data Terminal Equipment)
284 and DCE (Data Communication Equipment) modes of
285 operation of the serial device.
286 . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
287 receive buffer is empty, 0 otherwise.
288 . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
289 transmit buffer is empty, 0 otherwise.
290 . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
291 the hardware loopback is enabled (the ouput feeds the
292 receive buffer), 0 otherwise.
293 . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
294 a loopback is accomplished by software, 0 otherwise.
295 . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
296 one if the hardware flow control based on CTS (Clear
297 To Send) and RTS (Ready To Send) control signals is
298 enabled, 0 otherwise.
300 @retval RETURN_SUCCESS The control bits were read from the serial device.
305 PL011UartGetControl (
311 UINT32 ControlRegister
;
314 FlagRegister
= MmioRead32 (UartBase
+ UARTFR
);
315 ControlRegister
= MmioRead32 (UartBase
+ UARTCR
);
319 if ((FlagRegister
& PL011_UARTFR_CTS
) == PL011_UARTFR_CTS
) {
320 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
323 if ((FlagRegister
& PL011_UARTFR_DSR
) == PL011_UARTFR_DSR
) {
324 *Control
|= EFI_SERIAL_DATA_SET_READY
;
327 if ((FlagRegister
& PL011_UARTFR_RI
) == PL011_UARTFR_RI
) {
328 *Control
|= EFI_SERIAL_RING_INDICATE
;
331 if ((FlagRegister
& PL011_UARTFR_DCD
) == PL011_UARTFR_DCD
) {
332 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
335 if ((ControlRegister
& PL011_UARTCR_RTS
) == PL011_UARTCR_RTS
) {
336 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
339 if ((ControlRegister
& PL011_UARTCR_DTR
) == PL011_UARTCR_DTR
) {
340 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
343 if ((FlagRegister
& PL011_UARTFR_RXFE
) == PL011_UARTFR_RXFE
) {
344 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
347 if ((FlagRegister
& PL011_UARTFR_TXFE
) == PL011_UARTFR_TXFE
) {
348 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
351 if ((ControlRegister
& (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
))
352 == (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
)) {
353 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
356 if ((ControlRegister
& PL011_UARTCR_LBE
) == PL011_UARTCR_LBE
) {
357 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
360 return RETURN_SUCCESS
;
364 Write data to serial device.
366 @param Buffer Point of data buffer which need to be written.
367 @param NumberOfBytes Number of output bytes which are cached in Buffer.
369 @retval 0 Write data failed.
370 @retval !0 Actual number of bytes written to serial device.
378 IN UINTN NumberOfBytes
381 UINT8
* CONST Final
= &Buffer
[NumberOfBytes
];
383 while (Buffer
< Final
) {
384 // Wait until UART able to accept another char
385 while ((MmioRead32 (UartBase
+ UARTFR
) & UART_TX_FULL_FLAG_MASK
));
387 MmioWrite8 (UartBase
+ UARTDR
, *Buffer
++);
390 return NumberOfBytes
;
394 Read data from serial device and save the data in buffer.
396 @param Buffer Point of data buffer which need to be written.
397 @param NumberOfBytes Number of output bytes which are cached in Buffer.
399 @retval 0 Read data failed.
400 @retval !0 Actual number of bytes read from serial device.
408 IN UINTN NumberOfBytes
413 for (Count
= 0; Count
< NumberOfBytes
; Count
++, Buffer
++) {
414 while ((MmioRead32 (UartBase
+ UARTFR
) & UART_RX_EMPTY_FLAG_MASK
) != 0);
415 *Buffer
= MmioRead8 (UartBase
+ UARTDR
);
418 return NumberOfBytes
;
422 Check to see if any data is available to be read from the debug device.
424 @retval EFI_SUCCESS At least one byte of data is available to be read
425 @retval EFI_NOT_READY No data is available to be read
426 @retval EFI_DEVICE_ERROR The serial device is not functioning properly
435 return ((MmioRead32 (UartBase
+ UARTFR
) & UART_RX_EMPTY_FLAG_MASK
) == 0);