// SPDX-License-Identifier: GPL-2.0-or-later /* * AMD Address Translation Library * * umc.c : Unified Memory Controller (UMC) topology helpers * * Copyright (c) 2023, Advanced Micro Devices, Inc. * All Rights Reserved. * * Author: Yazen Ghannam <[email protected]> */ #include "internal.h" /* * MI300 has a fixed, model-specific mapping between a UMC instance and * its related Data Fabric Coherent Station instance. * * The MCA_IPID_UMC[InstanceId] field holds a unique identifier for the * UMC instance within a Node. Use this to find the appropriate Coherent * Station ID. * * Redundant bits were removed from the map below. */ static const u16 umc_coh_st_map[32] = …; #define UMC_ID_MI300 … static u8 get_coh_st_inst_id_mi300(struct atl_err *err) { … } /* XOR the bits in @val. */ static u16 bitwise_xor_bits(u16 val) { … } struct xor_bits { … }; #define NUM_BANK_BITS … #define NUM_COL_BITS … #define NUM_SID_BITS … static struct { … } addr_hash; static struct { … } bit_shifts; #define MI300_UMC_CH_BASE … #define MI300_ADDR_CFG … #define MI300_ADDR_SEL … #define MI300_COL_SEL_LO … #define MI300_ADDR_SEL_2 … #define MI300_ADDR_HASH_BANK0 … #define MI300_ADDR_HASH_PC … #define MI300_ADDR_HASH_PC2 … #define ADDR_HASH_XOR_EN … #define ADDR_HASH_COL_XOR … #define ADDR_HASH_ROW_XOR … #define ADDR_HASH_BANK_XOR … #define ADDR_CFG_NUM_ROW_LO … #define ADDR_CFG_NUM_ROW_HI … #define ADDR_SEL_BANK0 … #define ADDR_SEL_BANK1 … #define ADDR_SEL_BANK2 … #define ADDR_SEL_BANK3 … #define ADDR_SEL_BANK4 … #define ADDR_SEL_ROW_LO … #define ADDR_SEL_ROW_HI … #define COL_SEL_LO_COL0 … #define COL_SEL_LO_COL1 … #define COL_SEL_LO_COL2 … #define COL_SEL_LO_COL3 … #define COL_SEL_LO_COL4 … #define ADDR_SEL_2_BANK5 … #define ADDR_SEL_2_CHAN … /* * Read UMC::CH::AddrHash{Bank,PC,PC2} registers to get XOR bits used * for hashing. * * Also, read UMC::CH::Addr{Cfg,Sel,Sel2} and UMC::CH:ColSelLo registers to * get the values needed to reconstruct the normalized address. Apply additional * offsets to the raw register values, as needed. * * Do this during module init, since the values will not change during run time. * * These registers are instantiated for each UMC across each AMD Node. * However, they should be identically programmed due to the fixed hardware * design of MI300 systems. So read the values from Node 0 UMC 0 and keep a * single global structure for simplicity. */ int get_umc_info_mi300(void) { … } /* * MI300 systems report a DRAM address in MCA_ADDR for DRAM ECC errors. This must * be converted to the intermediate normalized address (NA) before translating to a * system physical address. * * The DRAM address includes bank, row, and column. Also included are bits for * pseudochannel (PC) and stack ID (SID). * * Abbreviations: (S)tack ID, (P)seudochannel, (R)ow, (B)ank, (C)olumn, (Z)ero * * The MCA address format is as follows: * MCA_ADDR[27:0] = {S[1:0], P[0], R[14:0], B[3:0], C[4:0], Z[0]} * * Additionally, the PC and Bank bits may be hashed. This must be accounted for before * reconstructing the normalized address. */ #define MI300_UMC_MCA_COL … #define MI300_UMC_MCA_BANK … #define MI300_UMC_MCA_ROW … #define MI300_UMC_MCA_PC … #define MI300_UMC_MCA_SID … static unsigned long convert_dram_to_norm_addr_mi300(unsigned long addr) { … } /* * When a DRAM ECC error occurs on MI300 systems, it is recommended to retire * all memory within that DRAM row. This applies to the memory with a DRAM * bank. * * To find the memory addresses, loop through permutations of the DRAM column * bits and find the System Physical address of each. The column bits are used * to calculate the intermediate Normalized address, so all permutations should * be checked. * * See amd_atl::convert_dram_to_norm_addr_mi300() for MI300 address formats. */ #define MI300_NUM_COL … static void retire_row_mi300(struct atl_err *a_err) { … } void amd_retire_dram_row(struct atl_err *a_err) { … } EXPORT_SYMBOL_GPL(…); static unsigned long get_addr(unsigned long addr) { … } #define MCA_IPID_INST_ID_HI … static u8 get_die_id(struct atl_err *err) { … } #define UMC_CHANNEL_NUM … static u8 get_coh_st_inst_id(struct atl_err *err) { … } unsigned long convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { … }