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
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.