Commit a4087a25 authored by Pu Wen's avatar Pu Wen
Browse files

EDAC/amd64: Add support for Hygon family 18h model 4h

hygon inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8U3K8


CVE: NA

---------------------------

Add support for Hygon family 18h model 4h to get UMC base, instance
number and determine DDR memory types.

Signed-off-by: default avatarPu Wen <puwen@hygon.cn>
parent 07f3e21d
Loading
Loading
Loading
Loading
+51 −10
Original line number Diff line number Diff line
@@ -96,6 +96,17 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
	return err;
}

static u32 get_umc_base_f18h_m4h(u16 node, u8 channel)
{
	struct pci_dev *f3 = node_to_amd_nb(node)->misc;
	u8 df_id;

	get_df_id(f3, &df_id);
	df_id -= 4;

	return get_umc_base(channel) + (0x80000000 + (0x10000000 * df_id));
}

/*
 * Select DCT to which PCI cfg accesses are routed
 */
@@ -1608,6 +1619,9 @@ static void umc_dump_misc_regs(struct amd64_pvt *pvt)
	u32 i, tmp, umc_base;

	for_each_umc(i) {
		if (hygon_f18h_m4h())
			umc_base = get_umc_base_f18h_m4h(pvt->mc_node_id, i);
		else
			umc_base = get_umc_base(i);
		umc = &pvt->umc[i];

@@ -1717,11 +1731,17 @@ static void umc_read_base_mask(struct amd64_pvt *pvt)
	u32 mask_reg, mask_reg_sec;
	u32 *base, *base_sec;
	u32 *mask, *mask_sec;
	u32 umc_base;
	int cs, umc;

	for_each_umc(umc) {
		umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR;
		umc_base_reg_sec = get_umc_base(umc) + UMCCH_BASE_ADDR_SEC;
		if (hygon_f18h_m4h())
			umc_base = get_umc_base_f18h_m4h(pvt->mc_node_id, umc);
		else
			umc_base = get_umc_base(umc);

		umc_base_reg = umc_base + UMCCH_BASE_ADDR;
		umc_base_reg_sec = umc_base + UMCCH_BASE_ADDR_SEC;

		for_each_chip_select(cs, umc, pvt) {
			base = &pvt->csels[umc].csbases[cs];
@@ -1739,8 +1759,8 @@ static void umc_read_base_mask(struct amd64_pvt *pvt)
					 umc, cs, *base_sec, base_reg_sec);
		}

		umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK;
		umc_mask_reg_sec = get_umc_base(umc) + get_umc_reg(pvt, UMCCH_ADDR_MASK_SEC);
		umc_mask_reg = umc_base + UMCCH_ADDR_MASK;
		umc_mask_reg_sec = umc_base + get_umc_reg(pvt, UMCCH_ADDR_MASK_SEC);

		for_each_chip_select_mask(cs, umc, pvt) {
			mask = &pvt->csels[umc].csmasks[cs];
@@ -1823,7 +1843,8 @@ static void umc_determine_memory_type(struct amd64_pvt *pvt)
		 * Check if the system supports the "DDR Type" field in UMC Config
		 * and has DDR5 DIMMs in use.
		 */
		if (pvt->flags.zn_regs_v2 && ((umc->umc_cfg & GENMASK(2, 0)) == 0x1)) {
		if ((pvt->flags.zn_regs_v2 || hygon_f18h_m4h()) &&
		    ((umc->umc_cfg & GENMASK(2, 0)) == 0x1)) {
			if (umc->dimm_cfg & BIT(5))
				umc->dram_type = MEM_LRDDR5;
			else if (umc->dimm_cfg & BIT(4))
@@ -3176,8 +3197,11 @@ static void umc_read_mc_regs(struct amd64_pvt *pvt)

	/* Read registers from each UMC */
	for_each_umc(i) {

		if (hygon_f18h_m4h())
			umc_base = get_umc_base_f18h_m4h(pvt->mc_node_id, i);
		else
			umc_base = get_umc_base(i);

		umc = &pvt->umc[i];

		amd_smn_read(nid, umc_base + get_umc_reg(pvt, UMCCH_DIMM_CFG), &umc->dimm_cfg);
@@ -4108,6 +4132,11 @@ static int per_family_init(struct amd64_pvt *pvt)
		break;

	case 0x18:
		if (pvt->model == 0x4) {
			pvt->ctl_name			= "F18h_M04h";
			pvt->max_mcs			= 3;
			break;
		}
		pvt->ctl_name				= "F18h";
		break;

@@ -4371,6 +4400,7 @@ static int __init amd64_edac_init(void)
{
	const char *owner;
	int err = -ENODEV;
	u16 instance_num;
	int i;

	if (ghes_get_devices())
@@ -4388,8 +4418,13 @@ static int __init amd64_edac_init(void)

	opstate_init();

	if (hygon_f18h_m4h())
		instance_num = hygon_nb_num();
	else
		instance_num = amd_nb_num();

	err = -ENOMEM;
	ecc_stngs = kcalloc(amd_nb_num(), sizeof(ecc_stngs[0]), GFP_KERNEL);
	ecc_stngs = kcalloc(instance_num, sizeof(ecc_stngs[0]), GFP_KERNEL);
	if (!ecc_stngs)
		goto err_free;

@@ -4397,7 +4432,7 @@ static int __init amd64_edac_init(void)
	if (!msrs)
		goto err_free;

	for (i = 0; i < amd_nb_num(); i++) {
	for (i = 0; i < instance_num; i++) {
		err = probe_one_instance(i);
		if (err) {
			/* unwind properly */
@@ -4442,6 +4477,7 @@ static int __init amd64_edac_init(void)

static void __exit amd64_edac_exit(void)
{
	u16 instance_num;
	int i;

	if (pci_ctl)
@@ -4453,7 +4489,12 @@ static void __exit amd64_edac_exit(void)
	else
		amd_unregister_ecc_decoder(decode_bus_error);

	for (i = 0; i < amd_nb_num(); i++)
	if (hygon_f18h_m4h())
		instance_num = hygon_nb_num();
	else
		instance_num = amd_nb_num();

	for (i = 0; i < instance_num; i++)
		remove_one_instance(i);

	kfree(ecc_stngs);