diff options
author | Duncan Laurie <dlaurie@chromium.org> | 2013-04-26 10:35:19 -0700 |
---|---|---|
committer | Alexandru Gagniuc <mr.nuke.me@gmail.com> | 2013-11-24 16:04:12 +0100 |
commit | e1e87e0ed6280f168abd92edcd692aec4ead8fe8 (patch) | |
tree | 0545c568254811a9b8204ebd880539a689ae1fe5 /src | |
parent | f24262d01822bd8634e44b5aab19dafe7e04ae72 (diff) |
haswell: Configure PCH power sharing for ULT
This reads PCH power levels via PCODE mailbox and writes the
values into the PMSYNC registers as indicated in the BWG.
Change-Id: Iddcdef9b7deb6365f874f629599d1f7376c9a190
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/49329
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/4143
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/cpu/intel/haswell/haswell.h | 2 | ||||
-rw-r--r-- | src/cpu/intel/haswell/haswell_init.c | 69 | ||||
-rw-r--r-- | src/southbridge/intel/lynxpoint/finalize.c | 3 | ||||
-rw-r--r-- | src/southbridge/intel/lynxpoint/pch.h | 2 |
4 files changed, 75 insertions, 1 deletions
diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index 96f94ebd0a..7dfba863d4 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -107,6 +107,8 @@ #define MAILBOX_BIOS_CMD_WRITE_PCS 2 #define MAILBOX_BIOS_CMD_READ_CALIBRATION 0x509 #define MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL 0x909 +#define MAILBOX_BIOS_CMD_READ_PCH_POWER 0xa +#define MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT 0xb /* Errors are returned back in bits 7:0. */ #define MAILBOX_BIOS_ERROR_NONE 0 #define MAILBOX_BIOS_ERROR_INVALID_COMMAND 1 diff --git a/src/cpu/intel/haswell/haswell_init.c b/src/cpu/intel/haswell/haswell_init.c index 0b7a8985cf..071135c3f2 100644 --- a/src/cpu/intel/haswell/haswell_init.c +++ b/src/cpu/intel/haswell/haswell_init.c @@ -274,6 +274,71 @@ static void calibrate_24mhz_bclk(void) MCHBAR32(BIOS_MAILBOX_DATA)); } +static u32 pcode_mailbox_read(u32 command) +{ + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return 0; + } + + /* Send command and start transaction */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return 0; + } + + /* Read mailbox */ + return MCHBAR32(BIOS_MAILBOX_DATA); +} + +static void configure_pch_power_sharing(void) +{ + u32 pch_power, pch_power_ext, pmsync, pmsync2; + int i; + + /* Read PCH Power levels from PCODE */ + pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER); + pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT); + + printk(BIOS_INFO, "PCH Power: PCODE Levels 0x%08x 0x%08x\n", + pch_power, pch_power_ext); + + pmsync = RCBA32(PMSYNC_CONFIG); + pmsync2 = RCBA32(PMSYNC_CONFIG2); + + /* Program PMSYNC_TPR_CONFIG PCH power limit values + * pmsync[0:4] = mailbox[0:5] + * pmsync[8:12] = mailbox[6:11] + * pmsync[16:20] = mailbox[12:17] + */ + for (i = 0; i < 3; i++) { + u32 level = pch_power & 0x3f; + pch_power >>= 6; + pmsync &= ~(0x1f << (i * 8)); + pmsync |= (level & 0x1f) << (i * 8); + } + RCBA32(PMSYNC_CONFIG) = pmsync; + + /* Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values + * pmsync2[0:4] = mailbox[23:18] + * pmsync2[8:12] = mailbox_ext[6:11] + * pmsync2[16:20] = mailbox_ext[12:17] + * pmsync2[24:28] = mailbox_ext[18:22] + */ + pmsync2 &= ~0x1f; + pmsync2 |= pch_power & 0x1f; + + for (i = 1; i < 4; i++) { + u32 level = pch_power_ext & 0x3f; + pch_power_ext >>= 6; + pmsync2 &= ~(0x1f << (i * 8)); + pmsync2 |= (level & 0x1f) << (i * 8); + } + RCBA32(PMSYNC_CONFIG2) = pmsync2; +} + int cpu_config_tdp_levels(void) { msr_t platform_info; @@ -574,8 +639,10 @@ static void bsp_init_before_ap_bringup(struct bus *cpu_bus) x86_setup_var_mtrrs(cpuid_eax(0x80000008) & 0xff, 2); x86_mtrr_check(); - if (is_ult()) + if (is_ult()) { calibrate_24mhz_bclk(); + configure_pch_power_sharing(); + } /* Call through the cpu driver's initialization. */ cpu_initialize(0); diff --git a/src/southbridge/intel/lynxpoint/finalize.c b/src/southbridge/intel/lynxpoint/finalize.c index d9bc22531c..d81f90ecdb 100644 --- a/src/southbridge/intel/lynxpoint/finalize.c +++ b/src/southbridge/intel/lynxpoint/finalize.c @@ -54,6 +54,9 @@ void intel_pch_finalize_smm(void) /* GEN_PMCON Lock */ pci_or_config8(PCH_LPC_DEV, 0xa6, (1 << 1) | (1 << 2)); + /* PMSYNC */ + RCBA32_OR(PMSYNC_CONFIG, (1 << 31)); + /* R/WO registers */ RCBA32(0x21a4) = RCBA32(0x21a4); pci_write_config32(PCI_DEV(0, 27, 0), 0x74, diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h index 4bdb9268e9..58b07d16cc 100644 --- a/src/southbridge/intel/lynxpoint/pch.h +++ b/src/southbridge/intel/lynxpoint/pch.h @@ -574,6 +574,8 @@ void set_gpio(int gpio_num, int value); #define D19IR 0x3168 /* 16bit */ #define ACPIIRQEN 0x31e0 /* 32bit */ #define OIC 0x31fe /* 16bit */ +#define PMSYNC_CONFIG 0x33c4 /* 32bit */ +#define PMSYNC_CONFIG2 0x33cc /* 32bit */ #define SOFT_RESET_CTRL 0x38f4 #define SOFT_RESET_DATA 0x38f8 |