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 - 2013, 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>
25 Initialise the serial port to the specified settings.
26 All unspecified settings will be set to the default values.
28 @return Always return EFI_SUCCESS or EFI_INVALID_PARAMETER.
33 PL011UartInitializePort (
34 IN OUT UINTN UartBase
,
35 IN OUT UINT64
*BaudRate
,
36 IN OUT UINT32
*ReceiveFifoDepth
,
37 IN OUT EFI_PARITY_TYPE
*Parity
,
38 IN OUT UINT8
*DataBits
,
39 IN OUT EFI_STOP_BITS_TYPE
*StopBits
47 // The PL011 supports a buffer of either 1 or 32 chars. Therefore we can accept
48 // 1 char buffer as the minimum fifo size. Because everything can be rounded down,
49 // there is no maximum fifo size.
50 if ((*ReceiveFifoDepth
== 0) || (*ReceiveFifoDepth
>= 32)) {
51 LineControl
|= PL011_UARTLCR_H_FEN
;
52 *ReceiveFifoDepth
= 32;
54 ASSERT (*ReceiveFifoDepth
< 32);
55 // Nothing else to do. 1 byte fifo is default.
56 *ReceiveFifoDepth
= 1;
66 // Nothing to do. Parity is disabled by default.
69 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_EPS
);
72 LineControl
|= PL011_UARTLCR_H_PEN
;
75 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_SPS
| PL011_UARTLCR_H_EPS
);
78 LineControl
|= (PL011_UARTLCR_H_PEN
| PL011_UARTLCR_H_SPS
);
81 return RETURN_INVALID_PARAMETER
;
91 LineControl
|= PL011_UARTLCR_H_WLEN_8
;
94 LineControl
|= PL011_UARTLCR_H_WLEN_7
;
97 LineControl
|= PL011_UARTLCR_H_WLEN_6
;
100 LineControl
|= PL011_UARTLCR_H_WLEN_5
;
103 return RETURN_INVALID_PARAMETER
;
110 case DefaultStopBits
:
111 *StopBits
= OneStopBit
;
113 // Nothing to do. One stop bit is enabled by default.
116 LineControl
|= PL011_UARTLCR_H_STP2
;
118 case OneFiveStopBits
:
119 // Only 1 or 2 stops bits are supported
121 return RETURN_INVALID_PARAMETER
;
124 // Don't send the LineControl value to the PL011 yet,
125 // wait until after the Baud Rate setting.
126 // This ensures we do not mess up the UART settings halfway through
127 // in the rare case when there is an error with the Baud Rate.
133 // If PL011 Integral value has been defined then always ignore the BAUD rate
134 if (PcdGet32 (PL011UartInteger
) != 0) {
135 MmioWrite32 (UartBase
+ UARTIBRD
, PcdGet32 (PL011UartInteger
));
136 MmioWrite32 (UartBase
+ UARTFBRD
, PcdGet32 (PL011UartFractional
));
138 // If BAUD rate is zero then replace it with the system default value
139 if (*BaudRate
== 0) {
140 *BaudRate
= PcdGet32 (PcdSerialBaudRate
);
141 ASSERT (*BaudRate
!= 0);
144 Divisor
= (PcdGet32 (PL011UartClkInHz
) * 4) / *BaudRate
;
145 MmioWrite32 (UartBase
+ UARTIBRD
, Divisor
>> 6);
146 MmioWrite32 (UartBase
+ UARTFBRD
, Divisor
& 0x3F);
149 // No parity, 1 stop, no fifo, 8 data bits
150 MmioWrite32 (UartBase
+ UARTLCR_H
, LineControl
);
152 // Clear any pending errors
153 MmioWrite32 (UartBase
+ UARTECR
, 0);
155 // Enable tx, rx, and uart overall
156 MmioWrite32 (UartBase
+ UARTCR
, PL011_UARTCR_RXE
| PL011_UARTCR_TXE
| PL011_UARTCR_UARTEN
);
158 return RETURN_SUCCESS
;
162 Set the serial device control bits.
164 @param UartBase The base address of the PL011 UART.
165 @param Control Control bits which are to be set on the serial device.
167 @retval EFI_SUCCESS The new control bits were set on the serial device.
168 @retval EFI_UNSUPPORTED The serial device does not support this operation.
169 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
174 PL011UartSetControl (
180 UINT32 ValidControlBits
;
182 ValidControlBits
= ( EFI_SERIAL_REQUEST_TO_SEND
183 | EFI_SERIAL_DATA_TERMINAL_READY
184 // | EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE // Not implemented yet.
185 // | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE // Not implemented yet.
186 | EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
189 if (Control
& (~ValidControlBits
)) {
190 return EFI_UNSUPPORTED
;
193 Bits
= MmioRead32 (UartBase
+ UARTCR
);
195 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
196 Bits
|= PL011_UARTCR_RTS
;
199 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
200 Bits
|= PL011_UARTCR_DTR
;
203 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
204 Bits
|= PL011_UARTCR_LBE
;
207 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
208 Bits
|= (PL011_UARTCR_CTSEN
& PL011_UARTCR_RTSEN
);
211 MmioWrite32 (UartBase
+ UARTCR
, Bits
);
213 return RETURN_SUCCESS
;
217 Get the serial device control bits.
219 @param UartBase The base address of the PL011 UART.
220 @param Control Control signals read from the serial device.
222 @retval EFI_SUCCESS The control bits were read from the serial device.
223 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
228 PL011UartGetControl (
234 UINT32 ControlRegister
;
237 FlagRegister
= MmioRead32 (UartBase
+ UARTFR
);
238 ControlRegister
= MmioRead32 (UartBase
+ UARTCR
);
242 if ((FlagRegister
& PL011_UARTFR_CTS
) == PL011_UARTFR_CTS
) {
243 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
246 if ((FlagRegister
& PL011_UARTFR_DSR
) == PL011_UARTFR_DSR
) {
247 *Control
|= EFI_SERIAL_DATA_SET_READY
;
250 if ((FlagRegister
& PL011_UARTFR_RI
) == PL011_UARTFR_RI
) {
251 *Control
|= EFI_SERIAL_RING_INDICATE
;
254 if ((FlagRegister
& PL011_UARTFR_DCD
) == PL011_UARTFR_DCD
) {
255 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
258 if ((ControlRegister
& PL011_UARTCR_RTS
) == PL011_UARTCR_RTS
) {
259 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
262 if ((ControlRegister
& PL011_UARTCR_DTR
) == PL011_UARTCR_DTR
) {
263 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
266 if ((FlagRegister
& PL011_UARTFR_RXFE
) == PL011_UARTFR_RXFE
) {
267 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
270 if ((FlagRegister
& PL011_UARTFR_TXFE
) == PL011_UARTFR_TXFE
) {
271 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
274 if ((ControlRegister
& (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
)) == (PL011_UARTCR_CTSEN
| PL011_UARTCR_RTSEN
)) {
275 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
279 // ToDo: Implement EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
280 if ((ControlRegister
& PL011_UARTCR_LBE
) == PL011_UARTCR_LBE
) {
281 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
284 // ToDo: Implement EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
285 if (SoftwareLoopbackEnable
) {
286 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
290 return RETURN_SUCCESS
;
294 Write data to serial device.
296 @param Buffer Point of data buffer which need to be written.
297 @param NumberOfBytes Number of output bytes which are cached in Buffer.
299 @retval 0 Write data failed.
300 @retval !0 Actual number of bytes written to serial device.
308 IN UINTN NumberOfBytes
311 UINT8
* CONST Final
= &Buffer
[NumberOfBytes
];
313 while (Buffer
< Final
) {
314 // Wait until UART able to accept another char
315 while ((MmioRead32 (UartBase
+ UARTFR
) & UART_TX_FULL_FLAG_MASK
));
317 MmioWrite8 (UartBase
+ UARTDR
, *Buffer
++);
320 return NumberOfBytes
;
324 Read data from serial device and save the data in buffer.
326 @param Buffer Point of data buffer which need to be written.
327 @param NumberOfBytes Number of output bytes which are cached in Buffer.
329 @retval 0 Read data failed.
330 @retval !0 Actual number of bytes read from serial device.
338 IN UINTN NumberOfBytes
343 for (Count
= 0; Count
< NumberOfBytes
; Count
++, Buffer
++) {
344 while ((MmioRead32 (UartBase
+ UARTFR
) & UART_RX_EMPTY_FLAG_MASK
) != 0);
345 *Buffer
= MmioRead8 (UartBase
+ UARTDR
);
348 return NumberOfBytes
;
352 Check to see if any data is available to be read from the debug device.
354 @retval EFI_SUCCESS At least one byte of data is available to be read
355 @retval EFI_NOT_READY No data is available to be read
356 @retval EFI_DEVICE_ERROR The serial device is not functioning properly
365 return ((MmioRead32 (UartBase
+ UARTFR
) & UART_RX_EMPTY_FLAG_MASK
) == 0);