xref: /linux/drivers/ras/amd/atl/internal.h (revision efdbe82a216191d77c8edd5e4dabc7cff7d790d9)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * AMD Address Translation Library
4  *
5  * internal.h : Helper functions and common defines
6  *
7  * Copyright (c) 2023, Advanced Micro Devices, Inc.
8  * All Rights Reserved.
9  *
10  * Author: Yazen Ghannam <Yazen.Ghannam@amd.com>
11  */
12 
13 #ifndef __AMD_ATL_INTERNAL_H__
14 #define __AMD_ATL_INTERNAL_H__
15 
16 #include <linux/bitfield.h>
17 #include <linux/bitops.h>
18 #include <linux/ras.h>
19 
20 #include <asm/amd_nb.h>
21 
22 #include "reg_fields.h"
23 
24 #undef pr_fmt
25 #define pr_fmt(fmt) "amd_atl: " fmt
26 
27 /* Maximum possible number of Coherent Stations within a single Data Fabric. */
28 #define MAX_COH_ST_CHANNELS		32
29 
30 /* PCI ID for Zen4 Server DF Function 0. */
31 #define DF_FUNC0_ID_ZEN4_SERVER		0x14AD1022
32 
33 /* PCI IDs for MI300 DF Function 0. */
34 #define DF_FUNC0_ID_MI300		0x15281022
35 
36 /* Shift needed for adjusting register values to true values. */
37 #define DF_DRAM_BASE_LIMIT_LSB		28
38 #define MI300_DRAM_LIMIT_LSB		20
39 
40 enum df_revisions {
41 	UNKNOWN,
42 	DF2,
43 	DF3,
44 	DF3p5,
45 	DF4,
46 	DF4p5,
47 };
48 
49 /* These are mapped 1:1 to the hardware values. Special cases are set at > 0x20. */
50 enum intlv_modes {
51 	NONE				= 0x00,
52 	NOHASH_2CHAN			= 0x01,
53 	NOHASH_4CHAN			= 0x03,
54 	NOHASH_8CHAN			= 0x05,
55 	DF3_6CHAN			= 0x06,
56 	NOHASH_16CHAN			= 0x07,
57 	NOHASH_32CHAN			= 0x08,
58 	DF3_COD4_2CHAN_HASH		= 0x0C,
59 	DF3_COD2_4CHAN_HASH		= 0x0D,
60 	DF3_COD1_8CHAN_HASH		= 0x0E,
61 	DF4_NPS4_2CHAN_HASH		= 0x10,
62 	DF4_NPS2_4CHAN_HASH		= 0x11,
63 	DF4_NPS1_8CHAN_HASH		= 0x12,
64 	DF4_NPS4_3CHAN_HASH		= 0x13,
65 	DF4_NPS2_6CHAN_HASH		= 0x14,
66 	DF4_NPS1_12CHAN_HASH		= 0x15,
67 	DF4_NPS2_5CHAN_HASH		= 0x16,
68 	DF4_NPS1_10CHAN_HASH		= 0x17,
69 	MI3_HASH_8CHAN			= 0x18,
70 	MI3_HASH_16CHAN			= 0x19,
71 	MI3_HASH_32CHAN			= 0x1A,
72 	DF2_2CHAN_HASH			= 0x21,
73 	/* DF4.5 modes are all IntLvNumChan + 0x20 */
74 	DF4p5_NPS1_16CHAN_1K_HASH	= 0x2C,
75 	DF4p5_NPS0_24CHAN_1K_HASH	= 0x2E,
76 	DF4p5_NPS4_2CHAN_1K_HASH	= 0x30,
77 	DF4p5_NPS2_4CHAN_1K_HASH	= 0x31,
78 	DF4p5_NPS1_8CHAN_1K_HASH	= 0x32,
79 	DF4p5_NPS4_3CHAN_1K_HASH	= 0x33,
80 	DF4p5_NPS2_6CHAN_1K_HASH	= 0x34,
81 	DF4p5_NPS1_12CHAN_1K_HASH	= 0x35,
82 	DF4p5_NPS2_5CHAN_1K_HASH	= 0x36,
83 	DF4p5_NPS1_10CHAN_1K_HASH	= 0x37,
84 	DF4p5_NPS4_2CHAN_2K_HASH	= 0x40,
85 	DF4p5_NPS2_4CHAN_2K_HASH	= 0x41,
86 	DF4p5_NPS1_8CHAN_2K_HASH	= 0x42,
87 	DF4p5_NPS1_16CHAN_2K_HASH	= 0x43,
88 	DF4p5_NPS4_3CHAN_2K_HASH	= 0x44,
89 	DF4p5_NPS2_6CHAN_2K_HASH	= 0x45,
90 	DF4p5_NPS1_12CHAN_2K_HASH	= 0x46,
91 	DF4p5_NPS0_24CHAN_2K_HASH	= 0x47,
92 	DF4p5_NPS2_5CHAN_2K_HASH	= 0x48,
93 	DF4p5_NPS1_10CHAN_2K_HASH	= 0x49,
94 };
95 
96 struct df_flags {
97 	__u8	legacy_ficaa		: 1,
98 		socket_id_shift_quirk	: 1,
99 		heterogeneous		: 1,
100 		__reserved_0		: 5;
101 };
102 
103 struct df_config {
104 	enum df_revisions rev;
105 
106 	/*
107 	 * These masks operate on the 16-bit Coherent Station IDs,
108 	 * e.g. Instance, Fabric, Destination, etc.
109 	 */
110 	u16 component_id_mask;
111 	u16 die_id_mask;
112 	u16 node_id_mask;
113 	u16 socket_id_mask;
114 
115 	/*
116 	 * Least-significant bit of Node ID portion of the
117 	 * system-wide Coherent Station Fabric ID.
118 	 */
119 	u8 node_id_shift;
120 
121 	/*
122 	 * Least-significant bit of Die portion of the Node ID.
123 	 * Adjusted to include the Node ID shift in order to apply
124 	 * to the Coherent Station Fabric ID.
125 	 */
126 	u8 die_id_shift;
127 
128 	/*
129 	 * Least-significant bit of Socket portion of the Node ID.
130 	 * Adjusted to include the Node ID shift in order to apply
131 	 * to the Coherent Station Fabric ID.
132 	 */
133 	u8 socket_id_shift;
134 
135 	/* Number of DRAM Address maps visible in a Coherent Station. */
136 	u8 num_coh_st_maps;
137 
138 	/* Global flags to handle special cases. */
139 	struct df_flags flags;
140 };
141 
142 extern struct df_config df_cfg;
143 
144 struct dram_addr_map {
145 	/*
146 	 * Each DRAM Address Map can operate independently
147 	 * in different interleaving modes.
148 	 */
149 	enum intlv_modes intlv_mode;
150 
151 	/* System-wide number for this address map. */
152 	u8 num;
153 
154 	/* Raw register values */
155 	u32 base;
156 	u32 limit;
157 	u32 ctl;
158 	u32 intlv;
159 
160 	/*
161 	 * Logical to Physical Coherent Station Remapping array
162 	 *
163 	 * Index: Logical Coherent Station Instance ID
164 	 * Value: Physical Coherent Station Instance ID
165 	 *
166 	 * phys_coh_st_inst_id = remap_array[log_coh_st_inst_id]
167 	 */
168 	u8 remap_array[MAX_COH_ST_CHANNELS];
169 
170 	/*
171 	 * Number of bits covering DRAM Address map 0
172 	 * when interleaving is non-power-of-2.
173 	 *
174 	 * Used only for DF3_6CHAN.
175 	 */
176 	u8 np2_bits;
177 
178 	/* Position of the 'interleave bit'. */
179 	u8 intlv_bit_pos;
180 	/* Number of channels interleaved in this map. */
181 	u8 num_intlv_chan;
182 	/* Number of dies interleaved in this map. */
183 	u8 num_intlv_dies;
184 	/* Number of sockets interleaved in this map. */
185 	u8 num_intlv_sockets;
186 	/*
187 	 * Total number of channels interleaved accounting
188 	 * for die and socket interleaving.
189 	 */
190 	u8 total_intlv_chan;
191 	/* Total bits needed to cover 'total_intlv_chan'. */
192 	u8 total_intlv_bits;
193 };
194 
195 /* Original input values cached for debug printing. */
196 struct addr_ctx_inputs {
197 	u64 norm_addr;
198 	u8 socket_id;
199 	u8 die_id;
200 	u8 coh_st_inst_id;
201 };
202 
203 struct addr_ctx {
204 	u64 ret_addr;
205 
206 	struct addr_ctx_inputs inputs;
207 	struct dram_addr_map map;
208 
209 	/* AMD Node ID calculated from Socket and Die IDs. */
210 	u8 node_id;
211 
212 	/*
213 	 * Coherent Station Instance ID
214 	 * Local ID used within a 'node'.
215 	 */
216 	u16 inst_id;
217 
218 	/*
219 	 * Coherent Station Fabric ID
220 	 * System-wide ID that includes 'node' bits.
221 	 */
222 	u16 coh_st_fabric_id;
223 };
224 
225 int df_indirect_read_instance(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo);
226 int df_indirect_read_broadcast(u16 node, u8 func, u16 reg, u32 *lo);
227 
228 int get_df_system_info(void);
229 int determine_node_id(struct addr_ctx *ctx, u8 socket_num, u8 die_num);
230 int get_addr_hash_mi300(void);
231 
232 int get_address_map(struct addr_ctx *ctx);
233 
234 int denormalize_address(struct addr_ctx *ctx);
235 int dehash_address(struct addr_ctx *ctx);
236 
237 unsigned long norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_inst_id, unsigned long addr);
238 unsigned long convert_umc_mca_addr_to_sys_addr(struct atl_err *err);
239 
240 /*
241  * Make a gap in @data that is @num_bits long starting at @bit_num.
242  * e.g. data		= 11111111'b
243  *	bit_num		= 3
244  *	num_bits	= 2
245  *	result		= 1111100111'b
246  */
247 static inline u64 expand_bits(u8 bit_num, u8 num_bits, u64 data)
248 {
249 	u64 temp1, temp2;
250 
251 	if (!num_bits)
252 		return data;
253 
254 	if (!bit_num) {
255 		WARN_ON_ONCE(num_bits >= BITS_PER_LONG);
256 		return data << num_bits;
257 	}
258 
259 	WARN_ON_ONCE(bit_num >= BITS_PER_LONG);
260 
261 	temp1 = data & GENMASK_ULL(bit_num - 1, 0);
262 
263 	temp2 = data & GENMASK_ULL(63, bit_num);
264 	temp2 <<= num_bits;
265 
266 	return temp1 | temp2;
267 }
268 
269 /*
270  * Remove bits in @data between @low_bit and @high_bit inclusive.
271  * e.g. data		= XXXYYZZZ'b
272  *	low_bit		= 3
273  *	high_bit	= 4
274  *	result		= XXXZZZ'b
275  */
276 static inline u64 remove_bits(u8 low_bit, u8 high_bit, u64 data)
277 {
278 	u64 temp1, temp2;
279 
280 	WARN_ON_ONCE(high_bit >= BITS_PER_LONG);
281 	WARN_ON_ONCE(low_bit  >= BITS_PER_LONG);
282 	WARN_ON_ONCE(low_bit  >  high_bit);
283 
284 	if (!low_bit)
285 		return data >> (high_bit++);
286 
287 	temp1 = GENMASK_ULL(low_bit - 1, 0) & data;
288 	temp2 = GENMASK_ULL(63, high_bit + 1) & data;
289 	temp2 >>= high_bit - low_bit + 1;
290 
291 	return temp1 | temp2;
292 }
293 
294 #define atl_debug(ctx, fmt, arg...) \
295 	pr_debug("socket_id=%u die_id=%u coh_st_inst_id=%u norm_addr=0x%016llx: " fmt,\
296 		 (ctx)->inputs.socket_id, (ctx)->inputs.die_id,\
297 		 (ctx)->inputs.coh_st_inst_id, (ctx)->inputs.norm_addr, ##arg)
298 
299 static inline void atl_debug_on_bad_df_rev(void)
300 {
301 	pr_debug("Unrecognized DF rev: %u", df_cfg.rev);
302 }
303 
304 static inline void atl_debug_on_bad_intlv_mode(struct addr_ctx *ctx)
305 {
306 	atl_debug(ctx, "Unrecognized interleave mode: %u", ctx->map.intlv_mode);
307 }
308 
309 #endif /* __AMD_ATL_INTERNAL_H__ */
310