summaryrefslogtreecommitdiffstats
path: root/ArmPlatformPkg
diff options
context:
space:
mode:
authorEvan Lloyd <evan.lloyd@arm.com>2016-06-15 13:52:43 +0100
committerArd Biesheuvel <ard.biesheuvel@linaro.org>2016-06-15 16:17:10 +0200
commit16146b984db10f87e30a6f6ac08ba9716a9eea79 (patch)
treeef127b1c4b117b2da529d46c84198583268efb83 /ArmPlatformPkg
parent090916d8bc8962d191e67cba24bfe46ad1cc892a (diff)
downloadedk2-16146b984db10f87e30a6f6ac08ba9716a9eea79.tar.gz
edk2-16146b984db10f87e30a6f6ac08ba9716a9eea79.tar.bz2
edk2-16146b984db10f87e30a6f6ac08ba9716a9eea79.zip
ArmPlatformPkg: Fix PL011 Glitches.
This change corrects 3 problems in the PL011 driver. 1. The TRM states "The UARTLCR_H, UARTIBRD, and UARTFBRD registers must not be changed:...when the UART is enabled" 2. The TRM (3.3.8) describes logic requiring the UART to be disabled and flushed before adjusting UARTCR. 3. Several redundant calls get made to PL011UartInitializePort, where the characteristics do not change, but updating the registers can cause glitches in the output stream. The parameters are compared to the current state and no action taken if no change of state is required. Where an update is required, the specified logic is followed, and the register updates only made when the UART is disabled. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Sami Mujawar <sami.mujawar@arm.com> Signed-off-by: Evan Lloyd <evan.lloyd@arm.com> Tested-by: Ryan Harkin <ryan.harkin@linaro.org> Reviewed-by: Ryan Harkin <ryan.harkin@linaro.org>
Diffstat (limited to 'ArmPlatformPkg')
-rw-r--r--ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.c b/ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.c
index 3c283fdf33..3748972acb 100644
--- a/ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.c
+++ b/ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.c
@@ -32,6 +32,8 @@ STATIC CONST UINT32 mInvalidControlBits = EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
/**
Initialise the serial port to the specified settings.
+ The serial port is re-configured only if the specified settings
+ are different from the current settings.
All unspecified settings will be set to the default values.
@param UartBase The base address of the serial device.
@@ -191,6 +193,26 @@ PL011UartInitializePort (
Integer = Divisor >> FRACTION_PART_SIZE_IN_BITS;
Fractional = Divisor & FRACTION_PART_MASK;
}
+
+ //
+ // If PL011 is already initialized, check the current settings
+ // and re-initialize only if the settings are different.
+ //
+ if (((MmioRead32 (UartBase + UARTCR) & PL011_UARTCR_UARTEN) != 0) &&
+ (MmioRead32 (UartBase + UARTLCR_H) == LineControl) &&
+ (MmioRead32 (UartBase + UARTIBRD) == Integer) &&
+ (MmioRead32 (UartBase + UARTFBRD) == Fractional)) {
+ // Nothing to do - already initialized with correct attributes
+ return RETURN_SUCCESS;
+ }
+
+ // Wait for the end of transmission
+ while ((MmioRead32 (UartBase + UARTFR) & PL011_UARTFR_TXFE) == 0);
+
+ // Disable UART: "The UARTLCR_H, UARTIBRD, and UARTFBRD registers must not be changed
+ // when the UART is enabled"
+ MmioWrite32 (UartBase + UARTCR, 0);
+
// Set Baud Rate Registers
MmioWrite32 (UartBase + UARTIBRD, Integer);
MmioWrite32 (UartBase + UARTFBRD, Fractional);