From 0af272c1a9b0c9ca8338456a56c2bac587cc5051 Mon Sep 17 00:00:00 2001 From: Mario Scheithauer Date: Tue, 10 Apr 2018 12:40:11 +0200 Subject: siemens/mc_apl1: Fix accuracy issue with 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 implemented in mainboard_init(). This logic consists of slope and offset as constants for Vcc and Vnn, which need to be programmed by coreboot. This fix compensates for the accuracy issue. Change-Id: I77faf95951d03ac6ce97a6721dba6e8466122a25 Signed-off-by: Mario Scheithauer Reviewed-on: https://review.coreboot.org/25585 Tested-by: build bot (Jenkins) Reviewed-by: Werner Zeh --- src/mainboard/siemens/mc_apl1/mainboard.c | 83 ++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/mainboard/siemens/mc_apl1/mainboard.c b/src/mainboard/siemens/mc_apl1/mainboard.c index fd19cd13ae..18cb660ea1 100644 --- a/src/mainboard/siemens/mc_apl1/mainboard.c +++ b/src/mainboard/siemens/mc_apl1/mainboard.c @@ -15,14 +15,17 @@ */ #include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -35,6 +38,11 @@ #define MAX_PATH_DEPTH 12 #define MAX_NUM_MAPPINGS 10 +#define BIOS_MAILBOX_WAIT_MAX_MS 1000 +#define BIOS_MAILBOX_DATA 0x7080 +#define BIOS_MAILBOX_INTERFACE 0x7084 +#define RUN_BUSY_STS (1 << 31) + /** \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 @@ -110,6 +118,77 @@ enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6]) return CB_ERR; } +/** \brief This function fixes an accuracy issue with IDT PMIC. + * The current reported system power consumption is higher than the + * actual consumption. With a correction of slope and offset for Vcc + * and Vnn, the issue is solved. + */ +static void config_pmic_imon(void) +{ + struct stopwatch sw; + uint32_t power_max; + + printk(BIOS_DEBUG, "PMIC: Configure PMIC IMON - Start\n"); + + /* Calculate CPU TDP in mW */ + power_max = cpu_get_power_max(); + printk(BIOS_INFO, "PMIC: CPU TDP %d mW.\n", power_max); + + /* + * Fix Vnn slope and offset value. + * slope = 0x4a4 # 2.32 + * offset = 0xfa0d # -2.975 + */ + stopwatch_init_msecs_expire(&sw, BIOS_MAILBOX_WAIT_MAX_MS); + /* Read P_CR_BIOS_MAILBOX_INTERFACE_0_0_0_MCHBAR and check RUN_BUSY. */ + while ((MCHBAR32(BIOS_MAILBOX_INTERFACE) & RUN_BUSY_STS)) { + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "PMIC: Power consumption measurement " + "setup fails for Vnn.\n"); + return; + } + } + /* 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 + */ + stopwatch_init_msecs_expire(&sw, BIOS_MAILBOX_WAIT_MAX_MS); + while ((MCHBAR32(BIOS_MAILBOX_INTERFACE) & RUN_BUSY_STS)) { + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "PMIC: Power consumption measurement " + "setup fails for Vcc.\n"); + return; + } + } + + /* + * 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_INFO, "PMIC: Fix Vcc for Premium SKU.\n"); + } else { + MCHBAR32(BIOS_MAILBOX_DATA) = 0xed3303b3; + MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000001d; + printk(BIOS_INFO, "PMIC: Fix Vcc for Low SKU.\n"); + } + + printk(BIOS_DEBUG, "PMIC: Configure PMIC IMON - End\n"); +} + static void mainboard_init(void *chip_info) { const struct pad_config *pads; @@ -117,6 +196,8 @@ static void mainboard_init(void *chip_info) pads = brd_gpio_table(&num); gpio_configure_pads(pads, num); + + config_pmic_imon(); } static void mainboard_final(void *chip_info) @@ -125,7 +206,7 @@ static void mainboard_final(void *chip_info) uint16_t cmd = 0; device_t dev = NULL; - /** + /* * Set up the DP2LVDS converter. * ptn3460_init() may only be executed after i2c bus init. */ -- cgit v1.2.3