lkml.org 
[lkml]   [2022]   [May]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 036/132] rtc: mc146818-lib: Fix the AltCentury for AMD platforms
    Date
    From: Mario Limonciello <mario.limonciello@amd.com>

    [ 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>
    ---
    drivers/rtc/rtc-mc146818-lib.c | 16 +++++++++++++++-
    include/linux/mc146818rtc.h | 2 ++
    2 files changed, 17 insertions(+), 1 deletion(-)

    diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c
    index 8abac672f3cb..f3f5a87fe376 100644
    --- a/drivers/rtc/rtc-mc146818-lib.c
    +++ b/drivers/rtc/rtc-mc146818-lib.c
    @@ -146,6 +146,17 @@ int mc146818_get_time(struct rtc_time *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. */
    int mc146818_set_time(struct rtc_time *time)
    {
    @@ -219,7 +230,10 @@ int mc146818_set_time(struct rtc_time *time)
    save_control = CMOS_READ(RTC_CONTROL);
    CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
    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
    CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
    diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
    index 37c74e25f53d..3038124c6115 100644
    --- a/include/linux/mc146818rtc.h
    +++ b/include/linux/mc146818rtc.h
    @@ -86,6 +86,8 @@ struct cmos_rtc_board_info {
    /* 2 values for divider stage reset, others for "testing purposes only" */
    # define RTC_DIV_RESET1 0x60
    # 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 */
    # define RTC_RATE_SELECT 0x0F

    --
    2.35.1


    \
     
     \ /
      Last update: 2022-05-23 19:33    [W:4.380 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site