diff options
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/charger/sy21612.c | 213 | ||||
-rw-r--r-- | driver/charger/sy21612.h | 164 | ||||
-rw-r--r-- | include/config.h | 1 |
4 files changed, 379 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 4427edae89..c8e5a6c9c0 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -56,6 +56,7 @@ driver-$(CONFIG_CHARGER_ISL9237)+=charger/isl923x.o driver-$(CONFIG_CHARGER_ISL9238)+=charger/isl923x.o driver-$(CONFIG_CHARGER_RT9466)+=charger/rt946x.o driver-$(CONFIG_CHARGER_RT9467)+=charger/rt946x.o +driver-$(CONFIG_CHARGER_SY21612)+=charger/sy21612.o # I/O expander driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander_pca9534.o diff --git a/driver/charger/sy21612.c b/driver/charger/sy21612.c new file mode 100644 index 0000000000..378c8891a3 --- /dev/null +++ b/driver/charger/sy21612.c @@ -0,0 +1,213 @@ +/* Copyright 2017 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. + * + * SILERGY SY21612 buck-boost converter driver. + */ + + +#include "console.h" +#include "hooks.h" +#include "i2c.h" +#include "sy21612.h" +#include "task.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_CHARGER, outstr) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) + +static int sy21612_clear_set_reg(int reg, int clear, int set) +{ + int val, old_val, rv; + + rv = i2c_read8(I2C_PORT_SY21612, SY21612_ADDR, reg, &old_val); + if (rv) + return rv; + + val = old_val; + val &= ~clear; + val |= set; + + if (val != old_val || clear || set) + rv = i2c_write8(I2C_PORT_SY21612, SY21612_ADDR, reg, val); + + return rv; +} + +static int sy21612_read(int reg, int *val) +{ + return i2c_read8(I2C_PORT_SY21612, SY21612_ADDR, reg, val); +} + +int sy21612_enable_regulator(int enable) +{ + return enable ? + sy21612_clear_set_reg(SY21612_CTRL1, 0, SY21612_CTRL1_REG_EN) : + sy21612_clear_set_reg(SY21612_CTRL1, SY21612_CTRL1_REG_EN, 0); +} + +int sy21612_enable_adc(int enable) +{ + return enable ? + sy21612_clear_set_reg(SY21612_CTRL1, 0, SY21612_CTRL1_ADC_EN) : + sy21612_clear_set_reg(SY21612_CTRL1, SY21612_CTRL1_ADC_EN, 0); +} + +int sy21612_set_adc_mode(int auto_mode) +{ + return auto_mode ? + sy21612_clear_set_reg(SY21612_CTRL1, + 0, SY21612_CTRL1_ADC_AUTO_MODE) : + sy21612_clear_set_reg(SY21612_CTRL1, + SY21612_CTRL1_ADC_AUTO_MODE, 0); +} + +int sy21612_set_vbus_discharge(int auto_discharge) +{ + return auto_discharge ? + sy21612_clear_set_reg(SY21612_CTRL1, + SY21612_CTRL1_VBUS_NDISCHG, 0) : + sy21612_clear_set_reg(SY21612_CTRL1, + 0, SY21612_CTRL1_VBUS_NDISCHG); +} + +int sy21612_set_switching_freq(enum sy21612_switching_freq freq) +{ + return sy21612_clear_set_reg(SY21612_CTRL2, + SY21612_CTRL2_FREQ_MASK, + freq << SY21612_CTRL2_FREQ_SHIFT); +} + +int sy21612_set_vbus_volt(enum sy21612_vbus_volt volt) +{ + return sy21612_clear_set_reg(SY21612_CTRL2, + SY21612_CTRL2_VBUS_MASK, + volt << SY21612_CTRL2_VBUS_SHIFT); +} + +int sy21612_set_vbus_adj(enum sy21612_vbus_adj adj) +{ + return sy21612_clear_set_reg(SY21612_CTRL2, + SY21612_CTRL2_VBUS_ADJ_MASK, + adj << SY21612_CTRL2_VBUS_ADJ_SHIFT); +} + +int sy21612_set_sink_mode(int sink_mode) +{ + return sink_mode ? + sy21612_clear_set_reg(SY21612_PROT2, + 0, SY21612_PROT2_SINK_MODE) : + sy21612_clear_set_reg(SY21612_PROT2, + SY21612_PROT2_SINK_MODE, 0); +} + +int sy21612_is_power_good(void) +{ + int reg; + + if (sy21612_read(SY21612_STATE, ®)) + return 0; + + return reg & SY21612_STATE_POWER_GOOD; +} + +int sy21612_read_clear_int(void) +{ + int reg; + + if (sy21612_read(SY21612_INT, ®)) + return 0; + + return reg; +} + +int sy21612_get_vbat_voltage(void) +{ + int reg; + + if (sy21612_read(SY21612_VBAT_VOLT, ®)) + return 0; + + return reg * 25000 / 255; +} + +int sy21612_get_vbus_voltage(void) +{ + int reg; + + if (sy21612_read(SY21612_VBUS_VOLT, ®)) + return 0; + + return reg * 25000 / 255; +} + +int sy21612_get_vbus_current(void) +{ + int reg; + + if (sy21612_read(SY21612_VBUS_CURRENT, ®)) + return 0; + + /* + * delta V in range 0 ~ 67mV + * sense resistor 10 mOhm + */ + return reg * 6700 / 255; +} + +void sy21612_int(enum gpio_signal signal) +{ +#ifdef HAS_TASK_SY21612 + task_wake(TASK_ID_SY21612); +#endif +} + +#ifdef HAS_TASK_SY21612 +void sy21612_task(void) +{ + int flags; + + while (1) { + task_wait_event(-1); + if (sy21612_read(SY21612_INT, &flags)) + continue; + /* TODO: notify the error condition and enable regulator */ + if (flags & SY21612_INT_VBUS_OCP) + CPUTS("buck-boost VBUS OCP\n"); + if (flags & SY21612_INT_INDUCTOR_OCP) + CPUTS("buck-boost inductor OCP\n"); + if (flags & SY21612_INT_UVP) + CPUTS("buck-boost UVP\n"); + if (flags & SY21612_INT_OTP) + CPUTS("buck-boost OTP\n"); + } +} +#endif + +#ifdef CONFIG_CMD_CHARGER +static int command_sy21612(int argc, char **argv) +{ + int i, val, rv; + + ccputs("sy21612 regs:\n"); + for (i = 0; i < 9; i++) { + ccprintf("[%02x] ", i); + rv = sy21612_read(i, &val); + if (rv) + ccprintf(" x (%d)\n", rv); + else + ccprintf("%02x - %08b\n", val, val); + } + + ccprintf("vbat voltage: %d mV\n", sy21612_get_vbat_voltage()); + ccprintf("vbus voltage: %d mV\n", sy21612_get_vbus_voltage()); + ccprintf("vbus current: %d mA\n", sy21612_get_vbus_current()); + + return 0; +} +DECLARE_CONSOLE_COMMAND(sy21612, command_sy21612, + NULL, NULL); +#endif + diff --git a/driver/charger/sy21612.h b/driver/charger/sy21612.h new file mode 100644 index 0000000000..9d531a1ee2 --- /dev/null +++ b/driver/charger/sy21612.h @@ -0,0 +1,164 @@ +/* Copyright 2017 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. + * + * SILERGY SY21612 buck-boost converter driver. + */ + +#ifndef __CROS_EC_SY21612_H +#define __CROS_EC_SY21612_H + +#include "gpio.h" + +#ifndef SY21612_ADDR +#define SY21612_ADDR 0xe2 /* 7bit address 1110_010 */ +#endif + +enum sy21612_switching_freq { + SY21612_FREQ_250KHZ = 0, + SY21612_FREQ_500KHZ, + SY21612_FREQ_750KHZ, + SY21612_FREQ_1MHZ +}; + +enum sy21612_vbus_volt { + SY21612_VBUS_5V = 2, + SY21612_VBUS_7V, + SY21612_VBUS_9V, + SY21612_VBUS_12V, + SY21612_VBUS_15V, + SY21612_VBUS_20V, +}; + +enum sy21612_vbus_adj { + SY21612_VBUS_M2_5 = 0, + SY21612_VBUS_M1_25, + SY21612_VBUS_0, + SY21612_VBUS_1_25, + SY21612_VBUS_2_5, + SY21612_VBUS_3_75, + SY21612_VBUS_5, +}; + +#define SY21612_CTRL1 0x00 +#define SY21612_CTRL1_REG_EN (1 << 7) +#define SY21612_CTRL1_LOW_BAT_MASK (7 << 4) +#define SY21612_CTRL1_LOW_BAT_10_2V (0 << 4) +#define SY21612_CTRL1_LOW_BAT_10_7V (1 << 4) +#define SY21612_CTRL1_LOW_BAT_11_2V (2 << 4) +#define SY21612_CTRL1_LOW_BAT_11_7V (3 << 4) +#define SY21612_CTRL1_LOW_BAT_22_0V (4 << 4) +#define SY21612_CTRL1_LOW_BAT_22_5V (5 << 4) +#define SY21612_CTRL1_LOW_BAT_23_0V (6 << 4) +#define SY21612_CTRL1_LOW_BAT_23_5V (7 << 4) +#define SY21612_CTRL1_ADC_EN (1 << 3) +#define SY21612_CTRL1_ADC_AUTO_MODE (1 << 2) +#define SY21612_CTRL1_VBUS_NDISCHG (1 << 1) + +#define SY21612_CTRL2 0x01 +#define SY21612_CTRL2_FREQ_MASK (3 << 6) +#define SY21612_CTRL2_FREQ_SHIFT 6 +#define SY21612_CTRL2_FREQ_250K (0 << 6) +#define SY21612_CTRL2_FREQ_500K (1 << 6) +#define SY21612_CTRL2_FREQ_750K (2 << 6) +#define SY21612_CTRL2_FREQ_1M (3 << 6) +#define SY21612_CTRL2_VBUS_MASK (7 << 3) +#define SY21612_CTRL2_VBUS_SHIFT 3 +#define SY21612_CTRL2_VBUS_5V (2 << 3) +#define SY21612_CTRL2_VBUS_7V (3 << 3) +#define SY21612_CTRL2_VBUS_9V (4 << 3) +#define SY21612_CTRL2_VBUS_12V (5 << 3) +#define SY21612_CTRL2_VBUS_15V (6 << 3) +#define SY21612_CTRL2_VBUS_20V (7 << 3) +#define SY21612_CTRL2_VBUS_ADJ_MASK 7 +#define SY21612_CTRL2_VBUS_ADJ_SHIFT 0 +#define SY21612_CTRL2_VBUS_ADJ_M2_5 0 +#define SY21612_CTRL2_VBUS_ADJ_M1_25 1 +#define SY21612_CTRL2_VBUS_ADJ_0 2 +#define SY21612_CTRL2_VBUS_ADJ_1_25 3 +#define SY21612_CTRL2_VBUS_ADJ_2_5 4 +#define SY21612_CTRL2_VBUS_ADJ_3_75 5 +#define SY21612_CTRL2_VBUS_ADJ_5 6 + +#define SY21612_PROT1 0x02 +#define SY21612_PROT1_I_THRESH_MASK (7 << 5) +#define SY21612_PROT1_I_THRESH_18MV (0 << 5) +#define SY21612_PROT1_I_THRESH_22MV (1 << 5) +#define SY21612_PROT1_I_THRESH_27MV (2 << 5) +#define SY21612_PROT1_I_THRESH_31MV (3 << 5) +#define SY21612_PROT1_I_THRESH_36MV (4 << 5) +#define SY21612_PROT1_I_THRESH_45MV (5 << 5) +#define SY21612_PROT1_I_THRESH_54MV (6 << 5) +#define SY21612_PROT1_I_THRESH_64MV (7 << 5) +#define SY21612_PROT1_OVP_THRESH_MASK (3 << 3) +#define SY21612_PROT1_OVP_THRESH_110 (0 << 3) +#define SY21612_PROT1_OVP_THRESH_115 (1 << 3) +#define SY21612_PROT1_OVP_THRESH_120 (2 << 3) +#define SY21612_PROT1_OVP_THRESH_125 (3 << 3) +#define SY21612_PROT1_UVP_THRESH_MASK (3 << 1) +#define SY21612_PROT1_UVP_THRESH_50 (0 << 1) +#define SY21612_PROT1_UVP_THRESH_60 (1 << 1) +#define SY21612_PROT1_UVP_THRESH_70 (2 << 1) +#define SY21612_PROT1_UVP_THRESH_80 (3 << 1) + +#define SY21612_PROT2 0x03 +#define SY21612_PROT2_I_LIMIT_MASK (3 << 6) +#define SY21612_PROT2_I_LIMIT_6A (0 << 6) +#define SY21612_PROT2_I_LIMIT_8A (2 << 6) +#define SY21612_PROT2_I_LIMIT_10A (3 << 6) +#define SY21612_PROT2_OCP_AUTORECOVER (1 << 5) +#define SY21612_PROT2_UVP_AUTORECOVER (1 << 4) +#define SY21612_PROT2_OTP_AUTORECOVER (1 << 3) +#define SY21612_PROT2_SINK_MODE (1 << 2) + +#define SY21612_STATE 0x04 +#define SY21612_STATE_POWER_GOOD (1 << 7) +#define SY21612_STATE_VBAT_LT_VBUS (1 << 6) +#define SY21612_STATE_VBAT_LOW (1 << 5) + +#define SY21612_INT 0x05 +#define SY21612_INT_ADC_READY (1 << 7) +#define SY21612_INT_VBUS_OCP (1 << 6) +#define SY21612_INT_INDUCTOR_OCP (1 << 5) +#define SY21612_INT_UVP (1 << 4) +#define SY21612_INT_OTP (1 << 3) + +/* Battery voltage range: 0 ~ 25V */ +#define SY21612_VBAT_VOLT 0x06 + +/* VBUS voltage range: 0 ~ 25V */ +#define SY21612_VBUS_VOLT 0x07 + +/* Output current sense voltage range 0 ~ 67mV */ +#define SY21612_VBUS_CURRENT 0x08 + +/* Enable or disable the regulator */ +int sy21612_enable_regulator(int enable); +/* Enable internal adc */ +int sy21612_enable_adc(int enable); +/* Set ADC mode to single or auto */ +int sy21612_set_adc_mode(int auto_mode); +/* Enable VBUS auto discharge when regulator is disabled */ +int sy21612_set_vbus_discharge(int auto_discharge); +/* Set buck-boost switching frequency */ +int sy21612_set_switching_freq(enum sy21612_switching_freq freq); +/* Set VBUS output voltage */ +int sy21612_set_vbus_volt(enum sy21612_vbus_volt volt); +/* Adjust VBUS output voltage */ +int sy21612_set_vbus_adj(enum sy21612_vbus_adj adj); +/* Set bidirection mode */ +int sy21612_set_sink_mode(int sink_mode); +/* Get power good status */ +int sy21612_is_power_good(void); +/* Read and clear interrupt flags */ +int sy21612_read_clear_int(void); +/* Get VBUS voltage in mV */ +int sy21612_get_vbat_voltage(void); +/* Get VBUS voltage in mV */ +int sy21612_get_vbus_voltage(void); +/* Get VBUS current in mA */ +int sy21612_get_vbus_current(void); +/* Interrupt handler */ +void sy21612_int(enum gpio_signal signal); + +#endif /* __CROS_EC_SY21612_H */ diff --git a/include/config.h b/include/config.h index b0c5a1a252..2b4a9a6e5c 100644 --- a/include/config.h +++ b/include/config.h @@ -469,6 +469,7 @@ #undef CONFIG_CHARGER_ISL9238 #undef CONFIG_CHARGER_RT9466 #undef CONFIG_CHARGER_RT9467 +#undef CONFIG_CHARGER_SY21612 /* * Enable the CHG_EN at initialization to turn-on the BGATE which allows voltage |