diff --git a/src/soc/intel/quark/Makefile.inc b/src/soc/intel/quark/Makefile.inc index c89a97e4c5..d8650fa8b9 100644 --- a/src/soc/intel/quark/Makefile.inc +++ b/src/soc/intel/quark/Makefile.inc @@ -26,6 +26,7 @@ ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c ramstage-y += chip.c ramstage-y += memmap.c ramstage-y += northcluster.c +ramstage-y += pmc.c ramstage-y += tsc_freq.c ramstage-$(CONFIG_ENABLE_BUILTIN_HSUART1) += uart_common.c ramstage-$(CONFIG_ENABLE_BUILTIN_HSUART1) += uart.c diff --git a/src/soc/intel/quark/acpi.c b/src/soc/intel/quark/acpi.c index f43a74c6cb..90adc344d2 100644 --- a/src/soc/intel/quark/acpi.c +++ b/src/soc/intel/quark/acpi.c @@ -16,6 +16,7 @@ */ #include +#include unsigned long acpi_fill_madt(unsigned long current) { @@ -30,4 +31,75 @@ unsigned long acpi_fill_mcfg(unsigned long current) void acpi_fill_in_fadt(acpi_fadt_t *fadt) { + struct device *dev = dev_find_slot(0, + PCI_DEVFN(PCI_DEVICE_NUMBER_QNC_LPC, + PCI_FUNCTION_NUMBER_QNC_LPC)); + uint32_t gpe0_base = pci_read_config32(dev, R_QNC_LPC_GPE0BLK) + & B_QNC_LPC_GPE0BLK_MASK; + uint32_t pmbase = pci_read_config32(dev, R_QNC_LPC_PM1BLK) + & B_QNC_LPC_PM1BLK_MASK; + + fadt->flags = ACPI_FADT_RESET_REGISTER | ACPI_FADT_PLATFORM_CLOCK; + + /* PM1 Status: ACPI 4.8.3.1.1 */ + fadt->pm1a_evt_blk = pmbase + R_QNC_PM1BLK_PM1S; + fadt->pm1_evt_len = 2; + + fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; + fadt->x_pm1a_evt_blk.addrl = pmbase + R_QNC_PM1BLK_PM1S; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + /* PM1 Control: ACPI 4.8.3.2.1 */ + fadt->pm1a_cnt_blk = pmbase + R_QNC_PM1BLK_PM1C; + fadt->pm1_cnt_len = 2; + + fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; + fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + /* PM Timer: ACPI 4.8.3.3 */ + fadt->pm_tmr_blk = pmbase + R_QNC_PM1BLK_PM1T; + fadt->pm_tmr_len = 4; + + fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk; + fadt->x_pm_tmr_blk.addrh = 0x0; + + /* Reset Register: ACPI 4.8.3.6, 5.2.3.2 */ + fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + /* Soft/Warm Reset */ + fadt->reset_value = 6; + + /* General-Purpose Event 0 Registers: ACPI 4.8.4.1 */ + fadt->gpe0_blk = gpe0_base; + fadt->gpe0_blk_len = 4 * 2; + + fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + fadt->x_gpe0_blk.addrl = fadt->gpe0_blk; + fadt->x_gpe0_blk.addrh = 0; + + /* Display the base registers */ + printk(BIOS_DEBUG, "FADT:\n"); + printk(BIOS_DEBUG, " 0x%08x: GPE0_BASE\n", gpe0_base); + printk(BIOS_DEBUG, " 0x%08x: PMBASE\n", pmbase); + printk(BIOS_DEBUG, " 0x%08x: RESET\n", fadt->reset_reg.addrl); + } diff --git a/src/soc/intel/quark/include/soc/iomap.h b/src/soc/intel/quark/include/soc/iomap.h index f033dcb560..31cf604844 100644 --- a/src/soc/intel/quark/include/soc/iomap.h +++ b/src/soc/intel/quark/include/soc/iomap.h @@ -24,4 +24,10 @@ /* UART MMIO */ #define UART_BASE_ADDRESS CONFIG_TTYS0_BASE +/* + * I/O port address space + */ +#define ACPI_BASE_ADDRESS 0x1000 +#define ACPI_BASE_SIZE 0x100 + #endif /* _QUARK_IOMAP_H_ */ diff --git a/src/soc/intel/quark/pmc.c b/src/soc/intel/quark/pmc.c new file mode 100644 index 0000000000..fbed93582e --- /dev/null +++ b/src/soc/intel/quark/pmc.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2015-2016 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 +#include +#include +#include +#include +#include + +static void pmc_read_resources(device_t dev) +{ + unsigned index = 0; + struct resource *res; + + /* Get the normal PCI resources of this device. */ + pci_dev_read_resources(dev); + + /* PMBASE */ + res = new_resource(dev, index++); + res->base = ACPI_BASE_ADDRESS; + res->size = ACPI_BASE_SIZE; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static struct device_operations device_ops = { + .read_resources = &pmc_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .scan_bus = &scan_lpc_bus, +}; + +static const struct pci_driver pmc __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = QUARK_V_LPC_DEVICE_ID_0, +};