1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <cbmem.h>
4 #include <console/console.h>
5 #include <device/pci_def.h>
6 #include <device/pci_ops.h>
7 #include <stdint.h>
8 #include <device/device.h>
9 #include <boot/tables.h>
10 #include <acpi/acpi.h>
11 #include <northbridge/intel/x4x/memmap.h>
12 #include <northbridge/intel/x4x/chip.h>
13 #include <northbridge/intel/x4x/x4x.h>
14 #include <cpu/intel/smm_reloc.h>
15 #include <cpu/intel/speedstep.h>
16 #include <cpu/x86/smm.h>
17
mch_domain_read_resources(struct device * dev)18 static void mch_domain_read_resources(struct device *dev)
19 {
20 u8 index;
21 u64 tom, touud;
22 u32 tolud;
23
24 index = 3;
25
26 pci_domain_read_resources(dev);
27
28 struct device *mch = pcidev_on_root(0, 0);
29
30 /* Top of Upper Usable DRAM, including remap */
31 touud = pci_read_config16(mch, D0F0_TOUUD);
32 touud <<= 20;
33
34 /* Top of Lower Usable DRAM */
35 tolud = pci_read_config16(mch, D0F0_TOLUD) & 0xfff0;
36 tolud <<= 16;
37
38 /* Top of Memory - does not account for any UMA */
39 tom = pci_read_config16(mch, D0F0_TOM) & 0x01ff;
40 tom <<= 26;
41
42 printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx\n", touud, tolud, tom);
43
44 /* Report the memory regions */
45 ram_from_to(dev, index++, 0, 0xa0000);
46 mmio_from_to(dev, index++, 0xa0000, 0xc0000);
47 reserved_ram_from_to(dev, index++, 0xc0000, 1 * MiB);
48 ram_from_to(dev, index++, 1 * MiB, cbmem_top());
49
50 /*
51 * If >= 4GB installed then memory from TOLUD to 4GB
52 * is remapped above TOM, TOUUD will account for both
53 */
54 upper_ram_end(dev, index++, touud);
55
56 uintptr_t tseg_base;
57 size_t tseg_size;
58 smm_region(&tseg_base, &tseg_size);
59 mmio_from_to(dev, index++, tseg_base, tolud);
60 reserved_ram_from_to(dev, index++, cbmem_top(), tseg_base);
61
62 /* Reserve high memory where the NB BARs are up to 4GiB */
63 mmio_from_to(dev, index++, DEFAULT_HECIBAR, 4ull * GiB);
64
65 mmconf_resource(dev, index++);
66 }
67
mch_domain_set_resources(struct device * dev)68 static void mch_domain_set_resources(struct device *dev)
69 {
70 struct resource *res;
71
72 for (res = dev->resource_list; res; res = res->next)
73 report_resource_stored(dev, res, "");
74
75 assign_resources(dev->downstream);
76 }
77
mch_domain_init(struct device * dev)78 static void mch_domain_init(struct device *dev)
79 {
80 /* Enable SERR */
81 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_SERR);
82 }
83
northbridge_acpi_name(const struct device * dev)84 static const char *northbridge_acpi_name(const struct device *dev)
85 {
86 if (dev->path.type == DEVICE_PATH_DOMAIN)
87 return "PCI0";
88
89 if (!is_pci_dev_on_bus(dev, 0))
90 return NULL;
91
92 switch (dev->path.pci.devfn) {
93 case PCI_DEVFN(0, 0):
94 return "MCHC";
95 }
96
97 return NULL;
98 }
99
northbridge_write_smram(u8 smram)100 void northbridge_write_smram(u8 smram)
101 {
102 struct device *dev = pcidev_on_root(0, 0);
103
104 if (!dev)
105 die("could not find pci 00:00.0!\n");
106
107 pci_write_config8(dev, D0F0_SMRAM, smram);
108 }
109
110 struct device_operations x4x_pci_domain_ops = {
111 .read_resources = mch_domain_read_resources,
112 .set_resources = mch_domain_set_resources,
113 .init = mch_domain_init,
114 .scan_bus = pci_host_bridge_scan_bus,
115 .write_acpi_tables = northbridge_write_acpi_tables,
116 .acpi_fill_ssdt = generate_cpu_entries,
117 .acpi_name = northbridge_acpi_name,
118 };
119
120 struct device_operations x4x_cpu_bus_ops = {
121 .read_resources = noop_read_resources,
122 .set_resources = noop_set_resources,
123 .init = mp_cpu_bus_init,
124 };
125
hide_pci_fn(const int dev_bit_base,const struct device * dev)126 static void hide_pci_fn(const int dev_bit_base, const struct device *dev)
127 {
128 if (!dev || dev->enabled)
129 return;
130 const unsigned int fn = PCI_FUNC(dev->path.pci.devfn);
131 const struct device *const d0f0 = pcidev_on_root(0, 0);
132 pci_update_config32(d0f0, D0F0_DEVEN, ~(1 << (dev_bit_base + fn)), 0);
133 }
134
hide_pci_dev(const int dev,int functions,const int dev_bit_base)135 static void hide_pci_dev(const int dev, int functions, const int dev_bit_base)
136 {
137 for (; functions >= 0; functions--)
138 hide_pci_fn(dev_bit_base, pcidev_on_root(dev, functions));
139 }
140
x4x_init(void * const chip_info)141 static void x4x_init(void *const chip_info)
142 {
143 struct device *const d0f0 = pcidev_on_root(0x0, 0);
144
145 /* Hide internal functions based on devicetree info. */
146 hide_pci_dev(6, 0, 13); /* PEG1: only on P45 */
147 hide_pci_dev(3, 3, 6); /* ME */
148 hide_pci_dev(2, 1, 3); /* IGD */
149 hide_pci_dev(1, 0, 1); /* PEG0 */
150
151 const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN);
152 if (!(deven & (0xf << 6)))
153 pci_write_config32(d0f0, D0F0_DEVEN, deven & ~(1 << 14));
154 }
155
156 struct chip_operations northbridge_intel_x4x_ops = {
157 .name = "Intel 4-Series Northbridge",
158 .init = x4x_init,
159 };
160
northbridge_support_slfm(void)161 bool northbridge_support_slfm(void)
162 {
163 return false;
164 }
165