From 13b3ad768f2c46fdf4083ee1c5d315f74fe00114 Mon Sep 17 00:00:00 2001 From: Eric Yilun Lin Date: Tue, 4 Aug 2020 16:22:20 +0800 Subject: mt6360: support regulator LDO6/LDO7 1. LDO6/7 uses different sub address to LDO3/5, so adding a additional addr entry in the config. 2. Renames LDO for regulator since that we also have buck. BUG=b:147789962 TEST=With chromium:2409487, emerge ec-utils; cros deploy ec-utils ectool regularinfo; ectool regulatorget; ectool regulatorset BRANCH=none Change-Id: I6d901ac3617479af56cbc3135b7dc8274cfed46c Signed-off-by: Eric Yilun Lin Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2337860 Reviewed-by: Ting Shen Commit-Queue: Ting Shen --- board/asurada/board.c | 21 ++++--- driver/bc12/mt6360.c | 170 ++++++++++++++++++++++++++++++++------------------ driver/bc12/mt6360.h | 39 ++++++++---- 3 files changed, 150 insertions(+), 80 deletions(-) diff --git a/board/asurada/board.c b/board/asurada/board.c index 075ec39128..249ee967c0 100644 --- a/board/asurada/board.c +++ b/board/asurada/board.c @@ -590,38 +590,39 @@ void lid_angle_peripheral_enable(int enable) int board_regulator_get_info(uint32_t index, char *name, uint16_t *num_voltages, uint16_t *voltages_mv) { - enum mt6360_ldo_id ldo_id = index; + enum mt6360_regulator_id id = index; - return mt6360_ldo_get_info(ldo_id, name, num_voltages, voltages_mv); + return mt6360_regulator_get_info(id, name, num_voltages, + voltages_mv); } int board_regulator_enable(uint32_t index, uint8_t enable) { - enum mt6360_ldo_id ldo_id = index; + enum mt6360_regulator_id id = index; - return mt6360_ldo_enable(ldo_id, enable); + return mt6360_regulator_enable(id, enable); } int board_regulator_is_enabled(uint32_t index, uint8_t *enabled) { - enum mt6360_ldo_id ldo_id = index; + enum mt6360_regulator_id id = index; - return mt6360_ldo_is_enabled(ldo_id, enabled); + return mt6360_regulator_is_enabled(id, enabled); } int board_regulator_set_voltage(uint32_t index, uint32_t min_mv, uint32_t max_mv) { - enum mt6360_ldo_id ldo_id = index; + enum mt6360_regulator_id id = index; - return mt6360_ldo_set_voltage(ldo_id, min_mv, max_mv); + return mt6360_regulator_set_voltage(id, min_mv, max_mv); } int board_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv) { - enum mt6360_ldo_id ldo_id = index; + enum mt6360_regulator_id id = index; - return mt6360_ldo_get_voltage(ldo_id, voltage_mv); + return mt6360_regulator_get_voltage(id, voltage_mv); } /* gpio */ diff --git a/driver/bc12/mt6360.c b/driver/bc12/mt6360.c index a5b5ceb487..00860fd9a3 100644 --- a/driver/bc12/mt6360.c +++ b/driver/bc12/mt6360.c @@ -179,22 +179,21 @@ static void mt6360_usb_charger_task(const int port) } } -/* LDO */ -static int mt6360_ldo_write8(int reg, int val) +/* Regulator: LDO & BUCK */ +static int mt6360_regulator_write8(uint8_t addr, int reg, int val) { /* * Note: The checksum from I2C_FLAG_PEC happens to be correct because * length == 1 -> the high 3 bits of the offset byte is 0. */ return i2c_write8(mt6360_config.i2c_port, - MT6360_LDO_SLAVE_ADDR_FLAGS | I2C_FLAG_PEC, reg, val); + addr | I2C_FLAG_PEC, reg, val); } -static int mt6360_ldo_read8(int reg, int *val) +static int mt6360_regulator_read8(int addr, int reg, int *val) { int rv; uint8_t crc = 0, real_crc; - uint8_t addr = MT6360_LDO_SLAVE_ADDR_FLAGS; uint8_t out[3] = {(addr << 1) | 1, reg}; rv = i2c_read16(mt6360_config.i2c_port, addr, reg, val); @@ -212,24 +211,25 @@ static int mt6360_ldo_read8(int reg, int *val) return EC_SUCCESS; } -static int mt6360_ldo_update_bits(int reg, int mask, int val) +static int mt6360_regulator_update_bits(int addr, int reg, int mask, int val) { int rv; int reg_val = 0; - rv = mt6360_ldo_read8(reg, ®_val); + rv = mt6360_regulator_read8(addr, reg, ®_val); if (rv) return rv; reg_val &= ~mask; reg_val |= (mask & val); - rv = mt6360_ldo_write8(reg, reg_val); + rv = mt6360_regulator_write8(addr, reg, reg_val); return rv; } -struct mt6360_ldo_data { +struct mt6360_regulator_data { const char *name; - const uint16_t *vosel_table; - uint16_t vosel_table_len; + const uint16_t *ldo_vosel_table; + uint16_t ldo_vosel_table_len; + uint8_t addr; uint8_t reg_en_ctrl2; uint8_t reg_ctrl3; uint8_t mask_vosel; @@ -250,11 +250,35 @@ static const uint16_t MT6360_LDO5_VOSEL_TABLE[8] = { [0x5] = 3300, }; -static const struct mt6360_ldo_data ldo_data[MT6360_LDO_COUNT] = { +static const uint16_t MT6360_LDO6_VOSEL_TABLE[16] = { + [0x2] = 700, + [0x3] = 800, + [0x4] = 900, + [0x5] = 1000, + [0x6] = 1100, + [0x7] = 1200, + [0x8] = 1300, + [0x9] = 1400, + [0xA] = 1500, + [0xB] = 1600, + [0xC] = 1700, + [0xD] = 1800, + [0xE] = 1900, + [0xF] = 2000, +}; + +/* LDO7 VOSEL table is the same as LDO6's. */ +static const uint16_t *const MT6360_LDO7_VOSEL_TABLE = MT6360_LDO6_VOSEL_TABLE; +static const uint16_t MT6360_LDO7_VOSEL_TABLE_SIZE = + ARRAY_SIZE(MT6360_LDO6_VOSEL_TABLE); + +static const +struct mt6360_regulator_data regulator_data[MT6360_REGULATOR_COUNT] = { [MT6360_LDO3] = { .name = "mt6360_ldo3", - .vosel_table = MT6360_LDO3_VOSEL_TABLE, - .vosel_table_len = ARRAY_SIZE(MT6360_LDO3_VOSEL_TABLE), + .ldo_vosel_table = MT6360_LDO3_VOSEL_TABLE, + .ldo_vosel_table_len = ARRAY_SIZE(MT6360_LDO3_VOSEL_TABLE), + .addr = MT6360_LDO_SLAVE_ADDR_FLAGS, .reg_en_ctrl2 = MT6360_REG_LDO3_EN_CTRL2, .reg_ctrl3 = MT6360_REG_LDO3_CTRL3, .mask_vosel = MT6360_MASK_LDO3_VOSEL, @@ -263,92 +287,118 @@ static const struct mt6360_ldo_data ldo_data[MT6360_LDO_COUNT] = { }, [MT6360_LDO5] = { .name = "mt6360_ldo5", - .vosel_table = MT6360_LDO5_VOSEL_TABLE, - .vosel_table_len = ARRAY_SIZE(MT6360_LDO5_VOSEL_TABLE), + .ldo_vosel_table = MT6360_LDO5_VOSEL_TABLE, + .ldo_vosel_table_len = ARRAY_SIZE(MT6360_LDO5_VOSEL_TABLE), + .addr = MT6360_LDO_SLAVE_ADDR_FLAGS, .reg_en_ctrl2 = MT6360_REG_LDO5_EN_CTRL2, .reg_ctrl3 = MT6360_REG_LDO5_CTRL3, .mask_vosel = MT6360_MASK_LDO5_VOSEL, .shift_vosel = MT6360_MASK_LDO5_VOSEL_SHIFT, .mask_vocal = MT6360_MASK_LDO5_VOCAL, }, + [MT6360_LDO6] = { + .name = "mt6360_ldo6", + .ldo_vosel_table = MT6360_LDO6_VOSEL_TABLE, + .ldo_vosel_table_len = ARRAY_SIZE(MT6360_LDO6_VOSEL_TABLE), + .addr = MT6360_PMIC_SLAVE_ADDR_FLAGS, + .reg_en_ctrl2 = MT6360_REG_LDO6_EN_CTRL2, + .reg_ctrl3 = MT6360_REG_LDO6_CTRL3, + .mask_vosel = MT6360_MASK_LDO6_VOSEL, + .shift_vosel = MT6360_MASK_LDO6_VOSEL_SHIFT, + .mask_vocal = MT6360_MASK_LDO6_VOCAL, + }, + [MT6360_LDO7] = { + .name = "mt6360_ldo7", + .ldo_vosel_table = MT6360_LDO7_VOSEL_TABLE, + .ldo_vosel_table_len = MT6360_LDO7_VOSEL_TABLE_SIZE, + .addr = MT6360_PMIC_SLAVE_ADDR_FLAGS, + .reg_en_ctrl2 = MT6360_REG_LDO7_EN_CTRL2, + .reg_ctrl3 = MT6360_REG_LDO7_CTRL3, + .mask_vosel = MT6360_MASK_LDO7_VOSEL, + .shift_vosel = MT6360_MASK_LDO7_VOSEL_SHIFT, + .mask_vocal = MT6360_MASK_LDO7_VOCAL, + }, }; -int mt6360_ldo_get_info(enum mt6360_ldo_id ldo_id, char *name, - uint16_t *num_voltages, uint16_t *voltages_mv) +int mt6360_regulator_get_info(enum mt6360_regulator_id id, char *name, + uint16_t *num_voltages, uint16_t *voltages_mv) { int i; int cnt = 0; - const struct mt6360_ldo_data *data; + const struct mt6360_regulator_data *data; - if (ldo_id >= MT6360_LDO_COUNT) + if (id >= MT6360_REGULATOR_COUNT) return EC_ERROR_INVAL; - data = &ldo_data[ldo_id]; + data = ®ulator_data[id]; strzcpy(name, data->name, EC_REGULATOR_NAME_MAX_LEN); - for (i = 0; i < data->vosel_table_len; i++) { - int mv = data->vosel_table[i]; + for (i = 0; i < data->ldo_vosel_table_len; i++) { + int mv = data->ldo_vosel_table[i]; if (!mv) continue; if (cnt < EC_REGULATOR_VOLTAGE_MAX_COUNT) voltages_mv[cnt++] = mv; else - CPRINTS("LDO3 Voltage info overflow: %d", mv); + CPRINTS("%s voltage info overflow: %d", data->name, mv); } *num_voltages = cnt; return EC_SUCCESS; } -int mt6360_ldo_enable(enum mt6360_ldo_id ldo_id, uint8_t enable) +int mt6360_regulator_enable(enum mt6360_regulator_id id, uint8_t enable) { - const struct mt6360_ldo_data *data; + const struct mt6360_regulator_data *data; - if (ldo_id >= MT6360_LDO_COUNT) + if (id >= MT6360_REGULATOR_COUNT) return EC_ERROR_INVAL; - data = &ldo_data[ldo_id]; + data = ®ulator_data[id]; if (enable) - return mt6360_ldo_update_bits( + return mt6360_regulator_update_bits( + data->addr, data->reg_en_ctrl2, - MT6360_MASK_LDO_SW_OP_EN | MT6360_MASK_LDO_SW_EN, - MT6360_MASK_LDO_SW_OP_EN | MT6360_MASK_LDO_SW_EN); + MT6360_MASK_RGL_SW_OP_EN | MT6360_MASK_RGL_SW_EN, + MT6360_MASK_RGL_SW_OP_EN | MT6360_MASK_RGL_SW_EN); else - return mt6360_ldo_update_bits( + return mt6360_regulator_update_bits( + data->addr, data->reg_en_ctrl2, - MT6360_MASK_LDO_SW_OP_EN | MT6360_MASK_LDO_SW_EN, - MT6360_MASK_LDO_SW_OP_EN); + MT6360_MASK_RGL_SW_OP_EN | MT6360_MASK_RGL_SW_EN, + MT6360_MASK_RGL_SW_OP_EN); } -int mt6360_ldo_is_enabled(enum mt6360_ldo_id ldo_id, uint8_t *enabled) +int mt6360_regulator_is_enabled(enum mt6360_regulator_id id, uint8_t *enabled) { int rv; int value; - const struct mt6360_ldo_data *data; + const struct mt6360_regulator_data *data; - if (ldo_id >= MT6360_LDO_COUNT) + if (id >= MT6360_REGULATOR_COUNT) return EC_ERROR_INVAL; - data = &ldo_data[ldo_id]; + data = ®ulator_data[id]; - rv = mt6360_ldo_read8(data->reg_en_ctrl2, &value); + rv = mt6360_regulator_read8(data->addr, data->reg_en_ctrl2, &value); if (rv) { - CPRINTS("Error reading LDO3 enabled: %d", rv); + CPRINTS("Error reading %s enabled: %d", data->name, rv); return rv; } - *enabled = !!(value & MT6360_MASK_LDO_SW_EN); + *enabled = !!(value & MT6360_MASK_RGL_SW_EN); return EC_SUCCESS; } -int mt6360_ldo_set_voltage(enum mt6360_ldo_id ldo_id, int min_mv, int max_mv) +int mt6360_regulator_set_voltage(enum mt6360_regulator_id id, int min_mv, + int max_mv) { int i; - const struct mt6360_ldo_data *data; + const struct mt6360_regulator_data *data; - if (ldo_id >= MT6360_LDO_COUNT) + if (id >= MT6360_REGULATOR_COUNT) return EC_ERROR_INVAL; - data = &ldo_data[ldo_id]; + data = ®ulator_data[id]; - for (i = 0; i < data->vosel_table_len; i++) { - int mv = data->vosel_table[i]; + for (i = 0; i < data->ldo_vosel_table_len; i++) { + int mv = data->ldo_vosel_table[i]; int step; if (!mv) @@ -360,36 +410,38 @@ int mt6360_ldo_set_voltage(enum mt6360_ldo_id ldo_id, int min_mv, int max_mv) MT6360_LDO_VOCAL_STEP_MV; if (mv > max_mv) continue; - step = (mv - data->vosel_table[i]) / MT6360_LDO_VOCAL_STEP_MV; + step = (mv - data->ldo_vosel_table[i]) / + MT6360_LDO_VOCAL_STEP_MV; - return mt6360_ldo_update_bits( + return mt6360_regulator_update_bits( + data->addr, data->reg_ctrl3, data->mask_vosel | data->mask_vocal, (i << data->shift_vosel) | step); } - CPRINTS("LDO3 voltage %d - %d out of range", min_mv, max_mv); + CPRINTS("%s voltage %d - %d out of range", data->name, min_mv, max_mv); return EC_ERROR_INVAL; } -int mt6360_ldo_get_voltage(enum mt6360_ldo_id ldo_id, int *voltage_mv) +int mt6360_regulator_get_voltage(enum mt6360_regulator_id id, int *voltage_mv) { int value; int rv; - const struct mt6360_ldo_data *data; + const struct mt6360_regulator_data *data; - if (ldo_id >= MT6360_LDO_COUNT) + if (id >= MT6360_REGULATOR_COUNT) return EC_ERROR_INVAL; - data = &ldo_data[ldo_id]; + data = ®ulator_data[id]; - rv = mt6360_ldo_read8(data->reg_ctrl3, &value); + rv = mt6360_regulator_read8(data->addr, data->reg_ctrl3, &value); if (rv) { - CPRINTS("Error reading LDO3 ctrl3: %d", rv); + CPRINTS("Error reading %s ctrl3: %d", data->name, rv); return rv; } - *voltage_mv = data->vosel_table[(value & data->mask_vosel) >> - data->shift_vosel]; + *voltage_mv = data->ldo_vosel_table[(value & data->mask_vosel) >> + data->shift_vosel]; if (*voltage_mv == 0) { - CPRINTS("Unknown LDO3 voltage value: %d", value); + CPRINTS("Unknown %s voltage value: %d", data->name, value); return EC_ERROR_INVAL; } *voltage_mv += diff --git a/driver/bc12/mt6360.h b/driver/bc12/mt6360.h index a51baee694..6af946a006 100644 --- a/driver/bc12/mt6360.h +++ b/driver/bc12/mt6360.h @@ -49,30 +49,47 @@ #define MT6360_MASK_LDO5_VOSEL_SHIFT 4 #define MT6360_MASK_LDO5_VOCAL 0x0F -/* This is same for LDO{3,5,2,1}_EN_CTRL2 */ -#define MT6360_MASK_LDO_SW_OP_EN BIT(7) -#define MT6360_MASK_LDO_SW_EN BIT(6) +#define MT6360_REG_LDO6_EN_CTRL2 0x37 + +#define MT6360_REG_LDO6_CTRL3 0x3B +#define MT6360_MASK_LDO6_VOSEL 0xF0 +#define MT6360_MASK_LDO6_VOSEL_SHIFT 4 +#define MT6360_MASK_LDO6_VOCAL 0x0F + +#define MT6360_REG_LDO7_EN_CTRL2 0x31 + +#define MT6360_REG_LDO7_CTRL3 0x35 +#define MT6360_MASK_LDO7_VOSEL 0xF0 +#define MT6360_MASK_LDO7_VOSEL_SHIFT 4 +#define MT6360_MASK_LDO7_VOCAL 0x0F + +/* This is same for LDO{1,2,3,5,6,7}_EN_CTRL2 */ +#define MT6360_MASK_RGL_SW_OP_EN BIT(7) +#define MT6360_MASK_RGL_SW_EN BIT(6) #define MT6360_LDO_VOCAL_STEP_MV 10 #define MT6360_LDO_VOCAL_MAX_STEP 10 -enum mt6360_ldo_id { +enum mt6360_regulator_id { MT6360_LDO3, MT6360_LDO5, + MT6360_LDO6, + MT6360_LDO7, - MT6360_LDO_COUNT, + MT6360_REGULATOR_COUNT, }; -int mt6360_ldo_get_info(enum mt6360_ldo_id ldo_id, char *name, - uint16_t *voltage_count, uint16_t *voltages_mv); +int mt6360_regulator_get_info(enum mt6360_regulator_id id, char *name, + uint16_t *voltage_count, uint16_t *voltages_mv); -int mt6360_ldo_enable(enum mt6360_ldo_id ldo_id, uint8_t enable); +int mt6360_regulator_enable(enum mt6360_regulator_id id, uint8_t enable); -int mt6360_ldo_is_enabled(enum mt6360_ldo_id ldo_id, uint8_t *enabled); +int mt6360_regulator_is_enabled(enum mt6360_regulator_id id, uint8_t *enabled); -int mt6360_ldo_set_voltage(enum mt6360_ldo_id ldo_id, int min_mv, int max_mv); +int mt6360_regulator_set_voltage(enum mt6360_regulator_id id, int min_mv, + int max_mv); -int mt6360_ldo_get_voltage(enum mt6360_ldo_id ldo_id, int *voltage_mv); +int mt6360_regulator_get_voltage(enum mt6360_regulator_id id, int *voltage_mv); enum mt6360_led_id { MT6360_LED_RGB1, -- cgit v1.2.1