summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-10-14 15:27:16 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-18 07:38:30 +0000
commitccc270368bb9193c5b368b1b82d5a8fecc5c4bc4 (patch)
tree4167a07afeb6597c828d1f157834d0a83cb6b364
parent316f369f1cc859880485cab7dd760fa19b48e70d (diff)
downloadchrome-ec-ccc270368bb9193c5b368b1b82d5a8fecc5c4bc4.tar.gz
Extend INA231 driver to support INA219 on Plankton
The register format of INA231 and INA219 are very much alike. In our use case, we only need to use different coversion coefficient. BRANCH=None BUG=chrome-os-partner:32764 TEST='ina 0' on Plankton V2. TEST=Build twinkie. Change-Id: I9c8e21e30ed844566793dcc1221f865400c3d90d Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/223370 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/plankton/board.c3
-rw-r--r--board/plankton/board.h1
-rw-r--r--board/twinkie/board.c6
-rw-r--r--driver/build.mk2
-rw-r--r--driver/ina231.h90
-rw-r--r--driver/ina2xx.c (renamed from driver/ina231.c)81
-rw-r--r--driver/ina2xx.h111
-rw-r--r--include/config.h10
8 files changed, 170 insertions, 134 deletions
diff --git a/board/plankton/board.c b/board/plankton/board.c
index 2770c5b0ea..a7666c3100 100644
--- a/board/plankton/board.c
+++ b/board/plankton/board.c
@@ -11,6 +11,7 @@
#include "gpio.h"
#include "hooks.h"
#include "i2c.h"
+#include "ina2xx.h"
#include "ioexpander_pca9534.h"
#include "registers.h"
#include "system.h"
@@ -168,6 +169,8 @@ static void board_init(void)
gpio_enable_interrupt(GPIO_DBG_CHG_TO_DEV_L);
gpio_enable_interrupt(GPIO_DBG_USB_TOGGLE_L);
gpio_enable_interrupt(GPIO_DBG_CABLE_FLIP_L);
+
+ ina2xx_init(0, 0x399f, INA2XX_CALIB_1MA(10 /* mOhm */));
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
diff --git a/board/plankton/board.h b/board/plankton/board.h
index 323143bcd3..46495178e0 100644
--- a/board/plankton/board.h
+++ b/board/plankton/board.h
@@ -24,6 +24,7 @@
#define CONFIG_ADC
#define CONFIG_HW_CRC
#define CONFIG_I2C
+#define CONFIG_INA219
#define CONFIG_IO_EXPANDER_PCA9534
#undef CONFIG_WATCHDOG_HELP
#undef CONFIG_LID_SWITCH
diff --git a/board/twinkie/board.c b/board/twinkie/board.c
index 69fe2735b2..109b90da41 100644
--- a/board/twinkie/board.c
+++ b/board/twinkie/board.c
@@ -11,7 +11,7 @@
#include "gpio.h"
#include "hooks.h"
#include "i2c.h"
-#include "ina231.h"
+#include "ina2xx.h"
#include "registers.h"
#include "task.h"
#include "usb.h"
@@ -49,9 +49,9 @@ static void board_init(void)
gpio_enable_interrupt(GPIO_VBUS_ALERT_L);
/* Calibrate INA0 (VBUS) with 1mA/LSB scale */
- ina231_init(0, 0x8000, INA231_CALIB_1MA(15 /*mOhm*/));
+ ina2xx_init(0, 0x8000, INA2XX_CALIB_1MA(15 /*mOhm*/));
/* Disable INA1 (VCONN2) to avoid leaking current */
- ina231_init(1, 0, INA231_CALIB_1MA(15 /*mOhm*/));
+ ina2xx_init(1, 0, INA2XX_CALIB_1MA(15 /*mOhm*/));
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
diff --git a/driver/build.mk b/driver/build.mk
index 409b7f8c6b..2d5de551a8 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -33,7 +33,7 @@ driver-$(CONFIG_CHARGER_BQ24773)+=charger/bq24773.o
driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander_pca9534.o
# Current/Power monitor
-driver-$(CONFIG_INA231)+=ina231.o
+driver-$(CONFIG_INA219)$(CONFIG_INA231)+=ina2xx.o
# LED drivers
driver-$(CONFIG_LED_DRIVER_DS2413)+=led/ds2413.o
diff --git a/driver/ina231.h b/driver/ina231.h
deleted file mode 100644
index 56ccb27d4e..0000000000
--- a/driver/ina231.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (c) 2014 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.
- *
- * TI INA231 Current/Power monitor driver.
- */
-
-#ifndef INA231_H
-#define INA231_H
-
-#define INA231_REG_CONFIG 0x00
-#define INA231_REG_SHUNT_VOLT 0x01
-#define INA231_REG_BUS_VOLT 0x02
-#define INA231_REG_POWER 0x03
-#define INA231_REG_CURRENT 0x04
-#define INA231_REG_CALIB 0x05
-#define INA231_REG_MASK 0x06
-#define INA231_REG_ALERT 0x07
-
-#define INA231_CONFIG_MODE_MASK (7 << 0)
-#define INA231_CONFIG_MODE_PWRDWN (0 << 0)
-#define INA231_CONFIG_MODE_SHUNT (1 << 0)
-#define INA231_CONFIG_MODE_BUS (1 << 1)
-#define INA231_CONFIG_MODE_TRG (0 << 2)
-#define INA231_CONFIG_MODE_CONT (1 << 2)
-
-/* Conversion time for bus and shunt in micro-seconds */
-enum ina231_conv_time {
- INA231_CONV_TIME_140 = 0x00,
- INA231_CONV_TIME_204 = 0x01,
- INA231_CONV_TIME_332 = 0x02,
- INA231_CONV_TIME_588 = 0x03,
- INA231_CONV_TIME_1100 = 0x04,
- INA231_CONV_TIME_2116 = 0x05,
- INA231_CONV_TIME_4156 = 0x06,
- INA231_CONV_TIME_8244 = 0x07,
-};
-#define INA231_CONV_TIME_MASK 0x7
-#define INA231_CONFIG_SHUNT_CONV_TIME(t) ((t) << 3)
-#define INA231_CONFIG_BUS_CONV_TIME(t) ((t) << 6)
-
-#define INA231_CONFIG_AVG_1 (0 << 9)
-#define INA231_CONFIG_AVG_4 (1 << 9)
-#define INA231_CONFIG_AVG_16 (2 << 9)
-#define INA231_CONFIG_AVG_64 (3 << 9)
-#define INA231_CONFIG_AVG_128 (4 << 9)
-#define INA231_CONFIG_AVG_256 (5 << 9)
-#define INA231_CONFIG_AVG_512 (6 << 9)
-#define INA231_CONFIG_AVG_1024 (7 << 9)
-
-#define INA231_MASK_EN_LEN (1 << 0)
-#define INA231_MASK_EN_APOL (1 << 1)
-#define INA231_MASK_EN_OVF (1 << 2)
-#define INA231_MASK_EN_CVRF (1 << 3)
-#define INA231_MASK_EN_AFF (1 << 4)
-#define INA231_MASK_EN_CNVR (1 << 10)
-#define INA231_MASK_EN_POL (1 << 11)
-#define INA231_MASK_EN_BUL (1 << 12)
-#define INA231_MASK_EN_BOL (1 << 13)
-#define INA231_MASK_EN_SUL (1 << 14)
-#define INA231_MASK_EN_SOL (1 << 15)
-
-/* Calibration value to get current LSB = 1mA */
-#define INA231_CALIB_1MA(rsense_mohm) (5120/(rsense_mohm))
-
-/* Bus voltage LSB : 1.25mV / bit */
-#define INA231_BUS_MV(reg) ((reg) * 125 / 100)
-
-/* Power LSB : 25mW / current_lsb */
-#define INA231_POW_MW(reg) ((reg) * 25 * 1/*Current mA/LSB*/)
-
-/* Read INA231 register. */
-uint16_t ina231_read(uint8_t idx, uint8_t reg);
-
-/* Write INA231 register. */
-int ina231_write(uint8_t idx, uint8_t reg, uint16_t val);
-
-/* Set measurement parameters */
-int ina231_init(uint8_t idx, uint16_t config, uint16_t calib);
-
-/* Return bus voltage in milliVolts */
-int ina231_get_voltage(uint8_t idx);
-
-/* Return current in milliAmps */
-int ina231_get_current(uint8_t idx);
-
-/* Return power in milliWatts */
-int ina231_get_power(uint8_t idx);
-
-#endif /* INA231_H */
diff --git a/driver/ina231.c b/driver/ina2xx.c
index 8736e916e9..47b716dea8 100644
--- a/driver/ina231.c
+++ b/driver/ina2xx.c
@@ -2,7 +2,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * TI INA231 Current/Power monitor driver.
+ * TI INA219/231 Current/Power monitor driver.
*/
#include "console.h"
@@ -10,7 +10,7 @@
#include "i2c.h"
#include "system.h"
#include "timer.h"
-#include "ina231.h"
+#include "ina2xx.h"
#include "uart.h"
#include "util.h"
@@ -18,81 +18,82 @@
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
/* 8-bit I2C base address */
-#define INA231_I2C_ADDR (0x40 << 1)
+#define INA2XX_I2C_ADDR (0x40 << 1)
-uint16_t ina231_read(uint8_t idx, uint8_t reg)
+uint16_t ina2xx_read(uint8_t idx, uint8_t reg)
{
int res;
int val;
- uint8_t addr = INA231_I2C_ADDR | (idx << 1);
+ uint8_t addr = INA2XX_I2C_ADDR | (idx << 1);
res = i2c_read16(I2C_PORT_MASTER, addr, reg, &val);
if (res) {
- CPRINTS("INA231 I2C read failed");
+ CPRINTS("INA2XX I2C read failed");
return 0x0bad;
}
return (val >> 8) | ((val & 0xff) << 8);
}
-int ina231_write(uint8_t idx, uint8_t reg, uint16_t val)
+int ina2xx_write(uint8_t idx, uint8_t reg, uint16_t val)
{
int res;
- uint8_t addr = INA231_I2C_ADDR | (idx << 1);
+ uint8_t addr = INA2XX_I2C_ADDR | (idx << 1);
uint16_t be_val = (val >> 8) | ((val & 0xff) << 8);
res = i2c_write16(I2C_PORT_MASTER, addr, reg, be_val);
if (res)
- CPRINTS("INA231 I2C write failed");
+ CPRINTS("INA2XX I2C write failed");
return res;
}
-int ina231_init(uint8_t idx, uint16_t config, uint16_t calib)
+int ina2xx_init(uint8_t idx, uint16_t config, uint16_t calib)
{
int res;
- res = ina231_write(idx, INA231_REG_CONFIG, config);
+ res = ina2xx_write(idx, INA2XX_REG_CONFIG, config);
/* TODO(crosbug.com/p/29730): assume 1mA/LSB, revisit later */
- res |= ina231_write(idx, INA231_REG_CALIB, calib);
+ res |= ina2xx_write(idx, INA2XX_REG_CALIB, calib);
return res;
}
-int ina231_get_voltage(uint8_t idx)
+int ina2xx_get_voltage(uint8_t idx)
{
- uint16_t bv = ina231_read(idx, INA231_REG_BUS_VOLT);
- /* Bus voltage LSB : 1.25mV / bit */
- return INA231_BUS_MV((int)bv);
+ uint16_t bv = ina2xx_read(idx, INA2XX_REG_BUS_VOLT);
+ return INA2XX_BUS_MV((int)bv);
}
-int ina231_get_current(uint8_t idx)
+int ina2xx_get_current(uint8_t idx)
{
- int16_t curr = ina231_read(idx, INA231_REG_CURRENT);
+ int16_t curr = ina2xx_read(idx, INA2XX_REG_CURRENT);
/* Current calibration: LSB = 1mA/bit */
return (int)curr;
}
-int ina231_get_power(uint8_t idx)
+int ina2xx_get_power(uint8_t idx)
{
- uint16_t pow = ina231_read(idx, INA231_REG_POWER);
- /* When current LSB = 1mA/bit, power LSB is 25mW/bit */
- return INA231_POW_MW((int)pow);
+ uint16_t pow = ina2xx_read(idx, INA2XX_REG_POWER);
+ return INA2XX_POW_MW((int)pow);
}
-static void ina231_dump(uint8_t idx)
+static void ina2xx_dump(uint8_t idx)
{
- uint16_t cfg = ina231_read(idx, INA231_REG_CONFIG);
- int16_t sv = ina231_read(idx, INA231_REG_SHUNT_VOLT);
- uint16_t bv = ina231_read(idx, INA231_REG_BUS_VOLT);
- uint16_t pow = ina231_read(idx, INA231_REG_POWER);
- int16_t curr = ina231_read(idx, INA231_REG_CURRENT);
- uint16_t calib = ina231_read(idx, INA231_REG_CALIB);
- uint16_t mask = ina231_read(idx, INA231_REG_MASK);
- uint16_t alert = ina231_read(idx, INA231_REG_ALERT);
+ uint16_t cfg = ina2xx_read(idx, INA2XX_REG_CONFIG);
+ int16_t sv = ina2xx_read(idx, INA2XX_REG_SHUNT_VOLT);
+ uint16_t bv = ina2xx_read(idx, INA2XX_REG_BUS_VOLT);
+ uint16_t pow = ina2xx_read(idx, INA2XX_REG_POWER);
+ int16_t curr = ina2xx_read(idx, INA2XX_REG_CURRENT);
+ uint16_t calib = ina2xx_read(idx, INA2XX_REG_CALIB);
+ uint16_t mask = ina2xx_read(idx, INA2XX_REG_MASK);
+ uint16_t alert = ina2xx_read(idx, INA2XX_REG_ALERT);
ccprintf("Configuration: %04x\n", cfg);
- ccprintf("Shunt voltage: %04x => %d uV\n", sv, (int)sv * 25 / 10);
- ccprintf("Bus voltage : %04x => %d mV\n", bv, INA231_BUS_MV((int)bv));
- ccprintf("Power : %04x => %d mW\n", pow, INA231_POW_MW(pow));
+ ccprintf("Shunt voltage: %04x => %d uV\n", sv,
+ INA2XX_SHUNT_UV((int)sv));
+ ccprintf("Bus voltage : %04x => %d mV\n", bv,
+ INA2XX_BUS_MV((int)bv));
+ ccprintf("Power : %04x => %d mW\n", pow,
+ INA2XX_POW_MW((int)pow));
ccprintf("Current : %04x => %d mA\n", curr, curr);
ccprintf("Calibration : %04x\n", calib);
ccprintf("Mask/Enable : %04x\n", mask);
@@ -116,7 +117,7 @@ static int command_ina(int argc, char **argv)
return EC_ERROR_PARAM1;
if (2 == argc) { /* dump all registers */
- ina231_dump(idx);
+ ina2xx_dump(idx);
return EC_SUCCESS;
} else if (4 == argc) {
val = strtoi(argv[3], &e, 16);
@@ -124,13 +125,13 @@ static int command_ina(int argc, char **argv)
return EC_ERROR_PARAM3;
if (!strcasecmp(argv[2], "config")) {
- ina231_write(idx, INA231_REG_CONFIG, val);
+ ina2xx_write(idx, INA2XX_REG_CONFIG, val);
} else if (!strcasecmp(argv[2], "calib")) {
- ina231_write(idx, INA231_REG_CALIB, val);
+ ina2xx_write(idx, INA2XX_REG_CALIB, val);
} else if (!strcasecmp(argv[2], "mask")) {
- ina231_write(idx, INA231_REG_MASK, val);
+ ina2xx_write(idx, INA2XX_REG_MASK, val);
} else if (!strcasecmp(argv[2], "alert")) {
- ina231_write(idx, INA231_REG_ALERT, val);
+ ina2xx_write(idx, INA2XX_REG_ALERT, val);
} else { /* read one register */
ccprintf("Invalid register: %s\n", argv[1]);
return EC_ERROR_INVAL;
@@ -142,5 +143,5 @@ static int command_ina(int argc, char **argv)
}
DECLARE_CONSOLE_COMMAND(ina, command_ina,
"<index> [config|calib|mask|alert <val>]",
- "INA231 power/current sensing",
+ "INA2XX power/current sensing",
NULL);
diff --git a/driver/ina2xx.h b/driver/ina2xx.h
new file mode 100644
index 0000000000..25b9f13296
--- /dev/null
+++ b/driver/ina2xx.h
@@ -0,0 +1,111 @@
+/* Copyright (c) 2014 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.
+ *
+ * TI INA219/231 Current/Power monitor driver.
+ */
+
+#ifndef INA2XX_H
+#define INA2XX_H
+
+#define INA2XX_REG_CONFIG 0x00
+#define INA2XX_REG_SHUNT_VOLT 0x01
+#define INA2XX_REG_BUS_VOLT 0x02
+#define INA2XX_REG_POWER 0x03
+#define INA2XX_REG_CURRENT 0x04
+#define INA2XX_REG_CALIB 0x05
+#define INA2XX_REG_MASK 0x06
+#define INA2XX_REG_ALERT 0x07
+
+#define INA2XX_CONFIG_MODE_MASK (7 << 0)
+#define INA2XX_CONFIG_MODE_PWRDWN (0 << 0)
+#define INA2XX_CONFIG_MODE_SHUNT (1 << 0)
+#define INA2XX_CONFIG_MODE_BUS (1 << 1)
+#define INA2XX_CONFIG_MODE_TRG (0 << 2)
+#define INA2XX_CONFIG_MODE_CONT (1 << 2)
+
+/* Conversion time for bus and shunt in micro-seconds */
+enum ina2xx_conv_time {
+ INA2XX_CONV_TIME_140 = 0x00,
+ INA2XX_CONV_TIME_204 = 0x01,
+ INA2XX_CONV_TIME_332 = 0x02,
+ INA2XX_CONV_TIME_588 = 0x03,
+ INA2XX_CONV_TIME_1100 = 0x04,
+ INA2XX_CONV_TIME_2116 = 0x05,
+ INA2XX_CONV_TIME_4156 = 0x06,
+ INA2XX_CONV_TIME_8244 = 0x07,
+};
+#define INA2XX_CONV_TIME_MASK 0x7
+#define INA2XX_CONFIG_SHUNT_CONV_TIME(t) ((t) << 3)
+#define INA2XX_CONFIG_BUS_CONV_TIME(t) ((t) << 6)
+
+#define INA2XX_CONFIG_AVG_1 (0 << 9)
+#define INA2XX_CONFIG_AVG_4 (1 << 9)
+#define INA2XX_CONFIG_AVG_16 (2 << 9)
+#define INA2XX_CONFIG_AVG_64 (3 << 9)
+#define INA2XX_CONFIG_AVG_128 (4 << 9)
+#define INA2XX_CONFIG_AVG_256 (5 << 9)
+#define INA2XX_CONFIG_AVG_512 (6 << 9)
+#define INA2XX_CONFIG_AVG_1024 (7 << 9)
+
+#define INA2XX_MASK_EN_LEN (1 << 0)
+#define INA2XX_MASK_EN_APOL (1 << 1)
+#define INA2XX_MASK_EN_OVF (1 << 2)
+#define INA2XX_MASK_EN_CVRF (1 << 3)
+#define INA2XX_MASK_EN_AFF (1 << 4)
+#define INA2XX_MASK_EN_CNVR (1 << 10)
+#define INA2XX_MASK_EN_POL (1 << 11)
+#define INA2XX_MASK_EN_BUL (1 << 12)
+#define INA2XX_MASK_EN_BOL (1 << 13)
+#define INA2XX_MASK_EN_SUL (1 << 14)
+#define INA2XX_MASK_EN_SOL (1 << 15)
+
+
+#if defined(CONFIG_INA231) && defined(CONFIG_INA219)
+#error CONFIG_INA231 and CONFIG_INA219 must not be both defined.
+#endif
+
+#ifdef CONFIG_INA231
+
+/* Calibration value to get current LSB = 1mA */
+#define INA2XX_CALIB_1MA(rsense_mohm) (5120/(rsense_mohm))
+/* Bus voltage: mV per LSB */
+#define INA2XX_BUS_MV(reg) ((reg) * 125 / 100)
+/* Shunt voltage: uV per LSB */
+#define INA2XX_SHUNT_UV(reg) ((reg) * 25 / 10)
+/* Power LSB: mW per current LSB */
+#define INA2XX_POW_MW(reg) ((reg) * 25 * 1/*Current mA/LSB*/)
+
+#else /* CONFIG_INA219 */
+
+/* Calibration value to get current LSB = 1mA */
+#define INA2XX_CALIB_1MA(rsense_mohm) (40960/(rsense_mohm))
+/* Bus voltage: mV per LSB */
+#define INA2XX_BUS_MV(reg) ((reg) / 2)
+/* Shunt voltage: uV per LSB */
+#define INA2XX_SHUNT_UV(reg) ((reg) * 2)
+/* Power LSB: mW per current LSB */
+#define INA2XX_POW_MW(reg) ((reg) * 20 * 1/*Current mA/LSB*/)
+
+#endif
+
+
+/* Read INA2XX register. */
+uint16_t ina2xx_read(uint8_t idx, uint8_t reg);
+
+/* Write INA2XX register. */
+int ina2xx_write(uint8_t idx, uint8_t reg, uint16_t val);
+
+/* Set measurement parameters */
+int ina2xx_init(uint8_t idx, uint16_t config, uint16_t calib);
+
+/* Return bus voltage in milliVolts */
+int ina2xx_get_voltage(uint8_t idx);
+
+/* Return current in milliAmps */
+int ina2xx_get_current(uint8_t idx);
+
+/* Return power in milliWatts */
+int ina2xx_get_power(uint8_t idx);
+
+#endif /* INA2XX_H */
diff --git a/include/config.h b/include/config.h
index 4522e69b5e..59256c816a 100644
--- a/include/config.h
+++ b/include/config.h
@@ -612,6 +612,16 @@
#undef CONFIG_I2C_SCL_GATE_GPIO
/*****************************************************************************/
+/* Current/Power monitor */
+
+/*
+ * Compile driver for INA219 or INA231. These two flags may not be both
+ * defined.
+ */
+#undef CONFIG_INA219
+#undef CONFIG_INA231
+
+/*****************************************************************************/
/* Inductive charging */
/* Enable inductive charging support */