xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c (revision d6dac2bc)
1 /*
2  * Copyright 2020 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "umc_v8_7.h"
24 #include "amdgpu_ras.h"
25 #include "amdgpu_umc.h"
26 #include "amdgpu.h"
27 
28 #include "rsmu/rsmu_0_0_2_offset.h"
29 #include "rsmu/rsmu_0_0_2_sh_mask.h"
30 #include "umc/umc_8_7_0_offset.h"
31 #include "umc/umc_8_7_0_sh_mask.h"
32 
33 #define UMC_8_INST_DIST			0x40000
34 
35 const uint32_t
36 	umc_v8_7_channel_idx_tbl[UMC_V8_7_UMC_INSTANCE_NUM][UMC_V8_7_CHANNEL_INSTANCE_NUM] = {
37 		{2, 11},  {4, 13},
38 		{1, 8},   {7, 14},
39 		{10, 3},  {12, 5},
40 		{9, 0},   {15, 6}
41 };
42 
43 static inline uint32_t get_umc_v8_7_reg_offset(struct amdgpu_device *adev,
44 					    uint32_t umc_inst,
45 					    uint32_t ch_inst)
46 {
47 	return adev->umc.channel_offs*ch_inst + UMC_8_INST_DIST*umc_inst;
48 }
49 
50 static inline uint32_t get_umc_v8_7_channel_index(struct amdgpu_device *adev,
51 						uint32_t umc_inst,
52 						uint32_t ch_inst)
53 {
54 	return adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
55 }
56 
57 static void umc_v8_7_ecc_info_query_correctable_error_count(struct amdgpu_device *adev,
58 						uint32_t umc_inst, uint32_t ch_inst,
59 						unsigned long *error_count)
60 {
61 	uint64_t mc_umc_status;
62 	uint32_t eccinfo_table_idx;
63 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
64 
65 	eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
66 
67 	/* check for SRAM correctable error
68 	 * MCUMC_STATUS is a 64 bit register
69 	 */
70 	mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
71 	if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
72 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
73 		*error_count += 1;
74 }
75 
76 static void umc_v8_7_ecc_info_querry_uncorrectable_error_count(struct amdgpu_device *adev,
77 							uint32_t umc_inst, uint32_t ch_inst,
78 							unsigned long *error_count)
79 {
80 	uint64_t mc_umc_status;
81 	uint32_t eccinfo_table_idx;
82 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
83 
84 	eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
85 
86 	/* check the MCUMC_STATUS */
87 	mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
88 	if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
89 	    (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
90 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
91 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
92 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
93 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1))
94 		*error_count += 1;
95 }
96 
97 static void umc_v8_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
98 					void *ras_error_status)
99 {
100 	struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
101 
102 	uint32_t umc_inst        = 0;
103 	uint32_t ch_inst         = 0;
104 
105 	/* TODO: driver needs to toggle DF Cstate to ensure
106 	 * safe access of UMC registers. Will add the protection
107 	 */
108 	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
109 		umc_v8_7_ecc_info_query_correctable_error_count(adev,
110 							umc_inst, ch_inst,
111 							&(err_data->ce_count));
112 		umc_v8_7_ecc_info_querry_uncorrectable_error_count(adev,
113 							umc_inst, ch_inst,
114 							&(err_data->ue_count));
115 	}
116 }
117 
118 static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev,
119 					struct ras_err_data *err_data,
120 					uint32_t ch_inst,
121 					uint32_t umc_inst)
122 {
123 	uint64_t mc_umc_status, err_addr, retired_page;
124 	struct eeprom_table_record *err_rec;
125 	uint32_t channel_index;
126 	uint32_t eccinfo_table_idx;
127 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
128 
129 	eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
130 	channel_index =
131 		adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
132 
133 	mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
134 
135 	if (mc_umc_status == 0)
136 		return;
137 
138 	if (!err_data->err_addr)
139 		return;
140 
141 	err_rec = &err_data->err_addr[err_data->err_addr_cnt];
142 
143 	/* calculate error address if ue/ce error is detected */
144 	if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
145 	    (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
146 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
147 
148 		err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr;
149 		err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
150 
151 		/* translate umc channel address to soc pa, 3 parts are included */
152 		retired_page = ADDR_OF_4KB_BLOCK(err_addr) |
153 				ADDR_OF_256B_BLOCK(channel_index) |
154 				OFFSET_IN_256B_BLOCK(err_addr);
155 
156 		/* we only save ue error information currently, ce is skipped */
157 		if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
158 				== 1) {
159 			err_rec->address = err_addr;
160 			/* page frame address is saved */
161 			err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
162 			err_rec->ts = (uint64_t)ktime_get_real_seconds();
163 			err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
164 			err_rec->cu = 0;
165 			err_rec->mem_channel = channel_index;
166 			err_rec->mcumc_id = umc_inst;
167 
168 			err_data->err_addr_cnt++;
169 		}
170 	}
171 }
172 
173 static void umc_v8_7_ecc_info_query_ras_error_address(struct amdgpu_device *adev,
174 					void *ras_error_status)
175 {
176 	struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
177 
178 	uint32_t umc_inst        = 0;
179 	uint32_t ch_inst         = 0;
180 
181 	/* TODO: driver needs to toggle DF Cstate to ensure
182 	 * safe access of UMC resgisters. Will add the protection
183 	 * when firmware interface is ready
184 	 */
185 	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
186 		umc_v8_7_ecc_info_query_error_address(adev,
187 						err_data,
188 						ch_inst,
189 						umc_inst);
190 	}
191 }
192 
193 static void umc_v8_7_clear_error_count_per_channel(struct amdgpu_device *adev,
194 					uint32_t umc_reg_offset)
195 {
196 	uint32_t ecc_err_cnt_addr;
197 	uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
198 
199 	ecc_err_cnt_sel_addr =
200 		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel);
201 	ecc_err_cnt_addr =
202 		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt);
203 
204 	/* select the lower chip */
205 	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
206 					umc_reg_offset) * 4);
207 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
208 					UMCCH0_0_GeccErrCntSel,
209 					GeccErrCntCsSel, 0);
210 	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
211 			ecc_err_cnt_sel);
212 
213 	/* clear lower chip error count */
214 	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
215 			UMC_V8_7_CE_CNT_INIT);
216 
217 	/* select the higher chip */
218 	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
219 					umc_reg_offset) * 4);
220 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
221 					UMCCH0_0_GeccErrCntSel,
222 					GeccErrCntCsSel, 1);
223 	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
224 			ecc_err_cnt_sel);
225 
226 	/* clear higher chip error count */
227 	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
228 			UMC_V8_7_CE_CNT_INIT);
229 }
230 
231 static void umc_v8_7_clear_error_count(struct amdgpu_device *adev)
232 {
233 	uint32_t umc_inst        = 0;
234 	uint32_t ch_inst         = 0;
235 	uint32_t umc_reg_offset  = 0;
236 
237 	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
238 		umc_reg_offset = get_umc_v8_7_reg_offset(adev,
239 						umc_inst,
240 						ch_inst);
241 
242 		umc_v8_7_clear_error_count_per_channel(adev,
243 						umc_reg_offset);
244 	}
245 }
246 
247 static void umc_v8_7_query_correctable_error_count(struct amdgpu_device *adev,
248 						   uint32_t umc_reg_offset,
249 						   unsigned long *error_count)
250 {
251 	uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
252 	uint32_t ecc_err_cnt, ecc_err_cnt_addr;
253 	uint64_t mc_umc_status;
254 	uint32_t mc_umc_status_addr;
255 
256 	/* UMC 8_7_2 registers */
257 	ecc_err_cnt_sel_addr =
258 		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel);
259 	ecc_err_cnt_addr =
260 		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt);
261 	mc_umc_status_addr =
262 		SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
263 
264 	/* select the lower chip and check the error count */
265 	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4);
266 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel,
267 					GeccErrCntCsSel, 0);
268 	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
269 
270 	ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
271 	*error_count +=
272 		(REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_GeccErrCnt, GeccErrCnt) -
273 		 UMC_V8_7_CE_CNT_INIT);
274 
275 	/* select the higher chip and check the err counter */
276 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel,
277 					GeccErrCntCsSel, 1);
278 	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
279 
280 	ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
281 	*error_count +=
282 		(REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_GeccErrCnt, GeccErrCnt) -
283 		 UMC_V8_7_CE_CNT_INIT);
284 
285 	/* check for SRAM correctable error
286 	  MCUMC_STATUS is a 64 bit register */
287 	mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
288 	if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 6 &&
289 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
290 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
291 		*error_count += 1;
292 }
293 
294 static void umc_v8_7_querry_uncorrectable_error_count(struct amdgpu_device *adev,
295 						      uint32_t umc_reg_offset,
296 						      unsigned long *error_count)
297 {
298 	uint64_t mc_umc_status;
299 	uint32_t mc_umc_status_addr;
300 
301 	mc_umc_status_addr = SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
302 
303 	/* check the MCUMC_STATUS */
304 	mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
305 	if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
306 	    (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
307 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
308 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
309 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
310 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1))
311 		*error_count += 1;
312 }
313 
314 static void umc_v8_7_query_ras_error_count(struct amdgpu_device *adev,
315 					   void *ras_error_status)
316 {
317 	struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
318 
319 	uint32_t umc_inst        = 0;
320 	uint32_t ch_inst         = 0;
321 	uint32_t umc_reg_offset  = 0;
322 
323 	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
324 		umc_reg_offset = get_umc_v8_7_reg_offset(adev,
325 						      umc_inst,
326 						      ch_inst);
327 
328 		umc_v8_7_query_correctable_error_count(adev,
329 						       umc_reg_offset,
330 						       &(err_data->ce_count));
331 		umc_v8_7_querry_uncorrectable_error_count(adev,
332 							  umc_reg_offset,
333 							  &(err_data->ue_count));
334 	}
335 
336 	umc_v8_7_clear_error_count(adev);
337 }
338 
339 static void umc_v8_7_query_error_address(struct amdgpu_device *adev,
340 					 struct ras_err_data *err_data,
341 					 uint32_t umc_reg_offset,
342 					 uint32_t ch_inst,
343 					 uint32_t umc_inst)
344 {
345 	uint32_t lsb, mc_umc_status_addr;
346 	uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0;
347 	struct eeprom_table_record *err_rec;
348 	uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
349 
350 	mc_umc_status_addr =
351 		SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
352 	mc_umc_addrt0 =
353 		SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_ADDRT0);
354 
355 	mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
356 
357 	if (mc_umc_status == 0)
358 		return;
359 
360 	if (!err_data->err_addr) {
361 		/* clear umc status */
362 		WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
363 		return;
364 	}
365 
366 	err_rec = &err_data->err_addr[err_data->err_addr_cnt];
367 
368 	/* calculate error address if ue/ce error is detected */
369 	if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
370 	    (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
371 	    REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
372 
373 		err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
374 		/* the lowest lsb bits should be ignored */
375 		lsb = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, LSB);
376 		err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
377 		err_addr &= ~((0x1ULL << lsb) - 1);
378 
379 		/* translate umc channel address to soc pa, 3 parts are included */
380 		retired_page = ADDR_OF_4KB_BLOCK(err_addr) |
381 				ADDR_OF_256B_BLOCK(channel_index) |
382 				OFFSET_IN_256B_BLOCK(err_addr);
383 
384 		/* we only save ue error information currently, ce is skipped */
385 		if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
386 				== 1) {
387 			err_rec->address = err_addr;
388 			/* page frame address is saved */
389 			err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
390 			err_rec->ts = (uint64_t)ktime_get_real_seconds();
391 			err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
392 			err_rec->cu = 0;
393 			err_rec->mem_channel = channel_index;
394 			err_rec->mcumc_id = umc_inst;
395 
396 			err_data->err_addr_cnt++;
397 		}
398 	}
399 
400 	/* clear umc status */
401 	WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
402 }
403 
404 static void umc_v8_7_query_ras_error_address(struct amdgpu_device *adev,
405 					     void *ras_error_status)
406 {
407 	struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
408 
409 	uint32_t umc_inst        = 0;
410 	uint32_t ch_inst         = 0;
411 	uint32_t umc_reg_offset  = 0;
412 
413 	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
414 		umc_reg_offset = get_umc_v8_7_reg_offset(adev,
415 						      umc_inst,
416 						      ch_inst);
417 
418 		umc_v8_7_query_error_address(adev,
419 					     err_data,
420 					     umc_reg_offset,
421 					     ch_inst,
422 					     umc_inst);
423 	}
424 }
425 
426 static void umc_v8_7_err_cnt_init_per_channel(struct amdgpu_device *adev,
427 					      uint32_t umc_reg_offset)
428 {
429 	uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
430 	uint32_t ecc_err_cnt_addr;
431 
432 	ecc_err_cnt_sel_addr =
433 		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel);
434 	ecc_err_cnt_addr =
435 		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt);
436 
437 	/* select the lower chip and check the error count */
438 	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4);
439 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel,
440 					GeccErrCntCsSel, 0);
441 	/* set ce error interrupt type to APIC based interrupt */
442 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel,
443 					GeccErrInt, 0x1);
444 	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
445 	/* set error count to initial value */
446 	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V8_7_CE_CNT_INIT);
447 
448 	/* select the higher chip and check the err counter */
449 	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel,
450 					GeccErrCntCsSel, 1);
451 	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
452 	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V8_7_CE_CNT_INIT);
453 }
454 
455 static void umc_v8_7_err_cnt_init(struct amdgpu_device *adev)
456 {
457 	uint32_t umc_inst        = 0;
458 	uint32_t ch_inst         = 0;
459 	uint32_t umc_reg_offset  = 0;
460 
461 	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
462 		umc_reg_offset = get_umc_v8_7_reg_offset(adev,
463 						      umc_inst,
464 						      ch_inst);
465 
466 		umc_v8_7_err_cnt_init_per_channel(adev, umc_reg_offset);
467 	}
468 }
469 
470 const struct amdgpu_ras_block_hw_ops umc_v8_7_ras_hw_ops = {
471 	.query_ras_error_count = umc_v8_7_query_ras_error_count,
472 	.query_ras_error_address = umc_v8_7_query_ras_error_address,
473 };
474 
475 struct amdgpu_umc_ras umc_v8_7_ras = {
476 	.ras_block = {
477 		.hw_ops = &umc_v8_7_ras_hw_ops,
478 	},
479 	.err_cnt_init = umc_v8_7_err_cnt_init,
480 	.ecc_info_query_ras_error_count = umc_v8_7_ecc_info_query_ras_error_count,
481 	.ecc_info_query_ras_error_address = umc_v8_7_ecc_info_query_ras_error_address,
482 };
483