From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.9304.1588690245331963720 for ; Tue, 05 May 2020 07:50:45 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: ard.biesheuvel@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id F287631B; Tue, 5 May 2020 07:50:44 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 831483F68F; Tue, 5 May 2020 07:50:43 -0700 (PDT) From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: leif@nuviainc.com, pete@akeo.ie, andrey.warkentin@gmail.com, Ard Biesheuvel Subject: [PATCH edk2-platforms 3/5] Platform/RaspberryPi: fix 16550 divisor calculation logic Date: Tue, 5 May 2020 16:50:27 +0200 Message-Id: <20200505145029.29826-4-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200505145029.29826-1-ard.biesheuvel@arm.com> References: <20200505145029.29826-1-ard.biesheuvel@arm.com> The 16550 'miniUART' on the Raspberry Pi gets its input clock from different sources on RPi3 and RPi3. Fix the logic that derives the divisor for the 16550 baud clock on the respective platforms. While at it, make the input clock PCD patchable for RPi3 so we can manipulate it at runtime in a future patch. Co-authored-by: Pete Batard Co-authored-by: Andrei Warkentin Co-authored-by: Ard Biesheuvel Signed-off-by: Pete Batard Signed-off-by: Ard Biesheuvel --- Platform/RaspberryPi/RPi3/RPi3.dsc | 4 +++- Platform/RaspberryPi/RPi4/RPi4.dsc | 2 +- Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c | 14 ++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Platform/RaspberryPi/RPi3/RPi3.dsc b/Platform/RaspberryPi/RPi3/RPi3.dsc index d7218219fc5a..96b27400eef8 100644 --- a/Platform/RaspberryPi/RPi3/RPi3.dsc +++ b/Platform/RaspberryPi/RPi3/RPi3.dsc @@ -409,7 +409,6 @@ [PcdsFixedAtBuild.common] gArmPlatformTokenSpaceGuid.PL011UartClkInHz|48000000 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|4 - gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|500000000 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|0x27 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|8 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 @@ -441,6 +440,9 @@ [PcdsFixedAtBuild.common] gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"EDK2" gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|TRUE +[PcdsPatchableInModule] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|250000000 + [PcdsDynamicHii.common.DEFAULT] # diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc index 4fb015b077e6..5d8bd88d7e34 100644 --- a/Platform/RaspberryPi/RPi4/RPi4.dsc +++ b/Platform/RaspberryPi/RPi4/RPi4.dsc @@ -420,7 +420,7 @@ [PcdsFixedAtBuild.common] gArmPlatformTokenSpaceGuid.PL011UartClkInHz|48000000 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|4 - gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|500000000 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|1000000000 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|0x27 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|8 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 diff --git a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c index b1d17d3fa04a..5e83bbf022eb 100644 --- a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c +++ b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c @@ -41,18 +41,20 @@ SerialPortGetDivisor ( // On the Raspberry Pi, the clock to use for the 16650-compatible UART // is the base clock divided by the 12.12 fixed point VPU clock divisor. // - BaseClockRate = (UINT64)PcdGet32 (PcdSerialClockRate) * 4; + BaseClockRate = (UINT64)PcdGet32 (PcdSerialClockRate); +#if (RPI_MODEL == 4) Divisor = MmioRead32(BCM2836_CM_BASE + BCM2836_CM_VPU_CLOCK_DIVISOR) & 0xFFFFFF; if (Divisor != 0) BaseClockRate = (BaseClockRate << 12) / Divisor; +#endif // - // Now calculate divisor for baud generator - // Ref_Clk_Rate / Baud_Rate / 16 + // As per the BCM2xxx datasheets: + // baudrate = system_clock_freq / (8 * (divisor + 1)). // - Divisor = (UINT32)BaseClockRate / (SerialBaudRate * 16); - if (((UINT32)BaseClockRate % (SerialBaudRate * 16)) >= SerialBaudRate * 8) { - Divisor++; + Divisor = (UINT32)BaseClockRate / (SerialBaudRate * 8); + if (Divisor != 0) { + Divisor--; } return Divisor; } -- 2.17.1