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 <console/console.h>
4 #include <acpi/acpi.h>
5 #include <arch/hpet.h>
6 #include <device/pci_ops.h>
7 #include <stdint.h>
9 #include <device/device.h>
10 #include <device/pci.h>
11 #include <device/pci_ids.h>
12 #include "chip.h"
13 #include <commonlib/bsd/helpers.h>
14 #include "ironlake.h"
15 #include <cpu/intel/smm_reloc.h>
16 
17 static int bridge_revision_id = -1;
18 
20 {
21  if (bridge_revision_id < 0) {
22  uint8_t stepping = cpuid_eax(1) & 0x0f;
24  bridge_revision_id = (bridge_id & 0xf0) | stepping;
25  }
26  return bridge_revision_id;
27 }
28 
29 /*
30  * Reserve everything between A segment and 1MB:
31  *
32  * 0xa0000 - 0xbffff: legacy VGA
33  * 0xc0000 - 0xcffff: VGA OPROM (needed by kernel)
34  * 0xe0000 - 0xfffff: SeaBIOS, if used, otherwise DMI
35  */
36 static const int legacy_hole_base_k = 0xa0000 / 1024;
37 
38 static void add_fixed_resources(struct device *dev, int index)
39 {
40  struct resource *resource;
41 
42  /* 0xe0000000-0xf0000000 PCIe config.
43  0xfed10000-0xfed14000 MCH
44  0xfed17000-0xfed18000 HECI
45  0xfed18000-0xfed19000 DMI
46  0xfed19000-0xfed1a000 EPBAR
47  0xfed1c000-0xfed20000 RCBA
48  0xfed90000-0xfed94000 IOMMU
49  0xff800000-0xffffffff ROM. */
50 
51  resource = new_resource(dev, index++);
53  resource->size = (resource_t) 0x00100000;
56 
58  reserved_ram_resource(dev, index++, 0xc0000 / KiB, (0x100000 - 0xc0000) / KiB);
59 }
60 
61 #if CONFIG(HAVE_ACPI_TABLES)
62 static const char *northbridge_acpi_name(const struct device *dev)
63 {
64  if (dev->path.type == DEVICE_PATH_DOMAIN)
65  return "PCI0";
66 
67  if (dev->path.type != DEVICE_PATH_PCI || dev->bus->secondary != 0)
68  return NULL;
69 
70  switch (dev->path.pci.devfn) {
71  case PCI_DEVFN(0, 0):
72  return "MCHC";
73  }
74 
75  return NULL;
76 }
77 #endif
78 
79 static struct device_operations pci_domain_ops = {
81  .set_resources = pci_domain_set_resources,
82  .scan_bus = pci_domain_scan_bus,
83 #if CONFIG(HAVE_ACPI_TABLES)
84  .acpi_name = northbridge_acpi_name,
85 #endif
86 };
87 
88 static void mc_read_resources(struct device *dev)
89 {
90  uint32_t tseg_base, tseg_end;
91  uint64_t touud;
92  uint16_t reg16;
93  int index = 3;
94 
96 
97  mmconf_resource(dev, 0x50);
98 
99  tseg_base = pci_read_config32(pcidev_on_root(0, 0), TSEG);
100  tseg_end = tseg_base + CONFIG_SMM_TSEG_SIZE;
101  touud = pci_read_config16(pcidev_on_root(0, 0),
102  TOUUD);
103 
104  printk(BIOS_DEBUG, "ram_before_4g_top: 0x%x\n", tseg_base);
105  printk(BIOS_DEBUG, "TOUUD: 0x%x\n", (unsigned int)touud);
106 
107  /* Report the memory regions */
108  ram_resource(dev, index++, 0, 0xa0000 / KiB);
109  ram_resource(dev, index++, 1 * MiB / KiB, (tseg_base - 1 * MiB) / KiB);
110 
111  mmio_resource(dev, index++, tseg_base / KiB, CONFIG_SMM_TSEG_SIZE / KiB);
112 
113  reg16 = pci_read_config16(pcidev_on_root(0, 0), GGC);
114  const int uma_sizes_gtt[16] =
115  { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42 };
116  /* Igd memory */
117  const int uma_sizes_igd[16] = {
118  0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352, 256, 512
119  };
120  u32 igd_base, gtt_base;
121  int uma_size_igd, uma_size_gtt;
122 
123  uma_size_igd = uma_sizes_igd[(reg16 >> 4) & 0xF];
124  uma_size_gtt = uma_sizes_gtt[(reg16 >> 8) & 0xF];
125 
126  igd_base =
128  gtt_base =
130  if (gtt_base > tseg_end) {
131  /* Reserve the gap. MMIO doesn't work in this range. Keep
132  it uncacheable, though, for easier MTRR allocation. */
133  mmio_resource(dev, index++, tseg_end / KiB, (gtt_base - tseg_end) / KiB);
134  }
135  mmio_resource(dev, index++, gtt_base / KiB, uma_size_gtt * KiB);
136  mmio_resource(dev, index++, igd_base / KiB, uma_size_igd * KiB);
137 
138  if (touud > 4096)
139  ram_resource(dev, index++, (4096 * KiB), ((touud - 4096) * KiB));
140 
141  /* This memory is not DMA-capable. */
142  if (touud >= 8192 - 64)
143  bad_ram_resource(dev, index++, 0x1fc000000ULL / KiB, 0x004000000 / KiB);
144 
145  add_fixed_resources(dev, index);
146 }
147 
148 static void northbridge_init(struct device *dev)
149 {
150  /* Clear error status bits */
151  dmibar_write32(DMIUESTS, 0xffffffff);
152  dmibar_write32(DMICESTS, 0xffffffff);
153 
154  dmibar_setbits32(DMILLTC, 1 << 29);
155 
156  dmibar_setbits32(0x1f8, 1 << 16);
157 
158  dmibar_setbits32(DMILCTL, 1 << 1 | 1 << 0);
159 }
160 
161 /* Disable unused PEG devices based on devicetree before PCI enumeration */
162 static void ironlake_init(void *const chip_info)
163 {
164  u32 deven_mask = UINT32_MAX;
165  const struct device *dev;
166 
167  dev = pcidev_on_root(1, 0);
168  if (!dev || !dev->enabled) {
169  printk(BIOS_DEBUG, "Disabling PEG10.\n");
170  deven_mask &= ~DEVEN_PEG10;
171  }
172  dev = pcidev_on_root(2, 0);
173  if (!dev || !dev->enabled) {
174  printk(BIOS_DEBUG, "Disabling IGD.\n");
175  deven_mask &= ~DEVEN_IGD;
176  }
177  const struct device *const d0f0 = pcidev_on_root(0, 0);
178  if (d0f0)
179  pci_update_config32(d0f0, DEVEN, deven_mask, 0);
180 
181 }
182 
183 static struct device_operations mc_ops = {
185  .set_resources = pci_dev_set_resources,
186  .enable_resources = pci_dev_enable_resources,
187  .init = northbridge_init,
188  .acpi_fill_ssdt = generate_cpu_entries,
189  .ops_pci = &pci_dev_ops_pci,
190 };
191 
192 /*
193  * The host bridge PCI device ID can be changed by the firmware. There
194  * is no documentation about it, though. There's 'official' IDs, which
195  * appear in spec updates and Windows drivers, and 'mysterious' IDs,
196  * which Intel doesn't want OSes to know about and thus are not listed.
197  *
198  * The current coreboot code seems to be able to change the device ID
199  * of the host bridge, but it seems to be missing a warm reset so that
200  * the device ID changes. Account for the 'mysterious' device IDs in
201  * the northbridge driver, so that booting an OS has a chance to work.
202  */
203 static const unsigned short pci_device_ids[] = {
204  /* 'Official' DIDs */
205  0x0040, /* Clarkdale */
206  0x0044, /* Arrandale */
207  0x0048, /* Unknown, but it appears in OS drivers and raminit */
208 
209  /* Mysterious DIDs, taken from Linux' intel-agp driver */
210  0x0062, /* Arrandale A-? */
211  0x0069, /* Clarkdale K-0 */
212  0x006a, /* Arrandale K-0 */
213  0
214 };
215 
216 static const struct pci_driver mc_driver_ilk __pci_driver = {
217  .ops = &mc_ops,
218  .vendor = PCI_VID_INTEL,
219  .devices = pci_device_ids,
220 };
221 
222 static struct device_operations cpu_bus_ops = {
224  .set_resources = noop_set_resources,
225  .init = mp_cpu_bus_init,
226 };
227 
228 static void enable_dev(struct device *dev)
229 {
230  /* Set the operations if it is a special bus type */
231  if (dev->path.type == DEVICE_PATH_DOMAIN) {
232  dev->ops = &pci_domain_ops;
233  } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
234  dev->ops = &cpu_bus_ops;
235  }
236 }
237 
239  CHIP_NAME("Intel Ironlake integrated Northbridge")
240  .enable_dev = enable_dev,
241  .init = ironlake_init,
242 };
static unsigned int cpuid_eax(unsigned int op)
Definition: cpu.h:79
#define HPET_BASE_ADDRESS
Definition: hpet.h:6
#define MiB
Definition: helpers.h:76
#define KiB
Definition: helpers.h:75
#define printk(level,...)
Definition: stdlib.h:16
void generate_cpu_entries(const struct device *device)
Definition: acpi.c:334
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
struct resource * new_resource(struct device *dev, unsigned int index)
See if a resource structure already exists for a given index and if not allocate one.
Definition: device_util.c:346
void mmconf_resource(struct device *dev, unsigned long index)
Definition: device_util.c:857
static __always_inline void dmibar_write32(const uintptr_t offset, const uint32_t value)
Definition: fixed_bars.h:91
#define dmibar_setbits32(addr, set)
Definition: fixed_bars.h:113
#define DMILCTL
Definition: gm45.h:364
#define DMIUESTS
Definition: dmibar.h:46
#define DMICESTS
Definition: dmibar.h:47
#define DMILLTC
Definition: dmibar.h:52
#define GGC
Definition: host_bridge.h:9
#define TOUUD
Definition: host_bridge.h:57
#define TSEG
Definition: host_bridge.h:60
#define DEVEN
Definition: host_bridge.h:16
#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
#define bad_ram_resource(dev, idx, basek, sizek)
Definition: device.h:328
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_update_config32(const struct device *dev, u16 reg, u32 mask, u32 or)
Definition: pci_ops.h:120
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
#define IGD_BASE
Definition: host_bridge.h:22
#define GTT_BASE
Definition: host_bridge.h:23
#define DEVEN_PEG10
Definition: host_bridge.h:11
#define DEVEN_IGD
Definition: host_bridge.h:10
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
static const char * northbridge_acpi_name(const struct device *dev)
Definition: northbridge.c:153
static struct device_operations cpu_bus_ops
Definition: northbridge.c:222
static struct device_operations pci_domain_ops
Definition: northbridge.c:79
static struct device_operations mc_ops
Definition: northbridge.c:183
static void mc_read_resources(struct device *dev)
Definition: northbridge.c:88
static void enable_dev(struct device *dev)
Definition: northbridge.c:228
struct chip_operations northbridge_intel_ironlake_ops
Definition: northbridge.c:238
static int bridge_revision_id
Definition: northbridge.c:17
static const struct pci_driver mc_driver_ilk __pci_driver
Definition: northbridge.c:216
static const int legacy_hole_base_k
Definition: northbridge.c:36
int bridge_silicon_revision(void)
Definition: northbridge.c:19
static const unsigned short pci_device_ids[]
Definition: northbridge.c:203
static void add_fixed_resources(struct device *dev, int index)
Definition: northbridge.c:38
static void ironlake_init(void *const chip_info)
Definition: northbridge.c:162
static void northbridge_init(struct device *dev)
Definition: northbridge.c:148
@ DEVICE_PATH_PCI
Definition: path.h:9
@ DEVICE_PATH_CPU_CLUSTER
Definition: path.h:14
@ DEVICE_PATH_DOMAIN
Definition: path.h:13
#define PCI_DEVFN(slot, func)
Definition: pci_def.h:548
#define PCI_DEVICE_ID
Definition: pci_def.h:9
void pci_domain_read_resources(struct device *dev)
Definition: pci_device.c:547
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_domain_set_resources(struct device *dev)
Definition: pci_device.c:564
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
struct pci_operations pci_dev_ops_pci
Default device operation for PCI devices.
Definition: pci_device.c:911
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
void pci_domain_scan_bus(struct device *dev)
Scan a PCI domain.
Definition: pci_device.c:1610
#define PCI_VID_INTEL
Definition: pci_ids.h:2157
#define IORESOURCE_RESERVE
Definition: resource.h:30
#define IORESOURCE_MEM
Definition: resource.h:10
#define IORESOURCE_STORED
Definition: resource.h:32
#define IORESOURCE_ASSIGNED
Definition: resource.h:34
u64 resource_t
Definition: resource.h:43
#define IORESOURCE_FIXED
Definition: resource.h:36
const char * stepping
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long long uint64_t
Definition: stdint.h:17
#define UINT32_MAX
Definition: stdint.h:67
unsigned char uint8_t
Definition: stdint.h:8
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
unsigned int enabled
Definition: device.h:122
unsigned int devfn
Definition: path.h:54
unsigned long flags
Definition: resource.h:49
resource_t base
Definition: resource.h:45
unsigned long index
Definition: resource.h:50
resource_t size
Definition: resource.h:46