diff options
author | Scott Collyer <scollyer@google.com> | 2020-09-23 14:15:03 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-15 21:07:00 +0000 |
commit | f0bd2049aa0af3a7147641cdec12f1086e88f438 (patch) | |
tree | 14e79c1c60338a6650fdb13fdf7f79ad38c2c391 /driver/mp4245.c | |
parent | d31a8e4b5ac2def50650690a76cb13c3ec834bae (diff) | |
download | chrome-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.c | 190 |
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."); + |