diff options
author | Naresh G Solanki <naresh.solanki@intel.com> | 2016-08-11 14:56:28 +0530 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2016-08-18 18:13:42 +0200 |
commit | ecd9a94213216f2f50e501e6b27ee390928e0dbf (patch) | |
tree | 33e48614fb462ccadb76e17950d6a8b49ee35dd5 /src/soc/intel/skylake/bootblock | |
parent | cf73c1317dd1ab62a96eb17ed6d9c8590fb4c514 (diff) | |
download | coreboot-ecd9a94213216f2f50e501e6b27ee390928e0dbf.tar.xz |
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')
-rw-r--r-- | src/soc/intel/skylake/bootblock/bootblock.c | 1 | ||||
-rw-r--r-- | src/soc/intel/skylake/bootblock/cpu.c | 26 | ||||
-rw-r--r-- | src/soc/intel/skylake/bootblock/i2c.c | 109 | ||||
-rw-r--r-- | src/soc/intel/skylake/bootblock/pch.c | 205 | ||||
-rw-r--r-- | src/soc/intel/skylake/bootblock/report_platform.c | 222 | ||||
-rw-r--r-- | src/soc/intel/skylake/bootblock/smbus.c | 47 |
6 files changed, 607 insertions, 3 deletions
diff --git a/src/soc/intel/skylake/bootblock/bootblock.c b/src/soc/intel/skylake/bootblock/bootblock.c index f644d1f638..b00fcf74ab 100644 --- a/src/soc/intel/skylake/bootblock/bootblock.c +++ b/src/soc/intel/skylake/bootblock/bootblock.c @@ -15,7 +15,6 @@ #include <bootblock_common.h> #include <soc/bootblock.h> -#include <soc/romstage.h> void asmlinkage bootblock_c_entry(uint64_t base_timestamp) { diff --git a/src/soc/intel/skylake/bootblock/cpu.c b/src/soc/intel/skylake/bootblock/cpu.c index 8c1e58a65f..3cea8bdcfc 100644 --- a/src/soc/intel/skylake/bootblock/cpu.c +++ b/src/soc/intel/skylake/bootblock/cpu.c @@ -17,9 +17,11 @@ #include <stdint.h> #include <delay.h> #include <arch/io.h> +#include <console/console.h> #include <cpu/intel/microcode/microcode.c> #include <reset.h> #include <soc/bootblock.h> +#include <soc/cpu.h> #include <soc/iomap.h> #include <soc/msr.h> #include <soc/pci_devs.h> @@ -105,3 +107,27 @@ void bootblock_cpu_init(void) set_flex_ratio_to_tdp_nominal(); intel_update_microcode_from_cbfs(); } + +void set_max_freq(void) +{ + msr_t msr, perf_ctl, platform_info; + + /* Check for configurable TDP option */ + platform_info = rdmsr(MSR_PLATFORM_INFO); + + if ((platform_info.hi >> 1) & 3) { + /* Set to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else { + /* Platform Info bits 15:8 give max ratio */ + msr = rdmsr(MSR_PLATFORM_INFO); + perf_ctl.lo = msr.lo & 0xff00; + } + + perf_ctl.hi = 0; + wrmsr(IA32_PERF_CTL, perf_ctl); + + printk(BIOS_DEBUG, "CPU: frequency set to %d MHz\n", + ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); +} diff --git a/src/soc/intel/skylake/bootblock/i2c.c b/src/soc/intel/skylake/bootblock/i2c.c new file mode 100644 index 0000000000..64b1fb57e7 --- /dev/null +++ b/src/soc/intel/skylake/bootblock/i2c.c @@ -0,0 +1,109 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 <arch/io.h> +#include <commonlib/helpers.h> +#include <device/device.h> +#include <device/i2c.h> +#include <device/pci_def.h> +#include <soc/intel/common/lpss_i2c.h> +#include <soc/iomap.h> +#include <soc/pci_devs.h> +#include <soc/bootblock.h> +#include <soc/serialio.h> +#include "chip.h" + +uintptr_t lpss_i2c_base_address(unsigned bus) +{ + int devfn; + pci_devfn_t dev; + + /* Find device+function for this controller */ + devfn = i2c_bus_to_devfn(bus); + if (devfn < 0) + return 0; + + /* Form a PCI address for this device */ + dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)); + + /* Read the first base address for this device */ + return ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16); +} + +static void i2c_early_init_bus(unsigned bus) +{ + ROMSTAGE_CONST struct soc_intel_skylake_config *config; + ROMSTAGE_CONST struct device *tree_dev; + const struct lpss_i2c_speed_config *sptr; + enum i2c_speed speed; + pci_devfn_t dev; + int devfn; + uintptr_t base; + uint32_t value; + void *reg; + + /* Find the PCI device for this bus controller */ + devfn = i2c_bus_to_devfn(bus); + if (devfn < 0) + return; + + /* Look up the controller device in the devicetree */ + dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)); + tree_dev = dev_find_slot(0, devfn); + if (!tree_dev || !tree_dev->enabled) + return; + + /* Skip if not enabled for early init */ + config = tree_dev->chip_info; + if (!config) + return; + if (!config->i2c[bus].early_init) + return; + + /* Prepare early base address for access before memory */ + base = EARLY_I2C_BASE(bus); + pci_write_config32(dev, PCI_BASE_ADDRESS_0, base); + pci_write_config32(dev, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + /* Take device out of reset */ + reg = (void *)(base + SIO_REG_PPR_RESETS); + value = read32(reg); + value |= SIO_REG_PPR_RESETS_FUNC | SIO_REG_PPR_RESETS_APB | + SIO_REG_PPR_RESETS_IDMA; + write32(reg, value); + + /* Initialize the controller */ + speed = config->i2c[bus].speed ? : I2C_SPEED_FAST; + lpss_i2c_init(bus, speed); + + /* Apply custom speed config if it has been set by the board */ + for (value = 0; value < LPSS_I2C_SPEED_CONFIG_COUNT; value++) { + sptr = &config->i2c[bus].speed_config[value]; + if (sptr->speed == speed) { + lpss_i2c_set_speed_config(bus, sptr); + break; + } + } +} + +void i2c_early_init(void) +{ + int bus; + + /* Initialize I2C controllers that are enabled in devicetree */ + for (bus = 0; bus < SKYLAKE_I2C_DEV_MAX; bus++) + i2c_early_init_bus(bus); +} 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(); +} diff --git a/src/soc/intel/skylake/bootblock/report_platform.c b/src/soc/intel/skylake/bootblock/report_platform.c new file mode 100644 index 0000000000..2610940859 --- /dev/null +++ b/src/soc/intel/skylake/bootblock/report_platform.c @@ -0,0 +1,222 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2015 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 <arch/cpu.h> +#include <arch/io.h> +#include <console/console.h> +#include <cpu/x86/msr.h> +#include <device/pci.h> +#include <soc/bootblock.h> +#include <soc/cpu.h> +#include <soc/pch.h> +#include <soc/pci_devs.h> +#include <soc/systemagent.h> +#include <string.h> + +static struct { + u32 cpuid; + const char *name; +} cpu_table[] = { + { CPUID_SKYLAKE_C0, "Skylake C0" }, + { CPUID_SKYLAKE_D0, "Skylake D0" }, + { CPUID_KABYLAKE_G0, "Kabylake G0" }, + { CPUID_KABYLAKE_H0, "Kabylake H0" }, +}; + +static struct { + u16 mchid; + const char *name; +} mch_table[] = { + { MCH_SKYLAKE_ID_U, "Skylake-U" }, + { MCH_SKYLAKE_ID_Y, "Skylake-Y" }, + { MCH_SKYLAKE_ID_ULX, "Skylake-ULX" }, + { MCH_KABYLAKE_ID_U, "Kabylake-U" }, + { MCH_KABYLAKE_ID_Y, "Kabylake-Y" }, +}; + +static struct { + u16 lpcid; + const char *name; +} pch_table[] = { + { PCH_SPT_LP_SAMPLE, "Skylake LP Sample" }, + { PCH_SPT_LP_U_BASE, "Skylake-U Base" }, + { PCH_SPT_LP_U_PREMIUM, "Skylake-U Premium" }, + { PCH_SPT_LP_Y_PREMIUM, "Skylake-Y Premium" }, + { PCH_KBL_LP_U_PREMIUM, "Kabylake-U Premium" }, + { PCH_KBL_LP_Y_PREMIUM, "Kabylake-Y Premium" }, +}; + +static struct { + u16 igdid; + const char *name; +} igd_table[] = { + { IGD_SKYLAKE_GT1_SULTM, "Skylake ULT GT1"}, + { IGD_SKYLAKE_GT2_SULXM, "Skylake ULX GT2" }, + { IGD_SKYLAKE_GT2_SULTM, "Skylake ULT GT2" }, +}; + +static void report_cpu_info(void) +{ + struct cpuid_result cpuidr; + u32 i, index; + char cpu_string[50], *cpu_name = cpu_string; /* 48 bytes are reported */ + int vt, txt, aes; + msr_t microcode_ver; + const char *mode[] = {"NOT ", ""}; + const char *cpu_type = "Unknown"; + + index = 0x80000000; + cpuidr = cpuid(index); + if (cpuidr.eax < 0x80000004) { + strcpy(cpu_string, "Platform info not available"); + } else { + u32 *p = (u32 *) cpu_string; + for (i = 2; i <= 4; i++) { + cpuidr = cpuid(index + i); + *p++ = cpuidr.eax; + *p++ = cpuidr.ebx; + *p++ = cpuidr.ecx; + *p++ = cpuidr.edx; + } + } + /* Skip leading spaces in CPU name string */ + while (cpu_name[0] == ' ') + cpu_name++; + + microcode_ver.lo = 0; + microcode_ver.hi = 0; + wrmsr(0x8B, microcode_ver); + cpuidr = cpuid(1); + microcode_ver = rdmsr(0x8b); + + /* Look for string to match the name */ + for (i = 0; i < ARRAY_SIZE(cpu_table); i++) { + if (cpu_table[i].cpuid == cpuidr.eax) { + cpu_type = cpu_table[i].name; + break; + } + } + + printk(BIOS_DEBUG, "CPU: %s\n", cpu_name); + printk(BIOS_DEBUG, "CPU: ID %x, %s, ucode: %08x\n", + cpuidr.eax, cpu_type, microcode_ver.hi); + + aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0; + txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0; + vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0; + printk(BIOS_DEBUG, + "CPU: AES %ssupported, TXT %ssupported, VT %ssupported\n", + mode[aes], mode[txt], mode[vt]); +} + +static void report_mch_info(void) +{ + int i; + u16 mchid = pci_read_config16(SA_DEV_ROOT, PCI_DEVICE_ID); + u8 mch_revision = pci_read_config8(SA_DEV_ROOT, PCI_REVISION_ID); + const char *mch_type = "Unknown"; + + for (i = 0; i < ARRAY_SIZE(mch_table); i++) { + if (mch_table[i].mchid == mchid) { + mch_type = mch_table[i].name; + break; + } + } + + printk(BIOS_DEBUG, "MCH: device id %04x (rev %02x) is %s\n", + mchid, mch_revision, mch_type); +} + +static void report_pch_info(void) +{ + int i; + u16 lpcid = pch_type(); + const char *pch_type = "Unknown"; + + for (i = 0; i < ARRAY_SIZE(pch_table); i++) { + if (pch_table[i].lpcid == lpcid) { + pch_type = pch_table[i].name; + break; + } + } + printk(BIOS_DEBUG, "PCH: device id %04x (rev %02x) is %s\n", + lpcid, pch_revision(), pch_type); +} + +static void report_igd_info(void) +{ + int i; + u16 igdid = pci_read_config16(SA_DEV_IGD, PCI_DEVICE_ID); + const char *igd_type = "Unknown"; + + for (i = 0; i < ARRAY_SIZE(igd_table); i++) { + if (igd_table[i].igdid == igdid) { + igd_type = igd_table[i].name; + break; + } + } + printk(BIOS_DEBUG, "IGD: device id %04x (rev %02x) is %s\n", + igdid, pci_read_config8(SA_DEV_IGD, PCI_REVISION_ID), igd_type); +} + +void report_platform_info(void) +{ + report_cpu_info(); + report_mch_info(); + report_pch_info(); + report_igd_info(); +} + +/* + * Dump in the log memory controller configuration as read from the memory + * controller registers. + */ +void report_memory_config(void) +{ + u32 addr_decoder_common, addr_decode_ch[2]; + int i; + + addr_decoder_common = MCHBAR32(0x5000); + addr_decode_ch[0] = MCHBAR32(0x5004); + addr_decode_ch[1] = MCHBAR32(0x5008); + + printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n", + (MCHBAR32(0x5e04) * 13333 * 2 + 50)/100); + printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n", + addr_decoder_common & 3, + (addr_decoder_common >> 2) & 3, + (addr_decoder_common >> 4) & 3); + + for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { + u32 ch_conf = addr_decode_ch[i]; + printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", + i, ch_conf); + printk(BIOS_DEBUG, " enhanced interleave mode %s\n", + ((ch_conf >> 22) & 1) ? "on" : "off"); + printk(BIOS_DEBUG, " rank interleave %s\n", + ((ch_conf >> 21) & 1) ? "on" : "off"); + printk(BIOS_DEBUG, " DIMMA %d MB width %s %s rank%s\n", + ((ch_conf >> 0) & 0xff) * 256, + ((ch_conf >> 19) & 1) ? "x16" : "x8 or x32", + ((ch_conf >> 17) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? "" : ", selected"); + printk(BIOS_DEBUG, " DIMMB %d MB width %s %s rank%s\n", + ((ch_conf >> 8) & 0xff) * 256, + ((ch_conf >> 19) & 1) ? "x16" : "x8 or x32", + ((ch_conf >> 18) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? ", selected" : ""); + } +} diff --git a/src/soc/intel/skylake/bootblock/smbus.c b/src/soc/intel/skylake/bootblock/smbus.c new file mode 100644 index 0000000000..bb305d5192 --- /dev/null +++ b/src/soc/intel/skylake/bootblock/smbus.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2015 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 <arch/io.h> +#include <console/console.h> +#include <device/pci_ids.h> +#include <device/pci_def.h> +#include <reg_script.h> +#include <soc/bootblock.h> +#include <soc/iomap.h> +#include <soc/pci_devs.h> +#include <soc/smbus.h> + +static const struct reg_script smbus_init_script[] = { + /* Set SMBUS I/O base address */ + REG_PCI_WRITE32(SMB_BASE, SMBUS_BASE_ADDRESS | 1), + /* Set SMBUS enable */ + REG_PCI_WRITE8(HOSTC, HST_EN), + /* Enable I/O access */ + REG_PCI_WRITE16(PCI_COMMAND, PCI_COMMAND_IO), + /* Disable interrupts */ + REG_IO_WRITE8(SMBUS_BASE_ADDRESS + SMBHSTCTL, 0), + /* Clear errors */ + REG_IO_WRITE8(SMBUS_BASE_ADDRESS + SMBHSTSTAT, 0xff), + /* Indicate the end of this array by REG_SCRIPT_END */ + REG_SCRIPT_END, +}; + +void enable_smbus(void) +{ + reg_script_run_on_dev(PCH_DEV_SMBUS, smbus_init_script); +} + |