summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYen Lin <yelin@nvidia.com>2013-11-26 13:12:21 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-12-04 01:52:11 +0000
commitebb54a453d32ccda52a01f0381b47846aaa953f1 (patch)
tree516a8ad774a9aac76af68bb83e20a4dbc2aaa5a7
parent804b24cc81ca2f954eef45695d8084d45827c061 (diff)
downloadchrome-ec-ebb54a453d32ccda52a01f0381b47846aaa953f1.tar.gz
nyan: add support of different battery types
Nyan EC supports 2 different boards: Venice2 and Norrin. Venice2 uses 2S battery, and Norrin uses 3S battery. This CL is to support 2 different battery types (2S or 3S) automatically at init time by reading battery's MANUF_NAME, DEVICE_NAME and DESIGN_VOLTAGE from Smart Battery Interface to determine which battery type to use. To workaround the problem that battery may not be attached at init time, a patch is added to call battery_get_info() in PWR_STATE_INIT state to get the current battery info. Note the battery info is only determined once. BUG=none BRANCH=nyan TEST=tested on Vencie2 with 2S battery and on Norrin with 3S battery attached at init time and made sure correct battery info are installed; tested on Venice2 and Norrin without battery at init time, then attached 2S or 3S battery and made sure correct battery info are installed. Change-Id: I135909c7fe1e1dfdb0f706e0eadba6e904b6221e Signed-off-by: Yen Lin <yelin@nvidia.com> Reviewed-on: https://chromium-review.googlesource.com/178088 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/nyan/battery.c209
-rw-r--r--common/charge_state.c4
2 files changed, 170 insertions, 43 deletions
diff --git a/board/nyan/battery.c b/board/nyan/battery.c
index 8e46df4e59..7c0058c1d6 100644
--- a/board/nyan/battery.c
+++ b/board/nyan/battery.c
@@ -6,14 +6,103 @@
*/
#include "battery.h"
+#include "battery_smart.h"
+#include "gpio.h"
+#include "host_command.h"
+#include "util.h"
+#include "console.h"
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+
+/* These 2 defines are for cut_off command for 3S battery */
+#define SB_SHIP_MODE_ADDR 0x3a
+#define SB_SHIP_MODE_DATA 0xc574
+
+static struct battery_info *battery_info;
+static int battery_cut_off;
+
+struct battery_device {
+ char manuf[9];
+ char device[9];
+ int design_mv;
+ struct battery_info *battery_info;
+ int support_cut_off;
+};
+
+static struct battery_info info_2s = {
+ /*
+ * Design voltage
+ * max = 8.4V
+ * normal = 7.4V
+ * min = 6.0V
+ */
+ .voltage_max = 8400,
+ .voltage_normal = 7400,
+ .voltage_min = 6000,
+
+ /* Pre-charge current: I <= 0.01C */
+ .precharge_current = 64, /* mA */
+
+ /*
+ * Operational temperature range
+ * 0 <= T_charge <= 50 deg C
+ * -20 <= T_discharge <= 60 deg C
+ */
+ .start_charging_min_c = 0,
+ .start_charging_max_c = 50,
+ .charging_min_c = 0,
+ .charging_max_c = 50,
+ .discharging_min_c = -20,
+ .discharging_max_c = 60,
+};
+
+static struct battery_info info_3s = {
+
+ .voltage_max = 12600,
+ .voltage_normal = 11100, /* Average of max & min */
+ .voltage_min = 9000,
+ /* Pre-charge values. */
+ .precharge_current = 392, /* mA */
+
+ .start_charging_min_c = 0,
+ .start_charging_max_c = 60,
+ .charging_min_c = 0,
+ .charging_max_c = 60,
+ .discharging_min_c = 0,
+ .discharging_max_c = 50,
+};
+
+static struct battery_device support_batteries[] = {
+ {
+ .manuf = "NVT",
+ .device = "ARROW",
+ .design_mv = 7400,
+ .battery_info = &info_2s,
+ .support_cut_off = 0,
+ },
+ {
+ .manuf = "SANYO",
+ .device = "AP13J3K",
+ .design_mv = 11250,
+ .battery_info = &info_3s,
+ .support_cut_off = 1,
+ },
+ {
+ .manuf = "SONYCorp",
+ .device = "AP13J4K",
+ .design_mv = 11400,
+ .battery_info = &info_3s,
+ .support_cut_off = 1,
+ }
+};
+
+#ifdef CONFIG_BATTERY_VENDOR_PARAMS
/*
- * Design capacity
- * Battery capacity = 8200 mAh
- * 1C = 8200 mA
+ * The following parameters are for 2S battery.
+ * There is no corresponding params for 3S battery.
*/
-#define DESIGN_CAPACITY 8200
-
enum {
TEMP_RANGE_10,
TEMP_RANGE_23,
@@ -47,57 +136,32 @@ static const int const current_limit[TEMP_RANGE_MAX][VOLT_RANGE_MAX] = {
{ 800, 1600, 800},
};
-static const struct battery_info info = {
- /*
- * Design voltage
- * max = 8.4V
- * normal = 7.4V
- * min = 6.0V
- */
- .voltage_max = 8400,
- .voltage_normal = 7400,
- .voltage_min = 6000,
-
- /* Pre-charge current: I <= 0.01C */
- .precharge_current = 64, /* mA */
-
- /*
- * Operational temperature range
- * 0 <= T_charge <= 50 deg C
- * -20 <= T_discharge <= 60 deg C
- */
- .start_charging_min_c = 0,
- .start_charging_max_c = 50,
- .charging_min_c = 0,
- .charging_max_c = 50,
- .discharging_min_c = -20,
- .discharging_max_c = 60,
-};
-
static inline void limit_value(int *val, int limit)
{
if (*val > limit)
*val = limit;
}
-const struct battery_info *battery_get_info(void)
-{
- return &info;
-}
-
void battery_vendor_params(struct batt_params *batt)
{
int *desired_current = &batt->desired_current;
int temp_range, volt_range;
int bat_temp_c = DECI_KELVIN_TO_CELSIUS(batt->temperature);
+ if (battery_info == NULL)
+ return;
+
+ /* Return if the battery is not a 2S battery */
+ if (battery_info->voltage_max != info_2s.voltage_max)
+ return;
+
/* Limit charging voltage */
- if (batt->desired_voltage > info.voltage_max)
- batt->desired_voltage = info.voltage_max;
+ if (batt->desired_voltage > battery_info->voltage_max)
+ batt->desired_voltage = battery_info->voltage_max;
/* Don't charge if outside of allowable temperature range */
- if (bat_temp_c >= info.charging_max_c ||
- bat_temp_c < info.charging_min_c) {
+ if (bat_temp_c >= battery_info->charging_max_c ||
+ bat_temp_c < battery_info->charging_min_c) {
batt->desired_voltage = 0;
batt->desired_current = 0;
batt->flags &= ~BATT_FLAG_WANT_CHARGE;
@@ -125,6 +189,65 @@ void battery_vendor_params(struct batt_params *batt)
limit_value(desired_current, current_limit[temp_range][volt_range]);
/* If battery wants current, give it at least the precharge current */
- if (*desired_current > 0 && *desired_current < info.precharge_current)
- *desired_current = info.precharge_current;
+ if (*desired_current > 0 &&
+ *desired_current < battery_info->precharge_current)
+ *desired_current = battery_info->precharge_current;
+}
+#endif /* CONFIG_BATTERY_VENDOR_PARAMS */
+
+const struct battery_info *battery_get_info(void)
+{
+ int i;
+ char manuf[9];
+ char device[9];
+ int design_mv;
+
+ if (battery_manufacturer_name(manuf, sizeof(manuf))) {
+ CPRINTF("[%T Failed to get MANUF name]\n");
+ return NULL;
+ }
+
+ if (battery_device_name(device, sizeof(device))) {
+ CPRINTF("[%T Failed to get DEVICE name]\n");
+ return NULL;
+ }
+ if (battery_design_voltage((int *)&design_mv)) {
+ CPRINTF("[%T Failed to get DESIGN_VOLTAGE]\n");
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(support_batteries); ++i) {
+ if ((strcasecmp(support_batteries[i].manuf, manuf) == 0) &&
+ (strcasecmp(support_batteries[i].device, device) == 0) &&
+ (support_batteries[i].design_mv == design_mv)) {
+ CPRINTF("[%T battery Manuf:%s, Device=%s, design=%u]\n",
+ manuf, device, design_mv);
+ battery_cut_off = support_batteries[i].support_cut_off;
+ battery_info = support_batteries[i].battery_info;
+ return battery_info;
+ }
+ }
+
+ return NULL;
+}
+
+int battery_command_cut_off(struct host_cmd_handler_args *args)
+{
+ if (battery_cut_off)
+ return sb_write(SB_SHIP_MODE_ADDR, SB_SHIP_MODE_DATA);
+ else
+ return EC_RES_INVALID_COMMAND;
+}
+DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cut_off,
+ EC_VER_MASK(0));
+
+
+#ifdef CONFIG_BATTERY_CHECK_CONNECTED
+/**
+ * Physical detection of battery connection.
+ */
+int battery_is_connected(void)
+{
+ return (gpio_get_level(GPIO_BAT_DETECT_L) == 0);
}
+#endif /* CONFIG_BATTERY_CHECK_CONNECTED */
diff --git a/common/charge_state.c b/common/charge_state.c
index 83efbd8d14..0984cfbf0b 100644
--- a/common/charge_state.c
+++ b/common/charge_state.c
@@ -385,6 +385,10 @@ static enum power_state state_init(struct power_state_context *ctx)
/* Stop charger, unconditionally */
charge_request(0, 0);
+ /* if battery was not detected initially, get battery info again */
+ if (ctx->battery == NULL)
+ ctx->battery = battery_get_info();
+
/* Update static battery info */
update_battery_info();