1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Intel Corp. 4 * Copyright (C) 2017-2019 Siemens AG 5 * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.) 6 * Copyright 2019 Google LLC 7 * 8 * Modified from coreboot apollolake/acpi.c 9 */ 10 11#define LOG_CATEGORY LOGC_ACPI 12 13#include <common.h> 14#include <cpu.h> 15#include <dm.h> 16#include <log.h> 17#include <p2sb.h> 18#include <pci.h> 19#include <acpi/acpigen.h> 20#include <acpi/acpi_s3.h> 21#include <asm/acpi_table.h> 22#include <asm/cpu_common.h> 23#include <asm/intel_acpi.h> 24#include <asm/intel_gnvs.h> 25#include <asm/intel_pinctrl.h> 26#include <asm/intel_pinctrl_defs.h> 27#include <asm/intel_regs.h> 28#include <asm/io.h> 29#include <asm/mpspec.h> 30#include <asm/tables.h> 31#include <asm/arch/iomap.h> 32#include <asm/arch/gpio.h> 33#include <asm/arch/pm.h> 34#include <asm/arch/systemagent.h> 35#include <dm/acpi.h> 36#include <dm/uclass-internal.h> 37#include <power/acpi_pmc.h> 38 39int arch_read_sci_irq_select(void) 40{ 41 struct acpi_pmc_upriv *upriv; 42 struct udevice *dev; 43 int ret; 44 45 ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev); 46 if (ret) 47 return log_msg_ret("pmc", ret); 48 upriv = dev_get_uclass_priv(dev); 49 50 return readl(upriv->pmc_bar0 + IRQ_REG); 51} 52 53int arch_write_sci_irq_select(uint scis) 54{ 55 struct acpi_pmc_upriv *upriv; 56 struct udevice *dev; 57 int ret; 58 59 ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev); 60 if (ret) 61 return log_msg_ret("pmc", ret); 62 upriv = dev_get_uclass_priv(dev); 63 writel(scis, upriv->pmc_bar0 + IRQ_REG); 64 65 return 0; 66} 67 68/** 69 * chromeos_init_acpi() - Initialise basic data to boot Chrome OS 70 * 71 * This tells Chrome OS to boot in developer mode 72 * 73 * @cros: Structure to initialise 74 */ 75static void chromeos_init_acpi(struct chromeos_acpi_gnvs *cros) 76{ 77 cros->active_main_fw = 1; 78 cros->active_main_fw = 1; /* A */ 79 cros->switches = CHSW_DEVELOPER_SWITCH; 80 cros->main_fw_type = 2; /* Developer */ 81} 82 83int acpi_create_gnvs(struct acpi_global_nvs *gnvs) 84{ 85 struct udevice *cpu; 86 int ret; 87 88 /* Clear out GNV */ 89 memset(gnvs, '\0', sizeof(*gnvs)); 90 91 /* TODO(sjg@chromium.org): Add the console log to gnvs->cbmc */ 92 93 if (IS_ENABLED(CONFIG_CHROMEOS)) 94 chromeos_init_acpi(&gnvs->chromeos); 95 96 /* Set unknown wake source */ 97 gnvs->pm1i = ~0ULL; 98 99 /* CPU core count */ 100 gnvs->pcnt = 1; 101 ret = uclass_find_first_device(UCLASS_CPU, &cpu); 102 if (cpu) { 103 ret = cpu_get_count(cpu); 104 if (ret > 0) 105 gnvs->pcnt = ret; 106 } 107 108 gnvs->dpte = 1; 109 110 return 0; 111} 112 113uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en) 114{ 115 /* 116 * WAK_STS bit is set when the system is in one of the sleep states 117 * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting 118 * this bit, the PMC will transition the system to the ON state and 119 * can only be set by hardware and can only be cleared by writing a one 120 * to this bit position. 121 */ 122 generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN; 123 124 return generic_pm1_en; 125} 126 127int arch_madt_sci_irq_polarity(int sci) 128{ 129 return MP_IRQ_POLARITY_LOW; 130} 131 132void fill_fadt(struct acpi_fadt *fadt) 133{ 134 fadt->pm_tmr_blk = IOMAP_ACPI_BASE + PM1_TMR; 135 136 fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED; 137 fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED; 138 139 fadt->pm_tmr_len = 4; 140 fadt->duty_width = 3; 141 142 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; 143 144 fadt->x_pm_tmr_blk.space_id = 1; 145 fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; 146 fadt->x_pm_tmr_blk.addrl = IOMAP_ACPI_BASE + PM1_TMR; 147} 148 149static int apl_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry) 150{ 151 struct acpi_table_header *header; 152 struct acpi_fadt *fadt; 153 154 fadt = ctx->current; 155 acpi_fadt_common(fadt, ctx->facs, ctx->dsdt); 156 intel_acpi_fill_fadt(fadt); 157 fill_fadt(fadt); 158 header = &fadt->header; 159 header->checksum = table_compute_checksum(fadt, header->length); 160 161 return acpi_add_fadt(ctx, fadt); 162} 163ACPI_WRITER(5fadt, "FADT", apl_write_fadt, 0); 164 165int apl_acpi_fill_dmar(struct acpi_ctx *ctx) 166{ 167 struct udevice *dev, *sa_dev; 168 u64 gfxvtbar = readq(MCHBAR_REG(GFXVTBAR)) & VTBAR_MASK; 169 u64 defvtbar = readq(MCHBAR_REG(DEFVTBAR)) & VTBAR_MASK; 170 bool gfxvten = readl(MCHBAR_REG(GFXVTBAR)) & VTBAR_ENABLED; 171 bool defvten = readl(MCHBAR_REG(DEFVTBAR)) & VTBAR_ENABLED; 172 void *tmp; 173 int ret; 174 175 uclass_find_first_device(UCLASS_VIDEO, &dev); 176 ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa_dev); 177 if (ret) 178 return log_msg_ret("no sa", ret); 179 180 /* IGD has to be enabled, GFXVTBAR set and enabled */ 181 if (dev && device_active(dev) && gfxvtbar && gfxvten) { 182 tmp = ctx->current; 183 184 acpi_create_dmar_drhd(ctx, 0, 0, gfxvtbar); 185 ret = acpi_create_dmar_ds_pci(ctx, PCI_BDF(0, 2, 0)); 186 if (ret) 187 return log_msg_ret("ds_pci", ret); 188 acpi_dmar_drhd_fixup(ctx, tmp); 189 190 /* Add RMRR entry */ 191 tmp = ctx->current; 192 acpi_create_dmar_rmrr(ctx->current, 0, sa_get_gsm_base(sa_dev), 193 sa_get_tolud_base(sa_dev) - 1); 194 acpi_create_dmar_ds_pci(ctx->current, PCI_BDF(0, 2, 0)); 195 acpi_dmar_rmrr_fixup(ctx, tmp); 196 } 197 198 /* DEFVTBAR has to be set and enabled */ 199 if (defvtbar && defvten) { 200 struct udevice *p2sb_dev; 201 u16 ibdf, hbdf; 202 uint ioapic, hpet; 203 int ret; 204 205 tmp = ctx->current; 206 /* 207 * P2SB may already be hidden. There's no clear rule, when. 208 * It is needed to get bus, device and function for IOAPIC and 209 * HPET device which is stored in P2SB device. So unhide it to 210 * get the info and hide it again when done. 211 * 212 * TODO(sjg@chromium.org): p2sb_unhide() ? 213 */ 214 ret = uclass_first_device_err(UCLASS_P2SB, &p2sb_dev); 215 if (ret) 216 return log_msg_ret("p2sb", ret); 217 218 dm_pci_read_config16(p2sb_dev, PCH_P2SB_IBDF, &ibdf); 219 ioapic = PCI_TO_BDF(ibdf); 220 dm_pci_read_config16(p2sb_dev, PCH_P2SB_HBDF, &hbdf); 221 hpet = PCI_TO_BDF(hbdf); 222 /* TODO(sjg@chromium.org): p2sb_hide() ? */ 223 224 acpi_create_dmar_drhd(ctx, DRHD_INCLUDE_PCI_ALL, 0, defvtbar); 225 acpi_create_dmar_ds_ioapic(ctx, 2, ioapic); 226 acpi_create_dmar_ds_msi_hpet(ctx, 0, hpet); 227 acpi_dmar_drhd_fixup(tmp, ctx->current); 228 } 229 230 return 0; 231} 232