blob: 81e4bed38f8d4633596720c3f3714f9b98c93e55 [file] [log] [blame]
Ravi Sarawadi91ffac82022-05-07 16:37:09 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
Eran Mitrani5f4f1b852022-12-19 10:32:46 -08003#include <arch/ioapic.h>
Ravi Sarawadi91ffac82022-05-07 16:37:09 -07004#include <console/console.h>
Eran Mitrani5f4f1b852022-12-19 10:32:46 -08005#include <cpu/x86/msr.h>
Ravi Sarawadi91ffac82022-05-07 16:37:09 -07006#include <device/device.h>
7#include <device/pci.h>
8#include <device/pci_ids.h>
9#include <delay.h>
Eran Mitrani5f4f1b852022-12-19 10:32:46 -080010#include <intelblocks/cpulib.h>
11#include <intelblocks/msr.h>
Ravi Sarawadi91ffac82022-05-07 16:37:09 -070012#include <intelblocks/power_limit.h>
13#include <intelblocks/systemagent.h>
14#include <soc/iomap.h>
15#include <soc/soc_chip.h>
16#include <soc/systemagent.h>
17
18/*
19 * SoC implementation
20 *
21 * Add all known fixed memory ranges for Host Controller/Memory
22 * controller.
23 */
24void soc_add_fixed_mmio_resources(struct device *dev, int *index)
25{
26 static const struct sa_mmio_descriptor soc_fixed_resources[] = {
Eran Mitrani5f4f1b852022-12-19 10:32:46 -080027 { MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" },
Ravi Sarawadi91ffac82022-05-07 16:37:09 -070028 { DMIBAR, DMI_BASE_ADDRESS, DMI_BASE_SIZE, "DMIBAR" },
29 { EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" },
30 { REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" },
31 { EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" },
Eran Mitrani5f4f1b852022-12-19 10:32:46 -080032
33 /* first field (sa_mmio_descriptor.index) is not used, setting to 0: */
34 { 0, CRAB_ABORT_BASE_ADDR, CRAB_ABORT_SIZE, "CRAB_ABORT" },
35 { 0, LT_SECURITY_BASE_ADDR, LT_SECURITY_SIZE, "LT_SECURITY" },
36 { 0, IO_APIC_ADDR, APIC_SIZE, "APIC" },
37 // PCH_PRESERVERD covers:
38 // TraceHub SW BAR, PMC MBAR, SPI BAR0, SerialIo BAR in ACPI mode
39 // eSPI LGMR BAR, eSPI2 SEGMR BAR, TraceHub MTB BAR, TraceHub FW BAR
40 // IOE PMC BAR, Tracehub RTIT BAR (SOC), HECI{1,2,3} BAR0
41 // see fsp/ClientOneSiliconPkg/Fru/MtlSoc/Include/PchReservedResources.h
42 { 0, PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE, "PCH_RESERVED" },
Ravi Sarawadi91ffac82022-05-07 16:37:09 -070043 };
44
45 sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources,
46 ARRAY_SIZE(soc_fixed_resources));
47
48 /* Add Vt-d resources if VT-d is enabled */
49 if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE))
50 return;
51
52 sa_add_fixed_mmio_resources(dev, index, soc_vtd_resources,
53 ARRAY_SIZE(soc_vtd_resources));
54}
55
56/*
Eran Mitrani5f4f1b852022-12-19 10:32:46 -080057 * set MMIO resource's fields
58 */
59static void set_mmio_resource(
60 struct sa_mmio_descriptor *resource,
61 uint64_t base,
62 uint64_t size,
63 const char *description)
64{
65 if (resource == NULL) {
66 printk(BIOS_ERR, "%s: argument resource is NULL for %s\n",
67 __func__, description);
68 return;
69 }
70 resource->base = base;
71 resource->size = size;
72 resource->description = description;
73}
74
75int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base,
76 uint64_t *prmrr_mask)
77{
78 msr_t msr;
79 msr = rdmsr(MSR_PRMRR_BASE_0);
80 *prmrr_base = (uint64_t)msr.hi << 32 | msr.lo;
81 msr = rdmsr(MSR_PRMRR_PHYS_MASK);
82 *prmrr_mask = (uint64_t)msr.hi << 32 | msr.lo;
83 return 0;
84}
85
86/*
87 * SoC implementation
88 *
89 * Add all known configurable memory ranges for Host Controller/Memory
90 * controller.
91 */
92void soc_add_configurable_mmio_resources(struct device *dev, int *resource_cnt)
93{
94 uint64_t size, base, tseg_base;
95 int count = 0;
96 struct sa_mmio_descriptor cfg_rsrc[6]; /* Increase size when adding more resources */
97
98 /* MMCONF */
99 size = get_mmcfg_size(dev);
100 if (size > 0)
101 set_mmio_resource(&(cfg_rsrc[count++]), CONFIG_ECAM_MMCONF_BASE_ADDRESS,
102 size, "MMCONF");
103
104 /* DSM */
105 size = get_dsm_size(dev);
106 if (size > 0) {
107 base = pci_read_config32(dev, DSM_BASE_ADDR_REG) & 0xFFF00000;
108 set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DSM");
109 }
110
111 /* TSEG */
112 size = sa_get_tseg_size();
113 tseg_base = sa_get_tseg_base();
114 if (size > 0)
115 set_mmio_resource(&(cfg_rsrc[count++]), tseg_base, size, "TSEG");
116
117 /* PMRR */
118 size = get_valid_prmrr_size();
119 if (size > 0) {
120 uint64_t mask;
121 if (soc_get_uncore_prmmr_base_and_mask(&base, &mask) == 0) {
122 base &= mask;
123 set_mmio_resource(&(cfg_rsrc[count++]), base, size, "PMRR");
124 } else {
125 printk(BIOS_ERR, "SA: Failed to get PRMRR base and mask\n");
126 }
127 }
128
129 /* GSM */
130 size = get_gsm_size(dev);
131 if (size > 0) {
132 base = sa_get_gsm_base();
133 set_mmio_resource(&(cfg_rsrc[count++]), base, size, "GSM");
134 }
135
136 /* DPR */
137 size = get_dpr_size(dev);
138 if (size > 0) {
139 /* DPR just below TSEG: */
140 base = tseg_base - size;
141 set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DPR");
142 }
143
144 /* Add all the above */
145 sa_add_fixed_mmio_resources(dev, resource_cnt, cfg_rsrc, count);
146}
147
148/*
Ravi Sarawadi91ffac82022-05-07 16:37:09 -0700149 * SoC implementation
150 *
151 * Perform System Agent Initialization during Ramstage phase.
152 */
153void soc_systemagent_init(struct device *dev)
154{
155 struct soc_power_limits_config *soc_config;
156 struct device *sa;
157 uint16_t sa_pci_id;
158 config_t *config;
159
160 /* Enable Power Aware Interrupt Routing */
161 enable_power_aware_intr();
162
Ravi Sarawadi91ffac82022-05-07 16:37:09 -0700163 config = config_of_soc();
164
165 /* Get System Agent PCI ID */
166 sa = pcidev_path_on_root(PCI_DEVFN_ROOT);
167 sa_pci_id = sa ? pci_read_config16(sa, PCI_DEVICE_ID) : 0xFFFF;
168
169 /* Choose a power limits configuration based on the SoC SKU type,
170 * differentiated here based on SA PCI ID. */
171 switch (sa_pci_id) {
172 case PCI_DID_INTEL_MTL_P_ID_1:
173 soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_1];
174 break;
175 case PCI_DID_INTEL_MTL_P_ID_2:
176 soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_2];
177 break;
178 case PCI_DID_INTEL_MTL_P_ID_3:
179 soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_3];
180 break;
Sridhar Siricillace4dc662022-11-14 08:47:34 +0530181 case PCI_DID_INTEL_MTL_P_ID_4:
182 soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_4];
183 break;
Ravi Sarawadi91ffac82022-05-07 16:37:09 -0700184 default:
185 printk(BIOS_ERR, "unknown SA ID: 0x%4x, skipping power limits configuration\n",
186 sa_pci_id);
187 return;
188 }
189
Arthur Heymanse55aa0b2022-07-29 10:47:02 +0200190 /* Remove once commented line below is enabled */
191 (void)soc_config;
Ravi Sarawadi91ffac82022-05-07 16:37:09 -0700192 /* UPDATEME: Need to enable later */
193 //set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
194}
195
196uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
197{
198 switch (capid0_a_ddrsz) {
199 case 1:
200 return 8192;
201 case 2:
202 return 4096;
203 case 3:
204 return 2048;
205 default:
206 return 65536;
207 }
208}
Eran Mitrani5f4f1b852022-12-19 10:32:46 -0800209
210uint64_t get_mmcfg_size(const struct device *dev)
211{
212 uint32_t pciexbar_reg;
213 uint64_t mmcfg_length;
214
215 if (!dev) {
216 printk(BIOS_DEBUG, "%s : device is null\n", __func__);
217 return 0;
218 }
219
220 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
221
222 if (!(pciexbar_reg & (1 << 0))) {
223 printk(BIOS_DEBUG, "%s : PCIEXBAR disabled\n", __func__);
224 return 0;
225 }
226
227 switch ((pciexbar_reg & MASK_PCIEXBAR_LENGTH) >> PCIEXBAR_LENGTH_LSB) {
228 case PCIEXBAR_LENGTH_4096MB:
229 mmcfg_length = 4 * ((uint64_t)GiB);
230 break;
231 case PCIEXBAR_LENGTH_2048MB:
232 mmcfg_length = 2 * ((uint64_t)GiB);
233 break;
234 case PCIEXBAR_LENGTH_1024MB:
235 mmcfg_length = 1 * GiB;
236 break;
237 case PCIEXBAR_LENGTH_512MB:
238 mmcfg_length = 512 * MiB;
239 break;
240 case PCIEXBAR_LENGTH_256MB:
241 mmcfg_length = 256 * MiB;
242 break;
243 case PCIEXBAR_LENGTH_128MB:
244 mmcfg_length = 128 * MiB;
245 break;
246 case PCIEXBAR_LENGTH_64MB:
247 mmcfg_length = 64 * MiB;
248 break;
249 default:
250 printk(BIOS_DEBUG, "%s : PCIEXBAR - invalid length (0x%x)\n", __func__,
251 pciexbar_reg & MASK_PCIEXBAR_LENGTH);
252 mmcfg_length = 0x0;
253 break;
254 }
255
256 return mmcfg_length;
257}
258
259uint64_t get_dsm_size(const struct device *dev)
260{
261 // - size : B0/D0/F0:R 50h [15:8]
262 uint32_t reg32 = pci_read_config32(dev, GGC);
263 uint64_t size;
264 uint32_t size_field = (reg32 & MASK_DSM_LENGTH) >> MASK_DSM_LENGTH_LSB;
265 if (size_field <= 0x10) { // 0x0 - 0x10
266 size = size_field * 32 * MiB;
267 } else if ((size_field >= 0xF0) && (size_field >= 0xFE)) {
268 size = ((uint64_t)size_field - 0xEF) * 4 * MiB;
269 } else {
270 switch (size_field) {
271 case 0x20:
272 size = 1 * GiB;
273 break;
274 case 0x30:
275 size = 1536 * MiB;
276 break;
277 case 0x40:
278 size = 2 * (uint64_t)GiB;
279 break;
280 default:
281 printk(BIOS_DEBUG, "%s : DSM - invalid length (0x%x)\n",
282 __func__, size_field);
283 size = 0x0;
284 break;
285 }
286 }
287 return size;
288}
289
290uint64_t get_gsm_size(const struct device *dev)
291{
292 const u32 gsm_size = pci_read_config32(dev, GGC);
293 uint64_t size;
294 uint32_t size_field = (gsm_size & MASK_GSM_LENGTH) >> MASK_GSM_LENGTH_LSB;
295 switch (size_field) {
296 case 0x0:
297 size = 0;
298 break;
299 case 0x1:
300 size = 2 * MiB;
301 break;
302 case 0x2:
303 size = 4 * MiB;
304 break;
305 case 0x3:
306 size = 8 * MiB;
307 break;
308 default:
309 size = 0;
310 break;
311 }
312 return size;
313}
314uint64_t get_dpr_size(const struct device *dev)
315{
316 uint64_t size;
317 uint32_t dpr_reg = pci_read_config32(dev, DPR_REG);
318 uint32_t size_field = (dpr_reg & MASK_DPR_LENGTH) >> MASK_DPR_LENGTH_LSB;
319 size = (uint64_t)size_field * MiB;
320 return size;
321}