soc/intel/common/block: Common ACPI

This patch adds the common acpi code.ACPI code is very similar
accross different intel chipsets.This patch is an effort to
move those code in common place so that it can be shared accross
different intel platforms instead of duplicating for each platform.
We are removing the common acpi files in src/soc/intel/common.
This removes the acpi.c file which was previously in
src/soc/common/acpi. The config for common acpi is
SOC_INTEL_COMMON_BLOCK_ACPI which can be defined in SOC's
Kconfig file in order to use the common ACPI code. This patch also
includes the changes in APL platform to use the common ACPI block.

TEST= Tested the patch as below:
1.Builds and system boots up with the patch.
2.Check all the ACPI tables are present in
  /sys/firmware/acpi/tables
3.Check SCI's are properly working as we are
  modifying the function to override madt.
4.Extract acpi tables like DSDT,APIC, FACP, FACS
  and decompile the by iasl and compare with good
  known tables.
5.Execute the extracted tables in aciexec to check
  acpi methods are working properly.

Change-Id: Ib6eb6fd5366e6e28fd81bc22d050b0efa05a2e5d
Signed-off-by: Shaunak Saha <shaunak.saha@intel.com>
Reviewed-on: https://review.coreboot.org/20630
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Sumeet R Pawnikar <sumeet.r.pawnikar@intel.com>
This commit is contained in:
Shaunak Saha
2017-07-18 00:19:33 -07:00
committed by Aaron Durbin
parent af896d071b
commit bd427803ab
13 changed files with 686 additions and 465 deletions

View File

@@ -59,9 +59,9 @@ config CPU_SPECIFIC_OPTIONS
select SMM_TSEG
select SA_ENABLE_IMR
select SOC_INTEL_COMMON
select SOC_INTEL_COMMON_ACPI
select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
select SOC_INTEL_COMMON_BLOCK
select SOC_INTEL_COMMON_BLOCK_ACPI
select SOC_INTEL_COMMON_BLOCK_CPU
select SOC_INTEL_COMMON_BLOCK_FAST_SPI
select SOC_INTEL_COMMON_BLOCK_GPIO

View File

@@ -17,20 +17,20 @@
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <arch/io.h>
#include <arch/ioapic.h>
#include <arch/smp/mpspec.h>
#include <cbmem.h>
#include <cpu/x86/smm.h>
#include <cpu/cpu.h>
#include <soc/acpi.h>
#include <soc/intel/common/acpi.h>
#include <gpio.h>
#include <intelblocks/acpi.h>
#include <intelblocks/pmclib.h>
#include <soc/iomap.h>
#include <soc/pm.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <string.h>
#include <soc/gpio.h>
#include <gpio.h>
#include "chip.h"
#define CSTATE_RES(address_space, width, offset, address) \
@@ -41,116 +41,41 @@
.addrl = address, \
}
unsigned long acpi_fill_mcfg(unsigned long current)
static acpi_cstate_t cstate_map[] = {
{
/* C1 */
.ctype = 1, /* ACPI C1 */
.latency = 1,
.power = 1000,
.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_FIXED, 0, 0, 0),
},
{
.ctype = 2, /* ACPI C2 */
.latency = 50,
.power = 10,
.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x415),
},
{
.ctype = 3, /* ACPI C3 */
.latency = 150,
.power = 10,
.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x419),
}
};
uint32_t soc_read_sci_irq_select(void)
{
/* PCI Segment Group 0, Start Bus Number 0, End Bus Number is 255 */
current += acpi_create_mcfg_mmconfig((void *) current,
CONFIG_MMCONF_BASE_ADDRESS, 0, 0,
255);
return current;
uintptr_t pmc_bar = soc_read_pmc_base();
return read32((void *)pmc_bar + IRQ_REG);
}
static int acpi_sci_irq(void)
acpi_cstate_t *soc_get_cstate_map(size_t *entries)
{
int sci_irq = 9;
return sci_irq;
*entries = ARRAY_SIZE(cstate_map);
return cstate_map;
}
static unsigned long acpi_madt_irq_overrides(unsigned long current)
{
int sci = acpi_sci_irq();
uint16_t flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW;
/* INT_SRC_OVR */
current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
/* SCI */
current += acpi_create_madt_irqoverride((void *)current, 0, sci, sci,
flags);
return current;
}
unsigned long acpi_fill_madt(unsigned long current)
{
/* Local APICs */
current = acpi_create_madt_lapics(current);
/* IOAPIC */
current += acpi_create_madt_ioapic((void *) current,
2, IO_APIC_ADDR, 0);
return acpi_madt_irq_overrides(current);
}
void acpi_fill_fadt(acpi_fadt_t *fadt)
{
const uint16_t pmbase = ACPI_BASE_ADDRESS;
/* Use ACPI 3.0 revision. */
fadt->header.revision = ACPI_FADT_REV_ACPI_3_0;
fadt->sci_int = acpi_sci_irq();
fadt->smi_cmd = APM_CNT;
fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
fadt->pm1a_evt_blk = pmbase + PM1_STS;
fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
fadt->pm_tmr_blk = pmbase + PM1_TMR;
fadt->gpe0_blk = pmbase + GPE0_STS(0);
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm_tmr_len = 4;
/* There are 4 GPE0 STS/EN pairs each 32 bits wide. */
fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
fadt->flush_size = 0x400; /* twice of cache size*/
fadt->flush_stride = 0x10; /* Cache line width */
fadt->duty_offset = 1;
fadt->duty_width = 3;
fadt->day_alrm = 0xd;
fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE |
ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
fadt->reset_reg.space_id = 1;
fadt->reset_reg.bit_width = 8;
fadt->reset_reg.addrl = 0xcf9;
fadt->reset_value = 6;
fadt->x_pm1a_evt_blk.space_id = 1;
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS;
fadt->x_pm1b_evt_blk.space_id = 1;
fadt->x_pm1a_cnt_blk.space_id = 1;
fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT;
fadt->x_pm1b_cnt_blk.space_id = 1;
fadt->x_pm_tmr_blk.space_id = 1;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
fadt->x_gpe1_blk.space_id = 1;
}
unsigned long southbridge_write_acpi_tables(device_t device,
unsigned long current,
struct acpi_rsdp *rsdp)
{
return acpi_write_hpet(device, current, rsdp);
}
static void acpi_create_gnvs(struct global_nvs_t *gnvs)
void acpi_create_gnvs(struct global_nvs_t *gnvs)
{
struct soc_intel_apollolake_config *cfg;
struct device *dev = SA_DEV_ROOT;
@@ -159,7 +84,7 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs)
memset(gnvs, 0, sizeof(*gnvs));
if (IS_ENABLED(CONFIG_CONSOLE_CBMEM))
gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);
gnvs->cbmc = (uintptr_t) cbmem_find(CBMEM_ID_CONSOLE);
if (IS_ENABLED(CONFIG_CHROMEOS)) {
/* Initialize Verified Boot data */
@@ -184,7 +109,7 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs)
/* Assign address of PERST_0 if GPIO is defined in devicetree */
if (cfg->prt0_gpio != GPIO_PRT0_UDEF)
gnvs->prt0 = (uintptr_t)gpio_dwx_address(cfg->prt0_gpio);
gnvs->prt0 = (uintptr_t) gpio_dwx_address(cfg->prt0_gpio);
/* Get sdcard cd GPIO portid if GPIO is defined in devicetree.
* Get offset of sdcard cd pin.
@@ -195,87 +120,50 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs)
}
}
/* Save wake source information for calculating ACPI _SWS values */
int soc_fill_acpi_wake(uint32_t *pm1, uint32_t **gpe0)
uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en,
const struct chipset_power_state *ps)
{
struct chipset_power_state *ps;
static uint32_t gpe0_sts[GPE0_REG_MAX];
uint32_t pm1_en;
int i;
ps = cbmem_find(CBMEM_ID_POWER_STATE);
if (ps == NULL)
return -1;
/*
* PM1_EN to check the basic wake events which can happen through
* powerbtn or any other wake source like lidopen, key board press etc.
* WAK_STS bit is set when the system is in one of the sleep states
* (via the SLP_EN bit) and an enabled wake event occurs. Upon setting
* this bit, the PMC will transition the system to the ON state and
* can only be set by hardware and can only be cleared by writing a one
* to this bit position.
*/
pm1_en = ps->pm1_en | WAK_STS | RTC_EN | PWRBTN_EN;
*pm1 = ps->pm1_sts & pm1_en;
/* Mask off GPE0 status bits that are not enabled */
*gpe0 = &gpe0_sts[0];
for (i = 0; i < GPE0_REG_MAX; i++)
gpe0_sts[i] = ps->gpe0_sts[i] & ps->gpe0_en[i];
return GPE0_REG_MAX;
generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN;
return generic_pm1_en;
}
void southbridge_inject_dsdt(device_t device)
int soc_madt_sci_irq_polarity(int sci)
{
struct global_nvs_t *gnvs;
gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
if (gnvs) {
acpi_create_gnvs(gnvs);
acpi_save_gnvs((uintptr_t)gnvs);
/* And tell SMI about it */
smm_setup_structures(gnvs, NULL, NULL);
/* Add it to DSDT. */
acpigen_write_scope("\\");
acpigen_write_name_dword("NVSA", (uintptr_t)gnvs);
acpigen_pop_len();
}
}
static acpi_cstate_t cstate_map[] = {
{
/* C1 */
.ctype = 1, /* ACPI C1 */
.latency = 1,
.power = 1000,
.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_FIXED, 0, 0, 0),
},
{
.ctype = 2, /* ACPI C2 */
.latency = 50,
.power = 10,
.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x415),
},
{
.ctype = 3, /* ACPI C3 */
.latency = 150,
.power = 10,
.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x419),
}
};
acpi_cstate_t *soc_get_cstate_map(int *entries)
{
*entries = ARRAY_SIZE(cstate_map);
return cstate_map;
return MP_IRQ_POLARITY_LOW;
}
uint16_t soc_get_acpi_base_address(void)
void soc_fill_fadt(acpi_fadt_t *fadt)
{
return ACPI_BASE_ADDRESS;
fadt->pm_tmr_blk = ACPI_BASE_ADDRESS + PM1_TMR;
fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
fadt->pm_tmr_len = 4;
fadt->duty_width = 3;
fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
fadt->x_pm_tmr_blk.space_id = 1;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.addrl = ACPI_BASE_ADDRESS + PM1_TMR;
}
void soc_power_states_generation(int core_id, int cores_per_package)
{
/* Generate P-state tables */
generate_p_state_entries(core_id, cores_per_package);
/* Generate T-state tables */
generate_t_state_entries(core_id, cores_per_package);
}
static void acpigen_soc_get_dw0_in_local5(uintptr_t addr)
@@ -294,7 +182,7 @@ static void acpigen_soc_get_dw0_in_local5(uintptr_t addr)
static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
{
assert(gpio_num < TOTAL_PADS);
uintptr_t addr = (uintptr_t)gpio_dwx_address(gpio_num);
uintptr_t addr = (uintptr_t) gpio_dwx_address(gpio_num);
acpigen_soc_get_dw0_in_local5(addr);
@@ -320,7 +208,7 @@ static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
{
assert(gpio_num < TOTAL_PADS);
uintptr_t addr = (uintptr_t)gpio_dwx_address(gpio_num);
uintptr_t addr = (uintptr_t) gpio_dwx_address(gpio_num);
acpigen_soc_get_dw0_in_local5(addr);

View File

@@ -1,28 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2016 Intel Corp.
* (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _SOC_APOLLOLAKE_ACPI_H_
#define _SOC_APOLLOLAKE_ACPI_H_
#include <arch/acpi.h>
unsigned long southbridge_write_acpi_tables(device_t device,
unsigned long current, struct acpi_rsdp *rsdp);
void southbridge_inject_dsdt(device_t device);
#endif /* _SOC_APOLLOLAKE_ACPI_H_ */

View File

@@ -202,6 +202,23 @@
#define PMC_GPE_W_31_0 9
#endif
#define IRQ_REG 0x106C
#define SCI_IRQ_ADJUST 24
#define SCI_IRQ_SEL (255 << SCI_IRQ_ADJUST)
#define SCIS_IRQ9 9
#define SCIS_IRQ10 10
#define SCIS_IRQ11 11
#define SCIS_IRQ20 20
#define SCIS_IRQ21 21
#define SCIS_IRQ22 22
#define SCIS_IRQ23 23
/* P-state configuration */
#define PSS_MAX_ENTRIES 8
#define PSS_RATIO_STEP 2
#define PSS_LATENCY_TRANSITION 10
#define PSS_LATENCY_BUSMASTER 10
/* Track power state from reset to log events. */
struct chipset_power_state {
uint16_t pm1_sts;