blob: e7d29ff799e031974cfd07c45695de9fa7bf2b45 [file] [log] [blame]
Angel Pons80d92382020-04-05 15:47:00 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Mariusz Szafranskia4041332017-08-02 17:28:17 +02002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +03004#include <acpi/acpi_gnvs.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07005#include <acpi/acpigen.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +02006#include <arch/smp/mpspec.h>
7#include <cpu/x86/smm.h>
8#include <string.h>
9#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020010#include <device/pci_ops.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +020011#include <cbmem.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010012#include <console/console.h>
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020013#include <intelblocks/acpi.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +020014#include <soc/acpi.h>
15#include <soc/cpu.h>
16#include <soc/soc_util.h>
17#include <soc/pmc.h>
18#include <soc/systemagent.h>
Julien Viard de Galberta0e50462018-04-05 11:59:07 +020019#include <soc/pci_devs.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +020020
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020021#define MWAIT_RES(state, sub_state) \
22 { \
23 .addrl = (((state) << 4) | (sub_state)), \
24 .space_id = ACPI_ADDRESS_SPACE_FIXED, \
25 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
26 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
27 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
28 }
29
30#define CSTATE_RES(address_space, width, offset, address) \
31 { \
32 .space_id = address_space, \
33 .bit_width = width, \
34 .bit_offset = offset, \
35 .addrl = address, \
36 }
37
38static acpi_cstate_t cstate_map[] = {
39 {
40 /* C1 */
41 .ctype = 1, /* ACPI C1 */
42 .latency = 2,
43 .power = 1000,
44 .resource = MWAIT_RES(0, 0),
45 },
46 {
47 .ctype = 2, /* ACPI C2 */
48 .latency = 10,
49 .power = 10,
50 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0,
51 ACPI_BASE_ADDRESS + 0x14),
52 },
53 {
54 .ctype = 3, /* ACPI C3 */
55 .latency = 50,
56 .power = 10,
57 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0,
58 ACPI_BASE_ADDRESS + 0x15),
59 }
60};
61
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +030062void acpi_init_gnvs(struct global_nvs *gnvs)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020063{
64 /* CPU core count */
65 gnvs->pcnt = dev_count_cpu();
66
67 /* Top of Low Memory (start of resource allocation) */
Michael Niewöhner46e68ac2019-11-04 22:07:29 +010068 gnvs->tolm = (uintptr_t)cbmem_top();
Mariusz Szafranskia4041332017-08-02 17:28:17 +020069
Julius Wernercd49cce2019-03-05 16:53:33 -080070#if CONFIG(CONSOLE_CBMEM)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020071 /* Update the mem console pointer. */
72 gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE);
73#endif
74
75 /* MMIO Low/High & TSEG base and length */
76 gnvs->mmiob = (u32)get_top_of_low_memory();
77 gnvs->mmiol = (u32)(get_pciebase() - 1);
78 gnvs->mmiohb = (u64)get_top_of_upper_memory();
79 gnvs->mmiohl = (u64)(((u64)1 << CONFIG_CPU_ADDR_BITS) - 1);
80 gnvs->tsegb = (u32)get_tseg_memory();
81 gnvs->tsegl = (u32)(get_top_of_low_memory() - get_tseg_memory());
82}
83
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020084uint32_t soc_read_sci_irq_select(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020085{
Elyes HAOUAS2ec41832018-05-27 17:40:58 +020086 struct device *dev = get_pmc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +020087
88 if (!dev)
89 return 0;
90
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020091 return pci_read_config32(dev, PMC_ACPI_CNT);
92}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020093
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020094acpi_cstate_t *soc_get_cstate_map(size_t *entries)
95{
96 *entries = ARRAY_SIZE(cstate_map);
97 return cstate_map;
Mariusz Szafranskia4041332017-08-02 17:28:17 +020098}
99
100unsigned long acpi_fill_mcfg(unsigned long current)
101{
102 u32 pciexbar_reg;
103 int max_buses;
104
105 pciexbar_reg = get_pciebase();
106 max_buses = get_pcielength();
107
108 if (!pciexbar_reg)
109 return current;
110
111 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
112 pciexbar_reg, 0x0, 0x0,
113 (u8)(max_buses - 1));
114
115 return current;
116}
117
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200118void soc_fill_fadt(acpi_fadt_t *fadt)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200119{
120 u16 pmbase = get_pmbase();
121
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200122 /* Power Control */
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200123 fadt->pm2_cnt_blk = pmbase + PM2_CNT;
124 fadt->pm_tmr_blk = pmbase + PM1_TMR;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200125
126 /* Control Registers - Length */
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200127 fadt->pm2_cnt_len = 1;
128 fadt->pm_tmr_len = 4;
129 fadt->gpe0_blk_len = 8;
Kyösti Mälkkic328a682019-11-23 07:23:40 +0200130
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200131 fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
132 fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200133 fadt->duty_offset = 1;
134 fadt->duty_width = 0;
135
136 /* RTC Registers */
137 fadt->day_alrm = 0x0D;
138 fadt->mon_alrm = 0x00;
139 fadt->century = 0x00;
140 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
141
Angel Ponsa208c6c2020-07-13 00:02:34 +0200142 fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
143 ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
Angel Pons79572e42020-07-13 00:17:43 +0200144 ACPI_FADT_SLEEP_TYPE | ACPI_FADT_S4_RTC_WAKE |
145 ACPI_FADT_PLATFORM_CLOCK;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200146
147 /* PM1 Status & PM1 Enable */
148 fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
149 fadt->x_pm1a_evt_blk.bit_width = 32;
150 fadt->x_pm1a_evt_blk.bit_offset = 0;
Angel Pons12a4d052020-07-14 01:31:27 +0200151 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200152 fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
153 fadt->x_pm1a_evt_blk.addrh = 0x00;
154
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200155 /* PM1 Control Registers */
156 fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
157 fadt->x_pm1a_cnt_blk.bit_width = 16;
158 fadt->x_pm1a_cnt_blk.bit_offset = 0;
159 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
160 fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
161 fadt->x_pm1a_cnt_blk.addrh = 0x00;
162
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200163 /* PM2 Control Registers */
164 fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
165 fadt->x_pm2_cnt_blk.bit_width = 8;
166 fadt->x_pm2_cnt_blk.bit_offset = 0;
167 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
168 fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
169 fadt->x_pm2_cnt_blk.addrh = 0x00;
170
171 /* PM1 Timer Register */
172 fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
173 fadt->x_pm_tmr_blk.bit_width = 32;
174 fadt->x_pm_tmr_blk.bit_offset = 0;
175 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
176 fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
177 fadt->x_pm_tmr_blk.addrh = 0x00;
178
179 /* General-Purpose Event Registers */
180 fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
181 fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + EventEnable */
182 fadt->x_gpe0_blk.bit_offset = 0;
Angel Ponsa23aff32020-06-21 20:47:54 +0200183 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200184 fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
185 fadt->x_gpe0_blk.addrh = 0x00;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200186}
187
Julien Viard de Galbert595202c2018-03-29 14:01:01 +0200188static acpi_tstate_t denverton_tss_table[] = {
189 { 100, 1000, 0, 0x00, 0 },
190 { 88, 875, 0, 0x1e, 0 },
191 { 75, 750, 0, 0x1c, 0 },
192 { 63, 625, 0, 0x1a, 0 },
193 { 50, 500, 0, 0x18, 0 },
194 { 38, 375, 0, 0x16, 0 },
195 { 25, 250, 0, 0x14, 0 },
196 { 13, 125, 0, 0x12, 0 },
197};
198
199acpi_tstate_t *soc_get_tss_table(int *entries)
200{
201 *entries = ARRAY_SIZE(denverton_tss_table);
202 return denverton_tss_table;
203}
204
205void soc_power_states_generation(int core_id, int cores_per_package)
206{
207 generate_p_state_entries(core_id, cores_per_package);
208
209 generate_t_state_entries(core_id, cores_per_package);
210}
211
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200212int soc_madt_sci_irq_polarity(int sci)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200213{
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200214 if (sci >= 20)
215 return MP_IRQ_POLARITY_LOW;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200216 else
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200217 return MP_IRQ_POLARITY_HIGH;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200218}
219
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700220unsigned long southcluster_write_acpi_tables(const struct device *device,
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200221 unsigned long current,
222 struct acpi_rsdp *rsdp)
223{
224 acpi_header_t *ssdt2;
225
226 current = acpi_write_hpet(device, current, rsdp);
227 current = (ALIGN(current, 16));
228
229 ssdt2 = (acpi_header_t *)current;
230 memset(ssdt2, 0, sizeof(acpi_header_t));
231 acpi_create_serialio_ssdt(ssdt2);
232 if (ssdt2->length) {
233 current += ssdt2->length;
234 acpi_add_table(rsdp, ssdt2);
235 printk(BIOS_DEBUG, "ACPI: * SSDT2 @ %p Length %x\n", ssdt2,
236 ssdt2->length);
237 current = (ALIGN(current, 16));
238 } else {
239 ssdt2 = NULL;
240 printk(BIOS_DEBUG, "ACPI: * SSDT2 not generated.\n");
241 }
242
243 printk(BIOS_DEBUG, "current = %lx\n", current);
244
245 return current;
246}
247
Furquan Shaikh338fd9a2020-04-24 22:57:05 -0700248void southcluster_inject_dsdt(const struct device *device)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200249{
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300250 struct global_nvs *gnvs;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200251
252 gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
253 if (!gnvs) {
254 gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
255 if (gnvs)
256 memset(gnvs, 0, sizeof(*gnvs));
257 }
258
259 if (gnvs) {
260 acpi_create_gnvs(gnvs);
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200261 /* And tell SMI about it */
Kyösti Mälkkic3c55212020-06-17 10:34:26 +0300262 apm_control(APM_CNT_GNVS_UPDATE);
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200263
264 /* Add it to DSDT. */
265 acpigen_write_scope("\\");
266 acpigen_write_name_dword("NVSA", (u32)gnvs);
267 acpigen_pop_len();
268 }
269}
270
Aaron Durbin64031672018-04-21 14:45:32 -0600271__weak void acpi_create_serialio_ssdt(acpi_header_t *ssdt) {}
Julien Viard de Galberta0e50462018-04-05 11:59:07 +0200272
273static unsigned long acpi_fill_dmar(unsigned long current)
274{
275 uint64_t vtbar;
276 unsigned long tmp = current;
277
278 vtbar = read64((void *)(DEFAULT_MCHBAR + MCH_VTBAR_OFFSET)) & MCH_VTBAR_MASK;
279 printk(BIOS_DEBUG, "DEFVTBAR:0x%llx\n", vtbar);
280 if (!vtbar)
281 return current;
282
283 current += acpi_create_dmar_drhd(current,
284 DRHD_INCLUDE_PCI_ALL, 0, vtbar);
285
286 current += acpi_create_dmar_ds_ioapic(current,
287 2, PCH_IOAPIC_PCI_BUS, PCH_IOAPIC_PCI_SLOT, 0);
288 current += acpi_create_dmar_ds_msi_hpet(current,
289 0, PCH_HPET_PCI_BUS, PCH_HPET_PCI_SLOT, 0);
290
291 acpi_dmar_drhd_fixup(tmp, current);
292
293 /* Create RMRR; see "VTD PLATFORM CONFIGURATION" in FSP log */
294 tmp = current;
295 current += acpi_create_dmar_rmrr(current, 0,
296 RMRR_USB_BASE_ADDRESS,
297 RMRR_USB_LIMIT_ADDRESS);
298 current += acpi_create_dmar_ds_pci(current,
299 0, XHCI_DEV, XHCI_FUNC);
300 acpi_dmar_rmrr_fixup(tmp, current);
301
302 return current;
303}
304
305unsigned long systemagent_write_acpi_tables(const struct device *dev,
306 unsigned long current,
307 struct acpi_rsdp *const rsdp)
308{
309 /* Create DMAR table only if we have VT-d capability. */
310 const u32 capid0_a = pci_read_config32(dev, CAPID0_A);
311 if (capid0_a & VTD_DISABLE)
312 return current;
313
314 acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
315 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
316 acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
317 current += dmar->header.length;
318 current = acpi_align_current(current);
319 acpi_add_table(rsdp, dmar);
320
321 return current;
322}