summaryrefslogtreecommitdiff
path: root/driver/mp4245.c
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2020-09-23 14:15:03 -0700
committerCommit Bot <commit-bot@chromium.org>2020-10-15 21:07:00 +0000
commitf0bd2049aa0af3a7147641cdec12f1086e88f438 (patch)
tree14e79c1c60338a6650fdb13fdf7f79ad38c2c391 /driver/mp4245.c
parentd31a8e4b5ac2def50650690a76cb13c3ec834bae (diff)
downloadchrome-ec-f0bd2049aa0af3a7147641cdec12f1086e88f438.tar.gz
mp4245: Buck boost converter initial driver
This CL adds support for the MPS mp4245 buck-boost converter which is designed to be used for USB PD Vbus generation. BUG=b:169312229 BRANCH=None TEST=verfied type-c attaches properly on quiche Signed-off-by: Scott Collyer <scollyer@google.com> Change-Id: Ie6c79a5509c6a85f9d6bcb95d4053f2803ca1ad4 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2436571 Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Commit-Queue: Scott Collyer <scollyer@chromium.org>
Diffstat (limited to 'driver/mp4245.c')
-rw-r--r--driver/mp4245.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/driver/mp4245.c b/driver/mp4245.c
new file mode 100644
index 0000000000..9ab56fe894
--- /dev/null
+++ b/driver/mp4245.c
@@ -0,0 +1,190 @@
+/* Copyright 2020 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.
+ */
+
+/* MPS MP4245 Buck-Boost converter driver. */
+
+#include "common.h"
+#include "console.h"
+#include "i2c.h"
+#include "mp4245.h"
+#include "util.h"
+
+
+static int mp4245_reg16_write(int offset, int data)
+{
+ return i2c_write16(I2C_PORT_MP4245, MP4245_SLAVE_ADDR, offset,
+ data);
+}
+
+int mp4245_set_voltage_out(int desired_mv)
+{
+ int vout;
+
+ /*
+ * For a desired voltage output Vdes, Vout = Vdes * 1024. This means
+ * there are 10 fractional and 6 integer bits. Vdes is stored in in mV
+ * so this scaling to mV must also be accounted for.
+ *
+ * VOUT_COMMAND = (Vdes (mV) * 1024 / 1000) / 1024
+ */
+ vout = (desired_mv * MP4245_VOUT_FROM_MV + (MP4245_VOUT_1V >> 1))
+ / MP4245_VOUT_1V;
+
+ return mp4245_reg16_write(MP4245_CMD_VOUT_COMMAND, vout);
+}
+
+int mp4245_set_current_lim(int desired_ma)
+{
+ int limit;
+
+ /* Current limit is stored as number of 50 mA steps */
+ limit = (desired_ma + (MP4245_ILIM_STEP_MA / 2)) / MP4245_ILIM_STEP_MA;
+
+ return mp4245_reg16_write(MP4245_CMD_MFR_CURRENT_LIM, limit);
+}
+
+int mp4245_votlage_out_enable(int enable)
+{
+ int cmd_val = enable ? MP4245_CMD_OPERATION_ON : 0;
+
+ return i2c_write8(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_OPERATION, cmd_val);
+}
+
+struct mp4245_info {
+ uint8_t cmd;
+ uint8_t len;
+};
+
+static struct mp4245_info mp4245_cmds[] = {
+ {MP4245_CMD_OPERATION, 1},
+ {MP4245_CMD_CLEAR_FAULTS, 1},
+ {MP4245_CMD_WRITE_PROTECT, 1},
+ {MP4245_CMD_STORE_USER_ALL, 1},
+ {MP4245_CMD_RESTORE_USER_ALL, 1},
+ {MP4245_CMD_VOUT_MODE, 1},
+ {MP4245_CMD_VOUT_COMMAND, 2},
+ {MP4245_CMD_VOUT_SCALE_LOOP, 2},
+ {MP4245_CMD_STATUS_BYTE, 1},
+ {MP4245_CMD_STATUS_WORD, 2},
+ {MP4245_CMD_STATUS_VOUT, 1},
+ {MP4245_CMD_STATUS_INPUT, 1},
+ {MP4245_CMD_STATUS_TEMP, 1},
+ {MP4245_CMD_STATUS_CML, 1},
+ {MP4245_CMD_READ_VIN, 2},
+ {MP4245_CMD_READ_VOUT, 2},
+ {MP4245_CMD_READ_IOUT, 2},
+ {MP4245_CMD_READ_TEMP, 2},
+ {MP4245_CMD_MFR_MODE_CTRL, 1},
+ {MP4245_CMD_MFR_CURRENT_LIM, 1},
+ {MP4245_CMD_MFR_LINE_DROP, 1},
+ {MP4245_CMD_MFR_OT_FAULT_LIM, 1},
+ {MP4245_CMD_MFR_OT_WARN_LIM, 1},
+ {MP4245_CMD_MFR_CRC_ERROR, 1},
+ {MP4245_CMD_MFF_MTP_CFG_CODE, 1},
+ {MP4245_CMD_MFR_MTP_REV_NUM, 1},
+ {MP4245_CMD_MFR_STATUS_MASK, 1},
+};
+
+static void mp4245_dump_reg(void)
+{
+ int i;
+ int val;
+ int rv;
+
+ for (i = 0; i < ARRAY_SIZE(mp4245_cmds); i++) {
+ if (mp4245_cmds[i].len == 1) {
+ rv = i2c_read8(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ mp4245_cmds[i].cmd, &val);
+ } else {
+ rv = i2c_read16(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ mp4245_cmds[i].cmd, &val);
+ }
+
+ if (!rv)
+ ccprintf("[%02x]:\t%04x\n", mp4245_cmds[i].cmd, val);
+ }
+}
+
+void mp4245_get_status(void)
+{
+ int status;
+ int on;
+ int vbus;
+ int ibus;
+ int ilim;
+ int vout;
+
+ /* Get Operation register */
+ i2c_read8(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_OPERATION, &on);
+ /* Vbus on/off is bit 7 */
+ on >>= 7;
+
+ /* Get status word */
+ i2c_read16(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_STATUS_WORD, &status);
+
+ /* Get Vbus measurement */
+ i2c_read16(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_READ_VOUT, &vbus);
+ vbus = MP4245_VOUT_TO_MV(vbus);
+
+ /* Get Ibus measurement */
+ i2c_read16(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_READ_IOUT, &ibus);
+ ibus = MP4245_IOUT_TO_MA(ibus);
+
+ /* Get Vout command (sets Vbus level) */
+ i2c_read16(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_VOUT_COMMAND, &vout);
+ vout = MP4245_VOUT_TO_MV(vout);
+
+ /* Get Input current limit */
+ i2c_read8(I2C_PORT_MP4245, MP4245_SLAVE_ADDR,
+ MP4245_CMD_MFR_CURRENT_LIM, &ilim);
+ ilim *= MP4245_ILIM_STEP_MA;
+
+ ccprintf("mp4245 Vbus %s:\n", on ? "On" : "Off");
+ ccprintf("\tstatus = 0x%04x\n", status);
+ ccprintf("\tVout = %d mV, Vbus = %d mV\n", vout, vbus);
+ ccprintf("\tIlim = %d mA, Ibus = %d mA\n", ilim, ibus);
+}
+
+static int command_mp4245(int argc, char **argv)
+{
+ char *e;
+ int val;
+
+ if (argc < 2)
+ return EC_ERROR_PARAM_COUNT;
+
+ if (!strcasecmp(argv[1], "info")) {
+ mp4245_get_status();
+ } else if (!strcasecmp(argv[1], "dump")) {
+ mp4245_dump_reg();
+ } else if (!strcasecmp(argv[1], "vbus")) {
+ if (argc < 3)
+ return EC_ERROR_PARAM_COUNT;
+ val = strtoi(argv[2], &e, 10);
+ /* If value out of bounds, turn off */
+ if (val < 0 || val > 20) {
+ return EC_ERROR_PARAM2;
+ }
+ if (val == 0) {
+ mp4245_votlage_out_enable(0);
+ } else {
+ mp4245_set_voltage_out(val * 1000);
+ mp4245_votlage_out_enable(1);
+ }
+ } else {
+ return EC_ERROR_PARAM1;
+ }
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(mp4245, command_mp4245,
+ "<info|dump|vbus|ilim>",
+ "Turn on/off|set vbus.");
+