From a70a512d2f72d44d3832266b304b7039e6f6857b Mon Sep 17 00:00:00 2001 From: Wenhui Fan Date: Wed, 2 Sep 2026 17:09:13 +0800 Subject: [PATCH 1/5] anolis:x86/pci, x86/hygon_nb: Add Hygon Northbridge driver support via PCI enumeration ANBZ: #45106 Separate Hygon NB drivers from AMD NB drivers The key changes as follows: 1. Implement Hygon NB driver by PCI device enumeration. 2. Add Hygon NB driver source file. 3. Add Kconfig entry (CONFIG_HYGON_NB) with dependencies on AMD_NB and CPU_SUP_HYGON. Hygon-SIG: commit none hygon anolis:x86/pci, x86/hygon_nb: Add Hygon Northbridge driver support via PCI enumeration Signed-off-by: Wenhui Fan --- .../configs/L1-RECOMMEND/x86/CONFIG_HYGON_NB | 1 + arch/x86/Kconfig | 4 + arch/x86/include/asm/hygon/hygon_nb.h | 63 +++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/amd_nb.c | 292 +------------ arch/x86/kernel/hygon_nb.c | 405 ++++++++++++++++++ include/linux/pci_ids.h | 2 + 7 files changed, 479 insertions(+), 289 deletions(-) create mode 100644 anolis/configs/L1-RECOMMEND/x86/CONFIG_HYGON_NB create mode 100644 arch/x86/include/asm/hygon/hygon_nb.h create mode 100644 arch/x86/kernel/hygon_nb.c diff --git a/anolis/configs/L1-RECOMMEND/x86/CONFIG_HYGON_NB b/anolis/configs/L1-RECOMMEND/x86/CONFIG_HYGON_NB new file mode 100644 index 000000000000..290c38414c64 --- /dev/null +++ b/anolis/configs/L1-RECOMMEND/x86/CONFIG_HYGON_NB @@ -0,0 +1 @@ +CONFIG_HYGON_NB=y diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d1e69f2645ee..5a6c23dd5c27 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -3092,6 +3092,10 @@ config AMD_NODE def_bool y depends on CPU_SUP_AMD && PCI +config HYGON_NB + def_bool y + depends on CPU_SUP_HYGON && PCI + config X86_SYSFB bool "Mark VGA/VBE/EFI FB as generic system framebuffer" help diff --git a/arch/x86/include/asm/hygon/hygon_nb.h b/arch/x86/include/asm/hygon/hygon_nb.h new file mode 100644 index 000000000000..9a791288af54 --- /dev/null +++ b/arch/x86/include/asm/hygon/hygon_nb.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_HYGON_NB_H +#define _ASM_X86_HYGON_NB_H + +#include + +struct hygon_northbridge { + struct pci_dev *root; + struct pci_dev *misc; + struct pci_dev *link; +}; + +struct hygon_northbridge_info { + u16 num; + struct hygon_northbridge *nb; +}; + +int hygon_smn_read(u16 node, u32 address, u32 *value); +int hygon_smn_write(u16 node, u32 address, u32 value); + +#ifdef CONFIG_HYGON_NB + +int northbridge_init_hygon(void); +u16 hygon_nb_num(void); +struct hygon_northbridge *node_to_hygon_nb(int node); +bool hygon_f18h_m4h(void); +bool hygon_f18h_m10h(void); +int get_df_id(struct pci_dev *misc, u8 *id); +u16 hygon_node_num(void); + +static inline u16 hygon_pci_dev_to_node_id(struct pci_dev *pdev) +{ + struct pci_dev *misc; + int i; + + for (i = 0; i != hygon_nb_num(); i++) { + misc = node_to_hygon_nb(i)->misc; + + if (pci_domain_nr(misc->bus) == pci_domain_nr(pdev->bus) && + PCI_SLOT(misc->devfn) == PCI_SLOT(pdev->devfn)) + return i; + } + + WARN(1, "Unable to find Hygon Northbridge id for %s\n", pci_name(pdev)); + return 0; +} + +#else + +#define northbridge_init_hygon(x) 0 +#define hygon_nb_num(x) 0 +#define hygon_f18h_m4h(x) false +#define hygon_f18h_m10h(x) false +#define get_df_id(x, y) NULL +#define hygon_node_num(x) 0 + +static inline struct hygon_northbridge *node_to_hygon_nb(int node) +{ + return NULL; +} +#endif + +#endif diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a19ce38df85d..a3f4b0b007c7 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -119,6 +119,7 @@ obj-$(CONFIG_APB_TIMER) += apb_timer.o obj-$(CONFIG_AMD_NB) += amd_nb.o obj-$(CONFIG_AMD_NODE) += amd_node.o +obj-$(CONFIG_HYGON_NB) += hygon_nb.o obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 9595b90e2bac..9a4e6dd09d4e 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -20,18 +20,7 @@ #define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 #define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494 -#define PCI_DEVICE_ID_HYGON_18H_M05H_ROOT 0x14a0 -#define PCI_DEVICE_ID_HYGON_18H_M10H_ROOT 0x14c0 -#define PCI_DEVICE_ID_HYGON_18H_M18H_ROOT 0x2000 -#define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1 0x1491 -#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1 0x14b1 -#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4 0x14b4 -#define PCI_DEVICE_ID_HYGON_18H_M10H_DF_F4 0x14d4 -#define PCI_DEVICE_ID_HYGON_18H_M18H_DF_F4 0x2014 -#define PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5 0x14b5 - static u32 *flush_words; -static u16 nb_num; static const struct pci_device_id amd_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, @@ -45,33 +34,6 @@ static const struct pci_device_id amd_nb_misc_ids[] = { {} }; -static const struct pci_device_id hygon_root_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_ROOT) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_M30H_ROOT) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_ROOT) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_ROOT) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_ROOT) }, - {} -}; - -static const struct pci_device_id hygon_nb_misc_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F3) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_DF_F3) }, - {} -}; - -static const struct pci_device_id hygon_nb_link_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F4) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_M30H_DF_F4) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F4) }, - { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_DF_F4) }, - {} -}; - const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = { { 0x00, 0x18, 0x20 }, { 0xff, 0x00, 0x20 }, @@ -110,244 +72,6 @@ static struct pci_dev *next_northbridge(struct pci_dev *dev, return dev; } - -bool hygon_f18h_m4h(void) -{ - if (boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) - return false; - - if (boot_cpu_data.x86 == 0x18 && - boot_cpu_data.x86_model >= 0x4 && - boot_cpu_data.x86_model <= 0xf) - return true; - - return false; -} -EXPORT_SYMBOL_GPL(hygon_f18h_m4h); - -bool hygon_f18h_m10h(void) -{ - if (boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) - return false; - - if (boot_cpu_data.x86 == 0x18 && - boot_cpu_data.x86_model >= 0x10 && - boot_cpu_data.x86_model <= 0x1f) - return true; - - return false; -} -EXPORT_SYMBOL_GPL(hygon_f18h_m10h); - -u16 hygon_nb_num(void) -{ - return nb_num; -} -EXPORT_SYMBOL_GPL(hygon_nb_num); - -static int get_df_register(struct pci_dev *misc, u8 func, int offset, u32 *value) -{ - struct pci_dev *df_func = NULL; - u32 device; - int err; - - if (func == 1) { - switch (boot_cpu_data.x86_model) { - case 0x4: - device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; - break; - case 0x5: - if (misc->device == PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) - device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; - else - device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; - break; - case 0x6 ... 0x8: - device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; - break; - default: - return -ENODEV; - } - } else if (func == 5) { - switch (boot_cpu_data.x86_model) { - case 0x6 ... 0x8: - device = PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5; - break; - default: - return -ENODEV; - } - } else { - return -ENODEV; - } - - while ((df_func = pci_get_device(misc->vendor, device, df_func))) - if (pci_domain_nr(df_func->bus) == pci_domain_nr(misc->bus) && - df_func->bus->number == misc->bus->number && - PCI_SLOT(df_func->devfn) == PCI_SLOT(misc->devfn)) - break; - - if (!df_func) { - pr_warn("Error getting DF F%d device.\n", func); - return -ENODEV; - } - - err = pci_read_config_dword(df_func, offset, value); - if (err) - pr_warn("Error reading DF F%d register.\n", func); - - return err; -} - -int get_df_id(struct pci_dev *misc, u8 *id) -{ - u32 value; - int ret; - - if (boot_cpu_data.x86_model >= 0x6 && - boot_cpu_data.x86_model <= 0xf) { - /* F5x180[19:16]: DF ID */ - ret = get_df_register(misc, 5, 0x180, &value); - *id = (value >> 16) & 0xf; - } else { - /* F1x200[23:20]: DF ID */ - ret = get_df_register(misc, 1, 0x200, &value); - *id = (value >> 20) & 0xf; - } - - return ret; -} -EXPORT_SYMBOL_GPL(get_df_id); - -static u8 get_socket_num(struct pci_dev *misc) -{ - u32 value; - int ret; - - /* F1x200[7:0]: Which socket is present. */ - ret = get_df_register(misc, 1, 0x200, &value); - - return ret ? 0 : hweight8(value & 0xff); -} - -static int northbridge_init_f18h_m4h(const struct pci_device_id *root_ids, - const struct pci_device_id *misc_ids, - const struct pci_device_id *link_ids) -{ - struct pci_dev *root, *misc, *link; - struct pci_dev *root_first = NULL; - struct amd_northbridge *nb; - u16 roots_per_socket = 0; - u16 miscs_per_socket = 0; - u16 socket_num = 0; - u16 root_count = 0; - u16 misc_count = 0; - int err = -ENODEV; - u8 i, j, m, n; - u8 id; - - pr_info("Hygon Fam%xh Model%xh NB driver.\n", - boot_cpu_data.x86, boot_cpu_data.x86_model); - - misc = next_northbridge(NULL, misc_ids); - if (misc != NULL) { - socket_num = get_socket_num(misc); - pr_info("Socket number: %d\n", socket_num); - if (!socket_num) { - err = -ENODEV; - goto ret; - } - } else { - err = -ENODEV; - goto ret; - } - - misc = NULL; - while ((misc = next_northbridge(misc, misc_ids)) != NULL) - misc_count++; - - root = NULL; - while ((root = next_northbridge(root, root_ids)) != NULL) - root_count++; - - if (!root_count || !misc_count) { - err = -ENODEV; - goto ret; - } - - /* - * There should be _exactly_ N roots for each DF/SMN - * interface, and M DF/SMN interfaces in one socket. - */ - roots_per_socket = root_count / socket_num; - miscs_per_socket = misc_count / socket_num; - - if (!roots_per_socket || !miscs_per_socket) { - err = -ENODEV; - goto ret; - } - - nb = kcalloc(misc_count, sizeof(struct amd_northbridge), GFP_KERNEL); - if (!nb) { - err = -ENOMEM; - goto ret; - } - - amd_northbridges.nb = nb; - amd_northbridges.num = misc_count; - - link = misc = root = NULL; - j = m = n = 0; - for (i = 0; i < amd_northbridges.num; i++) { - misc = next_northbridge(misc, misc_ids); - link = next_northbridge(link, link_ids); - - /* Only save the first PCI root device for each socket. */ - if (!(i % miscs_per_socket)) { - root_first = next_northbridge(root, root_ids); - root = root_first; - j = 1; - } - - if (get_df_id(misc, &id)) { - err = -ENODEV; - goto err; - } - pr_info("DF ID: %d\n", id); - - if (id < 4) { - /* Add the devices with id<4 from the tail. */ - node_to_amd_nb(misc_count - m - 1)->misc = misc; - node_to_amd_nb(misc_count - m - 1)->link = link; - node_to_amd_nb(misc_count - m - 1)->root = root_first; - m++; - } else { - node_to_amd_nb(n)->misc = misc; - node_to_amd_nb(n)->link = link; - node_to_amd_nb(n)->root = root_first; - n++; - } - - /* Skip the redundant PCI root devices per socket. */ - while (j < roots_per_socket) { - root = next_northbridge(root, root_ids); - j++; - } - } - nb_num = n; - - return 0; - -err: - kfree(nb); - amd_northbridges.nb = NULL; - -ret: - if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) - pr_err("Hygon Fam%xh Model%xh northbridge init failed(%d)!\n", - boot_cpu_data.x86, boot_cpu_data.x86_model, err); - return err; -} - static int amd_cache_northbridges(void) { struct amd_northbridge *nb; @@ -356,13 +80,6 @@ static int amd_cache_northbridges(void) if (amd_northbridges.num) return 0; - if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { - if (boot_cpu_data.x86_model >= 0x4 && - boot_cpu_data.x86_model <= 0xf) - return northbridge_init_f18h_m4h(hygon_root_ids, - hygon_nb_misc_ids, hygon_nb_link_ids); - } - amd_northbridges.num = amd_num_nodes(); nb = kcalloc(amd_northbridges.num, sizeof(struct amd_northbridge), GFP_KERNEL); @@ -426,8 +143,7 @@ bool __init early_is_amd_nb(u32 device) const struct pci_device_id *id; u32 vendor = device & 0xffff; - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && - boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return false; if (cpu_feature_enabled(X86_FEATURE_ZEN)) @@ -446,8 +162,7 @@ struct resource *amd_get_mmconfig_range(struct resource *res) u64 base, msr; unsigned int segn_busn_bits; - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && - boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return NULL; /* assume all cpus from fam10h have mmconfig */ @@ -619,8 +334,7 @@ static __init void fix_erratum_688(void) static __init int init_amd_nbs(void) { - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && - boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return 0; amd_cache_northbridges(); diff --git a/arch/x86/kernel/hygon_nb.c b/arch/x86/kernel/hygon_nb.c new file mode 100644 index 000000000000..f37b2e035902 --- /dev/null +++ b/arch/x86/kernel/hygon_nb.c @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Share support code for Hygon northbridges and derivatives. + * Copyright (C) 2026 Chengdu Haiguang IC Design Co., Ltd. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_DEVICE_ID_HYGON_18H_ROOT 0x1450 +#define PCI_DEVICE_ID_HYGON_18H_M05H_ROOT 0x14a0 +#define PCI_DEVICE_ID_HYGON_18H_M04H_ROOT 0x1480 + +#define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1 0x1491 +#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1 0x14b1 +#define PCI_DEVICE_ID_HYGON_18H_DF_F4 0x1464 +#define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F4 0x1494 +#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4 0x14b4 +#define PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5 0x14b5 + +static u16 node_num; +static struct pci_dev **hygon_roots; +static struct hygon_northbridge_info hygon_northbridges; + +/* Protect the PCI config register pairs used for SMN and DF indirect access. */ +static DEFINE_MUTEX(smn_mutex); + +static const struct pci_device_id hygon_root_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_ROOT) }, + {} +}; + +static const struct pci_device_id hygon_nb_misc_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) }, + {} +}; + +static const struct pci_device_id hygon_nb_link_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4) }, + {} +}; + +#define HYGON_SMN_INDEX_OFFSET 0x60 +#define HYGON_SMN_DATA_OFFSET 0x64 + +static int __hygon_smn_rw(u16 node, u32 address, u32 *value, bool write) +{ + struct pci_dev *root; + int err = -ENODEV; + + if (node >= hygon_nb_num()) + goto out; + + root = hygon_roots[node]; + if (!root) + goto out; + + mutex_lock(&smn_mutex); + + err = pci_write_config_dword(root, HYGON_SMN_INDEX_OFFSET, address); + if (err) { + pr_warn("Error programming SMN address 0x%x.\n", address); + goto out_unlock; + } + + err = (write ? pci_write_config_dword(root, HYGON_SMN_DATA_OFFSET, *value) + : pci_read_config_dword(root, HYGON_SMN_DATA_OFFSET, value)); + if (err) + pr_warn("Error %s SMN address 0x%x.\n", + (write ? "writing to" : "reading from"), address); + +out_unlock: + mutex_unlock(&smn_mutex); + +out: + return err; +} + +int hygon_smn_read(u16 node, u32 address, u32 *value) +{ + int err = __hygon_smn_rw(node, address, value, false); + + if (PCI_POSSIBLE_ERROR(*value)) { + err = -ENODEV; + *value = 0; + } + + return err; +} +EXPORT_SYMBOL_GPL(hygon_smn_read); + +int hygon_smn_write(u16 node, u32 address, u32 value) +{ + return __hygon_smn_rw(node, address, &value, true); +} +EXPORT_SYMBOL_GPL(hygon_smn_write); + +static struct pci_dev *next_northbridge(struct pci_dev *dev, + const struct pci_device_id *ids) +{ + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (!dev) + break; + } while (!pci_match_id(ids, dev)); + return dev; +} + +u16 hygon_node_num(void) +{ + return node_num; +} +EXPORT_SYMBOL_GPL(hygon_node_num); + +u16 hygon_nb_num(void) +{ + return hygon_northbridges.num; +} +EXPORT_SYMBOL_GPL(hygon_nb_num); + +struct hygon_northbridge *node_to_hygon_nb(int node) +{ + return (node < hygon_northbridges.num) ? &hygon_northbridges.nb[node] : NULL; +} +EXPORT_SYMBOL_GPL(node_to_hygon_nb); + +static int get_df_register(struct pci_dev *misc, u8 func, int offset, u32 *value) +{ + struct pci_dev *df_func = NULL; + u32 device; + int err; + + if (func == 1) { + switch (boot_cpu_data.x86_model) { + case 0x4: + device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; + break; + case 0x5: + if (misc->device == PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) + device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; + else + device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; + break; + case 0x6 ... 0x8: + device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; + break; + default: + return -ENODEV; + } + } else if (func == 5) { + switch (boot_cpu_data.x86_model) { + case 0x6 ... 0x8: + device = PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5; + break; + default: + return -ENODEV; + } + } else { + return -ENODEV; + } + + while ((df_func = pci_get_device(misc->vendor, device, df_func))) + if (pci_domain_nr(df_func->bus) == pci_domain_nr(misc->bus) && + df_func->bus->number == misc->bus->number && + PCI_SLOT(df_func->devfn) == PCI_SLOT(misc->devfn)) + break; + + if (!df_func) { + pr_warn("Error getting DF func device.\n"); + return -ENODEV; + } + + err = pci_read_config_dword(df_func, offset, value); + if (err) + pr_warn("Error reading DF func register.\n"); + + return err; +} + +bool hygon_f18h_m4h(void) +{ + if (boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) + return false; + + if (boot_cpu_data.x86 == 0x18 && + boot_cpu_data.x86_model >= 0x4 && + boot_cpu_data.x86_model <= 0xf) + return true; + + return false; +} +EXPORT_SYMBOL_GPL(hygon_f18h_m4h); + +bool hygon_f18h_m10h(void) +{ + if (boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) + return false; + + if (boot_cpu_data.x86 == 0x18 && + boot_cpu_data.x86_model >= 0x10 && + boot_cpu_data.x86_model <= 0x1f) + return true; + + return false; +} +EXPORT_SYMBOL_GPL(hygon_f18h_m10h); + +int get_df_id(struct pci_dev *misc, u8 *id) +{ + u32 value; + int ret; + + if (boot_cpu_data.x86_model >= 0x6 && + boot_cpu_data.x86_model <= 0xf) { + /* F5x180[19:16]: DF ID */ + ret = get_df_register(misc, 5, 0x180, &value); + *id = (value >> 16) & 0xf; + } else { + /* F1x200[23:20]: DF ID */ + ret = get_df_register(misc, 1, 0x200, &value); + *id = (value >> 20) & 0xf; + } + + return ret; +} +EXPORT_SYMBOL_GPL(get_df_id); + +static u8 get_socket_num(struct pci_dev *misc) +{ + u32 value; + int ret; + + /* F1x200[7:0]: Which socket is present. */ + ret = get_df_register(misc, 1, 0x200, &value); + + return ret ? 0 : hweight8(value & 0xff); +} + +int northbridge_init_hygon(void) +{ + const struct pci_device_id *misc_ids = hygon_nb_misc_ids; + const struct pci_device_id *link_ids = hygon_nb_link_ids; + const struct pci_device_id *root_ids = hygon_root_ids; + struct pci_dev *root, *misc, *link; + struct pci_dev *root_first = NULL; + struct hygon_northbridge *nb; + u16 roots_per_socket = 0; + u16 miscs_per_socket = 0; + u16 socket_num = 0; + u16 root_count = 0; + u16 misc_count = 0; + int err = -ENODEV; + u8 i, j, m, n; + u8 id; + + if (hygon_northbridges.num) + return 0; + + misc = NULL; + while ((misc = next_northbridge(misc, misc_ids))) + misc_count++; + + root = NULL; + while ((root = next_northbridge(root, root_ids)) != NULL) + root_count++; + + if (!root_count || !misc_count) { + err = -ENODEV; + goto out; + } + + if (hygon_f18h_m4h()) { + misc = NULL; + misc = next_northbridge(NULL, misc_ids); + if (misc != NULL) { + socket_num = get_socket_num(misc); + pr_info("Socket number: %d\n", socket_num); + if (!socket_num) { + err = -ENODEV; + goto out; + } + } else { + err = -ENODEV; + goto out; + } + + /* + * There should be _exactly_ N roots for each DF/SMN + * interface, and M DF/SMN interfaces in one socket. + */ + roots_per_socket = root_count / socket_num; + miscs_per_socket = misc_count / socket_num; + + if (!roots_per_socket || !miscs_per_socket) { + err = -ENODEV; + goto out; + } + } + + hygon_roots = kcalloc(misc_count, sizeof(*hygon_roots), GFP_KERNEL); + if (!hygon_roots) { + err = -ENOMEM; + goto out; + } + + nb = kcalloc(misc_count, sizeof(struct hygon_northbridge), GFP_KERNEL); + if (!nb) { + err = -ENOMEM; + goto err_free_roots; + } + + hygon_northbridges.nb = nb; + hygon_northbridges.num = misc_count; + + link = misc = root = NULL; + j = m = n = 0; + for (i = 0; i < hygon_northbridges.num; i++) { + misc = next_northbridge(misc, misc_ids); + link = next_northbridge(link, link_ids); + if (hygon_f18h_m4h()) { + /* Only save the first PCI root device for each socket. */ + if (!(i % miscs_per_socket)) { + root = root_first = next_northbridge(root, root_ids); + j = 1; + } + + if (get_df_id(misc, &id)) { + err = -ENODEV; + goto err_free_nb; + } + pr_info("DF ID: %d\n", id); + + if (id < 4) { + /* Add the devices with id<4 from the tail. */ + node_to_hygon_nb(misc_count - m - 1)->misc = misc; + node_to_hygon_nb(misc_count - m - 1)->link = link; + hygon_roots[misc_count - m - 1] = root_first; + m++; + } else { + node_to_hygon_nb(n)->misc = misc; + node_to_hygon_nb(n)->link = link; + hygon_roots[n] = root_first; + n++; + } + + /* Skip the redundant PCI root devices per socket. */ + while (j < roots_per_socket) { + root = next_northbridge(root, root_ids); + j++; + } + } else { + hygon_roots[i] = root = next_northbridge(root, root_ids); + node_to_hygon_nb(i)->misc = misc; + node_to_hygon_nb(i)->link = link; + n++; + } + } + node_num = n; + + pr_info("Hygon Fam%xh Model%xh NB driver init success.\n", + boot_cpu_data.x86, boot_cpu_data.x86_model); + + return 0; + +err_free_nb: + kfree(nb); + hygon_northbridges.nb = NULL; + hygon_northbridges.num = 0; +err_free_roots: + kfree(hygon_roots); + hygon_roots = NULL; + +out: + if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) + pr_err("Hygon Fam%xh Model%xh northbridge init failed(%d)!\n", + boot_cpu_data.x86, boot_cpu_data.x86_model, err); + return err; +} + +static __init int init_hygon_nbs(void) +{ + if (boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) + return 0; + + northbridge_init_hygon(); + + return 0; +} + +/* This has to go after the PCI subsystem */ +fs_initcall(init_hygon_nbs); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a78d5e0f50e5..fbe986b3e2cc 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2610,6 +2610,8 @@ #define PCI_VENDOR_ID_HYGON 0x1d94 #define PCI_DEVICE_ID_HYGON_18H_M05H_HDA 0x14a9 +#define PCI_DEVICE_ID_HYGON_18H_DF_F3 0x1463 +#define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F3 0x1493 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3 0x14b3 #define PCI_DEVICE_ID_HYGON_18H_M10H_DF_F3 0x14d3 #define PCI_DEVICE_ID_HYGON_18H_M18H_DF_F3 0x2013 -- Gitee From bba2a167a2912dc6a6a02837a323585b2badf1f3 Mon Sep 17 00:00:00 2001 From: Wenhui Fan Date: Wed, 2 Sep 2026 20:16:47 +0800 Subject: [PATCH 2/5] anolis:hwmon/k10temp: Update the SMN interface used by Hygon processos in k10temp ANBZ: #45106 The Hygon NB driver has been separated form AMD NB, and the SMN interface is now implemented separately. Therefore, the SMN interface used by Hygon must be updated accordingly. Hygon-SIG: commit none hygon anolis:hwmon/k10temp: Update the SMN interface used by Hygon processors in the k10temp Signed-off-by: Wenhui Fan --- drivers/hwmon/k10temp.c | 60 ++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index 4caa988f36c2..26e836ac4428 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -23,6 +23,7 @@ #include #include #include +#include MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); MODULE_AUTHOR("Clemens Ladisch "); @@ -168,6 +169,20 @@ static void read_tempreg_nb_zen(struct pci_dev *pdev, u32 *regval) *regval = 0; } +static void read_tempreg_nb_hygon(struct pci_dev *pdev, u32 *regval) +{ + if (hygon_smn_read(hygon_pci_dev_to_node_id(pdev), + ZEN_REPORTED_TEMP_CTRL_BASE, regval)) + *regval = 0; +} + +static int read_hygon_ccd_temp_reg(struct k10temp_data *data, int ccd, u32 *regval) +{ + u16 node_id = hygon_pci_dev_to_node_id(data->pdev); + + return hygon_smn_read(node_id, ZEN_CCD_TEMP(data->ccd_offset, ccd), regval); +} + static long get_raw_temp(struct k10temp_data *data) { u32 regval; @@ -211,21 +226,21 @@ static int k10temp_read_labels(struct device *dev, return 0; } -static void hygon_read_temp(struct k10temp_data *data, int channel, +static int hygon_read_temp(struct k10temp_data *data, int channel, u32 *regval) { struct hygon_private *h_priv; h_priv = (struct hygon_private *)data->priv; if ((channel - 2) < h_priv->index_2nd) - amd_smn_read(amd_pci_dev_to_node_id(data->pdev), - ZEN_CCD_TEMP(data->ccd_offset, channel - 2), - regval); + return hygon_smn_read(hygon_pci_dev_to_node_id(data->pdev), + ZEN_CCD_TEMP(data->ccd_offset, channel - 2), + regval); else - amd_smn_read(amd_pci_dev_to_node_id(data->pdev), - ZEN_CCD_TEMP(h_priv->offset_2nd, - channel - 2 - h_priv->index_2nd), - regval); + return hygon_smn_read(hygon_pci_dev_to_node_id(data->pdev), + ZEN_CCD_TEMP(h_priv->offset_2nd, + channel - 2 - h_priv->index_2nd), + regval); } static int k10temp_read_temp(struct device *dev, u32 attr, int channel, @@ -250,7 +265,9 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel, break; case 2 ... 13: /* Tccd{1-12} */ if (hygon_f18h_m4h()) { - hygon_read_temp(data, channel, ®val); + ret = hygon_read_temp(data, channel, ®val); + if (ret) + return ret; } else { ret = amd_smn_read(amd_pci_dev_to_node_id(data->pdev), ZEN_CCD_TEMP(data->ccd_offset, channel - 2), @@ -426,9 +443,15 @@ static void k10temp_get_ccd_support(struct pci_dev *pdev, * the register value. And this will incorrectly pass the TEMP_VALID * bit check. */ - if (amd_smn_read(amd_pci_dev_to_node_id(pdev), - ZEN_CCD_TEMP(data->ccd_offset, i), ®val)) - continue; + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON && + boot_cpu_data.x86 == 0x18) { + if (read_hygon_ccd_temp_reg(data, i, ®val)) + continue; + } else { + if (amd_smn_read(amd_pci_dev_to_node_id(pdev), + ZEN_CCD_TEMP(data->ccd_offset, i), ®val)) + continue; + } if (regval & ZEN_CCD_TEMP_VALID) data->show_temp |= BIT(TCCD_BIT(i)); @@ -444,10 +467,11 @@ static void k10temp_get_ccd_support_2nd(struct pci_dev *pdev, h_priv = (struct hygon_private *)data->priv; for (i = h_priv->index_2nd; i < limit; i++) { - amd_smn_read(amd_pci_dev_to_node_id(pdev), - ZEN_CCD_TEMP(h_priv->offset_2nd, - i - h_priv->index_2nd), - ®val); + if(hygon_smn_read(hygon_pci_dev_to_node_id(pdev), + ZEN_CCD_TEMP(h_priv->offset_2nd, + i - h_priv->index_2nd), + ®val)) + continue; if (regval & ZEN_CCD_TEMP_VALID) data->show_temp |= BIT(TCCD_BIT(i)); } @@ -523,7 +547,7 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON && boot_cpu_data.x86 == 0x18) { data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK; - data->read_tempreg = read_tempreg_nb_zen; + data->read_tempreg = read_tempreg_nb_hygon; data->is_zen = true; switch (boot_cpu_data.x86_model) { @@ -614,7 +638,7 @@ static const struct pci_device_id k10temp_id_table[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M50H_DF_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M90H_DF_F3) }, { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) }, - { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) }, + { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F3) }, { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) }, { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F3) }, { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_DF_F3) }, -- Gitee From 85e98e356f6f2cda18f8a2f590daca05880eb8ea Mon Sep 17 00:00:00 2001 From: Wenhui Fan Date: Wed, 2 Sep 2026 20:28:08 +0800 Subject: [PATCH 3/5] anolis:EDAC/amd64:Update the SMN and nb interface used by Hygon processors in EDAC ANBZ: #45106 Separate some Hygon EDAC function from AMD EDAC function because there are many interface changed. Hygon-SIG: commit none hygon anolis:EDAC/amd64:Update the SMN and nb interface used by Hygon processors in EDAC Signed-off-by: Wenhui Fan --- drivers/edac/amd64_edac.c | 146 ++++++++++++++++++++++++++++++++------ 1 file changed, 124 insertions(+), 22 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 7f7aaa2af189..d54c78416780 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3,6 +3,7 @@ #include "amd64_edac.h" #include #include +#include static struct edac_pci_ctl_info *pci_ctl; @@ -99,7 +100,7 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset, static u32 get_umc_base_f18h_m4h(u16 node, u8 channel) { - struct pci_dev *f3 = node_to_amd_nb(node)->misc; + struct pci_dev *f3 = node_to_hygon_nb(node)->misc; u8 df_id; get_df_id(f3, &df_id); @@ -753,10 +754,10 @@ static int __df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *l u32 ficaa; int err = -ENODEV; - if (node >= amd_nb_num()) + if (node >= hygon_nb_num()) goto out; - F4 = node_to_amd_nb(node)->link; + F4 = node_to_hygon_nb(node)->link; if (!F4) goto out; @@ -1507,7 +1508,7 @@ static void umc_prep_chip_selects(struct amd64_pvt *pvt) } } -static void umc_read_base_mask(struct amd64_pvt *pvt) +static void hygon_umc_read_base_mask(struct amd64_pvt *pvt) { u32 umc_base_reg, umc_base_reg_sec; u32 umc_mask_reg, umc_mask_reg_sec; @@ -1523,10 +1524,70 @@ static void umc_read_base_mask(struct amd64_pvt *pvt) if (!hygon_umc_channel_enabled(pvt, umc)) continue; - if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) - umc_base = hygon_get_umc_base(pvt, umc); - else - umc_base = get_umc_base(umc); + umc_base = hygon_get_umc_base(pvt, 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]; + base_sec = &pvt->csels[umc].csbases_sec[cs]; + + base_reg = umc_base_reg + (cs * 4); + base_reg_sec = umc_base_reg_sec + (cs * 4); + + if (!hygon_smn_read(pvt->mc_node_id, base_reg, &tmp)) { + *base = tmp; + edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *base, base_reg); + } + + if (!hygon_smn_read(pvt->mc_node_id, base_reg_sec, &tmp)) { + *base_sec = tmp; + edac_dbg(0, " DCSB_SEC%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *base_sec, base_reg_sec); + } + } + + umc_mask_reg = umc_base + UMCCH_ADDR_MASK; + umc_mask_reg_sec = umc_base + UMCCH_ADDR_MASK_SEC; + + for_each_chip_select_mask(cs, umc, pvt) { + mask = &pvt->csels[umc].csmasks[cs]; + mask_sec = &pvt->csels[umc].csmasks_sec[cs]; + + mask_reg = umc_mask_reg + (cs * 4); + mask_reg_sec = umc_mask_reg_sec + (cs * 4); + + if (!hygon_smn_read(pvt->mc_node_id, mask_reg, &tmp)) { + *mask = tmp; + edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *mask, mask_reg); + } + + if (!hygon_smn_read(pvt->mc_node_id, mask_reg_sec, &tmp)) { + *mask_sec = tmp; + edac_dbg(0, " DCSM_SEC%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *mask_sec, mask_reg_sec); + } + } + } +} + +static void umc_read_base_mask(struct amd64_pvt *pvt) +{ + u32 umc_base_reg, umc_base_reg_sec; + u32 umc_mask_reg, umc_mask_reg_sec; + u32 base_reg, base_reg_sec; + u32 mask_reg, mask_reg_sec; + u32 *base, *base_sec; + u32 *mask, *mask_sec; + u32 umc_base; + int cs, umc; + u32 tmp; + + for_each_umc(umc) { + umc_base = get_umc_base(umc); umc_base_reg = umc_base + UMCCH_BASE_ADDR; umc_base_reg_sec = umc_base + UMCCH_BASE_ADDR_SEC; @@ -3011,6 +3072,38 @@ static void determine_ecc_sym_sz(struct amd64_pvt *pvt) } } +static void hygon_umc_read_mc_regs(struct amd64_pvt *pvt) +{ + u8 nid = pvt->mc_node_id; + struct amd64_umc *umc; + u32 i, tmp, umc_base; + + /* Read registers from each UMC */ + for_each_umc(i) { + if (!hygon_umc_channel_enabled(pvt, i)) + continue; + + umc_base = hygon_get_umc_base(pvt, i); + + umc = &pvt->umc[i]; + + if (!hygon_smn_read(nid, umc_base + UMCCH_DIMM_CFG, &tmp)) + umc->dimm_cfg = tmp; + + if (!hygon_smn_read(nid, umc_base + UMCCH_UMC_CFG, &tmp)) + umc->umc_cfg = tmp; + + if (!hygon_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &tmp)) + umc->sdp_ctrl = tmp; + + if (!hygon_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &tmp)) + umc->ecc_ctrl = tmp; + + if (!hygon_smn_read(nid, umc_base + UMCCH_UMC_CAP_HI, &tmp)) + umc->umc_cap_hi = tmp; + } +} + /* * Retrieve the hardware registers of the memory controller. */ @@ -3022,13 +3115,7 @@ static void umc_read_mc_regs(struct amd64_pvt *pvt) /* Read registers from each UMC */ for_each_umc(i) { - if (!hygon_umc_channel_enabled(pvt, i)) - continue; - - if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) - umc_base = hygon_get_umc_base(pvt, i); - else - umc_base = get_umc_base(i); + umc_base = get_umc_base(i); umc = &pvt->umc[i]; @@ -3612,8 +3699,14 @@ static int umc_hw_info_get(struct amd64_pvt *pvt) return -ENOMEM; umc_prep_chip_selects(pvt); - umc_read_base_mask(pvt); - umc_read_mc_regs(pvt); + + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { + hygon_umc_read_base_mask(pvt); + hygon_umc_read_mc_regs(pvt); + } else { + umc_read_base_mask(pvt); + umc_read_mc_regs(pvt); + } umc_determine_memory_type(pvt); return 0; @@ -4148,7 +4241,7 @@ static bool instance_has_memory(struct amd64_pvt *pvt) static int probe_one_instance(unsigned int nid) { - struct pci_dev *F3 = node_to_amd_nb(nid)->misc; + struct pci_dev *F3; struct amd64_pvt *pvt = NULL; struct ecc_settings *s; int ret; @@ -4165,6 +4258,10 @@ static int probe_one_instance(unsigned int nid) goto err_settings; pvt->mc_node_id = nid; + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) + F3 = node_to_hygon_nb(nid)->misc; + else + F3 = node_to_amd_nb(nid)->misc; pvt->F3 = F3; ret = per_family_init(pvt); @@ -4228,11 +4325,16 @@ static int probe_one_instance(unsigned int nid) static void remove_one_instance(unsigned int nid) { - struct pci_dev *F3 = node_to_amd_nb(nid)->misc; + struct pci_dev *F3; struct ecc_settings *s = ecc_stngs[nid]; struct mem_ctl_info *mci; struct amd64_pvt *pvt; + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) + F3 = node_to_hygon_nb(nid)->misc; + else + F3 = node_to_amd_nb(nid)->misc; + /* Remove from EDAC CORE tracking list */ mci = edac_mc_del_mc(&F3->dev); if (!mci) @@ -4292,13 +4394,13 @@ static int __init amd64_edac_init(void) if (!x86_match_cpu(amd64_cpuids)) return -ENODEV; - if (!amd_nb_num()) + if (!amd_nb_num() && !hygon_node_num()) return -ENODEV; opstate_init(); if (hygon_f18h_m4h()) - instance_num = hygon_nb_num(); + instance_num = hygon_node_num(); else instance_num = amd_nb_num(); @@ -4369,7 +4471,7 @@ static void __exit amd64_edac_exit(void) amd_unregister_ecc_decoder(decode_bus_error); if (hygon_f18h_m4h()) - instance_num = hygon_nb_num(); + instance_num = hygon_node_num(); else instance_num = amd_nb_num(); -- Gitee From 261021c56799ed3ea37fcbd25555d0d8c736c787 Mon Sep 17 00:00:00 2001 From: Wenhui Fan Date: Wed, 9 Sep 2026 20:19:51 +0800 Subject: [PATCH 4/5] anolis: x86/hygon_nb: Add support for Hygon family 18h model 10h ANBZ: #45106 Add root and DF F1/F3/F4 device IDs for Hygon family 18h model 10h processors. Hygon-SIG: commit none hygon anolis: x86/hygon_nb: Add support for Hygon family 18h model 10h Signed-off-by: Wenhui Fan --- arch/x86/kernel/hygon_nb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/hygon_nb.c b/arch/x86/kernel/hygon_nb.c index f37b2e035902..ebd82b0a5351 100644 --- a/arch/x86/kernel/hygon_nb.c +++ b/arch/x86/kernel/hygon_nb.c @@ -16,14 +16,16 @@ #include #define PCI_DEVICE_ID_HYGON_18H_ROOT 0x1450 -#define PCI_DEVICE_ID_HYGON_18H_M05H_ROOT 0x14a0 #define PCI_DEVICE_ID_HYGON_18H_M04H_ROOT 0x1480 +#define PCI_DEVICE_ID_HYGON_18H_M05H_ROOT 0x14a0 +#define PCI_DEVICE_ID_HYGON_18H_M10H_ROOT 0x14c0 #define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1 0x1491 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1 0x14b1 #define PCI_DEVICE_ID_HYGON_18H_DF_F4 0x1464 #define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F4 0x1494 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4 0x14b4 +#define PCI_DEVICE_ID_HYGON_18H_M10H_DF_F4 0x14d4 #define PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5 0x14b5 static u16 node_num; @@ -37,6 +39,7 @@ static const struct pci_device_id hygon_root_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_ROOT) }, {} }; @@ -44,6 +47,7 @@ static const struct pci_device_id hygon_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F3) }, {} }; @@ -51,6 +55,7 @@ static const struct pci_device_id hygon_nb_link_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F4) }, {} }; -- Gitee From bf36cb91b3f257f670548a3a298caf81bba14d2a Mon Sep 17 00:00:00 2001 From: Wenhui Fan Date: Thu, 10 Sep 2026 11:19:28 +0800 Subject: [PATCH 5/5] anolis: x86/amd_nb: Add Hygon family 18h model 18h PCI IDs ANBZ: #45106 Add the PCI device IDs for Hygon family 18h model 18h processors. Hygon-SIG: commit none hygon anolis: x86/amd_nb: Add Hygon family 18h model 18h PCI IDs Signed-off-by: Wenhui Fan --- arch/x86/kernel/hygon_nb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/hygon_nb.c b/arch/x86/kernel/hygon_nb.c index ebd82b0a5351..fcb386e1eff8 100644 --- a/arch/x86/kernel/hygon_nb.c +++ b/arch/x86/kernel/hygon_nb.c @@ -19,6 +19,7 @@ #define PCI_DEVICE_ID_HYGON_18H_M04H_ROOT 0x1480 #define PCI_DEVICE_ID_HYGON_18H_M05H_ROOT 0x14a0 #define PCI_DEVICE_ID_HYGON_18H_M10H_ROOT 0x14c0 +#define PCI_DEVICE_ID_HYGON_18H_M18H_ROOT 0x2000 #define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1 0x1491 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1 0x14b1 @@ -26,6 +27,7 @@ #define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F4 0x1494 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4 0x14b4 #define PCI_DEVICE_ID_HYGON_18H_M10H_DF_F4 0x14d4 +#define PCI_DEVICE_ID_HYGON_18H_M18H_DF_F4 0x2014 #define PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5 0x14b5 static u16 node_num; @@ -40,6 +42,7 @@ static const struct pci_device_id hygon_root_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_ROOT) }, {} }; @@ -48,6 +51,7 @@ static const struct pci_device_id hygon_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_DF_F3) }, {} }; @@ -56,6 +60,7 @@ static const struct pci_device_id hygon_nb_link_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M04H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M10H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_HYGON_18H_M18H_DF_F4) }, {} }; -- Gitee