northbridge.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <acpi/acpi.h> 4 #include <acpi/acpigen.h> 5 #include <boot/tables.h> 6 #include <cbmem.h> 7 #include <commonlib/helpers.h> 8 #include <console/console.h> 9 #include <cpu/cpu.h> 10 #include <cpu/intel/speedstep.h> 11 #include <cpu/intel/smm_reloc.h> 12 #include <cpu/x86/smm.h> 13 #include <device/device.h> 14 #include <device/pci_def.h> 15 #include <device/pci_ops.h> 16 #include <static.h> 17 #include <stdint.h> 18 19 #include "chip.h" 20 #include "gm45.h" 21 22 static uint64_t get_touud(void) 23 { 24 uint64_t touud = pci_read_config16(__pci_0_00_0, D0F0_TOUUD); 25 touud <<= 20; 26 return touud; 27 } 28 29 static void mch_domain_read_resources(struct device *dev) 30 { 31 u64 tom, touud; 32 u32 tolud; 33 int idx = 3; 34 35 /* Total Memory 2GB example: 36 * 37 * 00000000 0000MB-2014MB 2014MB RAM (writeback) 38 * 7de00000 2014MB-2016MB 2MB GFX GTT (uncached) 39 * 7e000000 2016MB-2048MB 32MB GFX UMA (uncached) 40 * 80000000 2048MB TOLUD 41 * 80000000 2048MB TOM 42 * 43 * Total Memory 4GB example: 44 * 45 * 00000000 0000MB-3038MB 3038MB RAM (writeback) 46 * bde00000 3038MB-3040MB 2MB GFX GTT (uncached) 47 * be000000 3040MB-3072MB 32MB GFX UMA (uncached) 48 * be000000 3072MB TOLUD 49 * 100000000 4096MB TOM 50 * 100000000 4096MB-5120MB 1024MB RAM (writeback) 51 * 140000000 5120MB TOUUD 52 */ 53 54 pci_domain_read_resources(dev); 55 56 struct device *mch = pcidev_on_root(0, 0); 57 58 /* Top of Upper Usable DRAM, including remap */ 59 touud = get_touud(); 60 61 /* Top of Lower Usable DRAM */ 62 tolud = pci_read_config16(mch, D0F0_TOLUD) & 0xfff0; 63 tolud <<= 16; 64 65 /* Top of Memory - does not account for any UMA */ 66 tom = pci_read_config16(mch, D0F0_TOM) & 0x1ff; 67 tom <<= 27; 68 69 printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx\n", 70 touud, tolud, tom); 71 72 /* Report lowest memory region */ 73 ram_range(dev, idx++, 0, 0xa0000); 74 75 /* 76 * Reserve everything between A segment and 1MB: 77 * 78 * 0xa0000 - 0xbffff: Legacy VGA 79 * 0xc0000 - 0xfffff: RAM 80 */ 81 mmio_from_to(dev, idx++, 0xa0000, 0xc0000); 82 reserved_ram_from_to(dev, idx++, 0xc0000, 1*MiB); 83 84 /* Report < 4GB memory */ 85 ram_range(dev, idx++, 1*MiB, cbmem_top()); 86 87 /* TSEG */ 88 uintptr_t tseg_base; 89 size_t tseg_size; 90 smm_region(&tseg_base, &tseg_size); 91 mmio_range(dev, idx++, tseg_base, tseg_size); 92 93 /* cbmem_top can be shifted downwards due to alignment. 94 Mark the region between cbmem_top and tseg_base as unusable */ 95 if (cbmem_top() < tseg_base) { 96 printk(BIOS_DEBUG, "Unused RAM between cbmem_top and TOM: 0x%lx\n", 97 tseg_base - cbmem_top()); 98 mmio_from_to(dev, idx++, cbmem_top(), tseg_base); 99 } 100 101 /* graphic memory above TSEG */ 102 if (tseg_base + tseg_size < tolud) 103 mmio_from_to(dev, idx++, tseg_base + tseg_size, tolud); 104 105 /* 106 * If >= 4GB installed then memory from TOLUD to 4GB 107 * is remapped above TOM, TOUUD will account for both 108 */ 109 upper_ram_end(dev, idx++, touud); 110 111 mmconf_resource(dev, idx++); 112 } 113 114 static void mch_domain_set_resources(struct device *dev) 115 { 116 struct resource *resource; 117 int i; 118 119 for (i = 3; i <= 9; ++i) { 120 /* Report read resources. */ 121 resource = probe_resource(dev, i); 122 if (resource) 123 report_resource_stored(dev, resource, ""); 124 } 125 126 assign_resources(dev->downstream); 127 } 128 129 static void mch_domain_init(struct device *dev) 130 { 131 struct device *mch = pcidev_on_root(0, 0); 132 133 /* Enable SERR */ 134 pci_or_config16(mch, PCI_COMMAND, PCI_COMMAND_SERR); 135 } 136 137 static const char *northbridge_acpi_name(const struct device *dev) 138 { 139 if (dev->path.type == DEVICE_PATH_DOMAIN) 140 return "PCI0"; 141 142 if (!is_pci_dev_on_bus(dev, 0)) 143 return NULL; 144 145 switch (dev->path.pci.devfn) { 146 case PCI_DEVFN(0, 0): 147 return "MCHC"; 148 } 149 150 return NULL; 151 } 152 153 void northbridge_write_smram(u8 smram) 154 { 155 struct device *dev = pcidev_on_root(0, 0); 156 157 if (!dev) 158 die("could not find pci 00:00.0!\n"); 159 160 pci_write_config8(dev, D0F0_SMRAM, smram); 161 } 162 163 static void set_above_4g_pci(const struct device *dev) 164 { 165 const uint64_t touud = get_touud(); 166 const uint64_t len = POWER_OF_2(cpu_phys_address_size()) - touud; 167 168 const char *scope = acpi_device_path(dev); 169 acpigen_write_scope(scope); 170 acpigen_write_name_qword("A4GB", touud); 171 acpigen_write_name_qword("A4GS", len); 172 acpigen_pop_len(); 173 174 printk(BIOS_DEBUG, "PCI space above 4GB MMIO is at 0x%llx, len = 0x%llx\n", touud, len); 175 } 176 177 static void pci_domain_ssdt(const struct device *dev) 178 { 179 generate_cpu_entries(dev); 180 set_above_4g_pci(dev); 181 } 182 183 struct device_operations gm45_pci_domain_ops = { 184 .read_resources = mch_domain_read_resources, 185 .set_resources = mch_domain_set_resources, 186 .init = mch_domain_init, 187 .scan_bus = pci_host_bridge_scan_bus, 188 .write_acpi_tables = northbridge_write_acpi_tables, 189 .acpi_fill_ssdt = pci_domain_ssdt, 190 .acpi_name = northbridge_acpi_name, 191 }; 192 193 struct device_operations gm45_cpu_bus_ops = { 194 .read_resources = noop_read_resources, 195 .set_resources = noop_set_resources, 196 .init = mp_cpu_bus_init, 197 }; 198 199 static void gm45_init(void *const chip_info) 200 { 201 int dev, fn, bit_base; 202 203 struct device *const d0f0 = pcidev_on_root(0x0, 0); 204 205 /* Hide internal functions based on devicetree info. */ 206 for (dev = 3; dev > 0; --dev) { 207 switch (dev) { 208 case 3: /* ME */ 209 fn = 3; 210 bit_base = 6; 211 break; 212 case 2: /* IGD */ 213 fn = 1; 214 bit_base = 3; 215 break; 216 case 1: /* PEG */ 217 fn = 0; 218 bit_base = 1; 219 break; 220 } 221 for (; fn >= 0; --fn) { 222 const struct device *const d = pcidev_on_root(dev, fn); 223 if (!d || d->enabled) 224 continue; 225 /* FIXME: Using bitwise ops changes the binary */ 226 pci_write_config32(d0f0, D0F0_DEVEN, 227 pci_read_config32(d0f0, D0F0_DEVEN) & ~(1 << (bit_base + fn))); 228 } 229 } 230 231 const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN); 232 if (!(deven & (0xf << 6))) 233 pci_write_config32(d0f0, D0F0_DEVEN, deven & ~(1 << 14)); 234 } 235 236 struct chip_operations northbridge_intel_gm45_ops = { 237 .name = "Intel GM45 Northbridge", 238 .init = gm45_init, 239 }; 240 241 bool northbridge_support_slfm(void) 242 { 243 struct northbridge_intel_gm45_config *config = config_of_soc(); 244 return config->slfm == 1; 245 }