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