1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AMD Address Translation Library
5 * system.c : Functions to read and save system-wide data
7 * Copyright (c) 2023, Advanced Micro Devices, Inc.
10 * Author: Yazen Ghannam <Yazen.Ghannam@amd.com>
15 int determine_node_id(struct addr_ctx
*ctx
, u8 socket_id
, u8 die_id
)
17 u16 socket_id_bits
, die_id_bits
;
19 if (socket_id
> 0 && df_cfg
.socket_id_mask
== 0) {
20 atl_debug(ctx
, "Invalid socket inputs: socket_id=%u socket_id_mask=0x%x",
21 socket_id
, df_cfg
.socket_id_mask
);
25 /* Do each step independently to avoid shift out-of-bounds issues. */
26 socket_id_bits
= socket_id
;
27 socket_id_bits
<<= df_cfg
.socket_id_shift
;
28 socket_id_bits
&= df_cfg
.socket_id_mask
;
30 if (die_id
> 0 && df_cfg
.die_id_mask
== 0) {
31 atl_debug(ctx
, "Invalid die inputs: die_id=%u die_id_mask=0x%x",
32 die_id
, df_cfg
.die_id_mask
);
36 /* Do each step independently to avoid shift out-of-bounds issues. */
38 die_id_bits
<<= df_cfg
.die_id_shift
;
39 die_id_bits
&= df_cfg
.die_id_mask
;
41 ctx
->node_id
= (socket_id_bits
| die_id_bits
) >> df_cfg
.node_id_shift
;
45 static void df2_get_masks_shifts(u32 mask0
)
47 df_cfg
.socket_id_shift
= FIELD_GET(DF2_SOCKET_ID_SHIFT
, mask0
);
48 df_cfg
.socket_id_mask
= FIELD_GET(DF2_SOCKET_ID_MASK
, mask0
);
49 df_cfg
.die_id_shift
= FIELD_GET(DF2_DIE_ID_SHIFT
, mask0
);
50 df_cfg
.die_id_mask
= FIELD_GET(DF2_DIE_ID_MASK
, mask0
);
51 df_cfg
.node_id_shift
= df_cfg
.die_id_shift
;
52 df_cfg
.node_id_mask
= df_cfg
.socket_id_mask
| df_cfg
.die_id_mask
;
53 df_cfg
.component_id_mask
= ~df_cfg
.node_id_mask
;
56 static void df3_get_masks_shifts(u32 mask0
, u32 mask1
)
58 df_cfg
.component_id_mask
= FIELD_GET(DF3_COMPONENT_ID_MASK
, mask0
);
59 df_cfg
.node_id_mask
= FIELD_GET(DF3_NODE_ID_MASK
, mask0
);
61 df_cfg
.node_id_shift
= FIELD_GET(DF3_NODE_ID_SHIFT
, mask1
);
62 df_cfg
.socket_id_shift
= FIELD_GET(DF3_SOCKET_ID_SHIFT
, mask1
);
63 df_cfg
.socket_id_mask
= FIELD_GET(DF3_SOCKET_ID_MASK
, mask1
);
64 df_cfg
.die_id_mask
= FIELD_GET(DF3_DIE_ID_MASK
, mask1
);
67 static void df3p5_get_masks_shifts(u32 mask0
, u32 mask1
, u32 mask2
)
69 df_cfg
.component_id_mask
= FIELD_GET(DF4_COMPONENT_ID_MASK
, mask0
);
70 df_cfg
.node_id_mask
= FIELD_GET(DF4_NODE_ID_MASK
, mask0
);
72 df_cfg
.node_id_shift
= FIELD_GET(DF3_NODE_ID_SHIFT
, mask1
);
73 df_cfg
.socket_id_shift
= FIELD_GET(DF4_SOCKET_ID_SHIFT
, mask1
);
75 df_cfg
.socket_id_mask
= FIELD_GET(DF4_SOCKET_ID_MASK
, mask2
);
76 df_cfg
.die_id_mask
= FIELD_GET(DF4_DIE_ID_MASK
, mask2
);
79 static void df4_get_masks_shifts(u32 mask0
, u32 mask1
, u32 mask2
)
81 df3p5_get_masks_shifts(mask0
, mask1
, mask2
);
83 if (!(df_cfg
.flags
.socket_id_shift_quirk
&& df_cfg
.socket_id_shift
== 1))
86 df_cfg
.socket_id_shift
= 0;
87 df_cfg
.socket_id_mask
= 1;
88 df_cfg
.die_id_shift
= 0;
89 df_cfg
.die_id_mask
= 0;
90 df_cfg
.node_id_shift
= 8;
91 df_cfg
.node_id_mask
= 0x100;
94 static int df4_get_fabric_id_mask_registers(void)
96 u32 mask0
, mask1
, mask2
;
98 /* Read D18F4x1B0 (SystemFabricIdMask0) */
99 if (df_indirect_read_broadcast(0, 4, 0x1B0, &mask0
))
102 /* Read D18F4x1B4 (SystemFabricIdMask1) */
103 if (df_indirect_read_broadcast(0, 4, 0x1B4, &mask1
))
106 /* Read D18F4x1B8 (SystemFabricIdMask2) */
107 if (df_indirect_read_broadcast(0, 4, 0x1B8, &mask2
))
110 df4_get_masks_shifts(mask0
, mask1
, mask2
);
114 static int df4_determine_df_rev(u32 reg
)
116 df_cfg
.rev
= FIELD_GET(DF_MINOR_REVISION
, reg
) < 5 ? DF4
: DF4p5
;
118 /* Check for special cases or quirks based on Device/Vendor IDs.*/
120 /* Read D18F0x000 (DeviceVendorId0) */
121 if (df_indirect_read_broadcast(0, 0, 0, ®
))
124 if (reg
== DF_FUNC0_ID_ZEN4_SERVER
)
125 df_cfg
.flags
.socket_id_shift_quirk
= 1;
127 if (reg
== DF_FUNC0_ID_MI300
) {
128 df_cfg
.flags
.heterogeneous
= 1;
130 if (get_umc_info_mi300())
134 return df4_get_fabric_id_mask_registers();
137 static int determine_df_rev_legacy(void)
139 u32 fabric_id_mask0
, fabric_id_mask1
, fabric_id_mask2
;
144 * Component ID Mask must be non-zero. Register D18F1x150 is
145 * reserved pre-DF3.5, so value will be Read-as-Zero.
148 /* Read D18F1x150 (SystemFabricIdMask0). */
149 if (df_indirect_read_broadcast(0, 1, 0x150, &fabric_id_mask0
))
152 if (FIELD_GET(DF4_COMPONENT_ID_MASK
, fabric_id_mask0
)) {
155 /* Read D18F1x154 (SystemFabricIdMask1) */
156 if (df_indirect_read_broadcast(0, 1, 0x154, &fabric_id_mask1
))
159 /* Read D18F1x158 (SystemFabricIdMask2) */
160 if (df_indirect_read_broadcast(0, 1, 0x158, &fabric_id_mask2
))
163 df3p5_get_masks_shifts(fabric_id_mask0
, fabric_id_mask1
, fabric_id_mask2
);
170 * Component ID Mask must be non-zero. Field is Read-as-Zero on DF2.
173 /* Read D18F1x208 (SystemFabricIdMask). */
174 if (df_indirect_read_broadcast(0, 1, 0x208, &fabric_id_mask0
))
177 if (FIELD_GET(DF3_COMPONENT_ID_MASK
, fabric_id_mask0
)) {
180 /* Read D18F1x20C (SystemFabricIdMask1) */
181 if (df_indirect_read_broadcast(0, 1, 0x20C, &fabric_id_mask1
))
184 df3_get_masks_shifts(fabric_id_mask0
, fabric_id_mask1
);
188 /* Default to DF2. */
190 df2_get_masks_shifts(fabric_id_mask0
);
194 static int determine_df_rev(void)
199 if (df_cfg
.rev
!= UNKNOWN
)
202 /* Read D18F0x40 (FabricBlockInstanceCount). */
203 if (df_indirect_read_broadcast(0, 0, 0x40, ®
))
207 * Revision fields added for DF4 and later.
209 * Major revision of '0' is found pre-DF4. Field is Read-as-Zero.
211 rev
= FIELD_GET(DF_MAJOR_REVISION
, reg
);
213 return determine_df_rev_legacy();
216 * Fail out for major revisions other than '4'.
218 * Explicit support should be added for newer systems to avoid issues.
221 return df4_determine_df_rev(reg
);
226 static int get_dram_hole_base(void)
230 if (df_cfg
.rev
>= DF4
)
233 if (df_indirect_read_broadcast(0, func
, 0x104, &df_cfg
.dram_hole_base
))
236 df_cfg
.dram_hole_base
&= DF_DRAM_HOLE_BASE_MASK
;
241 static void get_num_maps(void)
243 switch (df_cfg
.rev
) {
247 df_cfg
.num_coh_st_maps
= 2;
251 df_cfg
.num_coh_st_maps
= 4;
254 atl_debug_on_bad_df_rev();
258 static void apply_node_id_shift(void)
260 if (df_cfg
.rev
== DF2
)
263 df_cfg
.die_id_shift
= df_cfg
.node_id_shift
;
264 df_cfg
.die_id_mask
<<= df_cfg
.node_id_shift
;
265 df_cfg
.socket_id_mask
<<= df_cfg
.node_id_shift
;
266 df_cfg
.socket_id_shift
+= df_cfg
.node_id_shift
;
269 static void dump_df_cfg(void)
271 pr_debug("rev=0x%x", df_cfg
.rev
);
273 pr_debug("component_id_mask=0x%x", df_cfg
.component_id_mask
);
274 pr_debug("die_id_mask=0x%x", df_cfg
.die_id_mask
);
275 pr_debug("node_id_mask=0x%x", df_cfg
.node_id_mask
);
276 pr_debug("socket_id_mask=0x%x", df_cfg
.socket_id_mask
);
278 pr_debug("die_id_shift=0x%x", df_cfg
.die_id_shift
);
279 pr_debug("node_id_shift=0x%x", df_cfg
.node_id_shift
);
280 pr_debug("socket_id_shift=0x%x", df_cfg
.socket_id_shift
);
282 pr_debug("num_coh_st_maps=%u", df_cfg
.num_coh_st_maps
);
284 pr_debug("dram_hole_base=0x%x", df_cfg
.dram_hole_base
);
285 pr_debug("flags.legacy_ficaa=%u", df_cfg
.flags
.legacy_ficaa
);
286 pr_debug("flags.socket_id_shift_quirk=%u", df_cfg
.flags
.socket_id_shift_quirk
);
289 int get_df_system_info(void)
291 if (determine_df_rev()) {
292 pr_warn("Failed to determine DF Revision");
293 df_cfg
.rev
= UNKNOWN
;
297 apply_node_id_shift();
301 if (get_dram_hole_base())
302 pr_warn("Failed to read DRAM hole base");