coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
northbridge.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <cbmem.h>
4 #include <commonlib/helpers.h>
5 #include <console/console.h>
6 #include <device/pci_def.h>
7 #include <device/pci_ops.h>
8 #include <stdint.h>
9 #include <device/device.h>
10 #include <boot/tables.h>
11 #include <acpi/acpi.h>
12 #include <cpu/intel/smm_reloc.h>
13 
14 #include "chip.h"
15 #include "gm45.h"
16 
17 static void mch_domain_read_resources(struct device *dev)
18 {
19  u64 tom, touud;
20  u32 tomk, tolud, uma_sizek = 0, delta_cbmem;
21 
22  /* Total Memory 2GB example:
23  *
24  * 00000000 0000MB-2014MB 2014MB RAM (writeback)
25  * 7de00000 2014MB-2016MB 2MB GFX GTT (uncached)
26  * 7e000000 2016MB-2048MB 32MB GFX UMA (uncached)
27  * 80000000 2048MB TOLUD
28  * 80000000 2048MB TOM
29  *
30  * Total Memory 4GB example:
31  *
32  * 00000000 0000MB-3038MB 3038MB RAM (writeback)
33  * bde00000 3038MB-3040MB 2MB GFX GTT (uncached)
34  * be000000 3040MB-3072MB 32MB GFX UMA (uncached)
35  * be000000 3072MB TOLUD
36  * 100000000 4096MB TOM
37  * 100000000 4096MB-5120MB 1024MB RAM (writeback)
38  * 140000000 5120MB TOUUD
39  */
40 
42 
43  struct device *mch = pcidev_on_root(0, 0);
44 
45  /* Top of Upper Usable DRAM, including remap */
46  touud = pci_read_config16(mch, D0F0_TOUUD);
47  touud <<= 20;
48 
49  /* Top of Lower Usable DRAM */
50  tolud = pci_read_config16(mch, D0F0_TOLUD) & 0xfff0;
51  tolud <<= 16;
52 
53  /* Top of Memory - does not account for any UMA */
54  tom = pci_read_config16(mch, D0F0_TOM) & 0x1ff;
55  tom <<= 27;
56 
57  printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx\n",
58  touud, tolud, tom);
59 
60  tomk = tolud >> 10;
61 
62  /* Graphics memory comes next */
63  const u16 ggc = pci_read_config16(mch, D0F0_GGC);
64  if (!(ggc & 2)) {
65  printk(BIOS_DEBUG, "IGD decoded, subtracting ");
66 
67  /* Graphics memory */
68  const u32 gms_sizek = decode_igd_memory_size((ggc >> 4) & 0xf);
69  printk(BIOS_DEBUG, "%uM UMA, ", gms_sizek >> 10);
70  tomk -= gms_sizek;
71 
72  /* GTT Graphics Stolen Memory Size (GGMS) */
73  const u32 gsm_sizek = decode_igd_gtt_size((ggc >> 8) & 0xf);
74  printk(BIOS_DEBUG, "%uM GTT", gsm_sizek >> 10);
75  tomk -= gsm_sizek;
76 
77  uma_sizek = gms_sizek + gsm_sizek;
78  }
79  const u8 esmramc = pci_read_config8(mch, D0F0_ESMRAMC);
80  const u32 tseg_sizek = decode_tseg_size(esmramc);
81  printk(BIOS_DEBUG, " and %uM TSEG\n", tseg_sizek >> 10);
82  tomk -= tseg_sizek;
83  uma_sizek += tseg_sizek;
84 
85  /* cbmem_top can be shifted downwards due to alignment.
86  Mark the region between cbmem_top and tomk as unusable */
87  delta_cbmem = tomk - ((uint32_t)cbmem_top() >> 10);
88  tomk -= delta_cbmem;
89  uma_sizek += delta_cbmem;
90 
91  printk(BIOS_DEBUG, "Unused RAM between cbmem_top and TOM: 0x%xK\n",
92  delta_cbmem);
93 
94  printk(BIOS_INFO, "Available memory below 4GB: %uM\n", tomk >> 10);
95 
96  /* Report lowest memory region */
97  ram_resource(dev, 3, 0, 0xa0000 / KiB);
98 
99  /*
100  * Reserve everything between A segment and 1MB:
101  *
102  * 0xa0000 - 0xbffff: Legacy VGA
103  * 0xc0000 - 0xfffff: RAM
104  */
105  mmio_resource(dev, 4, 0xa0000 / KiB, (0xc0000 - 0xa0000) / KiB);
106  reserved_ram_resource(dev, 5, 0xc0000 / KiB, (1*MiB - 0xc0000) / KiB);
107 
108  /* Report < 4GB memory */
109  ram_resource(dev, 6, 1*MiB / KiB, tomk - 1*MiB / KiB);
110 
111  /*
112  * If >= 4GB installed then memory from TOLUD to 4GB
113  * is remapped above TOM, TOUUD will account for both
114  */
115  touud >>= 10; /* Convert to KB */
116  if (touud > 4096 * 1024) {
117  ram_resource(dev, 7, 4096 * 1024, touud - (4096 * 1024));
118  printk(BIOS_INFO, "Available memory above 4GB: %lluM\n",
119  (touud >> 10) - 4096);
120  }
121 
122  printk(BIOS_DEBUG, "Adding UMA memory area base=0x%llx "
123  "size=0x%llx\n", ((u64)tomk) << 10, ((u64)uma_sizek) << 10);
124  /* Don't use uma_resource() as our UMA touches the PCI hole. */
125  fixed_mem_resource(dev, 8, tomk, uma_sizek, IORESOURCE_RESERVE);
126 
127  mmconf_resource(dev, 9);
128 }
129 
130 static void mch_domain_set_resources(struct device *dev)
131 {
132  struct resource *resource;
133  int i;
134 
135  for (i = 3; i <= 9; ++i) {
136  /* Report read resources. */
137  resource = probe_resource(dev, i);
138  if (resource)
140  }
141 
143 }
144 
145 static void mch_domain_init(struct device *dev)
146 {
147  struct device *mch = pcidev_on_root(0, 0);
148 
149  /* Enable SERR */
151 }
152 
153 static const char *northbridge_acpi_name(const struct device *dev)
154 {
155  if (dev->path.type == DEVICE_PATH_DOMAIN)
156  return "PCI0";
157 
158  if (dev->path.type != DEVICE_PATH_PCI || dev->bus->secondary != 0)
159  return NULL;
160 
161  switch (dev->path.pci.devfn) {
162  case PCI_DEVFN(0, 0):
163  return "MCHC";
164  }
165 
166  return NULL;
167 }
168 
170 {
171  struct device *dev = pcidev_on_root(0, 0);
172 
173  if (dev == NULL)
174  die("could not find pci 00:00.0!\n");
175 
176  pci_write_config8(dev, D0F0_SMRAM, smram);
177 }
178 
179 static struct device_operations pci_domain_ops = {
181  .set_resources = mch_domain_set_resources,
182  .init = mch_domain_init,
183  .scan_bus = pci_domain_scan_bus,
184  .write_acpi_tables = northbridge_write_acpi_tables,
185  .acpi_fill_ssdt = generate_cpu_entries,
186  .acpi_name = northbridge_acpi_name,
187 };
188 
189 static struct device_operations cpu_bus_ops = {
191  .set_resources = noop_set_resources,
192  .init = mp_cpu_bus_init,
193 };
194 
195 static void enable_dev(struct device *dev)
196 {
197  /* Set the operations if it is a special bus type */
198  if (dev->path.type == DEVICE_PATH_DOMAIN) {
199  dev->ops = &pci_domain_ops;
200  } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
201  dev->ops = &cpu_bus_ops;
202  }
203 }
204 
205 static void gm45_init(void *const chip_info)
206 {
207  int dev, fn, bit_base;
208 
209  struct device *const d0f0 = pcidev_on_root(0x0, 0);
210 
211  /* Hide internal functions based on devicetree info. */
212  for (dev = 3; dev > 0; --dev) {
213  switch (dev) {
214  case 3: /* ME */
215  fn = 3;
216  bit_base = 6;
217  break;
218  case 2: /* IGD */
219  fn = 1;
220  bit_base = 3;
221  break;
222  case 1: /* PEG */
223  fn = 0;
224  bit_base = 1;
225  break;
226  }
227  for (; fn >= 0; --fn) {
228  const struct device *const d = pcidev_on_root(dev, fn);
229  if (!d || d->enabled)
230  continue;
231  /* FIXME: Using bitwise ops changes the binary */
233  pci_read_config32(d0f0, D0F0_DEVEN) & ~(1 << (bit_base + fn)));
234  }
235  }
236 
237  const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN);
238  if (!(deven & (0xf << 6)))
239  pci_write_config32(d0f0, D0F0_DEVEN, deven & ~(1 << 14));
240 }
241 
243  CHIP_NAME("Intel GM45 Northbridge")
244  .enable_dev = enable_dev,
245  .init = gm45_init,
246 };
#define MiB
Definition: helpers.h:76
#define KiB
Definition: helpers.h:75
void * cbmem_top(void)
Definition: imd_cbmem.c:18
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
void generate_cpu_entries(const struct device *device)
Definition: acpi.c:334
void assign_resources(struct bus *bus)
Assign the computed resources to the devices on the bus.
Definition: device.c:268
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
void fixed_mem_resource(struct device *dev, unsigned long index, unsigned long basek, unsigned long sizek, unsigned long type)
Definition: device_util.c:825
void mmconf_resource(struct device *dev, unsigned long index)
Definition: device_util.c:857
struct resource * probe_resource(const struct device *dev, unsigned int index)
See if a resource structure already exists for a given index.
Definition: device_util.c:323
void report_resource_stored(struct device *dev, const struct resource *resource, const char *comment)
Print the resource that was just stored.
Definition: device_util.c:508
u32 decode_igd_memory_size(u32 gms)
Decodes used Graphics Mode Select (GMS) to kilobytes.
Definition: memmap.c:24
#define D0F0_ESMRAMC
Definition: gm45.h:187
#define D0F0_TOM
Definition: gm45.h:188
u32 decode_tseg_size(u8 esmramc)
Definition: memmap.c:57
#define D0F0_SMRAM
Definition: gm45.h:186
#define D0F0_TOLUD
Definition: gm45.h:190
u32 decode_igd_gtt_size(u32 gsm)
Decodes used Graphics Stolen Memory (GSM) to kilobytes.
Definition: memmap.c:36
#define D0F0_TOUUD
Definition: gm45.h:189
#define D0F0_DEVEN
Definition: gm45.h:177
#define D0F0_GGC
Definition: gm45.h:176
#define CHIP_NAME(X)
Definition: device.h:32
static void noop_read_resources(struct device *dev)
Standard device operations function pointers shims.
Definition: device.h:73
static void noop_set_resources(struct device *dev)
Definition: device.h:74
static void mp_cpu_bus_init(struct device *dev)
Definition: device.h:240
#define ram_resource(dev, idx, basek, sizek)
Definition: device.h:321
#define mmio_resource(dev, idx, basek, sizek)
Definition: device.h:334
#define reserved_ram_resource(dev, idx, basek, sizek)
Definition: device.h:324
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline void pci_or_config16(const struct device *dev, u16 reg, u16 ormask)
Definition: pci_ops.h:180
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline u8 pci_read_config8(const struct device *dev, u16 reg)
Definition: pci_ops.h:46
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
unsigned long northbridge_write_acpi_tables(struct device *device, unsigned long start)
static struct device_operations cpu_bus_ops
Definition: northbridge.c:189
static struct device_operations pci_domain_ops
Definition: northbridge.c:179
static void enable_dev(struct device *dev)
Definition: northbridge.c:195
struct chip_operations northbridge_intel_gm45_ops
Definition: northbridge.c:242
static void mch_domain_set_resources(struct device *dev)
Definition: northbridge.c:130
static void mch_domain_read_resources(struct device *dev)
Definition: northbridge.c:17
void northbridge_write_smram(u8 smram)
Definition: northbridge.c:169
static void mch_domain_init(struct device *dev)
Definition: northbridge.c:145
static const char * northbridge_acpi_name(const struct device *dev)
Definition: northbridge.c:153
static void gm45_init(void *const chip_info)
Definition: northbridge.c:205
@ DEVICE_PATH_PCI
Definition: path.h:9
@ DEVICE_PATH_CPU_CLUSTER
Definition: path.h:14
@ DEVICE_PATH_DOMAIN
Definition: path.h:13
#define PCI_COMMAND_SERR
Definition: pci_def.h:19
#define PCI_DEVFN(slot, func)
Definition: pci_def.h:548
#define PCI_COMMAND
Definition: pci_def.h:10
void pci_domain_read_resources(struct device *dev)
Definition: pci_device.c:547
void pci_domain_scan_bus(struct device *dev)
Scan a PCI domain.
Definition: pci_device.c:1610
#define IORESOURCE_RESERVE
Definition: resource.h:30
#define NULL
Definition: stddef.h:19
uint64_t u64
Definition: stdint.h:54
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
uint16_t secondary
Definition: device.h:84
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct pci_path pci
Definition: path.h:116
enum device_path_type type
Definition: path.h:114
Definition: device.h:107
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST struct bus * bus
Definition: device.h:108
DEVTREE_CONST struct bus * link_list
Definition: device.h:139
unsigned int enabled
Definition: device.h:122
unsigned int devfn
Definition: path.h:54