diff options
author | Subrata Banik <subrata.banik@intel.com> | 2018-10-31 23:08:14 +0530 |
---|---|---|
committer | Subrata Banik <subrata.banik@intel.com> | 2019-06-13 04:38:08 +0000 |
commit | 3d152ac388fa43b4c3d1bfeedcb6a40f1479ace3 (patch) | |
tree | ca39c17047de8a3059cea7314f95910f2b45a8a1 /src/soc/intel/icelake/espi.c | |
parent | 8a70918b8a78d8d5cd27e830cc4ae496b10d4f32 (diff) |
soc/intel/icelake: Replace PCI device LPC to ESPI as per EDS
As per Icelake EDS PCI device B:D:F (0:0x1f:0) referred as ESPI,
hence modify SoC code to reflect the same.
This patch replaces all SoC specific PCI LPC references with ESPI
except anything that touches intel common code block.
Change-Id: I4990ea6d9b7b4c0eac2b3eea559f5469f086e827
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/33190
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Lean Sheng Tan <lean.sheng.tan@intel.com>
Diffstat (limited to 'src/soc/intel/icelake/espi.c')
-rw-r--r-- | src/soc/intel/icelake/espi.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/soc/intel/icelake/espi.c b/src/soc/intel/icelake/espi.c new file mode 100644 index 0000000000..9ca0c7c295 --- /dev/null +++ b/src/soc/intel/icelake/espi.c @@ -0,0 +1,254 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018 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; 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 <device/device.h> +#include <device/pci.h> +#include <pc80/isa-dma.h> +#include <pc80/i8259.h> +#include <arch/io.h> +#include <device/pci_ops.h> +#include <arch/ioapic.h> +#include <intelblocks/itss.h> +#include <intelblocks/lpc_lib.h> +#include <intelblocks/pcr.h> +#include <reg_script.h> +#include <soc/espi.h> +#include <soc/iomap.h> +#include <soc/irq.h> +#include <soc/pci_devs.h> +#include <soc/pcr_ids.h> + +#include "chip.h" + +/* +* As per the BWG, Chapter 5.9.1. "PCH BIOS component will reserve +* certain memory range as reserved range for BIOS usage. +* For this SOC, the range will be from 0FC800000h till FE7FFFFFh" +*/ +static const struct lpc_mmio_range icl_lpc_fixed_mmio_ranges[] = { + { PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE }, + { 0, 0 } +}; + +const struct lpc_mmio_range *soc_get_fixed_mmio_ranges() +{ + return icl_lpc_fixed_mmio_ranges; +} + +void soc_get_gen_io_dec_range(const struct device *dev, uint32_t *gen_io_dec) +{ + const config_t *config = dev->chip_info; + + gen_io_dec[0] = config->gen1_dec; + gen_io_dec[1] = config->gen2_dec; + gen_io_dec[2] = config->gen3_dec; + gen_io_dec[3] = config->gen4_dec; +} + +void soc_setup_dmi_pcr_io_dec(uint32_t *gen_io_dec) +{ + /* Mirror these same settings in DMI PCR */ + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR1, gen_io_dec[0]); + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR2, gen_io_dec[1]); + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR3, gen_io_dec[2]); + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR4, gen_io_dec[3]); +} + +uint8_t get_pch_series(void) +{ + uint16_t lpc_did_hi_byte; + + /* + * Fetch upper 8 bits on ESPI device ID to determine PCH type + * Adding 1 to the offset to fetch upper 8 bits + */ + lpc_did_hi_byte = pci_read_config8(PCH_DEV_ESPI, PCI_DEVICE_ID + 1); + + if (lpc_did_hi_byte == 0x9D) + return PCH_LP; + else if (lpc_did_hi_byte == 0xA3) + return PCH_H; + else + return PCH_UNKNOWN_SERIES; +} + +#if ENV_RAMSTAGE +static void soc_mirror_dmi_pcr_io_dec(void) +{ + struct device *dev = pcidev_on_root(PCH_DEV_SLOT_ESPI, 0); + uint32_t io_dec_arr[] = { + pci_read_config32(dev, ESPI_GEN1_DEC), + pci_read_config32(dev, ESPI_GEN2_DEC), + pci_read_config32(dev, ESPI_GEN3_DEC), + pci_read_config32(dev, ESPI_GEN4_DEC), + }; + /* Mirror these same settings in DMI PCR */ + soc_setup_dmi_pcr_io_dec(&io_dec_arr[0]); +} + +static void pch_enable_ioapic(const struct device *dev) +{ + u32 reg32; + /* PCH-LP has 120 redirection entries */ + const int redir_entries = 120; + + set_ioapic_id((void *)IO_APIC_ADDR, 0x02); + + /* affirm full set of redirection table entries ("write once") */ + reg32 = io_apic_read((void *)IO_APIC_ADDR, 0x01); + + reg32 &= ~0x00ff0000; + reg32 |= (redir_entries - 1) << 16; + + io_apic_write((void *)IO_APIC_ADDR, 0x01, reg32); + + /* + * Select Boot Configuration register (0x03) and + * use Processor System Bus (0x01) to deliver interrupts. + */ + io_apic_write((void *)IO_APIC_ADDR, 0x03, 0x01); +} +/* + * PIRQ[n]_ROUT[3:0] - PIRQ Routing Control + * 0x00 - 0000 = Reserved + * 0x01 - 0001 = Reserved + * 0x02 - 0010 = Reserved + * 0x03 - 0011 = IRQ3 + * 0x04 - 0100 = IRQ4 + * 0x05 - 0101 = IRQ5 + * 0x06 - 0110 = IRQ6 + * 0x07 - 0111 = IRQ7 + * 0x08 - 1000 = Reserved + * 0x09 - 1001 = IRQ9 + * 0x0A - 1010 = IRQ10 + * 0x0B - 1011 = IRQ11 + * 0x0C - 1100 = IRQ12 + * 0x0D - 1101 = Reserved + * 0x0E - 1110 = IRQ14 + * 0x0F - 1111 = IRQ15 + * PIRQ[n]_ROUT[7] - PIRQ Routing Control + * 0x80 - The PIRQ is not routed. + */ + +void soc_pch_pirq_init(const struct device *dev) +{ + struct device *irq_dev; + uint8_t pch_interrupt_routing[MAX_PXRC_CONFIG]; + + pch_interrupt_routing[0] = PCH_IRQ11; + pch_interrupt_routing[1] = PCH_IRQ10; + pch_interrupt_routing[2] = PCH_IRQ11; + pch_interrupt_routing[3] = PCH_IRQ11; + pch_interrupt_routing[4] = PCH_IRQ11; + pch_interrupt_routing[5] = PCH_IRQ11; + pch_interrupt_routing[6] = PCH_IRQ11; + pch_interrupt_routing[7] = PCH_IRQ11; + + itss_irq_init(pch_interrupt_routing); + + for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + u8 int_pin = 0, int_line = 0; + + if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI) + continue; + + int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + + switch (int_pin) { + case 1: /* INTA# */ + int_line = PCH_IRQ11; + break; + case 2: /* INTB# */ + int_line = PCH_IRQ10; + break; + case 3: /* INTC# */ + int_line = PCH_IRQ11; + break; + case 4: /* INTD# */ + int_line = PCH_IRQ11; + break; + } + + if (!int_line) + continue; + + pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line); + } +} + +static void pch_misc_init(void) +{ + uint8_t reg8; + + /* Setup NMI on errors, disable SERR */ + reg8 = (inb(0x61)) & 0xf0; + outb(0x61, (reg8 | (1 << 2))); + + /* Disable NMI sources */ + outb(0x70, (1 << 7)); +}; + +static void clock_gate_8254(const struct device *dev) +{ + const config_t *config = dev->chip_info; + + if (!config->clock_gate_8254) + return; + + itss_clock_gate_8254(); +} + +void lpc_soc_init(struct device *dev) +{ + /* Legacy initialization */ + isa_dma_init(); + pch_misc_init(); + + /* Enable CLKRUN_EN for power gating ESPI */ + lpc_enable_pci_clk_cntl(); + + /* Set ESPI Serial IRQ mode */ + if (CONFIG(SERIRQ_CONTINUOUS_MODE)) + lpc_set_serirq_mode(SERIRQ_CONTINUOUS); + else + lpc_set_serirq_mode(SERIRQ_QUIET); + + /* Interrupt configuration */ + pch_enable_ioapic(dev); + soc_pch_pirq_init(dev); + setup_i8259(); + i8259_configure_irq_trigger(9, 1); + clock_gate_8254(dev); + soc_mirror_dmi_pcr_io_dec(); +} + +/* Fill up ESPI IO resource structure inside SoC directory */ +void pch_lpc_soc_fill_io_resources(struct device *dev) +{ + /* + * PMC pci device gets hidden from PCI bus due to Silicon + * policy hence bind ACPI BASE aka ABASE (offset 0x20) with + * ESPI IO resources to ensure that ABASE falls under PCI reserved + * IO memory range. + * + * Note: Don't add any more resource with same offset 0x20 + * under this device space. + */ + pch_lpc_add_new_resource(dev, PCI_BASE_ADDRESS_4, + ACPI_BASE_ADDRESS, ACPI_BASE_SIZE, IORESOURCE_IO | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED); +} + +#endif |