rtc: mc146818-lib: Fix the AltCentury for AMD platforms
[ Upstream commit 3ae8fd41573af4fb3a490c9ed947fc936ba87190 ] 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 7ad295d5196a ("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 <fanjinke@hygon.cn> Cc: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> 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 <rrangel@chromium.org> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Link: https://lore.kernel.org/r/20220111225750.1699-1-mario.limonciello@amd.com Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
7be785032c
commit
e7947c031f
@ -99,6 +99,17 @@ unsigned int mc146818_get_time(struct rtc_time *time)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mc146818_get_time);
|
EXPORT_SYMBOL_GPL(mc146818_get_time);
|
||||||
|
|
||||||
|
/* AMD systems don't allow access to AltCentury with DV1 */
|
||||||
|
static bool apply_amd_register_a_behavior(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86
|
||||||
|
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
|
||||||
|
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the current date and time in the real time clock. */
|
/* Set the current date and time in the real time clock. */
|
||||||
int mc146818_set_time(struct rtc_time *time)
|
int mc146818_set_time(struct rtc_time *time)
|
||||||
{
|
{
|
||||||
@ -172,7 +183,10 @@ int mc146818_set_time(struct rtc_time *time)
|
|||||||
save_control = CMOS_READ(RTC_CONTROL);
|
save_control = CMOS_READ(RTC_CONTROL);
|
||||||
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
|
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
|
||||||
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
|
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
|
||||||
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
|
if (apply_amd_register_a_behavior())
|
||||||
|
CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT);
|
||||||
|
else
|
||||||
|
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
|
||||||
|
|
||||||
#ifdef CONFIG_MACH_DECSTATION
|
#ifdef CONFIG_MACH_DECSTATION
|
||||||
CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
|
CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
|
||||||
|
@ -86,6 +86,8 @@ struct cmos_rtc_board_info {
|
|||||||
/* 2 values for divider stage reset, others for "testing purposes only" */
|
/* 2 values for divider stage reset, others for "testing purposes only" */
|
||||||
# define RTC_DIV_RESET1 0x60
|
# define RTC_DIV_RESET1 0x60
|
||||||
# define RTC_DIV_RESET2 0x70
|
# define RTC_DIV_RESET2 0x70
|
||||||
|
/* In AMD BKDG bit 5 and 6 are reserved, bit 4 is for select dv0 bank */
|
||||||
|
# define RTC_AMD_BANK_SELECT 0x10
|
||||||
/* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
|
/* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
|
||||||
# define RTC_RATE_SELECT 0x0F
|
# define RTC_RATE_SELECT 0x0F
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user