Mario Scheithauer has uploaded this change for review. ( https://review.coreboot.org/25585
Change subject: siemens/mc_apl1: Fix for using IDT PMIC ......................................................................
siemens/mc_apl1: Fix for using IDT PMIC
Due to an accuracy issue on IMON in the IDT PMIC, the reported system power consumption was higher than the actual consumption. To prevent this problem, a logic must be implement in mainboard_init(). This logic consists of slope and offset as constants for Vcc and Vnn, which needs to be programmed by coreboot. This fix compensates for the accuracy issue.
Change-Id: I77faf95951d03ac6ce97a6721dba6e8466122a25 Signed-off-by: Mario Scheithauer mario.scheithauer@siemens.com --- M src/mainboard/siemens/mc_apl1/mainboard.c 1 file changed, 80 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/85/25585/1
diff --git a/src/mainboard/siemens/mc_apl1/mainboard.c b/src/mainboard/siemens/mc_apl1/mainboard.c index fd19cd1..81e215b 100644 --- a/src/mainboard/siemens/mc_apl1/mainboard.c +++ b/src/mainboard/siemens/mc_apl1/mainboard.c @@ -15,14 +15,17 @@ */
#include <console/console.h> +#include <delay.h> #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> #include <gpio.h> #include <hwilib.h> #include <i210.h> +#include <intelblocks/cpulib.h> #include <intelblocks/lpc_lib.h> #include <intelblocks/pcr.h> +#include <intelblocks/systemagent.h> #include <soc/pci_devs.h> #include <soc/pcr_ids.h> #include <string.h> @@ -35,6 +38,9 @@ #define MAX_PATH_DEPTH 12 #define MAX_NUM_MAPPINGS 10
+#define BIOS_MAILBOX_DATA 0x7080 +#define BIOS_MAILBOX_INTERFACE 0x7084 + /** \brief This function can decide if a given MAC address is valid or not. * Currently, addresses filled with 0xff or 0x00 are not valid. * @param mac Buffer to the MAC address to check @@ -114,9 +120,82 @@ { const struct pad_config *pads; size_t num; + uint16_t stall_count; + uint32_t power_max, data;
pads = brd_gpio_table(&num); gpio_configure_pads(pads, num); + + printk(BIOS_DEBUG, "PMIC: Configure PMIC IMON - Start\n"); + + /* Calculate CPU TDP in mW */ + power_max = cpu_get_power_max(); + printk(BIOS_DEBUG, "PMIC: CPU TDP %d mW.\n", power_max); + + /* + * Fix Vnn slope and offset value. + * slope = 0x4a4 # 2.32 + * offset = 0xfa0d # -2.975 + */ + stall_count = 0; + while (stall_count < 1000) { + /* Read P_CR_BIOS_MAILBOX_INTERFACE_0_0_0_MCHBAR */ + data = MCHBAR32(BIOS_MAILBOX_INTERFACE); + /* Check RUN_BUSY bit. */ + if ((data & (1 << 31)) == (1 << 31)) + mdelay(1); + else + break; + stall_count++; + } + if (stall_count == 1000) { + printk(BIOS_ERR, + "PMIC: Cannot set Vnn slope and offset value.\n"); + } else { + /* Set Vnn values into P_CR_BIOS_MAILBOX_DATA_0_0_0_MCHBAR. */ + MCHBAR32(BIOS_MAILBOX_DATA) = 0xfa0d04a4; + /* Set command, address and busy bit. */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000011d; + printk(BIOS_DEBUG, "PMIC: Fix Vnn slope and offset value.\n"); + } + + /* + * Fix Vcc slope and offset value. + * Premium and High SKU: + * slope = 0x466 # 2.2 + * offset = 0xe833 # -11.9 + * Low and Intermediate SKU: + * slope = 0x3b3 # 1.85 + * offset = 0xed33 # -9.4 + */ + stall_count = 0; + while (stall_count < 1000) { + data = MCHBAR32(BIOS_MAILBOX_INTERFACE); + if ((data & (1 << 31)) == (1 << 31)) + mdelay(1); + else + break; + stall_count++; + } + if (stall_count == 1000) { + printk(BIOS_ERR, + "PMIC: Cannot set Vcc slope and offset value.\n"); + } else { + /* + * CPU TDP limit between Premium/High and Low/Intermediate SKU + * is 9010 mW. + */ + if (power_max > 9010) { + MCHBAR32(BIOS_MAILBOX_DATA) = 0xe8330466; + MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000001d; + printk(BIOS_DEBUG, "PMIC: Fix Vcc for Premium SKU.\n"); + } else { + MCHBAR32(BIOS_MAILBOX_DATA) = 0xed3303b3; + MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000001d; + printk(BIOS_DEBUG, "PMIC: Fix Vcc for Low SKU.\n"); + } + } + printk(BIOS_DEBUG, "PMIC: Configure PMIC IMON - End\n"); }
static void mainboard_final(void *chip_info) @@ -125,7 +204,7 @@ uint16_t cmd = 0; device_t dev = NULL;
- /** + /* * Set up the DP2LVDS converter. * ptn3460_init() may only be executed after i2c bus init. */