/ src / northbridge / intel / pineview / northbridge.c
northbridge.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <arch/hpet.h>
  4  #include <cbmem.h>
  5  #include <console/console.h>
  6  #include <commonlib/bsd/helpers.h>
  7  #include <device/pci_def.h>
  8  #include <device/pci_ops.h>
  9  #include <stdint.h>
 10  #include <device/device.h>
 11  #include <boot/tables.h>
 12  #include <acpi/acpi.h>
 13  #include <northbridge/intel/pineview/pineview.h>
 14  #include <cpu/intel/smm_reloc.h>
 15  #include <cpu/x86/smm.h>
 16  
 17  /*
 18   * Reserve everything between A segment and 1MB:
 19   *
 20   * 0xa0000 - 0xbffff: legacy VGA
 21   * 0xc0000 - 0xcffff: VGA OPROM (needed by kernel)
 22   * 0xe0000 - 0xfffff: SeaBIOS, if used, otherwise DMI
 23   */
 24  
 25  static void add_fixed_resources(struct device *dev, int index)
 26  {
 27  	mmio_range(dev, index++, HPET_BASE_ADDRESS, 0x00100000);
 28  	mmio_from_to(dev, index++, 0xa0000, 0xc0000);
 29  	reserved_ram_from_to(dev, index++, 0xc0000, 1 * MiB);
 30  }
 31  
 32  static void mch_domain_read_resources(struct device *dev)
 33  {
 34  	u64 tom, touud;
 35  	u32 tolud;
 36  	u16 index;
 37  
 38  	struct device *mch = pcidev_on_root(0, 0);
 39  
 40  	index = 3;
 41  
 42  	pci_domain_read_resources(dev);
 43  
 44  	/* Top of Upper Usable DRAM, including remap */
 45  	touud = pci_read_config16(mch, TOUUD);
 46  	touud <<= 20;
 47  
 48  	/* Top of Lower Usable DRAM */
 49  	tolud = pci_read_config16(mch, TOLUD) & 0xfff0;
 50  	tolud <<= 16;
 51  
 52  	/* Top of Memory - does not account for any UMA */
 53  	tom = pci_read_config16(mch, TOM) & 0x01ff;
 54  	tom <<= 27;
 55  
 56  	printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx ", touud, tolud, tom);
 57  
 58  	/* Graphics memory */
 59  	const u16 ggc = pci_read_config16(mch, GGC);
 60  	const u32 gms_size = decode_igd_memory_size((ggc >> 4) & 0xf) * KiB;
 61  	printk(BIOS_DEBUG, "%uM UMA", gms_size / MiB);
 62  
 63  	/* GTT Graphics Stolen Memory Size (GGMS) */
 64  	const u32 gsm_size = decode_igd_gtt_size((ggc >> 8) & 0xf) * KiB;
 65  	printk(BIOS_DEBUG, " and %uM GTT\n", gsm_size / MiB);
 66  
 67  	const u32 igd_base = pci_read_config32(mch, GBSM);
 68  	const u32 gtt_base = pci_read_config32(mch, BGSM);
 69  
 70  	/* Report the memory regions */
 71  	ram_range(dev, index++, 0, 0xa0000);
 72  	ram_from_to(dev, index++, 1 * MiB, cbmem_top());
 73  	uintptr_t tseg_base;
 74  	size_t tseg_size;
 75  	smm_region(&tseg_base, &tseg_size);
 76  	mmio_range(dev, index++, tseg_base, tseg_size);
 77  	mmio_range(dev, index++, gtt_base,  gsm_size);
 78  	mmio_range(dev, index++, igd_base,  gms_size);
 79  	printk(BIOS_DEBUG, "Unused RAM between cbmem_top and TOM: 0x%lx\n",
 80  	       tseg_base - cbmem_top());
 81  	reserved_ram_from_to(dev, index++, cbmem_top(), tseg_base);
 82  
 83  	/*
 84  	 * If > 4GB installed then memory from TOLUD to 4GB
 85  	 * is remapped above TOM, TOUUD will account for both
 86  	 */
 87  	upper_ram_end(dev, index++, touud);
 88  
 89  	mmconf_resource(dev, index++);
 90  
 91  	add_fixed_resources(dev, index);
 92  }
 93  
 94  void northbridge_write_smram(u8 smram)
 95  {
 96  	struct device *dev = pcidev_on_root(0, 0);
 97  
 98  	if (!dev)
 99  		die("could not find pci 00:00.0!\n");
100  
101  	pci_write_config8(dev, SMRAM, smram);
102  }
103  
104  static void mch_domain_set_resources(struct device *dev)
105  {
106  	struct resource *res;
107  
108  	for (res = dev->resource_list; res; res = res->next)
109  		report_resource_stored(dev, res, "");
110  
111  	assign_resources(dev->downstream);
112  }
113  
114  static void mch_domain_init(struct device *dev)
115  {
116  	/* Enable SERR */
117  	pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_SERR);
118  }
119  
120  static const char *northbridge_acpi_name(const struct device *dev)
121  {
122  	if (dev->path.type == DEVICE_PATH_DOMAIN)
123  		return "PCI0";
124  
125  	if (!is_pci_dev_on_bus(dev, 0))
126  		return NULL;
127  
128  	switch (dev->path.pci.devfn) {
129  	case PCI_DEVFN(0, 0):
130  		return "MCHC";
131  	}
132  
133  	return NULL;
134  }
135  
136  static struct device_operations pci_domain_ops = {
137  	.read_resources	= mch_domain_read_resources,
138  	.set_resources	= mch_domain_set_resources,
139  	.init		= mch_domain_init,
140  	.scan_bus	= pci_host_bridge_scan_bus,
141  	.acpi_fill_ssdt	= generate_cpu_entries,
142  	.acpi_name	= northbridge_acpi_name,
143  };
144  
145  static struct device_operations cpu_bus_ops = {
146  	.read_resources   = noop_read_resources,
147  	.set_resources    = noop_set_resources,
148  	.init             = mp_cpu_bus_init,
149  };
150  
151  static void enable_dev(struct device *dev)
152  {
153  	/* Set the operations if it is a special bus type */
154  	if (dev->path.type == DEVICE_PATH_DOMAIN) {
155  		dev->ops = &pci_domain_ops;
156  	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
157  		dev->ops = &cpu_bus_ops;
158  	}
159  }
160  
161  struct chip_operations northbridge_intel_pineview_ops = {
162  	.name = "Intel Pineview Northbridge",
163  	.enable_dev = enable_dev,
164  };