summaryrefslogtreecommitdiff
path: root/common/battery_link.c
blob: 74e794468456e1de29ce4485830daa4c85c8aa40 (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
/* 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 = 8500 mAh
 *   1C = 8500 mA
 */
#define C     8500
#define C_001 (int)(C * 0.01)
#define C_01  (int)(C * 0.1)
#define C_02  (int)(C * 0.2)
#define C_05  (int)(C * 0.5)
#define C_07  (int)(C * 0.7)

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    <= 45 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    =  45 * 10 + 2731,
	.temp_discharge_min = -20 * 10 + 2731,
	.temp_discharge_max =  60 * 10 + 2731,

	/* Maximum discharging current
	 * TODO(rong): Check if we need this in power manager
	 *
	 * 1.0C
	 * 25 <= T_maxdischarge <= 45
	 *
	 * .current_discharge_max = C,
	 * .temp_maxdisch_max     = 45,
	 * .temp_maxdisch_min     = 25
	 *
	 */

	/* 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;

	/* 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;
	}

	/* Vendor provided charging method
	 *      temp  :    I - V   ,   I - V
	 *  -  0 ~ 10 : 0.2C - 8.0V, 0.1C to 8.4V
	 *  - 10 ~ 23 : 0.5C - 8.0V, 0.2C to 8.4V
	 *  - 23 ~ 45 : 0.7C - 8.0V, 0.2C to 8.4V
	 */
	if (batt->temperature <= celsius_to_deci_kelvin(10)) {
		if (batt->voltage < 8000)
			limit_value(desired_current, C_02);
		else
			limit_value(desired_current, C_01);
	} else if (batt->temperature <= celsius_to_deci_kelvin(23)) {
		if (batt->voltage < 8000)
			limit_value(desired_current, C_05);
		else
			limit_value(desired_current, C_02);
	} else {
		if (batt->voltage < 8000)
			limit_value(desired_current, C_07);
		else
			limit_value(desired_current, C_02);
	}

#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 */

}