diff options
-rw-r--r-- | driver/build.mk | 3 | ||||
-rw-r--r-- | driver/mp2964.c | 152 | ||||
-rw-r--r-- | driver/mp2964.h | 22 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | zephyr/CMakeLists.txt | 6 | ||||
-rw-r--r-- | zephyr/Kconfig | 1 | ||||
-rw-r--r-- | zephyr/Kconfig.pmic | 27 | ||||
-rw-r--r-- | zephyr/shim/include/config_chip.h | 5 |
8 files changed, 217 insertions, 2 deletions
diff --git a/driver/build.mk b/driver/build.mk index e2db8da02c..88ffcf32c3 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -204,3 +204,6 @@ driver-$(HAS_TASK_WPC) += wpc/p9221.o # Buck-Boost converters driver-$(CONFIG_MP4245)+=mp4245.o + +# Power Management ICs +driver-$(CONFIG_MP2964)+=mp2964.o diff --git a/driver/mp2964.c b/driver/mp2964.c new file mode 100644 index 0000000000..21a23a8f4c --- /dev/null +++ b/driver/mp2964.c @@ -0,0 +1,152 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Driver for tuning the MP2964 IMVP8 - IMVP9.1 parameters */ + +#include "console.h" +#include "i2c.h" +#include "mp2964.h" +#include "timer.h" +#include "util.h" + +#define MP2964_STARTUP_WAIT_US (50 * MSEC) +#define MP2964_STORE_WAIT_US (300 * MSEC) +#define MP2964_RESTORE_WAIT_US (2 * MSEC) + +enum reg_page { + REG_PAGE_0, + REG_PAGE_1, + REG_PAGE_COUNT +}; + +static int mp2964_write8(uint8_t reg, uint8_t value) +{ + const uint8_t tx[2] = { reg, value }; + + return i2c_xfer_unlocked(I2C_PORT_MP2964, I2C_ADDR_MP2964_FLAGS, + tx, sizeof(tx), NULL, 0, I2C_XFER_SINGLE); +} + +static void mp2964_read16(uint8_t reg, uint16_t *value) +{ + const uint8_t tx[1] = { reg }; + uint8_t rx[2]; + + i2c_xfer_unlocked(I2C_PORT_MP2964, I2C_ADDR_MP2964_FLAGS, + tx, sizeof(tx), rx, sizeof(rx), I2C_XFER_SINGLE); + *value = (rx[1] << 8) | rx[0]; +} + +static void mp2964_write16(uint8_t reg, uint16_t value) +{ + const uint8_t tx[3] = { reg, value & 0xff, value >> 8 }; + + i2c_xfer_unlocked(I2C_PORT_MP2964, I2C_ADDR_MP2964_FLAGS, + tx, sizeof(tx), NULL, 0, I2C_XFER_SINGLE); +} + +static int mp2964_select_page(enum reg_page page) +{ + int status; + + if (page >= REG_PAGE_COUNT) + return EC_ERROR_INVAL; + + status = mp2964_write8(MP2964_PAGE, page); + if (status != EC_SUCCESS) { + ccprintf("%s: could not select page 0x%02x, error %d\n", + __func__, page, status); + } + return status; +} + +static void mp2964_write_vec16(const struct mp2964_reg_val *init_list, + int count, int *delta) +{ + const struct mp2964_reg_val *reg_val; + uint16_t outval; + int i; + + reg_val = init_list; + for (i = 0; i < count; ++i, ++reg_val) { + mp2964_read16(reg_val->reg, &outval); + if (outval == reg_val->val) { + ccprintf("mp2964: reg 0x%02x already 0x%04x\n", + reg_val->reg, outval); + continue; + } + ccprintf("mp2964: tuning reg 0x%02x from 0x%04x to 0x%04x\n", + reg_val->reg, outval, reg_val->val); + mp2964_write16(reg_val->reg, reg_val->val); + *delta += 1; + } +} + +static int mp2964_store_user_all(void) +{ + const uint8_t wr = MP2964_STORE_USER_ALL; + const uint8_t rd = MP2964_RESTORE_USER_ALL; + int status; + + ccprintf("%s: updating persistent settings\n", __func__); + + status = i2c_xfer_unlocked(I2C_PORT_MP2964, I2C_ADDR_MP2964_FLAGS, + &wr, sizeof(wr), NULL, 0, I2C_XFER_SINGLE); + if (status != EC_SUCCESS) + return status; + + usleep(MP2964_STORE_WAIT_US); + + status = i2c_xfer_unlocked(I2C_PORT_MP2964, I2C_ADDR_MP2964_FLAGS, + &rd, sizeof(rd), NULL, 0, I2C_XFER_SINGLE); + if (status != EC_SUCCESS) + return status; + + usleep(MP2964_RESTORE_WAIT_US); + + return EC_SUCCESS; +} + +static void mp2964_patch_rail(enum reg_page page, + const struct mp2964_reg_val *page_vals, + int count, + int *delta) +{ + if (mp2964_select_page(page) != EC_SUCCESS) + return; + mp2964_write_vec16(page_vals, count, delta); +} + +int mp2964_tune(const struct mp2964_reg_val *rail_a, int count_a, + const struct mp2964_reg_val *rail_b, int count_b) +{ + int tries = 2; + int delta; + + udelay(MP2964_STARTUP_WAIT_US); + + i2c_lock(I2C_PORT_MP2964, 1); + + do { + int status; + + delta = 0; + mp2964_patch_rail(REG_PAGE_0, rail_a, count_a, &delta); + mp2964_patch_rail(REG_PAGE_1, rail_b, count_b, &delta); + if (delta == 0) + break; + + status = mp2964_store_user_all(); + if (status != EC_SUCCESS) + ccprintf("%s: STORE_USER_ALL failed\n", __func__); + } while (--tries > 0); + + i2c_lock(I2C_PORT_MP2964, 0); + + if (delta) + return EC_ERROR_UNKNOWN; + else + return EC_SUCCESS; +} diff --git a/driver/mp2964.h b/driver/mp2964.h new file mode 100644 index 0000000000..8c0339c06e --- /dev/null +++ b/driver/mp2964.h @@ -0,0 +1,22 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_PMIC_MP2964_H +#define __CROS_EC_PMIC_MP2964_H + +#define MP2964_PAGE 0x00 +#define MP2964_STORE_USER_ALL 0x15 +#define MP2964_RESTORE_USER_ALL 0x16 +#define MP2964_MFR_ALT_SET 0x3f + +struct mp2964_reg_val { + uint8_t reg; + uint16_t val; +}; + +int mp2964_tune(const struct mp2964_reg_val *page0, int count0, + const struct mp2964_reg_val *page1, int count1); + +#endif /* __CROS_EC_PMIC_MP2964_H */ diff --git a/include/config.h b/include/config.h index aa3c67c534..c1c1633d86 100644 --- a/include/config.h +++ b/include/config.h @@ -4006,6 +4006,9 @@ /* Use this to include support for MP4245 buck boost converter */ #undef CONFIG_MP4245 +/* Use this to include support for MP2964 IMVP9.1 PMIC */ +#undef CONFIG_MP2964 + /*****************************************************************************/ /* USB PD config */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 0dfae5f01b..43930cf139 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -295,10 +295,12 @@ zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE "${PLATFORM_EC}/common/lid_angle.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LID_SWITCH "${PLATFORM_EC}/common/lid_switch.c") -zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_MOTIONSENSE - "${PLATFORM_EC}/common/motion_sense.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_MKBP_EVENT "${PLATFORM_EC}/common/mkbp_event.c") +zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_MOTIONSENSE + "${PLATFORM_EC}/common/motion_sense.c") +zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_MP2964 + "${PLATFORM_EC}/driver/mp2964.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_PORT80 "${PLATFORM_EC}/common/port80.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_POWER_BUTTON diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e5b617d9c3..191f49ace4 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -46,6 +46,7 @@ rsource "Kconfig.keyboard" rsource "Kconfig.led" rsource "Kconfig.panic" rsource "Kconfig.powerseq" +rsource "Kconfig.pmic" rsource "Kconfig.mkbp_event" rsource "Kconfig.motionsense" rsource "Kconfig.rtc" diff --git a/zephyr/Kconfig.pmic b/zephyr/Kconfig.pmic new file mode 100644 index 0000000000..dc79305439 --- /dev/null +++ b/zephyr/Kconfig.pmic @@ -0,0 +1,27 @@ +# Copyright 2021 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +menuconfig PLATFORM_EC_PMIC + bool "Power Management IC support" + help + Enables support for controlling PMICs (Power Management ICs). + A system may have one or more PMICs to control various power + rails. These devices operate autonomously, but can sometimes + be accessed to tune operational parameters or read fault + codes. + +if PLATFORM_EC_PMIC + +config PLATFORM_EC_MP2964 + bool "Enable MP2964 PMIC support" + depends on AP_X86_INTEL + depends on PLATFORM_EC_I2C + help + Enables support for the MPS MP2964 PMIC (Power Management IC). + This is a dual rail IMVP8 - IMVP9.1 compatible Digital + Multi-Phase Controller with an I2C interface. This driver + enables reprogramming configuration registers when initial the + factory settings need to be tuned in prototype devices. + +endif # PLATFORM_EC_PMIC diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index b6fcfd3517..179ffbc65d 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -1432,4 +1432,9 @@ #define CONFIG_USB_PD_ONLY_FIXED_PDOS #endif +#undef CONFIG_MP2964 +#ifdef CONFIG_PLATFORM_EC_MP2964 +#define CONFIG_MP2964 +#endif + #endif /* __CROS_EC_CONFIG_CHIP_H */ |