aboutsummaryrefslogtreecommitdiff
path: root/src/soc/intel/skylake/bootblock/pch.c
diff options
context:
space:
mode:
authorNaresh G Solanki <naresh.solanki@intel.com>2016-08-11 14:56:28 +0530
committerMartin Roth <martinroth@google.com>2016-08-18 18:13:42 +0200
commitecd9a94213216f2f50e501e6b27ee390928e0dbf (patch)
tree33e48614fb462ccadb76e17950d6a8b49ee35dd5 /src/soc/intel/skylake/bootblock/pch.c
parentcf73c1317dd1ab62a96eb17ed6d9c8590fb4c514 (diff)
soc/intel/skylake: Move bootblock specific code from skylake/romstage
There is a lot of code that is being referred to in bootblock but resides under skylake/romstage folder. Hence move this code into skylake/bootblock, and update the relevant header files and Makefiles. TEST=Build and Boot kunimitsu. Change-Id: If94e16fe54ccb7ced9c6b480a661609bdd2dfa41 Signed-off-by: Naresh G Solanki <naresh.solanki@intel.com> Reviewed-on: https://review.coreboot.org/16225 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/soc/intel/skylake/bootblock/pch.c')
-rw-r--r--src/soc/intel/skylake/bootblock/pch.c205
1 files changed, 203 insertions, 2 deletions
diff --git a/src/soc/intel/skylake/bootblock/pch.c b/src/soc/intel/skylake/bootblock/pch.c
index e7f414b721..22ab1090b8 100644
--- a/src/soc/intel/skylake/bootblock/pch.c
+++ b/src/soc/intel/skylake/bootblock/pch.c
@@ -15,13 +15,22 @@
* GNU General Public License for more details.
*/
#include <arch/io.h>
+#include <chip.h>
+#include <device/device.h>
+#include <device/pci_def.h>
#include <soc/bootblock.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/p2sb.h>
+#include <soc/pch.h>
#include <soc/pci_devs.h>
#include <soc/pcr.h>
-#include <soc/spi.h>
+#include <soc/pm.h>
+#include <soc/pmc.h>
+#include <soc/smbus.h>
+
+/* Max PXRC registers in ITSS*/
+#define MAX_PXRC_CONFIG 0x08
/*
* Enable Prefetching and Caching.
@@ -65,7 +74,6 @@ static void enable_p2sbbar(void)
/* Enable P2SB MSE */
pci_write_config8(dev, PCI_COMMAND,
PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-
/*
* Enable decoding for HPET memory address range.
* HPTC_OFFSET(0x60) bit 7, when set the P2SB will decode
@@ -81,3 +89,196 @@ void bootblock_pch_early_init(void)
enable_spi_prefetch();
enable_p2sbbar();
}
+
+static void pch_enable_lpc(void)
+{
+ /* Lookup device tree in romstage */
+ const struct device *dev;
+ const config_t *config;
+ u16 lpc_en;
+
+ /* IO Decode Range */
+ lpc_en = COMA_RANGE | (COMB_RANGE << 4);
+ pci_write_config16(PCH_DEV_LPC, LPC_IO_DEC, lpc_en);
+ pcr_write16(PID_DMI, R_PCH_PCR_DMI_LPCIOD, lpc_en);
+
+ /* IO Decode Enable */
+ lpc_en = COMA_LPC_EN | KBC_LPC_EN | MC_LPC_EN;
+ pci_write_config16(PCH_DEV_LPC, LPC_EN, lpc_en);
+ pcr_write16(PID_DMI, R_PCH_PCR_DMI_LPCIOE, lpc_en);
+
+ dev = dev_find_slot(0, PCI_DEVFN(PCH_DEV_SLOT_LPC, 0));
+ if (!dev || !dev->chip_info)
+ return;
+ config = dev->chip_info;
+
+ /* Set in PCI generic decode range registers */
+ pci_write_config32(PCH_DEV_LPC, LPC_GEN1_DEC, config->gen1_dec);
+ pci_write_config32(PCH_DEV_LPC, LPC_GEN2_DEC, config->gen2_dec);
+ pci_write_config32(PCH_DEV_LPC, LPC_GEN3_DEC, config->gen3_dec);
+ pci_write_config32(PCH_DEV_LPC, LPC_GEN4_DEC, config->gen4_dec);
+
+ /* Mirror these same settings in DMI PCR */
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_LPCLGIR1, config->gen1_dec);
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_LPCLGIR2, config->gen2_dec);
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_LPCLGIR3, config->gen3_dec);
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_LPCLGIR4, config->gen4_dec);
+}
+
+static void pch_interrupt_init(void)
+{
+ const struct device *dev;
+ const config_t *config;
+ u8 index = 0;
+ u8 pch_interrupt_routing[MAX_PXRC_CONFIG];
+
+ dev = dev_find_slot(0, PCI_DEVFN(PCH_DEV_SLOT_LPC, 0));
+ if (!dev || !dev->chip_info)
+ return;
+ config = dev->chip_info;
+
+ pch_interrupt_routing[0] = config->pirqa_routing;
+ pch_interrupt_routing[1] = config->pirqb_routing;
+ pch_interrupt_routing[2] = config->pirqc_routing;
+ pch_interrupt_routing[3] = config->pirqd_routing;
+ pch_interrupt_routing[4] = config->pirqe_routing;
+ pch_interrupt_routing[5] = config->pirqf_routing;
+ pch_interrupt_routing[6] = config->pirqg_routing;
+ pch_interrupt_routing[7] = config->pirqh_routing;
+
+ for (index = 0; index < MAX_PXRC_CONFIG; index++) {
+ if (pch_interrupt_routing[index] < 16 &&
+ pch_interrupt_routing[index] > 2 &&
+ pch_interrupt_routing[index] != 8 &&
+ pch_interrupt_routing[index] != 13) {
+ pcr_write8(PID_ITSS,
+ (R_PCH_PCR_ITSS_PIRQA_ROUT + index),
+ pch_interrupt_routing[index]);
+ }
+ }
+}
+
+static void soc_config_acpibase(void)
+{
+ uint32_t reg32;
+
+ /* Disable ABASE in PMC Device first before changing Base Address */
+ reg32 = pci_read_config32(PCH_DEV_PMC, ACTL);
+ pci_write_config32(PCH_DEV_PMC, ACTL, reg32 & ~ACPI_EN);
+
+ /* Program ACPI Base */
+ pci_write_config32(PCH_DEV_PMC, ABASE, ACPI_BASE_ADDRESS);
+
+ /* Enable ACPI in PMC */
+ pci_write_config32(PCH_DEV_PMC, ACTL, reg32 | ACPI_EN);
+
+ /*
+ * Program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0]
+ * to [0x3F, PMC PCI Offset 40h bit[15:2], 1]
+ */
+ reg32 = ((0x3f << 18) | ACPI_BASE_ADDRESS | 1);
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_ACPIBA, reg32);
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_ACPIBDID, 0x23A0);
+}
+
+static void soc_config_pwrmbase(void)
+{
+ uint32_t reg32;
+
+ /* Disable PWRMBASE in PMC Device first before changing Base address */
+ reg32 = pci_read_config32(PCH_DEV_PMC, ACTL);
+ pci_write_config32(PCH_DEV_PMC, ACTL, reg32 & ~PWRM_EN);
+
+ /* Program PWRM Base */
+ pci_write_config32(PCH_DEV_PMC, PWRMBASE, PCH_PWRM_BASE_ADDRESS);
+
+ /* Enable PWRM in PMC */
+ pci_write_config32(PCH_DEV_PMC, ACTL, reg32 | PWRM_EN);
+
+ /*
+ * Program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0]
+ * to the same value programmed in PMC PCI Offset 48h bit[31:16],
+ * this has an implication of making sure the PWRMBASE to be
+ * 64KB aligned.
+ *
+ * Program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16]
+ * to the value programmed in PMC PCI Offset 48h bit[31:16], this has an
+ * implication of making sure the memory allocated to PWRMBASE to be 64KB
+ * in size.
+ */
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_PMBASEA,
+ ((PCH_PWRM_BASE_ADDRESS & 0xFFFF0000) |
+ (PCH_PWRM_BASE_ADDRESS >> 16)));
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_PMBASEC, 0x800023A0);
+}
+
+static void soc_config_tco(void)
+{
+ uint32_t reg32 = 0;
+ uint16_t tcobase;
+ uint16_t tcocnt;
+
+ /* Disable TCO in SMBUS Device first before changing Base Address */
+ reg32 = pci_read_config32(PCH_DEV_SMBUS, TCOCTL);
+ reg32 &= ~SMBUS_TCO_EN;
+ pci_write_config32(PCH_DEV_SMBUS, TCOCTL, reg32);
+
+ /* Program TCO Base */
+ pci_write_config32(PCH_DEV_SMBUS, TCOBASE, TCO_BASE_ADDDRESS);
+
+ /* Enable TCO in SMBUS */
+ pci_write_config32(PCH_DEV_SMBUS, TCOCTL, reg32 | SMBUS_TCO_EN);
+
+ /*
+ * Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1]
+ * to [SMBUS PCI offset 50h[15:5], 1].
+ */
+ pcr_write32(PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ (TCO_BASE_ADDDRESS | (1 << 1)));
+
+ /* Program TCO timer halt */
+ tcobase = pci_read_config16(PCH_DEV_SMBUS, TCOBASE);
+ tcobase &= ~0x1f;
+ tcocnt = inw(tcobase + TCO1_CNT);
+ tcocnt |= TCO_TMR_HLT;
+ outw(tcocnt, tcobase + TCO1_CNT);
+}
+
+static void soc_config_rtc(void)
+{
+ /* Enable upper 128 bytes of CMOS */
+ pcr_andthenor32(PID_RTC, R_PCH_PCR_RTC_CONF, ~0,
+ B_PCH_PCR_RTC_CONF_UCMOS_EN);
+}
+
+void pch_early_init(void)
+{
+ /*
+ * Enabling ABASE for accessing PM1_STS, PM1_EN, PM1_CNT,
+ * GPE0_STS, GPE0_EN registers.
+ */
+ soc_config_acpibase();
+
+ /*
+ * Enabling PWRM Base for accessing
+ * Global Reset Cause Register.
+ */
+ soc_config_pwrmbase();
+
+ /* Programming TCO_BASE_ADDRESS and TCO Timer Halt */
+ soc_config_tco();
+
+ /*
+ * Interrupt Configuration Register Programming
+ * PIRQx to IRQ Programming
+ */
+ pch_interrupt_init();
+
+ /* Program generic IO Decode Range */
+ pch_enable_lpc();
+
+ /* Program SMBUS_BASE_ADDRESS and Enable it */
+ enable_smbus();
+
+ soc_config_rtc();
+}