mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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>
This commit is contained in:
committed by
chrome-internal-fetch
parent
804b24cc81
commit
ebb54a453d
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user