diff options
Diffstat (limited to 'src/soc/intel/common/block')
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/itss.h | 59 | ||||
-rw-r--r-- | src/soc/intel/common/block/itss/Kconfig | 4 | ||||
-rw-r--r-- | src/soc/intel/common/block/itss/Makefile.inc | 3 | ||||
-rw-r--r-- | src/soc/intel/common/block/itss/itss.c | 140 |
4 files changed, 206 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/include/intelblocks/itss.h b/src/soc/intel/common/block/include/intelblocks/itss.h new file mode 100644 index 0000000000..11f75980fb --- /dev/null +++ b/src/soc/intel/common/block/include/intelblocks/itss.h @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * 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. + */ + +#ifndef SOC_INTEL_COMMON_BLOCK_ITSS_H +#define SOC_INTEL_COMMON_BLOCK_ITSS_H + +/* Max PXRC registers in ITSS*/ +#define MAX_PXRC_CONFIG (PCR_ITSS_PIRQH_ROUT - PCR_ITSS_PIRQA_ROUT + 1) + +/* PIRQA Routing Control Register*/ +#define PCR_ITSS_PIRQA_ROUT 0x3100 +/* PIRQB Routing Control Register*/ +#define PCR_ITSS_PIRQB_ROUT 0x3101 +/* PIRQC Routing Control Register*/ +#define PCR_ITSS_PIRQC_ROUT 0x3102 +/* PIRQD Routing Control Register*/ +#define PCR_ITSS_PIRQD_ROUT 0x3103 +/* PIRQE Routing Control Register*/ +#define PCR_ITSS_PIRQE_ROUT 0x3104 +/* PIRQF Routing Control Register*/ +#define PCR_ITSS_PIRQF_ROUT 0x3105 +/* PIRQG Routing Control Register*/ +#define PCR_ITSS_PIRQG_ROUT 0x3106 +/* PIRQH Routing Control Register*/ +#define PCR_ITSS_PIRQH_ROUT 0x3107 +/* ITSS Interrupt polarity control*/ +#define PCR_ITSS_IPC0_CONF 0x3200 +/* ITSS Power reduction control */ +#define PCR_ITSS_ITSSPRC 0x3300 + +#if !defined(__ACPI__) + +#include <stdint.h> + +/* Set the interrupt polarity for provided IRQ to the APIC. */ +void itss_set_irq_polarity(int irq, int active_low); + +/* Snapshot and restore IRQ polarity settings for the inclusive range. */ +void itss_snapshot_irq_polarities(int start, int end); +void itss_restore_irq_polarities(int start, int end); + +void itss_irq_init(uint8_t pch_interrupt_routing[MAX_PXRC_CONFIG]); +void itss_clock_gate_8254(void); + +#endif /* !defined(__ACPI__) */ + +#endif /* SOC_INTEL_COMMON_BLOCK_ITSS_H */ diff --git a/src/soc/intel/common/block/itss/Kconfig b/src/soc/intel/common/block/itss/Kconfig new file mode 100644 index 0000000000..2f1a1004ad --- /dev/null +++ b/src/soc/intel/common/block/itss/Kconfig @@ -0,0 +1,4 @@ +config SOC_INTEL_COMMON_BLOCK_ITSS + bool + help + Intel Processor common interrupt timer subsystem support diff --git a/src/soc/intel/common/block/itss/Makefile.inc b/src/soc/intel/common/block/itss/Makefile.inc new file mode 100644 index 0000000000..bc0e97a2f9 --- /dev/null +++ b/src/soc/intel/common/block/itss/Makefile.inc @@ -0,0 +1,3 @@ +bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ITSS) += itss.c +romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ITSS) += itss.c +ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ITSS) += itss.c diff --git a/src/soc/intel/common/block/itss/itss.c b/src/soc/intel/common/block/itss/itss.c new file mode 100644 index 0000000000..a217675405 --- /dev/null +++ b/src/soc/intel/common/block/itss/itss.c @@ -0,0 +1,140 @@ +/* + * This file is part of the coreboot project. + * + * 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 <stdint.h> +#include <commonlib/helpers.h> +#include <console/console.h> +#include <intelblocks/itss.h> +#include <intelblocks/pcr.h> +#include <soc/itss.h> +#include <soc/pcr_ids.h> + +void itss_irq_init(uint8_t pch_interrupt_routing[MAX_PXRC_CONFIG]) +{ + uint8_t index = 0; + + for (index = 0; index < MAX_PXRC_CONFIG; index++) { + uint8_t val = pch_interrupt_routing[index]; + uint8_t irq = val & 0xf; + + if (irq == 8 || irq == 13) + continue; + if (irq <= 2) + continue; + + pcr_write8(PID_ITSS, PCR_ITSS_PIRQA_ROUT + index, val); + } +} + +void itss_clock_gate_8254(void) +{ + const uint32_t cge8254_mask = (1 << 2); + + pcr_rmw32(PID_ITSS, PCR_ITSS_ITSSPRC, ~cge8254_mask, cge8254_mask); +} + +void itss_set_irq_polarity(int irq, int active_low) +{ + uint32_t mask; + uint16_t reg; + const uint16_t port = PID_ITSS; + + if (irq < 0 || irq > ITSS_MAX_IRQ) + return; + + reg = PCR_ITSS_IPC0_CONF + sizeof(uint32_t) * (irq / IRQS_PER_IPC); + mask = 1 << (irq % IRQS_PER_IPC); + + pcr_rmw32(port, reg, ~mask, (active_low ? mask : 0)); +} + +static uint32_t irq_snapshot[NUM_IPC_REGS]; + +void itss_snapshot_irq_polarities(int start, int end) +{ + int i; + int reg_start; + int reg_end; + const uint16_t port = PID_ITSS; + + if (start < 0 || start > ITSS_MAX_IRQ || + end < 0 || end > ITSS_MAX_IRQ || end < start) + return; + + reg_start = start / IRQS_PER_IPC; + reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; + + for (i = reg_start; i < reg_end; i++) { + uint16_t reg = PCR_ITSS_IPC0_CONF + sizeof(uint32_t) * i; + irq_snapshot[i] = pcr_read32(port, reg); + } +} + +static void show_irq_polarities(const char *msg) +{ + int i; + const uint16_t port = PID_ITSS; + + printk(BIOS_INFO, "ITSS IRQ Polarities %s:\n", msg); + for (i = 0; i < NUM_IPC_REGS; i++) { + uint16_t reg = PCR_ITSS_IPC0_CONF + sizeof(uint32_t) * i; + printk(BIOS_INFO, "IPC%d: 0x%08x\n", i, pcr_read32(port, reg)); + } +} + +void itss_restore_irq_polarities(int start, int end) +{ + int i; + int reg_start; + int reg_end; + const uint16_t port = PID_ITSS; + + if (start < 0 || start > ITSS_MAX_IRQ || + end < 0 || end > ITSS_MAX_IRQ || end < start) + return; + + show_irq_polarities("Before"); + + reg_start = start / IRQS_PER_IPC; + reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; + + for (i = reg_start; i < reg_end; i++) { + uint32_t mask; + uint16_t reg; + int irq_start; + int irq_end; + + irq_start = i * IRQS_PER_IPC; + irq_end = MIN(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ); + + if (start > irq_end) + continue; + if (end < irq_start) + break; + + /* Track bits within the bounds of of the register. */ + irq_start = MAX(start, irq_start) % IRQS_PER_IPC; + irq_end = MIN(end, irq_end) % IRQS_PER_IPC; + + /* Create bitmask of the inclusive range of start and end. */ + mask = (((1U << irq_end) - 1) | (1U << irq_end)); + mask &= ~((1U << irq_start) - 1); + + reg = PCR_ITSS_IPC0_CONF + sizeof(uint32_t) * i; + pcr_rmw32(port, reg, ~mask, (mask & irq_snapshot[i])); + } + + show_irq_polarities("After"); +} |