summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2017-09-20 06:13:20 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-11-29 04:04:12 -0800
commit96bc7cd9b5fcc45322eb818c6b012c82b13683c3 (patch)
tree6b9841a14495b225ccb06541008d46fa7eb0e172
parentcf0153224ebe3acd6264fb15c514184b282e78bb (diff)
downloadchrome-ec-96bc7cd9b5fcc45322eb818c6b012c82b13683c3.tar.gz
charger: add sy21612 buck-boost converter driver
SY21612 is buck-boost converter with selectable source/sink mode. BRANCH=none BUG=none TEST=none Signed-off-by: Rong Chang <rongchang@chromium.org> Change-Id: I71248eedd9be775790d71010f69dfae41cd64a27 Reviewed-on: https://chromium-review.googlesource.com/673964 Reviewed-by: Benson Leung <bleung@chromium.org>
-rw-r--r--driver/build.mk1
-rw-r--r--driver/charger/sy21612.c213
-rw-r--r--driver/charger/sy21612.h164
-rw-r--r--include/config.h1
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, &reg))
+ return 0;
+
+ return reg & SY21612_STATE_POWER_GOOD;
+}
+
+int sy21612_read_clear_int(void)
+{
+ int reg;
+
+ if (sy21612_read(SY21612_INT, &reg))
+ return 0;
+
+ return reg;
+}
+
+int sy21612_get_vbat_voltage(void)
+{
+ int reg;
+
+ if (sy21612_read(SY21612_VBAT_VOLT, &reg))
+ return 0;
+
+ return reg * 25000 / 255;
+}
+
+int sy21612_get_vbus_voltage(void)
+{
+ int reg;
+
+ if (sy21612_read(SY21612_VBUS_VOLT, &reg))
+ return 0;
+
+ return reg * 25000 / 255;
+}
+
+int sy21612_get_vbus_current(void)
+{
+ int reg;
+
+ if (sy21612_read(SY21612_VBUS_CURRENT, &reg))
+ 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