summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/build.mk3
-rw-r--r--driver/mp2964.c152
-rw-r--r--driver/mp2964.h22
-rw-r--r--include/config.h3
-rw-r--r--zephyr/CMakeLists.txt6
-rw-r--r--zephyr/Kconfig1
-rw-r--r--zephyr/Kconfig.pmic27
-rw-r--r--zephyr/shim/include/config_chip.h5
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 */