Skip to content

Commit 258a7a7

Browse files
superm1gregkh
authored andcommitted
rtc: mc146818-lib: Fix the AltCentury for AMD platforms
[ Upstream commit 3ae8fd4 ] Setting the century forward has been failing on AMD platforms. There was a previous attempt at fixing this for family 0x17 as part of commit 7ad295d ("rtc: Fix the AltCentury value on AMD/Hygon platform") but this was later reverted due to some problems reported that appeared to stem from an FW bug on a family 0x17 desktop system. The same comments mentioned in the previous commit continue to apply to the newer platforms as well. ``` MC146818 driver use function mc146818_set_time() to set register RTC_FREQ_SELECT(RTC_REG_A)'s bit4-bit6 field which means divider stage reset value on Intel platform to 0x7. While AMD/Hygon RTC_REG_A(0Ah)'s bit4 is defined as DV0 [Reference]: DV0 = 0 selects Bank 0, DV0 = 1 selects Bank 1. Bit5-bit6 is defined as reserved. DV0 is set to 1, it will select Bank 1, which will disable AltCentury register(0x32) access. As UEFI pass acpi_gbl_FADT.century 0x32 (AltCentury), the CMOS write will be failed on code: CMOS_WRITE(century, acpi_gbl_FADT.century). Correct RTC_REG_A bank select bit(DV0) to 0 on AMD/Hygon CPUs, it will enable AltCentury(0x32) register writing and finally setup century as expected. ``` However in closer examination the change previously submitted was also modifying bits 5 & 6 which are declared reserved in the AMD documentation. So instead modify just the DV0 bank selection bit. Being cognizant that there was a failure reported before, split the code change out to a static function that can also be used for exclusions if any regressions such as Mikhail's pop up again. Cc: Jinke Fan <[email protected]> Cc: Mikhail Gavrilov <[email protected]> Link: https://lore.kernel.org/all/CABXGCsMLob0DC25JS8wwAYydnDoHBSoMh2_YLPfqm3TTvDE-Zw@mail.gmail.com/ Link: https://www.amd.com/system/files/TechDocs/51192_Bolton_FCH_RRG.pdf Signed-off-by: Raul E Rangel <[email protected]> Signed-off-by: Mario Limonciello <[email protected]> Signed-off-by: Alexandre Belloni <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sasha Levin <[email protected]>
1 parent 9690e98 commit 258a7a7

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

drivers/rtc/rtc-mc146818-lib.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ int mc146818_get_time(struct rtc_time *time)
146146
}
147147
EXPORT_SYMBOL_GPL(mc146818_get_time);
148148

149+
/* AMD systems don't allow access to AltCentury with DV1 */
150+
static bool apply_amd_register_a_behavior(void)
151+
{
152+
#ifdef CONFIG_X86
153+
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
154+
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
155+
return true;
156+
#endif
157+
return false;
158+
}
159+
149160
/* Set the current date and time in the real time clock. */
150161
int mc146818_set_time(struct rtc_time *time)
151162
{
@@ -219,7 +230,10 @@ int mc146818_set_time(struct rtc_time *time)
219230
save_control = CMOS_READ(RTC_CONTROL);
220231
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
221232
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
222-
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
233+
if (apply_amd_register_a_behavior())
234+
CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT);
235+
else
236+
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
223237

224238
#ifdef CONFIG_MACH_DECSTATION
225239
CMOS_WRITE(real_yrs, RTC_DEC_YEAR);

include/linux/mc146818rtc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ struct cmos_rtc_board_info {
8686
/* 2 values for divider stage reset, others for "testing purposes only" */
8787
# define RTC_DIV_RESET1 0x60
8888
# define RTC_DIV_RESET2 0x70
89+
/* In AMD BKDG bit 5 and 6 are reserved, bit 4 is for select dv0 bank */
90+
# define RTC_AMD_BANK_SELECT 0x10
8991
/* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
9092
# define RTC_RATE_SELECT 0x0F
9193

0 commit comments

Comments
 (0)