Remove global variable from SerialPortLib because this module is not necessarily executed in memory.
Cc: Sunil V L <suni...@ventanamicro.com> Cc: Daniel Schaefer <daniel.schae...@hpe.com> Signed-off-by: Abner Chang <abner.ch...@hpe.com> --- .../SiFive/U5SeriesPkg/Include/SifiveU5Uart.h | 1 + .../Library/SerialIoLib/SerialPortLib.c | 58 +++++++++++++++---- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/Platform/SiFive/U5SeriesPkg/Include/SifiveU5Uart.h b/Platform/SiFive/U5SeriesPkg/Include/SifiveU5Uart.h index 0ccb98e874..be8dce8c96 100644 --- a/Platform/SiFive/U5SeriesPkg/Include/SifiveU5Uart.h +++ b/Platform/SiFive/U5SeriesPkg/Include/SifiveU5Uart.h @@ -10,6 +10,7 @@ #ifndef SIFIVE_U5_SERIES_UART_H_ #define SIFIVE_U5_SERIES_UART_H_ +#include <include/sbi/riscv_io.h> #include <include/sbi_utils/serial/sifive-uart.h> #endif diff --git a/Platform/SiFive/U5SeriesPkg/Library/SerialIoLib/SerialPortLib.c b/Platform/SiFive/U5SeriesPkg/Library/SerialIoLib/SerialPortLib.c index 7bc73a0b82..42e5aa7b76 100644 --- a/Platform/SiFive/U5SeriesPkg/Library/SerialIoLib/SerialPortLib.c +++ b/Platform/SiFive/U5SeriesPkg/Library/SerialIoLib/SerialPortLib.c @@ -8,6 +8,7 @@ **/ #include <Base.h> +#include <Library/DebugLib.h> #include <Library/IoLib.h> #include <Library/SerialPortLib.h> #include <Include/SifiveU5Uart.h> @@ -41,7 +42,7 @@ #define UART_BAUDRATE 115200 #define SYS_CLK FixedPcdGet32(PcdU5PlatformSystemClock) -BOOLEAN Initiated = FALSE; +BOOLEAN Initiated = TRUE; /** Get value from serial port register. @@ -55,7 +56,9 @@ UINT32 GetReg ( IN UINT32 RegIndex ) { - return MmioRead32 (FixedPcdGet32(PcdU5UartBase) + (RegIndex * 0x4)); + STATIC volatile UINT32 * const uart = (UINT32 *)FixedPcdGet32(PcdU5UartBase); + + return readl ((volatile void *)(uart + RegIndex)); } /** @@ -70,7 +73,9 @@ VOID SetReg ( IN UINT32 Value ) { - MmioWrite32 (Value, FixedPcdGet32(PcdU5UartBase) + (RegIndex * 0x4)); + STATIC volatile UINT32 * const uart = (UINT32 *)FixedPcdGet32(PcdU5UartBase); + + writel (Value, (volatile void *)(uart + RegIndex)); } /** @@ -104,7 +109,36 @@ UINT32 SifiveUartGetChar (VOID) } return -1; } +/** + Find minimum divisor divides in_freq to max_target_hz; + Based on uart driver n SiFive FSBL. + + f_baud = f_in / (div + 1) => div = (f_in / f_baud) - 1 + The nearest integer solution requires rounding up as to not exceed max_target_hz. + div = ceil(f_in / f_baud) - 1 + = floor((f_in - 1 + f_baud) / f_baud) - 1 + This should not overflow as long as (f_in - 1 + f_baud) does not exceed + 2^32 - 1, which is unlikely since we represent frequencies in kHz. + + @param Freq The given clock to UART. + @param MaxTargetHZ Target baudrate. +**/ +UINT32 +UartMinClkDivisor ( + IN UINT64 Freq, + IN UINT64 MaxTargetHZ + ) +{ + UINT64 Quotient; + + Quotient = (Freq + MaxTargetHZ - 1) / (MaxTargetHZ); + if (Quotient == 0) { + return 0; + } else { + return Quotient - 1; + } +} /** Initialize the serial device hardware. @@ -116,20 +150,24 @@ UINT32 SifiveUartGetChar (VOID) @retval RETURN_DEVICE_ERROR The serail device could not be initialized. **/ -RETURN_STATUS +EFI_STATUS EFIAPI SerialPortInitialize ( VOID ) { - if (Initiated) { - return RETURN_SUCCESS; + UINT32 Divisor; + UINT32 CurrentDivisor; + + Divisor = UartMinClkDivisor (SYS_CLK / 2, UART_BAUDRATE); + if (Divisor == 0) { + return EFI_INVALID_PARAMETER; } - if (sifive_uart_init (FixedPcdGet32(PcdU5UartBase), SYS_CLK / 2, UART_BAUDRATE) != 0) { - return EFI_DEVICE_ERROR; + CurrentDivisor = GetReg(UART_REG_DIV); + if (Divisor != CurrentDivisor) { + sifive_uart_init (FixedPcdGet32(PcdU5UartBase), SYS_CLK / 2, UART_BAUDRATE); } - Initiated = TRUE; - return RETURN_SUCCESS; + return EFI_SUCCESS; } /** -- 2.31.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#82337): https://edk2.groups.io/g/devel/message/82337 Mute This Topic: https://groups.io/mt/86435691/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-