File Index
Files and directories
Sign in
FILE

ras_umc_v12_0.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/ras/rascore/ras_umc_v12_0.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright 2025 Advanced Micro Devices, Inc.
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a
  6 * copy of this software and associated documentation files (the "Software"),
  7 * to deal in the Software without restriction, including without limitation
  8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9 * and/or sell copies of the Software, and to permit persons to whom the
 10 * Software is furnished to do so, subject to the following conditions:
 11 *
 12 * The above copyright notice and this permission notice shall be included in
 13 * all copies or substantial portions of the Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 21 * OTHER DEALINGS IN THE SOFTWARE.
 22 *
 23 */
 24#include "ras.h"
 25#include "ras_umc.h"
 26#include "ras_core_status.h"
 27#include "ras_umc_v12_0.h"
 28
 29#define NumDieInterleaved 4
 30
 31static const uint32_t umc_v12_0_channel_idx_tbl[]
 32	[UMC_V12_0_UMC_INSTANCE_NUM][UMC_V12_0_CHANNEL_INSTANCE_NUM] = {
 33	{{3,   7,   11,  15,  2,   6,   10,  14},  {1,   5,   9,   13,  0,   4,   8,   12},
 34	 {19,  23,  27,  31,  18,  22,  26,  30},  {17,  21,  25,  29,  16,  20,  24,  28}},
 35	{{47,  43,  39,  35,  46,  42,  38,  34},  {45,  41,  37,  33,  44,  40,  36,  32},
 36	 {63,  59,  55,  51,  62,  58,  54,  50},  {61,  57,  53,  49,  60,  56,  52,  48}},
 37	{{79,  75,  71,  67,  78,  74,  70,  66},  {77,  73,  69,  65,  76,  72,  68,  64},
 38	 {95,  91,  87,  83,  94,  90,  86,  82},  {93,  89,  85,  81,  92,  88,  84,  80}},
 39	{{99,  103, 107, 111, 98,  102, 106, 110}, {97,  101, 105, 109, 96,  100, 104, 108},
 40	 {115, 119, 123, 127, 114, 118, 122, 126}, {113, 117, 121, 125, 112, 116, 120, 124}}
 41};
 42
 43/* mapping of MCA error address to normalized address */
 44static const uint32_t umc_v12_0_ma2na_mapping[] = {
 45	0,  5,  6,  8,  9,  14, 12, 13,
 46	10, 11, 15, 16, 17, 18, 19, 20,
 47	21, 22, 23, 24, 25, 26, 27, 28,
 48	24, 7,  29, 30,
 49};
 50
 51static bool umc_v12_0_bit_wise_xor(uint32_t val)
 52{
 53	bool result = 0;
 54	int i;
 55
 56	for (i = 0; i < 32; i++)
 57		result = result ^ ((val >> i) & 0x1);
 58
 59	return result;
 60}
 61
 62static void __get_nps_pa_flip_bits(struct ras_core_context *ras_core,
 63			enum umc_memory_partition_mode nps,
 64			struct umc_flip_bits *flip_bits)
 65{
 66	uint32_t vram_type = ras_core->ras_umc.umc_vram_type;
 67
 68	/* default setting */
 69	flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_C2_BIT;
 70	flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C3_BIT;
 71	flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_C4_BIT;
 72	flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R13_BIT;
 73	flip_bits->flip_row_bit = 13;
 74	flip_bits->bit_num = 4;
 75	flip_bits->r13_in_pa = UMC_V12_0_PA_R13_BIT;
 76
 77	if (nps == UMC_MEMORY_PARTITION_MODE_NPS2) {
 78		flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH5_BIT;
 79		flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C2_BIT;
 80		flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B1_BIT;
 81		flip_bits->r13_in_pa = UMC_V12_0_PA_R12_BIT;
 82	} else if (nps == UMC_MEMORY_PARTITION_MODE_NPS4) {
 83		flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH4_BIT;
 84		flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_CH5_BIT;
 85		flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B0_BIT;
 86		flip_bits->r13_in_pa = UMC_V12_0_PA_R11_BIT;
 87	}
 88
 89	switch (vram_type) {
 90	case UMC_VRAM_TYPE_HBM:
 91		/* other nps modes are taken as nps1 */
 92		if (nps == UMC_MEMORY_PARTITION_MODE_NPS2)
 93			flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT;
 94		else if (nps == UMC_MEMORY_PARTITION_MODE_NPS4)
 95			flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
 96
 97		break;
 98	case UMC_VRAM_TYPE_HBM3E:
 99		flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT;
100		flip_bits->flip_row_bit = 12;
101
102		if (nps == UMC_MEMORY_PARTITION_MODE_NPS2)
103			flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
104		else if (nps == UMC_MEMORY_PARTITION_MODE_NPS4)
105			flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R10_BIT;
106
107		break;
108	default:
109		RAS_DEV_WARN(ras_core->dev,
110			"Unknown HBM type, set RAS retire flip bits to the value in NPS1 mode.\n");
111		break;
112	}
113}
114
115static uint64_t  convert_nps_pa_to_row_pa(struct ras_core_context *ras_core,
116		uint64_t pa, enum umc_memory_partition_mode nps, bool zero_pfn_ok)
117{
118	struct umc_flip_bits flip_bits = {0};
119	uint64_t row_pa;
120	int i;
121
122	__get_nps_pa_flip_bits(ras_core, nps, &flip_bits);
123
124	row_pa = pa;
125	/* clear loop bits in soc physical address */
126	for (i = 0; i < flip_bits.bit_num; i++)
127		row_pa &= ~BIT_ULL(flip_bits.flip_bits_in_pa[i]);
128
129	if (!zero_pfn_ok && !RAS_ADDR_TO_PFN(row_pa))
130		row_pa |= BIT_ULL(flip_bits.flip_bits_in_pa[2]);
131
132	return row_pa;
133}
134
135static int lookup_bad_pages_in_a_row(struct ras_core_context *ras_core,
136		struct eeprom_umc_record *record, uint32_t nps,
137		uint64_t *pfns, uint32_t num,
138		uint64_t seq_no, bool dump)
139{
140	uint32_t col, col_lower, row, row_lower, idx, row_high;
141	uint64_t soc_pa, row_pa, column, err_addr;
142	uint64_t retired_addr = RAS_PFN_TO_ADDR(record->cur_nps_retired_row_pfn);
143	struct umc_flip_bits flip_bits = {0};
144	uint32_t retire_unit;
145	uint32_t i;
146
147	__get_nps_pa_flip_bits(ras_core, nps, &flip_bits);
148
149	row_pa = convert_nps_pa_to_row_pa(ras_core, retired_addr, nps, true);
150
151	err_addr = record->address;
152	/* get column bit 0 and 1 in mca address */
153	col_lower = (err_addr >> 1) & 0x3ULL;
154	/* MA_R13_BIT will be handled later */
155	row_lower = (err_addr >> UMC_V12_0_MCA_R0_BIT) & 0x1fffULL;
156	row_lower &= ~BIT_ULL(flip_bits.flip_row_bit);
157
158	if (ras_core->ras_gfx.gfx_ip_version >= IP_VERSION(9, 5, 0)) {
159		row_high = (row_pa >> flip_bits.r13_in_pa) & 0x3ULL;
160		/* it's 2.25GB in each channel, from MCA address to PA
161		 * [R14 R13] is converted if the two bits value are 0x3,
162		 * get them from PA instead of MCA address.
163		 */
164		row_lower |= (row_high << 13);
165	}
166
167	idx = 0;
168	row = 0;
169	retire_unit = 0x1 << flip_bits.bit_num;
170	/* loop for all possibilities of retire bits */
171	for (column = 0; column < retire_unit; column++) {
172		soc_pa = row_pa;
173		for (i = 0; i < flip_bits.bit_num; i++)
174			soc_pa |= (((column >> i) & 0x1ULL) << flip_bits.flip_bits_in_pa[i]);
175
176		col = ((column & 0x7) << 2) | col_lower;
177
178		/* add row bit 13 */
179		if (flip_bits.bit_num == UMC_PA_FLIP_BITS_NUM)
180			row = ((column >> 3) << flip_bits.flip_row_bit) | row_lower;
181
182		if (dump)
183			RAS_DEV_INFO(ras_core->dev,
184				"{%llu} Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n",
185				seq_no, soc_pa, row, col,
186				record->cur_nps_bank, record->mem_channel);
187
188
189		if (pfns && (idx < num))
190			pfns[idx++] = RAS_ADDR_TO_PFN(soc_pa);
191	}
192
193	return idx;
194}
195
196static int umc_v12_convert_ma_to_pa(struct ras_core_context *ras_core,
197			struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
198			uint32_t nps)
199{
200	uint32_t i, na_shift;
201	uint64_t soc_pa, na, na_nps;
202	uint32_t bank_hash0, bank_hash1, bank_hash2, bank_hash3, col, row;
203	uint32_t bank0, bank1, bank2, bank3, bank;
204	uint32_t ch_inst = addr_in->ch_inst;
205	uint32_t umc_inst = addr_in->umc_inst;
206	uint32_t node_inst = addr_in->node_inst;
207	uint32_t socket_id = addr_in->socket_id;
208	uint32_t channel_index;
209	uint64_t err_addr = addr_in->err_addr;
210
211	if (node_inst != UMC_INV_AID_NODE) {
212		if (ch_inst >= UMC_V12_0_CHANNEL_INSTANCE_NUM ||
213			umc_inst >= UMC_V12_0_UMC_INSTANCE_NUM ||
214			node_inst >= UMC_V12_0_AID_NUM_MAX ||
215			socket_id >= UMC_V12_0_SOCKET_NUM_MAX)
216			return -EINVAL;
217	} else {
218		if (socket_id >= UMC_V12_0_SOCKET_NUM_MAX ||
219			ch_inst >= UMC_V12_0_TOTAL_CHANNEL_NUM)
220			return -EINVAL;
221	}
222
223	bank_hash0 = (err_addr >> UMC_V12_0_MCA_B0_BIT) & 0x1ULL;
224	bank_hash1 = (err_addr >> UMC_V12_0_MCA_B1_BIT) & 0x1ULL;
225	bank_hash2 = (err_addr >> UMC_V12_0_MCA_B2_BIT) & 0x1ULL;
226	bank_hash3 = (err_addr >> UMC_V12_0_MCA_B3_BIT) & 0x1ULL;
227	col = (err_addr >> 1) & 0x1fULL;
228	row = (err_addr >> 10) & 0x3fffULL;
229
230	/* apply bank hash algorithm */
231	bank0 =
232		bank_hash0 ^ (UMC_V12_0_XOR_EN0 &
233		(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR0) ^
234		(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR0))));
235	bank1 =
236		bank_hash1 ^ (UMC_V12_0_XOR_EN1 &
237		(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR1) ^
238		(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR1))));
239	bank2 =
240		bank_hash2 ^ (UMC_V12_0_XOR_EN2 &
241		(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR2) ^
242		(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR2))));
243	bank3 =
244		bank_hash3 ^ (UMC_V12_0_XOR_EN3 &
245		(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR3) ^
246		(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR3))));
247
248	bank = bank0 | (bank1 << 1) | (bank2 << 2) | (bank3 << 3);
249	err_addr &= ~0x3c0ULL;
250	err_addr |= (bank << UMC_V12_0_MCA_B0_BIT);
251
252	na_nps = 0x0;
253	/* convert mca error address to normalized address */
254	for (i = 1; i < ARRAY_SIZE(umc_v12_0_ma2na_mapping); i++)
255		na_nps |= ((err_addr >> i) & 0x1ULL) << umc_v12_0_ma2na_mapping[i];
256
257	if (nps == UMC_MEMORY_PARTITION_MODE_NPS1)
258		na_shift = 8;
259	else if (nps == UMC_MEMORY_PARTITION_MODE_NPS2)
260		na_shift = 9;
261	else if (nps == UMC_MEMORY_PARTITION_MODE_NPS4)
262		na_shift = 10;
263	else if (nps == UMC_MEMORY_PARTITION_MODE_NPS8)
264		na_shift = 11;
265	else
266		return -EINVAL;
267
268	na = ((na_nps >> na_shift) << 8) | (na_nps & 0xff);
269
270	if (node_inst != UMC_INV_AID_NODE)
271		channel_index =
272			umc_v12_0_channel_idx_tbl[node_inst][umc_inst][ch_inst];
273	else {
274		channel_index = ch_inst;
275		node_inst = channel_index /
276			(UMC_V12_0_UMC_INSTANCE_NUM * UMC_V12_0_CHANNEL_INSTANCE_NUM);
277	}
278
279	/* translate umc channel address to soc pa, 3 parts are included */
280	soc_pa = ADDR_OF_32KB_BLOCK(na) |
281		ADDR_OF_256B_BLOCK(channel_index) |
282		OFFSET_IN_256B_BLOCK(na);
283
284	/* calc channel hash based on absolute address */
285	soc_pa += socket_id * SOCKET_LFB_SIZE;
286	/* the umc channel bits are not original values, they are hashed */
287	UMC_V12_0_SET_CHANNEL_HASH(channel_index, soc_pa);
288	/* restore pa */
289	soc_pa -= socket_id * SOCKET_LFB_SIZE;
290
291	/* get some channel bits from na_nps directly and
292	 * add nps section offset
293	 */
294	if (nps == UMC_MEMORY_PARTITION_MODE_NPS2) {
295		soc_pa &= ~(0x1ULL << UMC_V12_0_PA_CH5_BIT);
296		soc_pa |= ((na_nps & 0x100) << 5);
297		soc_pa += (node_inst >> 1) * (SOCKET_LFB_SIZE >> 1);
298	} else if (nps == UMC_MEMORY_PARTITION_MODE_NPS4) {
299		soc_pa &= ~(0x3ULL << UMC_V12_0_PA_CH4_BIT);
300		soc_pa |= ((na_nps & 0x300) << 4);
301		soc_pa += node_inst * (SOCKET_LFB_SIZE >> 2);
302	} else if (nps == UMC_MEMORY_PARTITION_MODE_NPS8) {
303		soc_pa &= ~(0x7ULL << UMC_V12_0_PA_CH4_BIT);
304		soc_pa |= ((na_nps & 0x700) << 4);
305		soc_pa += node_inst * (SOCKET_LFB_SIZE >> 2) +
306			(channel_index >> 4) * (SOCKET_LFB_SIZE >> 3);
307	}
308
309	addr_out->pa = soc_pa;
310	addr_out->bank = bank;
311	addr_out->channel_idx = channel_index;
312
313	return 0;
314}
315
316static int convert_ma_to_pa(struct ras_core_context *ras_core,
317			struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
318			uint32_t nps)
319{
320	int ret;
321
322	if (ras_psp_check_supported_cmd(ras_core, RAS_TA_CMD_ID__QUERY_ADDRESS))
323		ret = ras_umc_psp_convert_ma_to_pa(ras_core,
324				addr_in, addr_out, nps);
325	else
326		ret = umc_v12_convert_ma_to_pa(ras_core,
327				addr_in, addr_out, nps);
328
329	return ret;
330}
331
332static int convert_bank_to_nps_addr(struct ras_core_context *ras_core,
333			struct ras_bank_ecc *bank, struct umc_phy_addr *pa_addr, uint32_t nps)
334{
335	struct umc_mca_addr addr_in;
336	struct umc_phy_addr addr_out;
337	int ret;
338
339	memset(&addr_in, 0, sizeof(addr_in));
340	memset(&addr_out, 0, sizeof(addr_out));
341
342	addr_in.err_addr = ACA_ADDR_2_ERR_ADDR(bank->addr);
343	addr_in.ch_inst = ACA_IPID_2_UMC_CH(bank->ipid);
344	addr_in.umc_inst = ACA_IPID_2_UMC_INST(bank->ipid);
345	addr_in.node_inst = ACA_IPID_2_DIE_ID(bank->ipid);
346	addr_in.socket_id = ACA_IPID_2_SOCKET_ID(bank->ipid);
347
348	ret = convert_ma_to_pa(ras_core, &addr_in, &addr_out, nps);
349	if (!ret) {
350		pa_addr->pa =
351			convert_nps_pa_to_row_pa(ras_core, addr_out.pa, nps, false);
352		pa_addr->channel_idx = addr_out.channel_idx;
353		pa_addr->bank = addr_out.bank;
354	}
355
356	return ret;
357}
358
359static int umc_v12_0_bank_to_eeprom_record(struct ras_core_context *ras_core,
360		struct ras_bank_ecc *bank, struct eeprom_umc_record *record)
361{
362	struct umc_phy_addr nps_addr;
363	int ret;
364
365	memset(&nps_addr, 0, sizeof(nps_addr));
366
367	ret = convert_bank_to_nps_addr(ras_core, bank,
368			&nps_addr, bank->nps);
369	if (ret)
370		return ret;
371
372	ras_umc_fill_eeprom_record(ras_core,
373		ACA_ADDR_2_ERR_ADDR(bank->addr), ACA_IPID_2_UMC_INST(bank->ipid),
374		&nps_addr, bank->nps, record);
375
376	lookup_bad_pages_in_a_row(ras_core, record,
377		bank->nps, NULL, 0, bank->seq_no, true);
378
379	return 0;
380}
381
382static int convert_eeprom_record_to_nps_addr(struct ras_core_context *ras_core,
383			struct eeprom_umc_record *record, uint64_t *pa, uint32_t nps)
384{
385	struct device_system_info dev_info = {0};
386	struct umc_mca_addr addr_in;
387	struct umc_phy_addr addr_out;
388	int ret;
389
390	memset(&addr_in, 0, sizeof(addr_in));
391	memset(&addr_out, 0, sizeof(addr_out));
392
393	ras_core_get_device_system_info(ras_core, &dev_info);
394
395	addr_in.err_addr = record->address;
396	addr_in.ch_inst = record->mem_channel;
397	addr_in.umc_inst = record->mcumc_id;
398	addr_in.node_inst = UMC_INV_AID_NODE;
399	addr_in.socket_id = dev_info.socket_id;
400
401	ret = convert_ma_to_pa(ras_core, &addr_in, &addr_out, nps);
402	if (ret)
403		return ret;
404
405	*pa = convert_nps_pa_to_row_pa(ras_core, addr_out.pa, nps, false);
406
407	return 0;
408}
409
410static int umc_v12_0_eeprom_record_to_nps_record(struct ras_core_context *ras_core,
411				struct eeprom_umc_record *record, uint32_t nps)
412{
413	uint64_t pa = 0;
414	int ret = 0;
415
416	if (nps == EEPROM_RECORD_UMC_NPS_MODE(record)) {
417		record->cur_nps_retired_row_pfn = EEPROM_RECORD_UMC_ADDR_PFN(record);
418	} else {
419		ret = convert_eeprom_record_to_nps_addr(ras_core,
420				record, &pa, nps);
421		if (!ret)
422			record->cur_nps_retired_row_pfn = RAS_ADDR_TO_PFN(pa);
423	}
424
425	record->cur_nps = nps;
426
427	return ret;
428}
429
430static int umc_v12_0_eeprom_record_to_nps_pages(struct ras_core_context *ras_core,
431			struct eeprom_umc_record *record, uint32_t nps,
432			uint64_t *pfns, uint32_t num)
433{
434	return lookup_bad_pages_in_a_row(ras_core,
435				record, nps, pfns, num, 0, false);
436}
437
438static int umc_12_0_soc_pa_to_bank(struct ras_core_context *ras_core,
439			uint64_t soc_pa,
440			struct umc_bank_addr *bank_addr)
441{
442
443	int channel_hashed = 0;
444	int channel_real = 0;
445	int channel_reversed = 0;
446	int i = 0;
447
448	bank_addr->stack_id = UMC_V12_0_SOC_PA_TO_SID(soc_pa);
449	bank_addr->bank_group = 0; /* This is a combination of SID & Bank. Needed?? */
450	bank_addr->bank = UMC_V12_0_SOC_PA_TO_BANK(soc_pa);
451	bank_addr->row = UMC_V12_0_SOC_PA_TO_ROW(soc_pa);
452	bank_addr->column = UMC_V12_0_SOC_PA_TO_COL(soc_pa);
453
454	/* Channel bits 4-6 are hashed. Bruteforce reverse the hash */
455	channel_hashed = (soc_pa >> UMC_V12_0_PA_CH4_BIT) & 0x7;
456
457	for (i = 0; i < 8; i++) {
458		channel_reversed = 0;
459		channel_reversed |= UMC_V12_0_CHANNEL_HASH_CH4((i << 4), soc_pa);
460		channel_reversed |= (UMC_V12_0_CHANNEL_HASH_CH5((i << 4), soc_pa) << 1);
461		channel_reversed |= (UMC_V12_0_CHANNEL_HASH_CH6((i << 4), soc_pa) << 2);
462		if (channel_reversed == channel_hashed)
463			channel_real = ((i << 4)) | ((soc_pa >> UMC_V12_0_PA_CH0_BIT) & 0xf);
464	}
465
466	bank_addr->channel = channel_real;
467	bank_addr->subchannel = UMC_V12_0_SOC_PA_TO_PC(soc_pa);
468
469	return 0;
470}
471
472static int umc_12_0_bank_to_soc_pa(struct ras_core_context *ras_core,
473			struct umc_bank_addr bank_addr,
474			uint64_t *soc_pa)
475{
476	uint64_t na = 0;
477	uint64_t tmp_pa = 0;
478	*soc_pa = 0;
479
480	tmp_pa |= UMC_V12_0_SOC_SID_TO_PA(bank_addr.stack_id);
481	tmp_pa |= UMC_V12_0_SOC_BANK_TO_PA(bank_addr.bank);
482	tmp_pa |= UMC_V12_0_SOC_ROW_TO_PA(bank_addr.row);
483	tmp_pa |= UMC_V12_0_SOC_COL_TO_PA(bank_addr.column);
484	tmp_pa |= UMC_V12_0_SOC_CH_TO_PA(bank_addr.channel);
485	tmp_pa |= UMC_V12_0_SOC_PC_TO_PA(bank_addr.subchannel);
486
487	/* Get the NA */
488	na = ((tmp_pa >> UMC_V12_0_PA_C2_BIT) << UMC_V12_0_NA_C2_BIT);
489	na |= tmp_pa & 0xff;
490
491	/* translate umc channel address to soc pa, 3 parts are included */
492	tmp_pa = ADDR_OF_32KB_BLOCK(na) |
493		ADDR_OF_256B_BLOCK(bank_addr.channel) |
494		OFFSET_IN_256B_BLOCK(na);
495
496	/* the umc channel bits are not original values, they are hashed */
497	UMC_V12_0_SET_CHANNEL_HASH(bank_addr.channel, tmp_pa);
498
499	*soc_pa = tmp_pa;
500
501	return 0;
502}
503
504const struct ras_umc_ip_func ras_umc_func_v12_0 = {
505	.bank_to_eeprom_record = umc_v12_0_bank_to_eeprom_record,
506	.eeprom_record_to_nps_record = umc_v12_0_eeprom_record_to_nps_record,
507	.eeprom_record_to_nps_pages = umc_v12_0_eeprom_record_to_nps_pages,
508	.bank_to_soc_pa = umc_12_0_bank_to_soc_pa,
509	.soc_pa_to_bank = umc_12_0_soc_pa_to_bank,
510};
511
~/ Read-only file preview.