blob: 34f760ff424d889f2e6029cc168e1bf299c75de8 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Lance Zhaof51b1272015-11-09 17:06:34 -08002
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>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +01006#include <console/console.h>
Felix Singer6c3a89c2020-07-26 09:26:52 +02007#include <device/device.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Lance Zhao2fc82d62015-11-16 18:33:21 -08009#include <arch/smp/mpspec.h>
Elyes HAOUAScd4fe0f2019-03-29 17:12:15 +010010#include <assert.h>
Werner Zeh90cc7e22018-12-14 13:26:04 +010011#include <device/pci_ops.h>
Shaunak Sahabd427802017-07-18 00:19:33 -070012#include <gpio.h>
13#include <intelblocks/acpi.h>
14#include <intelblocks/pmclib.h>
Pratik Prajapatid06c7642017-10-11 11:52:16 -070015#include <intelblocks/sgx.h>
Werner Zeh90cc7e22018-12-14 13:26:04 +010016#include <intelblocks/p2sb.h>
Lance Zhaoe904c7c2015-11-10 19:00:18 -080017#include <soc/iomap.h>
18#include <soc/pm.h>
Lance Zhao1bd0c0c2016-04-19 18:04:21 -070019#include <soc/nvs.h>
Shaunak Sahacd9e1e42016-07-12 01:22:33 -070020#include <soc/pci_devs.h>
Werner Zeh90cc7e22018-12-14 13:26:04 +010021#include <soc/systemagent.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010022
Shaunak Sahacd9e1e42016-07-12 01:22:33 -070023#include "chip.h"
Lance Zhaof51b1272015-11-09 17:06:34 -080024
Hannah Williams0f61da82016-04-18 13:47:08 -070025#define CSTATE_RES(address_space, width, offset, address) \
26 { \
27 .space_id = address_space, \
28 .bit_width = width, \
29 .bit_offset = offset, \
30 .addrl = address, \
31 }
32
Shaunak Sahabd427802017-07-18 00:19:33 -070033static acpi_cstate_t cstate_map[] = {
34 {
35 /* C1 */
36 .ctype = 1, /* ACPI C1 */
37 .latency = 1,
38 .power = 1000,
39 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_FIXED, 0, 0, 0),
40 },
41 {
42 .ctype = 2, /* ACPI C2 */
43 .latency = 50,
44 .power = 10,
45 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x415),
46 },
47 {
48 .ctype = 3, /* ACPI C3 */
49 .latency = 150,
50 .power = 10,
51 .resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x419),
52 }
53};
54
55uint32_t soc_read_sci_irq_select(void)
Lance Zhaof51b1272015-11-09 17:06:34 -080056{
Shaunak Sahabd427802017-07-18 00:19:33 -070057 uintptr_t pmc_bar = soc_read_pmc_base();
58 return read32((void *)pmc_bar + IRQ_REG);
Lance Zhaof51b1272015-11-09 17:06:34 -080059}
Lance Zhaoe904c7c2015-11-10 19:00:18 -080060
Mario Scheithauer841416f2017-09-18 17:08:48 +020061void soc_write_sci_irq_select(uint32_t scis)
62{
63 uintptr_t pmc_bar = soc_read_pmc_base();
64 write32((void *)pmc_bar + IRQ_REG, scis);
65}
66
Shaunak Sahabd427802017-07-18 00:19:33 -070067acpi_cstate_t *soc_get_cstate_map(size_t *entries)
Lance Zhaoe904c7c2015-11-10 19:00:18 -080068{
Shaunak Sahabd427802017-07-18 00:19:33 -070069 *entries = ARRAY_SIZE(cstate_map);
70 return cstate_map;
Lance Zhaoe904c7c2015-11-10 19:00:18 -080071}
72
Kyösti Mälkkic2b0a4f2020-06-28 22:39:59 +030073void soc_fill_gnvs(struct global_nvs *gnvs)
Lance Zhao1bd0c0c2016-04-19 18:04:21 -070074{
Shaunak Sahacd9e1e42016-07-12 01:22:33 -070075 struct soc_intel_apollolake_config *cfg;
Kyösti Mälkkid5f645c2019-09-28 00:20:27 +030076 cfg = config_of_soc();
Shaunak Sahacd9e1e42016-07-12 01:22:33 -070077
Aaron Durbin9e815402016-09-13 12:31:57 -050078 /* Enable DPTF based on mainboard configuration */
79 gnvs->dpte = cfg->dptf_enable;
Vaibhav Shankaref8deaf2016-08-23 17:56:17 -070080
81 /* Assign address of PERST_0 if GPIO is defined in devicetree */
82 if (cfg->prt0_gpio != GPIO_PRT0_UDEF)
Shaunak Sahabd427802017-07-18 00:19:33 -070083 gnvs->prt0 = (uintptr_t) gpio_dwx_address(cfg->prt0_gpio);
Venkateswarlu Vinjamuri6dd7b402017-02-24 15:37:30 -080084
Venkateswarlu Vinjamuri99ce8a92017-03-22 18:24:52 -070085 /* Get sdcard cd GPIO portid if GPIO is defined in devicetree.
86 * Get offset of sdcard cd pin.
87 */
88 if (cfg->sdcard_cd_gpio) {
89 gnvs->scdp = gpio_get_pad_portid(cfg->sdcard_cd_gpio);
90 gnvs->scdo = gpio_acpi_pin(cfg->sdcard_cd_gpio);
91 }
Pratik Prajapatid06c7642017-10-11 11:52:16 -070092
Julius Wernercd49cce2019-03-05 16:53:33 -080093 if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX))
Pratik Prajapatid06c7642017-10-11 11:52:16 -070094 sgx_fill_gnvs(gnvs);
Subrata Banikb6df6b02020-01-03 15:29:02 +053095
96 /* Fill in Above 4GB MMIO resource */
97 sa_fill_gnvs(gnvs);
Shaunak Saha60b46182016-08-02 17:25:13 -070098}
99
Shaunak Sahabd427802017-07-18 00:19:33 -0700100uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en,
101 const struct chipset_power_state *ps)
Shaunak Saha60b46182016-08-02 17:25:13 -0700102{
Shaunak Saha60b46182016-08-02 17:25:13 -0700103 /*
Shaunak Saha60b46182016-08-02 17:25:13 -0700104 * WAK_STS bit is set when the system is in one of the sleep states
105 * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting
106 * this bit, the PMC will transition the system to the ON state and
107 * can only be set by hardware and can only be cleared by writing a one
108 * to this bit position.
109 */
Shaunak Saha60b46182016-08-02 17:25:13 -0700110
Shaunak Sahabd427802017-07-18 00:19:33 -0700111 generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN;
112 return generic_pm1_en;
Lance Zhao1bd0c0c2016-04-19 18:04:21 -0700113}
114
Shaunak Sahabd427802017-07-18 00:19:33 -0700115int soc_madt_sci_irq_polarity(int sci)
Lance Zhao1bd0c0c2016-04-19 18:04:21 -0700116{
Shaunak Sahabd427802017-07-18 00:19:33 -0700117 return MP_IRQ_POLARITY_LOW;
Hannah Williams0f61da82016-04-18 13:47:08 -0700118}
119
Shaunak Sahabd427802017-07-18 00:19:33 -0700120void soc_fill_fadt(acpi_fadt_t *fadt)
Hannah Williams0f61da82016-04-18 13:47:08 -0700121{
Shaunak Saha7210ec02017-12-13 09:37:05 -0800122 const struct soc_intel_apollolake_config *cfg;
Kyösti Mälkkid5f645c2019-09-28 00:20:27 +0300123 cfg = config_of_soc();
Shaunak Saha7210ec02017-12-13 09:37:05 -0800124
Shaunak Sahabd427802017-07-18 00:19:33 -0700125 fadt->pm_tmr_blk = ACPI_BASE_ADDRESS + PM1_TMR;
126
127 fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
128 fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
129
130 fadt->pm_tmr_len = 4;
131 fadt->duty_width = 3;
132
133 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
134
Elyes HAOUAS04071f42020-07-20 17:05:24 +0200135 fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
Shaunak Sahabd427802017-07-18 00:19:33 -0700136 fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
137 fadt->x_pm_tmr_blk.addrl = ACPI_BASE_ADDRESS + PM1_TMR;
Patrick Rudolphc02bda02020-02-28 10:19:41 +0100138 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
Shaunak Saha7210ec02017-12-13 09:37:05 -0800139
Kyösti Mälkki28dc7dc2019-07-12 13:10:19 +0300140 if (cfg->lpss_s0ix_enable)
Shaunak Saha7210ec02017-12-13 09:37:05 -0800141 fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
Shaunak Sahabd427802017-07-18 00:19:33 -0700142}
143
Werner Zeh90cc7e22018-12-14 13:26:04 +0100144static unsigned long soc_fill_dmar(unsigned long current)
145{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +0300146 struct device *const igfx_dev = pcidev_path_on_root(SA_DEVFN_IGD);
Werner Zeh90cc7e22018-12-14 13:26:04 +0100147 uint64_t gfxvtbar = MCHBAR64(GFXVTBAR) & VTBAR_MASK;
148 uint64_t defvtbar = MCHBAR64(DEFVTBAR) & VTBAR_MASK;
149 bool gfxvten = MCHBAR32(GFXVTBAR) & VTBAR_ENABLED;
150 bool defvten = MCHBAR32(DEFVTBAR) & VTBAR_ENABLED;
151 unsigned long tmp;
152
153 /* IGD has to be enabled, GFXVTBAR set and enabled. */
Angel Ponsc05a3f82020-08-03 12:14:20 +0200154 const bool emit_igd = is_dev_enabled(igfx_dev) && gfxvtbar && gfxvten;
155
156 /* First, add DRHD entries */
157 if (emit_igd) {
Werner Zeh90cc7e22018-12-14 13:26:04 +0100158 tmp = current;
159
160 current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar);
161 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
162 acpi_dmar_drhd_fixup(tmp, current);
Werner Zeh90cc7e22018-12-14 13:26:04 +0100163 }
164
165 /* DEFVTBAR has to be set and enabled. */
166 if (defvtbar && defvten) {
167 tmp = current;
Arthur Heymans054026c2020-11-12 21:09:56 +0100168 union p2sb_bdf ibdf = p2sb_get_ioapic_bdf();
Arthur Heymans281868e2020-11-12 21:02:11 +0100169 union p2sb_bdf hbdf = p2sb_get_hpet_bdf();
Werner Zeh90cc7e22018-12-14 13:26:04 +0100170 p2sb_hide();
171
172 current += acpi_create_dmar_drhd(current,
173 DRHD_INCLUDE_PCI_ALL, 0, defvtbar);
174 current += acpi_create_dmar_ds_ioapic(current,
Arthur Heymans054026c2020-11-12 21:09:56 +0100175 2, ibdf.bus, ibdf.dev, ibdf.fn);
Werner Zeh90cc7e22018-12-14 13:26:04 +0100176 current += acpi_create_dmar_ds_msi_hpet(current,
Arthur Heymans281868e2020-11-12 21:02:11 +0100177 0, hbdf.bus, hbdf.dev, hbdf.fn);
Werner Zeh90cc7e22018-12-14 13:26:04 +0100178 acpi_dmar_drhd_fixup(tmp, current);
179 }
180
Angel Ponsc05a3f82020-08-03 12:14:20 +0200181 /* Then, add RMRR entries after all DRHD entries */
182 if (emit_igd) {
183 tmp = current;
184 current += acpi_create_dmar_rmrr(current, 0,
185 sa_get_gsm_base(), sa_get_tolud_base() - 1);
186 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
187 acpi_dmar_rmrr_fixup(tmp, current);
188 }
189
Werner Zeh90cc7e22018-12-14 13:26:04 +0100190 return current;
191}
192
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700193unsigned long sa_write_acpi_tables(const struct device *const dev,
Werner Zeh90cc7e22018-12-14 13:26:04 +0100194 unsigned long current,
195 struct acpi_rsdp *const rsdp)
196{
197 acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
198
199 /* Create DMAR table only if virtualization is enabled. Due to some
200 * constraints on Apollo Lake SoC (some stepping affected), VTD could
201 * not be enabled together with IPU. Doing so will override and disable
202 * VTD while leaving CAPID0_A still reporting that VTD is available.
203 * As in this case FSP will lock VTD to disabled state, we need to make
204 * sure that DMAR table generation only happens when at least DEFVTBAR
205 * is enabled. Otherwise the DMAR header will be generated while the
206 * content of the table will be missing.
207 */
208
209 if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE) ||
210 !(MCHBAR32(DEFVTBAR) & VTBAR_ENABLED))
211 return current;
212
213 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
214 acpi_create_dmar(dmar, DMAR_INTR_REMAP, soc_fill_dmar);
215 current += dmar->header.length;
216 current = acpi_align_current(current);
217 acpi_add_table(rsdp, dmar);
218 current = acpi_align_current(current);
219
220 return current;
221}
222
Shaunak Sahabd427802017-07-18 00:19:33 -0700223void soc_power_states_generation(int core_id, int cores_per_package)
224{
225 /* Generate P-state tables */
226 generate_p_state_entries(core_id, cores_per_package);
227
228 /* Generate T-state tables */
229 generate_t_state_entries(core_id, cores_per_package);
Hannah Williams0f61da82016-04-18 13:47:08 -0700230}
Furquan Shaikh00a9e382016-10-20 22:45:26 -0700231
232static void acpigen_soc_get_dw0_in_local5(uintptr_t addr)
233{
234 /*
235 * Store (\_SB.GPC0 (addr), Local5)
236 * \_SB.GPC0 is used to read cfg0 value from dw0. It is defined in
237 * gpiolib.asl.
238 */
239 acpigen_write_store();
240 acpigen_emit_namestring("\\_SB.GPC0");
241 acpigen_write_integer(addr);
242 acpigen_emit_byte(LOCAL5_OP);
243}
244
245static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
246{
Lee Leahyd8fb3622017-03-09 10:10:25 -0800247 assert(gpio_num < TOTAL_PADS);
Shaunak Sahabd427802017-07-18 00:19:33 -0700248 uintptr_t addr = (uintptr_t) gpio_dwx_address(gpio_num);
Furquan Shaikh00a9e382016-10-20 22:45:26 -0700249
250 acpigen_soc_get_dw0_in_local5(addr);
251
252 /* If (And (Local5, mask)) */
253 acpigen_write_if_and(LOCAL5_OP, mask);
254
255 /* Store (One, Local0) */
256 acpigen_write_store_ops(ONE_OP, LOCAL0_OP);
257
Furquan Shaikh00a9e382016-10-20 22:45:26 -0700258 /* Else */
259 acpigen_write_else();
260
261 /* Store (Zero, Local0) */
262 acpigen_write_store_ops(ZERO_OP, LOCAL0_OP);
263
264 acpigen_pop_len(); /* Else */
265
266 return 0;
267}
268
269static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
270{
Lee Leahyd8fb3622017-03-09 10:10:25 -0800271 assert(gpio_num < TOTAL_PADS);
Shaunak Sahabd427802017-07-18 00:19:33 -0700272 uintptr_t addr = (uintptr_t) gpio_dwx_address(gpio_num);
Furquan Shaikh00a9e382016-10-20 22:45:26 -0700273
274 acpigen_soc_get_dw0_in_local5(addr);
275
276 if (val) {
277 /* Or (Local5, PAD_CFG0_TX_STATE, Local5) */
278 acpigen_write_or(LOCAL5_OP, PAD_CFG0_TX_STATE, LOCAL5_OP);
279 } else {
280 /* Not (PAD_CFG0_TX_STATE, Local6) */
281 acpigen_write_not(PAD_CFG0_TX_STATE, LOCAL6_OP);
282
283 /* And (Local5, Local6, Local5) */
284 acpigen_write_and(LOCAL5_OP, LOCAL6_OP, LOCAL5_OP);
285 }
286
287 /*
288 * \_SB.SPC0 (addr, Local5)
289 * \_SB.SPC0 is used to write cfg0 value in dw0. It is defined in
290 * gpiolib.asl.
291 */
292 acpigen_emit_namestring("\\_SB.SPC0");
293 acpigen_write_integer(addr);
294 acpigen_emit_byte(LOCAL5_OP);
295
296 return 0;
297}
298
299int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
300{
301 return acpigen_soc_get_gpio_val(gpio_num, PAD_CFG0_RX_STATE);
302}
303
304int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
305{
306 return acpigen_soc_get_gpio_val(gpio_num, PAD_CFG0_TX_STATE);
307}
308
309int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
310{
311 return acpigen_soc_set_gpio_val(gpio_num, 1);
312}
313
314int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
315{
316 return acpigen_soc_set_gpio_val(gpio_num, 0);
317}