.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Shared support code for AMD K8 northbridges and derivates. |
---|
3 | | - * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2. |
---|
| 4 | + * Copyright 2006 Andi Kleen, SUSE Labs. |
---|
4 | 5 | */ |
---|
5 | 6 | |
---|
6 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
17 | 18 | #define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450 |
---|
18 | 19 | #define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0 |
---|
19 | 20 | #define PCI_DEVICE_ID_AMD_17H_M30H_ROOT 0x1480 |
---|
| 21 | +#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT 0x1630 |
---|
20 | 22 | #define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 |
---|
21 | 23 | #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec |
---|
22 | 24 | #define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494 |
---|
| 25 | +#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c |
---|
23 | 26 | #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444 |
---|
24 | 27 | #define PCI_DEVICE_ID_AMD_19H_DF_F4 0x1654 |
---|
25 | 28 | |
---|
.. | .. |
---|
32 | 35 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) }, |
---|
33 | 36 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) }, |
---|
34 | 37 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_ROOT) }, |
---|
| 38 | + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_ROOT) }, |
---|
35 | 39 | {} |
---|
36 | 40 | }; |
---|
37 | 41 | |
---|
38 | | - |
---|
39 | 42 | #define PCI_DEVICE_ID_AMD_CNB17H_F4 0x1704 |
---|
40 | 43 | |
---|
41 | | -const struct pci_device_id amd_nb_misc_ids[] = { |
---|
| 44 | +static const struct pci_device_id amd_nb_misc_ids[] = { |
---|
42 | 45 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, |
---|
43 | 46 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, |
---|
44 | 47 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, |
---|
.. | .. |
---|
50 | 53 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, |
---|
51 | 54 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) }, |
---|
52 | 55 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) }, |
---|
| 56 | + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) }, |
---|
53 | 57 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, |
---|
54 | 58 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) }, |
---|
55 | 59 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) }, |
---|
56 | 60 | {} |
---|
57 | 61 | }; |
---|
58 | | -EXPORT_SYMBOL_GPL(amd_nb_misc_ids); |
---|
59 | 62 | |
---|
60 | 63 | static const struct pci_device_id amd_nb_link_ids[] = { |
---|
61 | 64 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, |
---|
.. | .. |
---|
66 | 69 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) }, |
---|
67 | 70 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F4) }, |
---|
68 | 71 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F4) }, |
---|
| 72 | + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F4) }, |
---|
69 | 73 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F4) }, |
---|
70 | 74 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F4) }, |
---|
71 | 75 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, |
---|
| 76 | + {} |
---|
| 77 | +}; |
---|
| 78 | + |
---|
| 79 | +static const struct pci_device_id hygon_root_ids[] = { |
---|
| 80 | + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_ROOT) }, |
---|
| 81 | + {} |
---|
| 82 | +}; |
---|
| 83 | + |
---|
| 84 | +static const struct pci_device_id hygon_nb_misc_ids[] = { |
---|
| 85 | + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) }, |
---|
| 86 | + {} |
---|
| 87 | +}; |
---|
| 88 | + |
---|
| 89 | +static const struct pci_device_id hygon_nb_link_ids[] = { |
---|
| 90 | + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F4) }, |
---|
72 | 91 | {} |
---|
73 | 92 | }; |
---|
74 | 93 | |
---|
.. | .. |
---|
205 | 224 | |
---|
206 | 225 | int amd_cache_northbridges(void) |
---|
207 | 226 | { |
---|
208 | | - u16 i = 0; |
---|
209 | | - struct amd_northbridge *nb; |
---|
| 227 | + const struct pci_device_id *misc_ids = amd_nb_misc_ids; |
---|
| 228 | + const struct pci_device_id *link_ids = amd_nb_link_ids; |
---|
| 229 | + const struct pci_device_id *root_ids = amd_root_ids; |
---|
210 | 230 | struct pci_dev *root, *misc, *link; |
---|
| 231 | + struct amd_northbridge *nb; |
---|
| 232 | + u16 roots_per_misc = 0; |
---|
| 233 | + u16 misc_count = 0; |
---|
| 234 | + u16 root_count = 0; |
---|
| 235 | + u16 i, j; |
---|
211 | 236 | |
---|
212 | 237 | if (amd_northbridges.num) |
---|
213 | 238 | return 0; |
---|
214 | 239 | |
---|
215 | | - misc = NULL; |
---|
216 | | - while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL) |
---|
217 | | - i++; |
---|
| 240 | + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { |
---|
| 241 | + root_ids = hygon_root_ids; |
---|
| 242 | + misc_ids = hygon_nb_misc_ids; |
---|
| 243 | + link_ids = hygon_nb_link_ids; |
---|
| 244 | + } |
---|
218 | 245 | |
---|
219 | | - if (!i) |
---|
| 246 | + misc = NULL; |
---|
| 247 | + while ((misc = next_northbridge(misc, misc_ids)) != NULL) |
---|
| 248 | + misc_count++; |
---|
| 249 | + |
---|
| 250 | + if (!misc_count) |
---|
220 | 251 | return -ENODEV; |
---|
221 | 252 | |
---|
222 | | - nb = kcalloc(i, sizeof(struct amd_northbridge), GFP_KERNEL); |
---|
| 253 | + root = NULL; |
---|
| 254 | + while ((root = next_northbridge(root, root_ids)) != NULL) |
---|
| 255 | + root_count++; |
---|
| 256 | + |
---|
| 257 | + if (root_count) { |
---|
| 258 | + roots_per_misc = root_count / misc_count; |
---|
| 259 | + |
---|
| 260 | + /* |
---|
| 261 | + * There should be _exactly_ N roots for each DF/SMN |
---|
| 262 | + * interface. |
---|
| 263 | + */ |
---|
| 264 | + if (!roots_per_misc || (root_count % roots_per_misc)) { |
---|
| 265 | + pr_info("Unsupported AMD DF/PCI configuration found\n"); |
---|
| 266 | + return -ENODEV; |
---|
| 267 | + } |
---|
| 268 | + } |
---|
| 269 | + |
---|
| 270 | + nb = kcalloc(misc_count, sizeof(struct amd_northbridge), GFP_KERNEL); |
---|
223 | 271 | if (!nb) |
---|
224 | 272 | return -ENOMEM; |
---|
225 | 273 | |
---|
226 | 274 | amd_northbridges.nb = nb; |
---|
227 | | - amd_northbridges.num = i; |
---|
| 275 | + amd_northbridges.num = misc_count; |
---|
228 | 276 | |
---|
229 | 277 | link = misc = root = NULL; |
---|
230 | | - for (i = 0; i != amd_northbridges.num; i++) { |
---|
| 278 | + for (i = 0; i < amd_northbridges.num; i++) { |
---|
231 | 279 | node_to_amd_nb(i)->root = root = |
---|
232 | | - next_northbridge(root, amd_root_ids); |
---|
| 280 | + next_northbridge(root, root_ids); |
---|
233 | 281 | node_to_amd_nb(i)->misc = misc = |
---|
234 | | - next_northbridge(misc, amd_nb_misc_ids); |
---|
| 282 | + next_northbridge(misc, misc_ids); |
---|
235 | 283 | node_to_amd_nb(i)->link = link = |
---|
236 | | - next_northbridge(link, amd_nb_link_ids); |
---|
| 284 | + next_northbridge(link, link_ids); |
---|
| 285 | + |
---|
| 286 | + /* |
---|
| 287 | + * If there are more PCI root devices than data fabric/ |
---|
| 288 | + * system management network interfaces, then the (N) |
---|
| 289 | + * PCI roots per DF/SMN interface are functionally the |
---|
| 290 | + * same (for DF/SMN access) and N-1 are redundant. N-1 |
---|
| 291 | + * PCI roots should be skipped per DF/SMN interface so |
---|
| 292 | + * the following DF/SMN interfaces get mapped to |
---|
| 293 | + * correct PCI roots. |
---|
| 294 | + */ |
---|
| 295 | + for (j = 1; j < roots_per_misc; j++) |
---|
| 296 | + root = next_northbridge(root, root_ids); |
---|
237 | 297 | } |
---|
238 | 298 | |
---|
239 | 299 | if (amd_gart_present()) |
---|
.. | .. |
---|
272 | 332 | */ |
---|
273 | 333 | bool __init early_is_amd_nb(u32 device) |
---|
274 | 334 | { |
---|
| 335 | + const struct pci_device_id *misc_ids = amd_nb_misc_ids; |
---|
275 | 336 | const struct pci_device_id *id; |
---|
276 | 337 | u32 vendor = device & 0xffff; |
---|
277 | 338 | |
---|
| 339 | + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && |
---|
| 340 | + boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) |
---|
| 341 | + return false; |
---|
| 342 | + |
---|
| 343 | + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) |
---|
| 344 | + misc_ids = hygon_nb_misc_ids; |
---|
| 345 | + |
---|
278 | 346 | device >>= 16; |
---|
279 | | - for (id = amd_nb_misc_ids; id->vendor; id++) |
---|
| 347 | + for (id = misc_ids; id->vendor; id++) |
---|
280 | 348 | if (vendor == id->vendor && device == id->device) |
---|
281 | 349 | return true; |
---|
282 | 350 | return false; |
---|
.. | .. |
---|
288 | 356 | u64 base, msr; |
---|
289 | 357 | unsigned int segn_busn_bits; |
---|
290 | 358 | |
---|
291 | | - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) |
---|
| 359 | + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && |
---|
| 360 | + boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) |
---|
292 | 361 | return NULL; |
---|
293 | 362 | |
---|
294 | 363 | /* assume all cpus from fam10h have mmconfig */ |
---|