summaryrefslogtreecommitdiff
path: root/common/battery_link.c
blob: 2a524dea3858279161d759d0b69eb88d6fdd9a43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Copyright (c) 2012 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.
 *
 * Battery pack vendor provided charging profile
 */

#include "battery_pack.h"

/* Design capacity
 *   Battery capacity = 8200 mAh
 *   1C = 8200 mA
 */
#define C     8200
#define C_001 (int)(C * 0.01)
/*
 * Common charging currents:
 *   #define C_01  (int)(C * 0.1) ==  820mA
 *   #define C_02  (int)(C * 0.2) == 1640mA
 *   #define C_05  (int)(C * 0.5) == 4100mA
 *   #define C_07  (int)(C * 0.7) == 5740mA
 */

enum {
	TEMP_RANGE_10,
	TEMP_RANGE_23,
	TEMP_RANGE_35,
	TEMP_RANGE_45,
	TEMP_RANGE_50,
	TEMP_RANGE_MAX
};

enum {
	VOLT_RANGE_7200,
	VOLT_RANGE_8000,
	VOLT_RANGE_8400,
	VOLT_RANGE_MAX
};

/* Vendor provided charging method
 *      temp  : < 7.2V, 7.2V ~ 8.0V, 8.0V ~ 8.4V
 *  -  0 ~ 10 :  0.8A       1.6A         0.8A
 *  - 10 ~ 23 :  1.6A       4.0A         1.6A
 *  - 23 ~ 35 :  4.0A       4.0A         4.0A
 *  - 35 ~ 45 :  1.6A       4.0A         1.6A
 *  - 45 ~ 50 :  0.8A       1.6A         0.8A
 */
static const int const current_limit[TEMP_RANGE_MAX][VOLT_RANGE_MAX] = {
	{ 800, 1600,  800},
	{1600, 4000, 1600},
	{4000, 4000, 4000},
	{1600, 4000, 1600},
	{ 800, 1600,  800},
};

static const struct battery_info info = {
	/* Designed voltage
	 *   max    = 8.4V
	 *   normal = 7.4V
	 *   min    = 6.0V
	 */
	.voltage_max    = 8400,
	.voltage_normal = 7400,
	.voltage_min    = 6000,

	/* Operation temperation range
	 *   0   <= T_charge    <= 50 deg C
	 *   -20 <= T_discharge <= 60 deg C
	 *
	 * The temperature values below should be deci-Kelvin
	 */
	.temp_charge_min    =   0 * 10 + 2731,
	.temp_charge_max    =  50 * 10 + 2731,
	.temp_discharge_min = -20 * 10 + 2731,
	.temp_discharge_max =  60 * 10 + 2731,

	/* Pre-charge voltage and current
	 *   I <= 0.01C
	 */
	.precharge_current  = C_001,
};

/* Convert Celsius degree to Deci Kelvin degree */
static inline int celsius_to_deci_kelvin(int degree_c)
{
	return degree_c * 10 + 2731;
}

static inline void limit_value(int *val, int limit)
{
	if (*val > limit)
		*val = limit;
}

const struct battery_info *battery_get_info(void)
{
	return &info;
}

/* Vendor provided parameters for battery charging */
void battery_vendor_params(struct batt_params *batt)
{
	int *desired_current = &batt->desired_current;
	int temp_range, volt_range;

	/* Hard limits
	 *  - charging voltage < 8.4V
	 *  - charging temperature range 0 ~ 45 degree Celcius
	 *  */
	if (batt->desired_voltage > info.voltage_max)
		batt->desired_voltage = info.voltage_max;
	if (batt->temperature >= info.temp_charge_max ||
	    batt->temperature <= info.temp_charge_min) {
		batt->desired_voltage = 0;
		batt->desired_current = 0;
		return;
	}

	if (batt->temperature <= celsius_to_deci_kelvin(10))
		temp_range = TEMP_RANGE_10;
	else if (batt->temperature <= celsius_to_deci_kelvin(23))
		temp_range = TEMP_RANGE_23;
	else if (batt->temperature <= celsius_to_deci_kelvin(35))
		temp_range = TEMP_RANGE_35;
	else if (batt->temperature <= celsius_to_deci_kelvin(45))
		temp_range = TEMP_RANGE_45;
	else
		temp_range = TEMP_RANGE_50;

	if (batt->voltage < 7200)
		volt_range = VOLT_RANGE_7200;
	else if (batt->voltage < 8000)
		volt_range = VOLT_RANGE_8000;
	else
		volt_range = VOLT_RANGE_8400;

	limit_value(desired_current, current_limit[temp_range][volt_range]);

#ifndef CONFIG_SLOW_PRECHARGE
	/* Trickle charging and pre-charging current should be 0.01 C */
	if (*desired_current < info.precharge_current)
		*desired_current = info.precharge_current;
#endif /* CONFIG_SLOW_PRECHARGE */

}