blob: 48a81c0e9507d1045acf21197a0dd962cca8a8eb [file] [log] [blame]
Patrick Georgi2efc8802012-11-06 11:03:53 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Patrick Georgi2efc8802012-11-06 11:03:53 +010018 */
19
20#include <console/console.h>
21#include <arch/io.h>
22#include <stdint.h>
23#include <device/device.h>
24#include <device/pci.h>
25#include <device/pci_ids.h>
26#include <device/hypertransport.h>
27#include <stdlib.h>
28#include <string.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +010029#include <cpu/cpu.h>
30#include <boot/tables.h>
31#include <arch/acpi.h>
32#include <cbmem.h>
33#include "chip.h"
34#include "gm45.h"
Vladimir Serbinenko06667a52014-08-12 09:07:13 +020035#include "arch/acpi.h"
Patrick Georgi2efc8802012-11-06 11:03:53 +010036
37/* Reserve everything between A segment and 1MB:
38 *
39 * 0xa0000 - 0xbffff: legacy VGA
40 * 0xc0000 - 0xcffff: VGA OPROM (needed by kernel)
41 * 0xe0000 - 0xfffff: SeaBIOS, if used, otherwise DMI
42 */
43static const int legacy_hole_base_k = 0xa0000 / 1024;
44static const int legacy_hole_size_k = 384;
45
46static int decode_pcie_bar(u32 *const base, u32 *const len)
47{
48 *base = 0;
49 *len = 0;
50
51 const device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0));
52 if (!dev)
53 return 0;
54
55 const u32 pciexbar_reg = pci_read_config32(dev, D0F0_PCIEXBAR_LO);
56
57 if (!(pciexbar_reg & (1 << 0)))
58 return 0;
59
60 switch ((pciexbar_reg >> 1) & 3) {
61 case 0: /* 256MB */
62 *base = pciexbar_reg & (0x0f << 28);
63 *len = 256 * 1024 * 1024;
64 return 1;
65 case 1: /* 128M */
66 *base = pciexbar_reg & (0x1f << 27);
67 *len = 128 * 1024 * 1024;
68 return 1;
69 case 2: /* 64M */
70 *base = pciexbar_reg & (0x3f << 26);
71 *len = 64 * 1024 * 1024;
72 return 1;
73 }
74
75 return 0;
76}
77
78static void mch_domain_read_resources(device_t dev)
79{
80 u64 tom, touud;
81 u32 tomk, tolud, uma_sizek = 0;
82 u32 pcie_config_base, pcie_config_size;
83
84 /* Total Memory 2GB example:
85 *
86 * 00000000 0000MB-2014MB 2014MB RAM (writeback)
87 * 7de00000 2014MB-2016MB 2MB GFX GTT (uncached)
88 * 7e000000 2016MB-2048MB 32MB GFX UMA (uncached)
89 * 80000000 2048MB TOLUD
90 * 80000000 2048MB TOM
91 *
92 * Total Memory 4GB example:
93 *
94 * 00000000 0000MB-3038MB 3038MB RAM (writeback)
95 * bde00000 3038MB-3040MB 2MB GFX GTT (uncached)
96 * be000000 3040MB-3072MB 32MB GFX UMA (uncached)
97 * be000000 3072MB TOLUD
98 * 100000000 4096MB TOM
99 * 100000000 4096MB-5120MB 1024MB RAM (writeback)
100 * 140000000 5120MB TOUUD
101 */
102
103 pci_domain_read_resources(dev);
104
105 /* Top of Upper Usable DRAM, including remap */
106 touud = pci_read_config16(dev, D0F0_TOUUD);
107 touud <<= 20;
108
109 /* Top of Lower Usable DRAM */
110 tolud = pci_read_config16(dev, D0F0_TOLUD) & 0xfff0;
111 tolud <<= 16;
112
113 /* Top of Memory - does not account for any UMA */
114 tom = pci_read_config16(dev, D0F0_TOM) & 0x1ff;
115 tom <<= 27;
116
117 printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx\n",
118 touud, tolud, tom);
119
120 tomk = tolud >> 10;
121
122 /* Graphics memory comes next */
123 const u16 ggc = pci_read_config16(dev, D0F0_GGC);
124 if (!(ggc & 2)) {
125 printk(BIOS_DEBUG, "IGD decoded, subtracting ");
126
127 /* Graphics memory */
128 const u32 gms_sizek = decode_igd_memory_size((ggc >> 4) & 0xf);
129 printk(BIOS_DEBUG, "%uM UMA", gms_sizek >> 10);
130 tomk -= gms_sizek;
131
132 /* GTT Graphics Stolen Memory Size (GGMS) */
133 const u32 gsm_sizek = decode_igd_gtt_size((ggc >> 8) & 0xf);
134 printk(BIOS_DEBUG, " and %uM GTT\n", gsm_sizek >> 10);
135 tomk -= gsm_sizek;
136
137 uma_sizek = gms_sizek + gsm_sizek;
138 }
139
140 printk(BIOS_INFO, "Available memory below 4GB: %uM\n", tomk >> 10);
141
142 /* Report the memory regions */
143 ram_resource(dev, 3, 0, legacy_hole_base_k);
144 ram_resource(dev, 4, legacy_hole_base_k + legacy_hole_size_k,
145 (tomk - (legacy_hole_base_k + legacy_hole_size_k)));
146
147 /*
148 * If >= 4GB installed then memory from TOLUD to 4GB
149 * is remapped above TOM, TOUUD will account for both
150 */
151 touud >>= 10; /* Convert to KB */
152 if (touud > 4096 * 1024) {
153 ram_resource(dev, 5, 4096 * 1024, touud - (4096 * 1024));
154 printk(BIOS_INFO, "Available memory above 4GB: %lluM\n",
155 (touud >> 10) - 4096);
156 }
157
158 printk(BIOS_DEBUG, "Adding UMA memory area base=0x%llx "
159 "size=0x%llx\n", ((u64)tomk) << 10, ((u64)uma_sizek) << 10);
160 /* Don't use uma_resource() as our UMA touches the PCI hole. */
161 fixed_mem_resource(dev, 6, tomk, uma_sizek, IORESOURCE_RESERVE);
162
163 if (decode_pcie_bar(&pcie_config_base, &pcie_config_size)) {
164 printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x "
165 "size=0x%x\n", pcie_config_base, pcie_config_size);
166 fixed_mem_resource(dev, 7, pcie_config_base >> 10,
167 pcie_config_size >> 10, IORESOURCE_RESERVE);
168 }
Patrick Georgi2efc8802012-11-06 11:03:53 +0100169}
170
171static void mch_domain_set_resources(device_t dev)
172{
173 struct resource *resource;
174 int i;
175
176 for (i = 3; i < 8; ++i) {
177 /* Report read resources. */
178 resource = find_resource(dev, i);
179 if (resource)
180 report_resource_stored(dev, resource, "");
181 }
182
183 assign_resources(dev->link_list);
184}
185
186static void mch_domain_init(device_t dev)
187{
188 u32 reg32;
189
190 /* Enable SERR */
191 reg32 = pci_read_config32(dev, PCI_COMMAND);
192 reg32 |= PCI_COMMAND_SERR;
193 pci_write_config32(dev, PCI_COMMAND, reg32);
194}
195
196static struct device_operations pci_domain_ops = {
197 .read_resources = mch_domain_read_resources,
198 .set_resources = mch_domain_set_resources,
199 .enable_resources = NULL,
200 .init = mch_domain_init,
201 .scan_bus = pci_domain_scan_bus,
Kyösti Mälkki872c9222013-07-03 09:44:28 +0300202 .ops_pci_bus = pci_bus_default_ops,
Patrick Georgi2efc8802012-11-06 11:03:53 +0100203};
204
205
206static void cpu_bus_init(device_t dev)
207{
208 initialize_cpus(dev->link_list);
209}
210
211static void cpu_bus_noop(device_t dev)
212{
213}
214
215static struct device_operations cpu_bus_ops = {
216 .read_resources = cpu_bus_noop,
217 .set_resources = cpu_bus_noop,
218 .enable_resources = cpu_bus_noop,
219 .init = cpu_bus_init,
220 .scan_bus = 0,
221};
222
223
224static void enable_dev(device_t dev)
225{
226 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800227 if (dev->path.type == DEVICE_PATH_DOMAIN) {
Patrick Georgi2efc8802012-11-06 11:03:53 +0100228 dev->ops = &pci_domain_ops;
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800229 } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
Patrick Georgi2efc8802012-11-06 11:03:53 +0100230 dev->ops = &cpu_bus_ops;
231 }
Vladimir Serbinenko06667a52014-08-12 09:07:13 +0200232
233#if CONFIG_HAVE_ACPI_RESUME
234 switch (pci_read_config32(dev_find_slot(0, PCI_DEVFN(0, 0)), /*D0F0_SKPD*/0xdc)) {
235 case SKPAD_NORMAL_BOOT_MAGIC:
236 printk(BIOS_DEBUG, "Normal boot.\n");
237 acpi_slp_type=0;
238 break;
239 case SKPAD_ACPI_S3_MAGIC:
240 printk(BIOS_DEBUG, "S3 Resume.\n");
241 acpi_slp_type=3;
242 break;
243 default:
244 printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n");
245 acpi_slp_type=0;
246 break;
247 }
248#endif
Patrick Georgi2efc8802012-11-06 11:03:53 +0100249}
250
251static void gm45_init(void *const chip_info)
252{
253 int dev, fn, bit_base;
254
255 struct device *const d0f0 = dev_find_slot(0, 0);
256
257 /* Hide internal functions based on devicetree info. */
258 for (dev = 3; dev > 0; --dev) {
259 switch (dev) {
260 case 3: /* ME */
261 fn = 3;
262 bit_base = 6;
263 break;
264 case 2: /* IGD */
265 fn = 1;
266 bit_base = 3;
267 break;
268 case 1: /* PEG */
269 fn = 0;
270 bit_base = 1;
271 break;
272 }
273 for (; fn >= 0; --fn) {
274 const struct device *const d =
275 dev_find_slot(0, PCI_DEVFN(dev, fn));
276 if (!d || d->enabled) continue;
277 const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN);
278 pci_write_config32(d0f0, D0F0_DEVEN,
279 deven & ~(1 << (bit_base + fn)));
280 }
281 }
282
283 const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN);
284 if (!(deven & (0xf << 6)))
285 pci_write_config32(d0f0, D0F0_DEVEN, deven & ~(1 << 14));
286}
287
288struct chip_operations northbridge_intel_gm45_ops = {
289 CHIP_NAME("Intel GM45 Northbridge")
290 .enable_dev = enable_dev,
291 .init = gm45_init,
292};