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 - 2014, 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>
24 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE is the only
25 // control bit that is not supported.
27 STATIC CONST UINT32 mInvalidControlBits
= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
31 Initialise the serial port to the specified settings.
32 All unspecified settings will be set to the default values.
34 @return Always return EFI_SUCCESS or EFI_INVALID_PARAMETER.
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
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;
61 *ReceiveFifoDepth
= 16;
63 ASSERT (*ReceiveFifoDepth
< 32);
64 // Nothing else to do. 1 byte fifo is default.
65 *ReceiveFifoDepth
= 1;
75 // Nothing to do. Parity is disabled by default.
78 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_EPS
);
81 LineControl
|= PL011_UARTLCR_H_PEN
;
84 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_SPS
| PL011_UARTLCR_H_EPS
);
87 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_SPS
);
90 return RETURN_INVALID_PARAMETER
;
100 LineControl
|= PL011_UARTLCR_H_WLEN_8
;
103 LineControl
|= PL011_UARTLCR_H_WLEN_7
;
106 LineControl
|= PL011_UARTLCR_H_WLEN_6
;
109 LineControl
|= PL011_UARTLCR_H_WLEN_5
;
112 return RETURN_INVALID_PARAMETER
;
119 case DefaultStopBits
:
120 *StopBits
= OneStopBit
;
122 // Nothing to do. One stop bit is enabled by default.
125 LineControl
|= PL011_UARTLCR_H_STP2
;
127 case OneFiveStopBits
:
128 // Only 1 or 2 stops bits are supported
130 return RETURN_INVALID_PARAMETER
;
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.
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
));
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);
153 Divisor
= (PcdGet32 (PL011UartClkInHz
) * 4) / *BaudRate
;
154 MmioWrite32 (UartBase
+ UARTIBRD
, Divisor
>> 6);
155 MmioWrite32 (UartBase
+ UARTFBRD
, Divisor
& 0x3F);
158 // No parity, 1 stop, no fifo, 8 data bits
159 MmioWrite32 (UartBase
+ UARTLCR_H
, LineControl
);
161 // Clear any pending errors
162 MmioWrite32 (UartBase
+ UARTECR
, 0);
164 // Enable tx, rx, and uart overall
165 MmioWrite32 (UartBase
+ UARTCR
, PL011_UARTCR_RXE
| PL011_UARTCR_TXE
| PL011_UARTCR_UARTEN
);
167 return RETURN_SUCCESS
;
172 Assert or deassert the control signals on a serial port.
173 The following control signals are set according their bit settings :
175 . Data Terminal Ready
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
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
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.
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.
199 PL011UartSetControl (
206 if (Control
& (mInvalidControlBits
)) {
207 return RETURN_UNSUPPORTED
;
210 Bits
= MmioRead32 (UartBase
+ UARTCR
);
212 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
213 Bits
|= PL011_UARTCR_RTS
;
215 Bits
&= ~PL011_UARTCR_RTS
;
218 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
219 Bits
|= PL011_UARTCR_DTR
;
221 Bits
&= ~PL011_UARTCR_DTR
;
224 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
225 Bits
|= PL011_UARTCR_LBE
;
227 Bits
&= ~PL011_UARTCR_LBE
;
230 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
231 Bits
|= (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
);
233 Bits
&= ~(PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
);
236 MmioWrite32 (UartBase
+ UARTCR
, Bits
);
238 return RETURN_SUCCESS
;
243 Retrieve the status of the control bits on a serial device.
245 @param[in] UartBase UART registers base address
246 @param[out] Control Status of the control bits on a serial device :
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
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.
267 @retval RETURN_SUCCESS The control bits were read from the serial device.
272 PL011UartGetControl (
278 UINT32 ControlRegister
;
281 FlagRegister
= MmioRead32 (UartBase
+ UARTFR
);
282 ControlRegister
= MmioRead32 (UartBase
+ UARTCR
);
286 if ((FlagRegister
& PL011_UARTFR_CTS
) == PL011_UARTFR_CTS
) {
287 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
290 if ((FlagRegister
& PL011_UARTFR_DSR
) == PL011_UARTFR_DSR
) {
291 *Control
|= EFI_SERIAL_DATA_SET_READY
;
294 if ((FlagRegister
& PL011_UARTFR_RI
) == PL011_UARTFR_RI
) {
295 *Control
|= EFI_SERIAL_RING_INDICATE
;
298 if ((FlagRegister
& PL011_UARTFR_DCD
) == PL011_UARTFR_DCD
) {
299 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
302 if ((ControlRegister
& PL011_UARTCR_RTS
) == PL011_UARTCR_RTS
) {
303 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
306 if ((ControlRegister
& PL011_UARTCR_DTR
) == PL011_UARTCR_DTR
) {
307 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
310 if ((FlagRegister
& PL011_UARTFR_RXFE
) == PL011_UARTFR_RXFE
) {
311 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
314 if ((FlagRegister
& PL011_UARTFR_TXFE
) == PL011_UARTFR_TXFE
) {
315 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
318 if ((ControlRegister
& (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
))
319 == (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
)) {
320 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
323 if ((ControlRegister
& PL011_UARTCR_LBE
) == PL011_UARTCR_LBE
) {
324 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
327 return RETURN_SUCCESS
;
331 Write data to serial device.
333 @param Buffer Point of data buffer which need to be written.
334 @param NumberOfBytes Number of output bytes which are cached in Buffer.
336 @retval 0 Write data failed.
337 @retval !0 Actual number of bytes written to serial device.
345 IN UINTN NumberOfBytes
348 UINT8
* CONST Final
= &Buffer
[NumberOfBytes
];
350 while (Buffer
< Final
) {
351 // Wait until UART able to accept another char
352 while ((MmioRead32 (UartBase
+ UARTFR
) & UART_TX_FULL_FLAG_MASK
));
354 MmioWrite8 (UartBase
+ UARTDR
, *Buffer
++);
357 return NumberOfBytes
;
361 Read data from serial device and save the data in buffer.
363 @param Buffer Point of data buffer which need to be written.
364 @param NumberOfBytes Number of output bytes which are cached in Buffer.
366 @retval 0 Read data failed.
367 @retval !0 Actual number of bytes read from serial device.
375 IN UINTN NumberOfBytes
380 for (Count
= 0; Count
< NumberOfBytes
; Count
++, Buffer
++) {
381 while ((MmioRead32 (UartBase
+ UARTFR
) & UART_RX_EMPTY_FLAG_MASK
) != 0);
382 *Buffer
= MmioRead8 (UartBase
+ UARTDR
);
385 return NumberOfBytes
;
389 Check to see if any data is available to be read from the debug device.
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
402 return ((MmioRead32 (UartBase
+ UARTFR
) & UART_RX_EMPTY_FLAG_MASK
) == 0);