diff options
-rw-r--r-- | src/soc/intel/cannonlake/Makefile.inc | 2 | ||||
-rw-r--r-- | src/soc/intel/cannonlake/chip.h | 6 | ||||
-rw-r--r-- | src/soc/intel/cannonlake/gpio.c | 17 | ||||
-rw-r--r-- | src/soc/intel/cannonlake/include/soc/pmc.h | 1 | ||||
-rw-r--r-- | src/soc/intel/cannonlake/pmc.c | 180 |
5 files changed, 204 insertions, 2 deletions
diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc index 0493c1b8ea1a..e06c3ef50ac0 100644 --- a/src/soc/intel/cannonlake/Makefile.inc +++ b/src/soc/intel/cannonlake/Makefile.inc @@ -31,7 +31,9 @@ ramstage-y += chip.c ramstage-y += cpu.c ramstage-y += gpio.c ramstage-y += gspi.c +ramstage-y += gpio.c ramstage-y += memmap.c +ramstage-y += pmc.c ramstage-y += pmutil.c ramstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c ramstage-y += spi.c diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index 6d16327f2743..5a4dfd312c0f 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -63,8 +63,10 @@ struct soc_intel_cannonlake_config { int dptf_enable; /* Deep SX enable for both AC and DC */ - int deep_s3_enable; - int deep_s5_enable; + int deep_s3_enable_ac; + int deep_s3_enable_dc; + int deep_s5_enable_ac; + int deep_s5_enable_dc; /* Deep Sx Configuration * DSX_EN_WAKE_PIN - Enable WAKE# pin diff --git a/src/soc/intel/cannonlake/gpio.c b/src/soc/intel/cannonlake/gpio.c index 68b137d74298..0cc416424aa3 100644 --- a/src/soc/intel/cannonlake/gpio.c +++ b/src/soc/intel/cannonlake/gpio.c @@ -96,3 +96,20 @@ const struct pad_community *soc_gpio_get_community(size_t *num_communities) *num_communities = ARRAY_SIZE(cnl_communities); return cnl_communities; } + +const struct pmc_to_gpio_route *soc_pmc_gpio_routes(size_t *num) +{ + static const struct pmc_to_gpio_route routes[] = { + { GPP_A, GPP_A }, + { GPP_B, GPP_B }, + { GPP_C, GPP_C }, + { GPP_D, GPP_D }, + { GPP_E, GPP_E }, + { GPP_F, GPP_F }, + { GPP_G, GPP_G }, + { GPP_H, GPP_H }, + { GPD, GPD }, + }; + *num = ARRAY_SIZE(routes); + return routes; +} diff --git a/src/soc/intel/cannonlake/include/soc/pmc.h b/src/soc/intel/cannonlake/include/soc/pmc.h index 69954db6cee1..a98b4bad7f9e 100644 --- a/src/soc/intel/cannonlake/include/soc/pmc.h +++ b/src/soc/intel/cannonlake/include/soc/pmc.h @@ -105,6 +105,7 @@ #define DSX_EN_WAKE_PIN (1 << 2) #define DSX_EN_AC_PRESENT_PIN (1 << 1) #define DSX_EN_LAN_WAKE_PIN (1 << 0) +#define DSX_CFG_MASK (0x1f << 0) #define PMSYNC_TPR_CFG 0x18C4 #define PCH2CPU_TPR_CFG_LOCK (1 << 31) diff --git a/src/soc/intel/cannonlake/pmc.c b/src/soc/intel/cannonlake/pmc.c new file mode 100644 index 000000000000..a91e5eaecd61 --- /dev/null +++ b/src/soc/intel/cannonlake/pmc.c @@ -0,0 +1,180 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2017 Intel Corporation. + * + * 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; version 2 of the License. + * + * 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. + */ + +#include <chip.h> +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <arch/io.h> +#include <arch/ioapic.h> +#include <arch/acpi.h> +#include <cpu/cpu.h> +#include <intelblocks/pcr.h> +#include <intelblocks/pmclib.h> +#include <intelblocks/rtc.h> +#include <pc80/mc146818rtc.h> +#include <string.h> +#include <soc/gpio.h> +#include <soc/iomap.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> +#include <cpu/x86/smm.h> +#include <soc/pcr_ids.h> +#include <soc/ramstage.h> +#include <vboot/vbnv.h> +#include <vboot/vbnv_layout.h> + +static void pch_pmc_add_mmio_resources(device_t dev) +{ + struct resource *res; + + /* Memory-mmapped I/O registers. */ + res = new_resource(dev, PWRMBASE); + res->base = PCH_PWRM_BASE_ADDRESS; + res->size = PCH_PWRM_BASE_SIZE; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | + IORESOURCE_FIXED | IORESOURCE_RESERVE; +} + +static void pch_pmc_add_io_resource(device_t dev, u16 base, u16 size, int index) +{ + struct resource *res; + res = new_resource(dev, index); + res->base = base; + res->size = size; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void pch_pmc_add_io_resources(device_t dev) +{ + /* PMBASE */ + pch_pmc_add_io_resource(dev, ACPI_BASE_ADDRESS, ACPI_BASE_SIZE, ABASE); +} + +static void pch_pmc_read_resources(device_t dev) +{ + /* Get the normal PCI resources of this device. */ + pci_dev_read_resources(dev); + + /* Add non-standard MMIO resources. */ + pch_pmc_add_mmio_resources(dev); + + /* Add IO resources. */ + pch_pmc_add_io_resources(dev); +} + +static void pch_set_acpi_mode(void) +{ + if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER) && !acpi_is_wakeup_s3()) { + printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n"); + outb(APM_CNT_ACPI_DISABLE, APM_CNT); + printk(BIOS_DEBUG, "done.\n"); + } +} + +int soc_get_rtc_failed(void) +{ + uint8_t reg8; + int rtc_failed; + uint8_t *pmcbase = pmc_mmio_regs(); + + reg8 = read8(pmcbase + GEN_PMCON_B); + rtc_failed = reg8 & RTC_BATTERY_DEAD; + if (rtc_failed) { + reg8 &= ~RTC_BATTERY_DEAD; + write8(pmcbase + GEN_PMCON_B, reg8); + printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); + } + return rtc_failed; +} + +static void config_deep_sX(uint32_t offset, uint32_t mask, int sx, int enable) +{ + uint32_t reg; + uint8_t *pmcbase = pmc_mmio_regs(); + + printk(BIOS_DEBUG, "%sabling Deep S%c\n", + enable ? "En" : "Dis", sx + '0'); + reg = read32(pmcbase + offset); + if (enable) + reg |= mask; + else + reg &= ~mask; + write32(pmcbase + offset, reg); +} + +static void config_deep_s5(int on_ac, int on_dc) +{ + /* Treat S4 the same as S5. */ + config_deep_sX(S4_PWRGATE_POL, S4AC_GATE_SUS, 4, on_ac); + config_deep_sX(S4_PWRGATE_POL, S4DC_GATE_SUS, 4, on_dc); + config_deep_sX(S5_PWRGATE_POL, S5AC_GATE_SUS, 5, on_ac); + config_deep_sX(S5_PWRGATE_POL, S5DC_GATE_SUS, 5, on_dc); +} + +static void config_deep_s3(int on_ac, int on_dc) +{ + config_deep_sX(S3_PWRGATE_POL, S3AC_GATE_SUS, 3, on_ac); + config_deep_sX(S3_PWRGATE_POL, S3DC_GATE_SUS, 3, on_dc); +} + +static void config_deep_sx(uint32_t deepsx_config) +{ + uint32_t reg; + uint8_t *pmcbase = pmc_mmio_regs(); + + reg = read32(pmcbase + DSX_CFG); + reg &= ~DSX_CFG_MASK; + reg |= deepsx_config; + write32(pmcbase + DSX_CFG, reg); +} + +static void pmc_init(struct device *dev) +{ + config_t *config = dev->chip_info; + + rtc_init(); + + /* Initialize power management */ + pmc_gpe_init(); + + pch_set_acpi_mode(); + + config_deep_s3(config->deep_s3_enable_ac, config->deep_s3_enable_dc); + config_deep_s5(config->deep_s5_enable_ac, config->deep_s5_enable_dc); + config_deep_sx(config->deep_sx_config); +} + +static struct device_operations device_ops = { + .read_resources = &pch_pmc_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &pmc_init, + .scan_bus = &scan_lpc_bus, +}; + +static const unsigned short pci_device_ids[] = { + PCI_DEVICE_ID_INTEL_CNL_PMC, + 0 +}; + +static const struct pci_driver pch_lpc __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; |