|
@@ -8,7 +8,9 @@
|
|
|
#include <cpu.h>
|
|
|
#include <dm.h>
|
|
|
#include <dm/uclass-internal.h>
|
|
|
+#include <asm/acpi_s3.h>
|
|
|
#include <asm/acpi_table.h>
|
|
|
+#include <asm/io.h>
|
|
|
#include <asm/ioapic.h>
|
|
|
#include <asm/mpspec.h>
|
|
|
#include <asm/tables.h>
|
|
@@ -187,3 +189,48 @@ void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
|
|
|
else
|
|
|
gnvs->iuart_en = 0;
|
|
|
}
|
|
|
+
|
|
|
+#ifdef CONFIG_HAVE_ACPI_RESUME
|
|
|
+/*
|
|
|
+ * The following two routines are called at a very early stage, even before
|
|
|
+ * FSP 2nd phase API fsp_init() is called. Registers off ACPI_BASE_ADDRESS
|
|
|
+ * and PMC_BASE_ADDRESS are accessed, so we need make sure the base addresses
|
|
|
+ * of these two blocks are programmed by either U-Boot or FSP.
|
|
|
+ *
|
|
|
+ * It has been verified that 1st phase API (see arch/x86/lib/fsp/fsp_car.S)
|
|
|
+ * on Intel BayTrail SoC already initializes these two base addresses so
|
|
|
+ * we are safe to access these registers here.
|
|
|
+ */
|
|
|
+
|
|
|
+enum acpi_sleep_state chipset_prev_sleep_state(void)
|
|
|
+{
|
|
|
+ u32 pm1_sts;
|
|
|
+ u32 pm1_cnt;
|
|
|
+ u32 gen_pmcon1;
|
|
|
+ enum acpi_sleep_state prev_sleep_state = ACPI_S0;
|
|
|
+
|
|
|
+ /* Read Power State */
|
|
|
+ pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
|
|
|
+ pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
|
|
|
+ gen_pmcon1 = readl(PMC_BASE_ADDRESS + GEN_PMCON1);
|
|
|
+
|
|
|
+ debug("PM1_STS = 0x%x PM1_CNT = 0x%x GEN_PMCON1 = 0x%x\n",
|
|
|
+ pm1_sts, pm1_cnt, gen_pmcon1);
|
|
|
+
|
|
|
+ if (pm1_sts & WAK_STS)
|
|
|
+ prev_sleep_state = acpi_sleep_from_pm1(pm1_cnt);
|
|
|
+
|
|
|
+ if (gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR))
|
|
|
+ prev_sleep_state = ACPI_S5;
|
|
|
+
|
|
|
+ return prev_sleep_state;
|
|
|
+}
|
|
|
+
|
|
|
+void chipset_clear_sleep_state(void)
|
|
|
+{
|
|
|
+ u32 pm1_cnt;
|
|
|
+
|
|
|
+ pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
|
|
|
+ outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
|
|
|
+}
|
|
|
+#endif
|