static int get_registers()

in pnd2_edac.c [511:607]


static int get_registers(void)
{
	const int intlv[] = { 10, 11, 12, 12 };

	if (RD_REG(&tolud, b_cr_tolud_pci) ||
		RD_REG(&touud_lo, b_cr_touud_lo_pci) ||
		RD_REG(&touud_hi, b_cr_touud_hi_pci) ||
		RD_REG(&asym0, b_cr_asym_mem_region0_mchbar) ||
		RD_REG(&asym1, b_cr_asym_mem_region1_mchbar) ||
		RD_REG(&mot_base, b_cr_mot_out_base_mchbar) ||
		RD_REG(&mot_mask, b_cr_mot_out_mask_mchbar) ||
		RD_REG(&chash, b_cr_slice_channel_hash))
		return -ENODEV;

	if (ops->get_registers())
		return -ENODEV;

	if (ops->type == DNV) {
		/* PMI channel idx (always 0) for asymmetric region */
		asym0.slice0_asym_channel_select = 0;
		asym1.slice1_asym_channel_select = 0;
		/* PMI channel bitmap (always 1) for symmetric region */
		chash.sym_slice0_channel_enabled = 0x1;
		chash.sym_slice1_channel_enabled = 0x1;
	}

	if (asym0.slice0_asym_enable)
		ops->mk_region("as0", &as0, &asym0);

	if (asym1.slice1_asym_enable)
		ops->mk_region("as1", &as1, &asym1);

	if (asym_2way.asym_2way_interleave_enable) {
		mk_region("as2way", &as2,
				  U64_LSHIFT(asym_2way.asym_2way_base, APL_ASYMSHIFT),
				  U64_LSHIFT(asym_2way.asym_2way_limit, APL_ASYMSHIFT) +
				  GENMASK_ULL(APL_ASYMSHIFT - 1, 0));
	}

	if (mot_base.imr_en) {
		mk_region_mask("mot", &mot,
					   U64_LSHIFT(mot_base.mot_out_base, MOT_SHIFT),
					   U64_LSHIFT(mot_mask.mot_out_mask, MOT_SHIFT));
	}

	top_lm = U64_LSHIFT(tolud.tolud, 20);
	top_hm = U64_LSHIFT(touud_hi.touud, 32) | U64_LSHIFT(touud_lo.touud, 20);

	two_slices = !chash.slice_1_disabled &&
				 !chash.slice_0_mem_disabled &&
				 (chash.sym_slice0_channel_enabled != 0) &&
				 (chash.sym_slice1_channel_enabled != 0);
	two_channels = !chash.ch_1_disabled &&
				 !chash.enable_pmi_dual_data_mode &&
				 ((chash.sym_slice0_channel_enabled == 3) ||
				 (chash.sym_slice1_channel_enabled == 3));

	sym_chan_mask = gen_sym_mask(&chash);
	asym_chan_mask = gen_asym_mask(&chash, &asym0, &asym1, &asym_2way);
	chan_mask = sym_chan_mask | asym_chan_mask;

	if (two_slices && !two_channels) {
		if (chash.hvm_mode)
			slice_selector = 29;
		else
			slice_selector = intlv[chash.interleave_mode];
	} else if (!two_slices && two_channels) {
		if (chash.hvm_mode)
			chan_selector = 29;
		else
			chan_selector = intlv[chash.interleave_mode];
	} else if (two_slices && two_channels) {
		if (chash.hvm_mode) {
			slice_selector = 29;
			chan_selector = 30;
		} else {
			slice_selector = intlv[chash.interleave_mode];
			chan_selector = intlv[chash.interleave_mode] + 1;
		}
	}

	if (two_slices) {
		if (!chash.hvm_mode)
			slice_hash_mask = chash.slice_hash_mask << SLICE_HASH_MASK_LSB;
		if (!two_channels)
			slice_hash_mask |= BIT_ULL(slice_selector);
	}

	if (two_channels) {
		if (!chash.hvm_mode)
			chan_hash_mask = chash.ch_hash_mask << CH_HASH_MASK_LSB;
		if (!two_slices)
			chan_hash_mask |= BIT_ULL(chan_selector);
	}

	return 0;
}