^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/topology.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/range.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/amd_nb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/pci_x86.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/pci-direct.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "bus_numa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define AMD_NB_F0_NODE_ID 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define AMD_NB_F0_UNIT_ID 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define AMD_NB_F1_CONFIG_MAP_REG 0xe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define RANGE_NUM 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define AMD_NB_F1_CONFIG_MAP_RANGES 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct amd_hostbridge {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) u32 bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u32 device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * IMPORTANT NOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * hb_probes[] and early_root_info_init() is in maintenance mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * It only supports K8, Fam10h, Fam11h, and Fam15h_00h-0fh .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Future processor will rely on information in ACPI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static struct amd_hostbridge hb_probes[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) { 0, 0x18, 0x1100 }, /* K8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { 0, 0x18, 0x1200 }, /* Family10h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) { 0xff, 0, 0x1200 }, /* Family10h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { 0, 0x18, 0x1300 }, /* Family11h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { 0, 0x18, 0x1600 }, /* Family15h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static struct pci_root_info __init *find_pci_root_info(int node, int link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct pci_root_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* find the position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) list_for_each_entry(info, &pci_root_infos, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (info->node == node && info->link == link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * early_root_info_init()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * called before pcibios_scan_root and pci_scan_bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * fills the mp_bus_to_cpumask array based according
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * to the LDT Bus Number Registers found in the northbridge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int __init early_root_info_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int def_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int def_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct pci_root_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u64 end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct range range[RANGE_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) bool found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct resource fam10h_mmconf_res, *fam10h_mmconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u64 fam10h_mmconf_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u64 fam10h_mmconf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!early_pci_allowed())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) for (i = 0; i < ARRAY_SIZE(hb_probes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u16 device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u16 vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bus = hb_probes[i].bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) slot = hb_probes[i].slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) vendor = id & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) device = (id>>16) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (vendor != PCI_VENDOR_ID_AMD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) vendor != PCI_VENDOR_ID_HYGON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (hb_probes[i].device == device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * We should learn topology and routing information from _PXM and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * _CRS methods in the ACPI namespace. We extract node numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * here to work around BIOSes that don't supply _PXM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) for (i = 0; i < AMD_NB_F1_CONFIG_MAP_RANGES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int min_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int max_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) reg = read_pci_config(bus, slot, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) AMD_NB_F1_CONFIG_MAP_REG + (i << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Check if that register is enabled for bus range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if ((reg & 7) != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) min_bus = (reg >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) max_bus = (reg >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) node = (reg >> 4) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) link = (reg >> 8) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) info = alloc_pci_root_info(min_bus, max_bus, node, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * The following code extracts routing information for use on old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * systems where Linux doesn't automatically use host bridge _CRS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * methods (or when the user specifies "pci=nocrs").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * We only do this through Fam11h, because _CRS should be enough on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * newer systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (boot_cpu_data.x86 > 0x11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* get the default node and link for left over res */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) reg = read_pci_config(bus, slot, 0, AMD_NB_F0_NODE_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) def_node = (reg >> 8) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) reg = read_pci_config(bus, slot, 0, AMD_NB_F0_UNIT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) def_link = (reg >> 8) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) memset(range, 0, sizeof(range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) add_range(range, RANGE_NUM, 0, 0, 0xffff + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* io port resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!(reg & 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) start = reg & 0xfff000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) node = reg & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) link = (reg >> 4) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) end = (reg & 0xfff000) | 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) info = find_pci_root_info(node, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) continue; /* not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) node, link, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* kernel only handle 16 bit only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (end > 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) end = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) update_res(info, start, end, IORESOURCE_IO, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) subtract_range(range, RANGE_NUM, start, end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* add left over io port range to def node/link, [0, 0xffff] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* find the position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) info = find_pci_root_info(def_node, def_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) for (i = 0; i < RANGE_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (!range[i].end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) update_res(info, range[i].start, range[i].end - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) IORESOURCE_IO, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) memset(range, 0, sizeof(range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* 0xfd00000000-0xffffffffff for HT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) end = cap_resource((0xfdULL<<32) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) end++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) add_range(range, RANGE_NUM, 0, 0, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* need to take out [0, TOM) for RAM*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) address = MSR_K8_TOP_MEM1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) rdmsrl(address, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) end = (val & 0xffffff800000ULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printk(KERN_INFO "TOM: %016llx aka %lldM\n", end, end>>20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (end < (1ULL<<32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) subtract_range(range, RANGE_NUM, 0, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* get mmconfig */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) fam10h_mmconf = amd_get_mmconfig_range(&fam10h_mmconf_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* need to take out mmconf range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (fam10h_mmconf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) printk(KERN_DEBUG "Fam 10h mmconf %pR\n", fam10h_mmconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) fam10h_mmconf_start = fam10h_mmconf->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) fam10h_mmconf_end = fam10h_mmconf->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) subtract_range(range, RANGE_NUM, fam10h_mmconf_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) fam10h_mmconf_end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) fam10h_mmconf_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) fam10h_mmconf_end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* mmio resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!(reg & 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) start = reg & 0xffffff00; /* 39:16 on 31:8*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) start <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) node = reg & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) link = (reg >> 4) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) end = (reg & 0xffffff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) end <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) end |= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) info = find_pci_root_info(node, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) node, link, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * some sick allocation would have range overlap with fam10h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * mmconf range, so need to update start and end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (fam10h_mmconf_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u64 endx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (start >= fam10h_mmconf_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) start <= fam10h_mmconf_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) start = fam10h_mmconf_end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (end >= fam10h_mmconf_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) end <= fam10h_mmconf_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) end = fam10h_mmconf_start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (start < fam10h_mmconf_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) end > fam10h_mmconf_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* we got a hole */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) endx = fam10h_mmconf_start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) update_res(info, start, endx, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) subtract_range(range, RANGE_NUM, start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) endx + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) printk(KERN_CONT " ==> [%llx, %llx]", start, endx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) start = fam10h_mmconf_end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (start <= end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) printk(KERN_CONT " %s [%llx, %llx]", endx ? "and" : "==>", start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) printk(KERN_CONT "%s\n", endx?"":" ==> none");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) update_res(info, cap_resource(start), cap_resource(end),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) subtract_range(range, RANGE_NUM, start, end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) printk(KERN_CONT "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* need to take out [4G, TOM2) for RAM*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* SYS_CFG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) address = MSR_K8_SYSCFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) rdmsrl(address, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* TOP_MEM2 is enabled? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (val & (1<<21)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* TOP_MEM2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) address = MSR_K8_TOP_MEM2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) rdmsrl(address, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) end = (val & 0xffffff800000ULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) printk(KERN_INFO "TOM2: %016llx aka %lldM\n", end, end>>20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) subtract_range(range, RANGE_NUM, 1ULL<<32, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * add left over mmio range to def node/link ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * that is tricky, just record range in from start_min to 4G
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) info = find_pci_root_info(def_node, def_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) for (i = 0; i < RANGE_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!range[i].end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) update_res(info, cap_resource(range[i].start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) cap_resource(range[i].end - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) list_for_each_entry(info, &pci_root_infos, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int busnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct pci_root_res *root_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) busnum = info->busn.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) printk(KERN_DEBUG "bus: %pR on node %x link %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) &info->busn, info->node, info->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) list_for_each_entry(root_res, &info->resources, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) printk(KERN_DEBUG "bus: %02x %pR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) busnum, &root_res->res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #define ENABLE_CF8_EXT_CFG (1ULL << 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int amd_bus_cpu_online(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u64 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) rdmsrl(MSR_AMD64_NB_CFG, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!(reg & ENABLE_CF8_EXT_CFG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) reg |= ENABLE_CF8_EXT_CFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) wrmsrl(MSR_AMD64_NB_CFG, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static void __init pci_enable_pci_io_ecs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) #ifdef CONFIG_AMD_NB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) unsigned int i, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) for (n = i = 0; !n && amd_nb_bus_dev_ranges[i].dev_limit; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) u8 bus = amd_nb_bus_dev_ranges[i].bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) u8 slot = amd_nb_bus_dev_ranges[i].dev_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) u8 limit = amd_nb_bus_dev_ranges[i].dev_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) for (; slot < limit; ++slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u32 val = read_pci_config(bus, slot, 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (!early_is_amd_nb(val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) val = read_pci_config(bus, slot, 3, 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (!(val & (ENABLE_CF8_EXT_CFG >> 32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) val |= ENABLE_CF8_EXT_CFG >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) write_pci_config(bus, slot, 3, 0x8c, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ++n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static int __init pci_io_ecs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* assume all cpus from fam10h have IO ECS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (boot_cpu_data.x86 < 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* Try the PCI method first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (early_pci_allowed())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pci_enable_pci_io_ecs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/amd_bus:online",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) amd_bus_cpu_online, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) WARN_ON(ret < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pci_probe |= PCI_HAS_IO_ECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int __init amd_postcore_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) early_root_info_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) pci_io_ecs_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) postcore_initcall(amd_postcore_init);