blob: 00c9ba4f8530fdb6f028f4bf3546ce4f03c7d68b [file] [log] [blame]
Angel Pons80d92382020-04-05 15:47:00 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Mariusz Szafranskia4041332017-08-02 17:28:17 +02003
4#include <arch/acpi.h>
5#include <arch/acpigen.h>
6#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>
19
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020020#define MWAIT_RES(state, sub_state) \
21 { \
22 .addrl = (((state) << 4) | (sub_state)), \
23 .space_id = ACPI_ADDRESS_SPACE_FIXED, \
24 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
25 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
26 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
27 }
28
29#define CSTATE_RES(address_space, width, offset, address) \
30 { \
31 .space_id = address_space, \
32 .bit_width = width, \
33 .bit_offset = offset, \
34 .addrl = address, \
35 }
36
37static acpi_cstate_t cstate_map[] = {
38 {
39 /* C1 */
40 .ctype = 1, /* ACPI C1 */
41 .latency = 2,
42 .power = 1000,
43 .resource = MWAIT_RES(0, 0),
44 },
45 {
46 .ctype = 2, /* ACPI C2 */
47 .latency = 10,
48 .power = 10,
49 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0,
50 ACPI_BASE_ADDRESS + 0x14),
51 },
52 {
53 .ctype = 3, /* ACPI C3 */
54 .latency = 50,
55 .power = 10,
56 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0,
57 ACPI_BASE_ADDRESS + 0x15),
58 }
59};
60
Mariusz Szafranskia4041332017-08-02 17:28:17 +020061void acpi_init_gnvs(global_nvs_t *gnvs)
62{
63 /* CPU core count */
64 gnvs->pcnt = dev_count_cpu();
65
66 /* Top of Low Memory (start of resource allocation) */
Michael Niewöhner46e68ac2019-11-04 22:07:29 +010067 gnvs->tolm = (uintptr_t)cbmem_top();
Mariusz Szafranskia4041332017-08-02 17:28:17 +020068
Julius Wernercd49cce2019-03-05 16:53:33 -080069#if CONFIG(CONSOLE_CBMEM)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020070 /* Update the mem console pointer. */
71 gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE);
72#endif
73
74 /* MMIO Low/High & TSEG base and length */
75 gnvs->mmiob = (u32)get_top_of_low_memory();
76 gnvs->mmiol = (u32)(get_pciebase() - 1);
77 gnvs->mmiohb = (u64)get_top_of_upper_memory();
78 gnvs->mmiohl = (u64)(((u64)1 << CONFIG_CPU_ADDR_BITS) - 1);
79 gnvs->tsegb = (u32)get_tseg_memory();
80 gnvs->tsegl = (u32)(get_top_of_low_memory() - get_tseg_memory());
81}
82
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020083uint32_t soc_read_sci_irq_select(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020084{
Elyes HAOUAS2ec41832018-05-27 17:40:58 +020085 struct device *dev = get_pmc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +020086
87 if (!dev)
88 return 0;
89
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020090 return pci_read_config32(dev, PMC_ACPI_CNT);
91}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020092
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +020093acpi_cstate_t *soc_get_cstate_map(size_t *entries)
94{
95 *entries = ARRAY_SIZE(cstate_map);
96 return cstate_map;
Mariusz Szafranskia4041332017-08-02 17:28:17 +020097}
98
99unsigned long acpi_fill_mcfg(unsigned long current)
100{
101 u32 pciexbar_reg;
102 int max_buses;
103
104 pciexbar_reg = get_pciebase();
105 max_buses = get_pcielength();
106
107 if (!pciexbar_reg)
108 return current;
109
110 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
111 pciexbar_reg, 0x0, 0x0,
112 (u8)(max_buses - 1));
113
114 return current;
115}
116
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200117__attribute__ ((weak)) void motherboard_fill_fadt(acpi_fadt_t *fadt)
118{
119}
120
121void soc_fill_fadt(acpi_fadt_t *fadt)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200122{
123 u16 pmbase = get_pmbase();
124
125 /* System Management */
Julius Wernercd49cce2019-03-05 16:53:33 -0800126 if (!CONFIG(HAVE_SMI_HANDLER)) {
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200127 fadt->smi_cmd = 0x00;
128 fadt->acpi_enable = 0x00;
129 fadt->acpi_disable = 0x00;
130 }
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200131
132 /* Power Control */
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200133 fadt->pm2_cnt_blk = pmbase + PM2_CNT;
134 fadt->pm_tmr_blk = pmbase + PM1_TMR;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200135 fadt->gpe1_blk = 0;
136
137 /* Control Registers - Length */
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200138 fadt->pm2_cnt_len = 1;
139 fadt->pm_tmr_len = 4;
140 fadt->gpe0_blk_len = 8;
141 fadt->gpe1_blk_len = 0;
142 fadt->gpe1_base = 0;
143 fadt->cst_cnt = 0;
144 fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
145 fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
146 fadt->flush_size = 0; /* set to 0 if WBINVD is 1 in flags */
147 fadt->flush_stride = 0; /* set to 0 if WBINVD is 1 in flags */
148 fadt->duty_offset = 1;
149 fadt->duty_width = 0;
150
151 /* RTC Registers */
152 fadt->day_alrm = 0x0D;
153 fadt->mon_alrm = 0x00;
154 fadt->century = 0x00;
155 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
156
157 fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
158 ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
159 ACPI_FADT_RESET_REGISTER | ACPI_FADT_SLEEP_TYPE |
160 ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
161
162 /* Reset Register */
163 fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
164 fadt->reset_reg.bit_width = 8;
165 fadt->reset_reg.bit_offset = 0;
166 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
167 fadt->reset_reg.addrl = 0xCF9;
168 fadt->reset_reg.addrh = 0x00;
169 fadt->reset_value = 6;
170
171 /* PM1 Status & PM1 Enable */
172 fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
173 fadt->x_pm1a_evt_blk.bit_width = 32;
174 fadt->x_pm1a_evt_blk.bit_offset = 0;
175 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
176 fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
177 fadt->x_pm1a_evt_blk.addrh = 0x00;
178
179 fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
180 fadt->x_pm1b_evt_blk.bit_width = 0;
181 fadt->x_pm1b_evt_blk.bit_offset = 0;
182 fadt->x_pm1b_evt_blk.access_size = 0;
183 fadt->x_pm1b_evt_blk.addrl = fadt->pm1b_evt_blk;
184 fadt->x_pm1b_evt_blk.addrh = 0x00;
185
186 /* PM1 Control Registers */
187 fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
188 fadt->x_pm1a_cnt_blk.bit_width = 16;
189 fadt->x_pm1a_cnt_blk.bit_offset = 0;
190 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
191 fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
192 fadt->x_pm1a_cnt_blk.addrh = 0x00;
193
194 fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
195 fadt->x_pm1b_cnt_blk.bit_width = 0;
196 fadt->x_pm1b_cnt_blk.bit_offset = 0;
197 fadt->x_pm1b_cnt_blk.access_size = 0;
198 fadt->x_pm1b_cnt_blk.addrl = fadt->pm1b_cnt_blk;
199 fadt->x_pm1b_cnt_blk.addrh = 0x00;
200
201 /* PM2 Control Registers */
202 fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
203 fadt->x_pm2_cnt_blk.bit_width = 8;
204 fadt->x_pm2_cnt_blk.bit_offset = 0;
205 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
206 fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
207 fadt->x_pm2_cnt_blk.addrh = 0x00;
208
209 /* PM1 Timer Register */
210 fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
211 fadt->x_pm_tmr_blk.bit_width = 32;
212 fadt->x_pm_tmr_blk.bit_offset = 0;
213 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
214 fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
215 fadt->x_pm_tmr_blk.addrh = 0x00;
216
217 /* General-Purpose Event Registers */
218 fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
219 fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + EventEnable */
220 fadt->x_gpe0_blk.bit_offset = 0;
221 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
222 fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
223 fadt->x_gpe0_blk.addrh = 0x00;
224
225 fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
226 fadt->x_gpe1_blk.bit_width = 0;
227 fadt->x_gpe1_blk.bit_offset = 0;
228 fadt->x_gpe1_blk.access_size = 0;
229 fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
230 fadt->x_gpe1_blk.addrh = 0x00;
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200231
232 motherboard_fill_fadt(fadt);
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200233}
234
Julien Viard de Galbert595202c2018-03-29 14:01:01 +0200235static acpi_tstate_t denverton_tss_table[] = {
236 { 100, 1000, 0, 0x00, 0 },
237 { 88, 875, 0, 0x1e, 0 },
238 { 75, 750, 0, 0x1c, 0 },
239 { 63, 625, 0, 0x1a, 0 },
240 { 50, 500, 0, 0x18, 0 },
241 { 38, 375, 0, 0x16, 0 },
242 { 25, 250, 0, 0x14, 0 },
243 { 13, 125, 0, 0x12, 0 },
244};
245
246acpi_tstate_t *soc_get_tss_table(int *entries)
247{
248 *entries = ARRAY_SIZE(denverton_tss_table);
249 return denverton_tss_table;
250}
251
252void soc_power_states_generation(int core_id, int cores_per_package)
253{
254 generate_p_state_entries(core_id, cores_per_package);
255
256 generate_t_state_entries(core_id, cores_per_package);
257}
258
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200259int soc_madt_sci_irq_polarity(int sci)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200260{
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200261 if (sci >= 20)
262 return MP_IRQ_POLARITY_LOW;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200263 else
Julien Viard de Galbertcf2b72f2018-04-05 11:24:45 +0200264 return MP_IRQ_POLARITY_HIGH;
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200265}
266
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200267unsigned long southcluster_write_acpi_tables(struct device *device,
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200268 unsigned long current,
269 struct acpi_rsdp *rsdp)
270{
271 acpi_header_t *ssdt2;
272
273 current = acpi_write_hpet(device, current, rsdp);
274 current = (ALIGN(current, 16));
275
276 ssdt2 = (acpi_header_t *)current;
277 memset(ssdt2, 0, sizeof(acpi_header_t));
278 acpi_create_serialio_ssdt(ssdt2);
279 if (ssdt2->length) {
280 current += ssdt2->length;
281 acpi_add_table(rsdp, ssdt2);
282 printk(BIOS_DEBUG, "ACPI: * SSDT2 @ %p Length %x\n", ssdt2,
283 ssdt2->length);
284 current = (ALIGN(current, 16));
285 } else {
286 ssdt2 = NULL;
287 printk(BIOS_DEBUG, "ACPI: * SSDT2 not generated.\n");
288 }
289
290 printk(BIOS_DEBUG, "current = %lx\n", current);
291
292 return current;
293}
294
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200295void southcluster_inject_dsdt(struct device *device)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200296{
297 global_nvs_t *gnvs;
298
299 gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
300 if (!gnvs) {
301 gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
302 if (gnvs)
303 memset(gnvs, 0, sizeof(*gnvs));
304 }
305
306 if (gnvs) {
307 acpi_create_gnvs(gnvs);
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200308 /* And tell SMI about it */
309 smm_setup_structures(gnvs, NULL, NULL);
310
311 /* Add it to DSDT. */
312 acpigen_write_scope("\\");
313 acpigen_write_name_dword("NVSA", (u32)gnvs);
314 acpigen_pop_len();
315 }
316}
317
Aaron Durbin64031672018-04-21 14:45:32 -0600318__weak void acpi_create_serialio_ssdt(acpi_header_t *ssdt) {}