blob: abf47b77823c99364f5279af2dcfb9382314c19f [file] [log] [blame]
Hannah Williams01bc8972016-02-04 20:13:34 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
5 * Copyright (C) 2015-2016 Intel Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
Alexandru Gagniuca6339802016-04-05 12:40:24 -070018#define __SIMPLE_DEVICE__
19
Duncan Laurie2e790092016-09-19 12:05:49 -070020#include <arch/acpi.h>
Hannah Williams01bc8972016-02-04 20:13:34 -080021#include <arch/io.h>
Aaron Durbin3118b622017-09-15 11:48:53 -060022#include <cbmem.h>
Hannah Williams01bc8972016-02-04 20:13:34 -080023#include <console/console.h>
Andrey Petrov3b637532016-11-30 17:39:16 -080024#include <cpu/x86/msr.h>
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070025#include <device/device.h>
26#include <device/pci.h>
Hannah Williams01bc8972016-02-04 20:13:34 -080027#include <device/pci_def.h>
Barnali Sarkar66fe0c42017-05-23 18:17:14 +053028#include <intelblocks/msr.h>
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070029#include <intelblocks/pmclib.h>
Aaron Durbin3118b622017-09-15 11:48:53 -060030#include <intelblocks/rtc.h>
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070031#include <rules.h>
Hannah Williams01bc8972016-02-04 20:13:34 -080032#include <soc/iomap.h>
Andrey Petrov3b637532016-11-30 17:39:16 -080033#include <soc/cpu.h>
Alexandru Gagniuca6339802016-04-05 12:40:24 -070034#include <soc/pci_devs.h>
Hannah Williams01bc8972016-02-04 20:13:34 -080035#include <soc/pm.h>
Duncan Laurie2f3736e2016-11-03 10:33:43 -070036#include <timer.h>
Duncan Lauriea673d1c2016-09-19 12:02:54 -070037#include "chip.h"
Hannah Williams01bc8972016-02-04 20:13:34 -080038
Alexandru Gagniuca6339802016-04-05 12:40:24 -070039static uintptr_t read_pmc_mmio_bar(void)
40{
Lijian Zhao91086802016-09-06 18:15:29 -070041 return PMC_BAR0;
Alexandru Gagniuca6339802016-04-05 12:40:24 -070042}
Hannah Williams01bc8972016-02-04 20:13:34 -080043
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070044uintptr_t soc_read_pmc_base(void)
Shaunak Saha9a0c9ac2016-06-27 23:00:15 -070045{
46 return read_pmc_mmio_bar();
47}
48
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070049const char *const *soc_smi_sts_array(size_t *a)
Hannah Williams01bc8972016-02-04 20:13:34 -080050{
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070051 static const char *const smi_sts_bits[] = {
Aaron Durbin7929dd02016-06-10 18:01:45 -050052 [BIOS_SMI_STS] = "BIOS",
53 [LEGACY_USB_SMI_STS] = "LEGACY USB",
54 [SLP_SMI_STS] = "SLP_SMI",
55 [APM_SMI_STS] = "APM",
56 [SWSMI_TMR_SMI_STS] = "SWSMI_TMR",
Aaron Durbina554b712016-06-10 18:04:21 -050057 [FAKE_PM1_SMI_STS] = "PM1",
Lee Leahy320b7ca2017-03-09 09:42:48 -080058 [GPIO_SMI_STS] = "GPIO_SMI",
59 [GPIO_UNLOCK_SMI_STS] = "GPIO_UNLOCK_SSMI",
Aaron Durbin7929dd02016-06-10 18:01:45 -050060 [MC_SMI_STS] = "MCSMI",
61 [TCO_SMI_STS] = "TCO",
62 [PERIODIC_SMI_STS] = "PERIODIC",
63 [SERIRQ_SMI_STS] = "SERIRQ",
64 [SMBUS_SMI_STS] = "SMBUS_SMI",
65 [XHCI_SMI_STS] = "XHCI",
66 [HSMBUS_SMI_STS] = "HOST_SMBUS",
67 [SCS_SMI_STS] = "SCS",
68 [PCIE_SMI_STS] = "PCI_EXP_SMI",
69 [SCC2_SMI_STS] = "SCC2",
70 [SPI_SSMI_STS] = "SPI_SSMI",
71 [SPI_SMI_STS] = "SPI",
72 [PMC_OCP_SMI_STS] = "OCP_CSE",
Hannah Williams01bc8972016-02-04 20:13:34 -080073 };
74
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070075 *a = ARRAY_SIZE(smi_sts_bits);
76 return smi_sts_bits;
Hannah Williams01bc8972016-02-04 20:13:34 -080077}
78
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070079/*
80 * For APL/GLK this check for power button status if nothing else
81 * is indicating an SMI and SMIs aren't turned into SCIs.
82 * Apparently, there is no PM1 status bit in the SMI status
83 * register. That makes things difficult for
84 * determining if the power button caused an SMI.
85 */
86uint32_t soc_get_smi_status(uint32_t generic_sts)
Hannah Williams01bc8972016-02-04 20:13:34 -080087{
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070088 if (generic_sts == 0 && !(inl(ACPI_BASE_ADDRESS + PM1_CNT) & SCI_EN)) {
Barnali Sarkar9e55ff62017-06-05 20:01:14 +053089 uint16_t pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
Aaron Durbina554b712016-06-10 18:04:21 -050090
91 /* Fake PM1 status bit if power button pressed. */
92 if (pm1_sts & PWRBTN_STS)
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070093 generic_sts |= (1 << FAKE_PM1_SMI_STS);
Aaron Durbina554b712016-06-10 18:04:21 -050094 }
95
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070096 return generic_sts;
Hannah Williams01bc8972016-02-04 20:13:34 -080097}
98
Shaunak Saha93cdc8b2017-04-18 15:42:09 -070099const char *const *soc_tco_sts_array(size_t *a)
Hannah Williams01bc8972016-02-04 20:13:34 -0800100{
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700101 static const char *const tco_sts_bits[] = {
Hannah Williams01bc8972016-02-04 20:13:34 -0800102 [3] = "TIMEOUT",
103 [17] = "SECOND_TO",
104 };
105
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700106 *a = ARRAY_SIZE(tco_sts_bits);
107 return tco_sts_bits;
Hannah Williams01bc8972016-02-04 20:13:34 -0800108}
109
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700110const char *const *soc_gpe_sts_array(size_t *a)
Hannah Williams01bc8972016-02-04 20:13:34 -0800111{
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700112 static const char *const gpe_sts_bits[] = {
Hannah Williams01bc8972016-02-04 20:13:34 -0800113 [0] = "PCIE_SCI",
114 [2] = "SWGPE",
115 [3] = "PCIE_WAKE0",
116 [4] = "PUNIT",
117 [6] = "PCIE_WAKE1",
118 [7] = "PCIE_WAKE2",
119 [8] = "PCIE_WAKE3",
120 [9] = "PCI_EXP",
121 [10] = "BATLOW",
122 [11] = "CSE_PME",
123 [12] = "XDCI_PME",
124 [13] = "XHCI_PME",
125 [14] = "AVS_PME",
126 [15] = "GPIO_TIER1_SCI",
127 [16] = "SMB_WAK",
128 [17] = "SATA_PME",
129 };
130
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700131 *a = ARRAY_SIZE(gpe_sts_bits);
132 return gpe_sts_bits;
Hannah Williams01bc8972016-02-04 20:13:34 -0800133}
134
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700135uint32_t soc_reset_tco_status(void)
Hannah Williams01bc8972016-02-04 20:13:34 -0800136{
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700137 uint32_t tco_sts = inl(ACPI_BASE_ADDRESS + TCO_STS);
138 uint32_t tco_en = inl(ACPI_BASE_ADDRESS + TCO1_CNT);
139
140 outl(tco_sts, ACPI_BASE_ADDRESS + TCO_STS);
141 return tco_sts & tco_en;
Hannah Williams01bc8972016-02-04 20:13:34 -0800142}
143
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700144void soc_clear_pm_registers(uintptr_t pmc_bar)
Duncan Laurie2e790092016-09-19 12:05:49 -0700145{
Hannah Williams01bc8972016-02-04 20:13:34 -0800146 uint32_t gen_pmcon1;
147
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700148 gen_pmcon1 = read32((void *)(pmc_bar + GEN_PMCON1));
Hannah Williams01bc8972016-02-04 20:13:34 -0800149 /* Clear the status bits. The RPS field is cleared on a 0 write. */
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700150 write32((void *)(pmc_bar + GEN_PMCON1), gen_pmcon1 & ~RPS);
Hannah Williams01bc8972016-02-04 20:13:34 -0800151}
152
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700153void soc_get_gpe_configs(uint8_t *dw0, uint8_t *dw1, uint8_t *dw2)
Hannah Williams01bc8972016-02-04 20:13:34 -0800154{
Aaron Durbine4d7abc2017-04-16 22:05:36 -0500155 DEVTREE_CONST struct soc_intel_apollolake_config *config;
Duncan Lauriea673d1c2016-09-19 12:02:54 -0700156
157 /* Look up the device in devicetree */
Aaron Durbine4d7abc2017-04-16 22:05:36 -0500158 DEVTREE_CONST struct device *dev = dev_find_slot(0, SA_DEVFN_ROOT);
Duncan Lauriea673d1c2016-09-19 12:02:54 -0700159 if (!dev || !dev->chip_info) {
160 printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
161 return;
162 }
163 config = dev->chip_info;
164
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700165 /* Assign to out variable */
166 *dw0 = config->gpe0_dw1;
167 *dw1 = config->gpe0_dw2;
168 *dw2 = config->gpe0_dw3;
169}
Duncan Lauriea673d1c2016-09-19 12:02:54 -0700170
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700171void soc_fill_power_state(struct chipset_power_state *ps)
172{
173 uintptr_t pmc_bar0 = read_pmc_mmio_bar();
Duncan Lauriea673d1c2016-09-19 12:02:54 -0700174
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700175 ps->tco_sts = inl(ACPI_BASE_ADDRESS + TCO_STS);
176 ps->prsts = read32((void *)(pmc_bar0 + PRSTS));
177 ps->gen_pmcon1 = read32((void *)(pmc_bar0 + GEN_PMCON1));
178 ps->gen_pmcon2 = read32((void *)(pmc_bar0 + GEN_PMCON2));
179 ps->gen_pmcon3 = read32((void *)(pmc_bar0 + GEN_PMCON3));
Duncan Lauriea673d1c2016-09-19 12:02:54 -0700180
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700181 printk(BIOS_DEBUG, "prsts: %08x tco_sts: %08x\n",
182 ps->prsts, ps->tco_sts);
183 printk(BIOS_DEBUG,
184 "gen_pmcon1: %08x gen_pmcon2: %08x gen_pmcon3: %08x\n",
185 ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3);
Duncan Lauriea673d1c2016-09-19 12:02:54 -0700186}
Andrey Petrov3b637532016-11-30 17:39:16 -0800187
188void enable_pm_timer_emulation(void)
189{
190 /* ACPI PM timer emulation */
191 msr_t msr;
192 /*
193 * The derived frequency is calculated as follows:
194 * (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
195 * Back solve the multiplier so the 3.579545MHz ACPI timer
196 * frequency is used.
197 */
198 msr.hi = (3579545ULL << 32) / CTC_FREQ;
Shaunak Saha93cdc8b2017-04-18 15:42:09 -0700199 /* Set PM1 timer IO port and enable */
Barnali Sarkar9e55ff62017-06-05 20:01:14 +0530200 msr.lo = EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + R_ACPI_PM1_TMR);
Andrey Petrov3b637532016-11-30 17:39:16 -0800201 wrmsr(MSR_EMULATE_PM_TMR, msr);
202}
Aaron Durbin3118b622017-09-15 11:48:53 -0600203
204static int rtc_failed(uint32_t gen_pmcon1)
205{
206 return !!(gen_pmcon1 & RPS);
207}
208
209int soc_get_rtc_failed(void)
210{
211 const struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
212
213 if (!ps) {
214 printk(BIOS_ERR, "Could not find power state in cbmem, RTC init aborted\n");
215 return 1;
216 }
217
218 return rtc_failed(ps->gen_pmcon1);
219}