From ee3c56a04cd0888b1005fd75d8be186ef3c49ca2 Mon Sep 17 00:00:00 2001 From: Eric Yilun Lin Date: Wed, 5 Aug 2020 14:07:46 +0800 Subject: mt6360: support buck regulator BUG=b:147789962 TEST=With chromium:2409487, emerge ec-utils; cros deploy ec-utils ectool regularinfo; ectool regulatorget; ectool regulatorset BRANCH=none Change-Id: I571a6a3903c7c88837c8d0666f833f3252756dcf Signed-off-by: Eric Yilun Lin Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2337862 Reviewed-by: Ting Shen Commit-Queue: Ting Shen --- driver/bc12/mt6360.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++----- driver/bc12/mt6360.h | 25 ++++++++++++++- 2 files changed, 107 insertions(+), 9 deletions(-) diff --git a/driver/bc12/mt6360.c b/driver/bc12/mt6360.c index 00860fd9a3..e4f99d4088 100644 --- a/driver/bc12/mt6360.c +++ b/driver/bc12/mt6360.c @@ -318,8 +318,32 @@ struct mt6360_regulator_data regulator_data[MT6360_REGULATOR_COUNT] = { .shift_vosel = MT6360_MASK_LDO7_VOSEL_SHIFT, .mask_vocal = MT6360_MASK_LDO7_VOCAL, }, + [MT6360_BUCK1] = { + .name = "mt6360_buck1", + .addr = MT6360_PMIC_SLAVE_ADDR_FLAGS, + .reg_en_ctrl2 = MT6360_REG_BUCK1_EN_CTRL2, + .reg_ctrl3 = MT6360_REG_BUCK1_VOSEL, + .mask_vosel = MT6360_MASK_BUCK1_VOSEL, + .shift_vosel = MT6360_MASK_BUCK1_VOSEL_SHIFT, + .mask_vocal = MT6360_MASK_BUCK1_VOCAL, + }, + [MT6360_BUCK2] = { + .name = "mt6360_buck2", + .addr = MT6360_PMIC_SLAVE_ADDR_FLAGS, + .reg_en_ctrl2 = MT6360_REG_BUCK2_EN_CTRL2, + .reg_ctrl3 = MT6360_REG_BUCK2_VOSEL, + .mask_vosel = MT6360_MASK_BUCK2_VOSEL, + .shift_vosel = MT6360_MASK_BUCK2_VOSEL_SHIFT, + .mask_vocal = MT6360_MASK_BUCK2_VOCAL, + }, }; +static bool is_buck_regulator(const struct mt6360_regulator_data *data) +{ + /* There's no ldo_vosel_table, it's a buck. */ + return !(data->ldo_vosel_table); +} + int mt6360_regulator_get_info(enum mt6360_regulator_id id, char *name, uint16_t *num_voltages, uint16_t *voltages_mv) { @@ -332,16 +356,33 @@ int mt6360_regulator_get_info(enum mt6360_regulator_id id, char *name, data = ®ulator_data[id]; strzcpy(name, data->name, EC_REGULATOR_NAME_MAX_LEN); - 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("%s voltage info overflow: %d", data->name, mv); + if (is_buck_regulator(data)) { + for (i = 0; i < MT6360_BUCK_VOSEL_MAX_STEP; ++i) { + int mv = MT6360_BUCK_VOSEL_MIN + + i * MT6360_BUCK_VOSEL_STEP_MV; + + if (cnt < EC_REGULATOR_VOLTAGE_MAX_COUNT) + voltages_mv[cnt++] = mv; + else + CPRINTS("%s voltage info overflow: %d-%d", + data->name, mv, MT6360_BUCK_VOSEL_MAX); + } + } else { + /* It's a LDO */ + 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("%s voltage info overflow: %d", + data->name, mv); + } } + *num_voltages = cnt; return EC_SUCCESS; } @@ -397,6 +438,29 @@ int mt6360_regulator_set_voltage(enum mt6360_regulator_id id, int min_mv, return EC_ERROR_INVAL; data = ®ulator_data[id]; + if (is_buck_regulator(data)) { + int mv; + int step; + + if (max_mv < MT6360_BUCK_VOSEL_MIN) + goto error; + + if (min_mv > MT6360_BUCK_VOSEL_MAX) + goto error; + + mv = DIV_ROUND_UP((min_mv + max_mv) / 2, + MT6360_BUCK_VOSEL_STEP_MV) * + MT6360_BUCK_VOSEL_STEP_MV; + mv = MIN(MAX(mv, MT6360_BUCK_VOSEL_MIN), MT6360_BUCK_VOSEL_MAX); + + step = (mv - MT6360_BUCK_VOSEL_MIN) / MT6360_BUCK_VOSEL_STEP_MV; + + return mt6360_regulator_update_bits(data->addr, + data->reg_ctrl3, + data->mask_vosel, step); + } + + /* It's a LDO. */ for (i = 0; i < data->ldo_vosel_table_len; i++) { int mv = data->ldo_vosel_table[i]; int step; @@ -419,6 +483,8 @@ int mt6360_regulator_set_voltage(enum mt6360_regulator_id id, int min_mv, data->mask_vosel | data->mask_vocal, (i << data->shift_vosel) | step); } + +error: CPRINTS("%s voltage %d - %d out of range", data->name, min_mv, max_mv); return EC_ERROR_INVAL; } @@ -438,6 +504,15 @@ int mt6360_regulator_get_voltage(enum mt6360_regulator_id id, int *voltage_mv) CPRINTS("Error reading %s ctrl3: %d", data->name, rv); return rv; } + + /* BUCK */ + if (is_buck_regulator(data)) { + *voltage_mv = MT6360_BUCK_VOSEL_MIN + + value * MT6360_BUCK_VOSEL_STEP_MV; + return EC_SUCCESS; + } + + /* LDO */ *voltage_mv = data->ldo_vosel_table[(value & data->mask_vosel) >> data->shift_vosel]; if (*voltage_mv == 0) { diff --git a/driver/bc12/mt6360.h b/driver/bc12/mt6360.h index 6af946a006..e5fb47384c 100644 --- a/driver/bc12/mt6360.h +++ b/driver/bc12/mt6360.h @@ -63,18 +63,41 @@ #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_REG_BUCK1_EN_CTRL2 0x17 + +#define MT6360_REG_BUCK1_VOSEL 0x10 +#define MT6360_MASK_BUCK1_VOSEL 0xFF +#define MT6360_MASK_BUCK1_VOSEL_SHIFT 0 +#define MT6360_MASK_BUCK1_VOCAL 0x0 + +#define MT6360_REG_BUCK2_EN_CTRL2 0x26 + +#define MT6360_REG_BUCK2_VOSEL 0x20 +#define MT6360_MASK_BUCK2_VOSEL 0xFF +#define MT6360_MASK_BUCK2_VOSEL_SHIFT 0 +#define MT6360_MASK_BUCK2_VOCAL 0x0 + +/* This is same for LDO{1,2,3,5,6,7}_EN_CTRL2, BUCK{1,2}_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 +#define MT6360_BUCK_VOSEL_STEP_MV 5 +#define MT6360_BUCK_VOSEL_MAX_STEP 200 +#define MT6360_BUCK_VOSEL_MIN 300 +#define MT6360_BUCK_VOSEL_MAX \ + (MT6360_BUCK_VOSEL_MIN + \ + MT6360_BUCK_VOSEL_STEP_MV * MT6360_BUCK_VOSEL_MAX_STEP) + enum mt6360_regulator_id { MT6360_LDO3, MT6360_LDO5, MT6360_LDO6, MT6360_LDO7, + MT6360_BUCK1, + MT6360_BUCK2, MT6360_REGULATOR_COUNT, }; -- cgit v1.2.1