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