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
148
149
150
151
152
153
154
155
|
/* 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.
*
* Battery pack vendor provided charging profile
*/
#include "battery.h"
#include "battery_smart.h"
#include "charger.h"
#include "charge_state.h"
#include "console.h"
#include "driver/charger/bq24715.h"
#include "extpower.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "util.h"
/* FET ON/OFF cammand write to fet off register */
#define SB_FET_OFF 0x34
#define SB_FETOFF_DATA1 0x0000
#define SB_FETOFF_DATA2 0x1000
#define SB_FETON_DATA1 0x2000
#define SB_FETON_DATA2 0x4000
#define BATTERY_FETOFF 0x0100
/* First use day base */
#define BATT_FUD_BASE 0x38
static const struct battery_info info = {
.voltage_max = 8400, /* mV */
.voltage_normal = 7400,
.voltage_min = 6000,
.precharge_current = 200, /* mA */
.start_charging_min_c = 0,
.start_charging_max_c = 45,
.charging_min_c = 0,
.charging_max_c = 45,
.discharging_min_c = -20,
.discharging_max_c = 60,
};
const struct battery_info *battery_get_info(void)
{
return &info;
}
static void wakeup_deferred(void)
{
int d;
sb_read(SB_FET_OFF, &d);
if (extpower_is_present() && (BATTERY_FETOFF == d)) {
sb_write(SB_FET_OFF, SB_FETON_DATA1);
sb_write(SB_FET_OFF, SB_FETON_DATA2);
}
}
DECLARE_DEFERRED(wakeup_deferred);
static void wakeup(void)
{
/*
* The deferred call ensures that wakeup_deferred is called from a
* task. This is required to talk to the battery over I2C.
*/
hook_call_deferred(wakeup_deferred, 0);
}
DECLARE_HOOK(HOOK_INIT, wakeup, HOOK_PRIO_DEFAULT);
static int cutoff(void)
{
int rv;
/* Ship mode command must be sent sequentially to take effect */
rv = sb_write(SB_FET_OFF, SB_FETOFF_DATA1);
if (rv != EC_SUCCESS)
return rv;
return sb_write(SB_FET_OFF, SB_FETOFF_DATA2);
}
static int battery_command_cut_off(struct host_cmd_handler_args *args)
{
return cutoff() ? EC_RES_ERROR : EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cut_off,
EC_VER_MASK(0));
static int command_battcutoff(int argc, char **argv)
{
return cutoff();
}
DECLARE_CONSOLE_COMMAND(battcutoff, command_battcutoff,
NULL,
"Enable battery cutoff (ship mode)",
NULL);
/**
* Initialize charger additional option value
*/
static void charger_init(void)
{
if ((charge_get_state() == PWR_STATE_INIT) ||
(charge_get_state() == PWR_STATE_REINIT)) {
int option;
charger_get_option(&option);
/* Disable LDO mode */
option &= ~OPT_LDO_MODE_MASK;
charger_set_option(option);
}
}
DECLARE_HOOK(HOOK_CHARGE_STATE_CHANGE, charger_init, HOOK_PRIO_DEFAULT);
int battery_get_vendor_param(uint32_t param, uint32_t *value)
{
return EC_ERROR_UNIMPLEMENTED;
}
/* parameter 0 for first use day */
int battery_set_vendor_param(uint32_t param, uint32_t value)
{
if (param == 0) {
int rv, ymd;
rv = sb_read(BATT_FUD_BASE, &ymd);
if (rv != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
if (ymd == 0)
return sb_write(BATT_FUD_BASE, value) ?
EC_ERROR_UNKNOWN : EC_SUCCESS;
rv = sb_read(BATT_FUD_BASE | 0x03, &ymd);
if (rv != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
if (ymd == 0)
return sb_write(BATT_FUD_BASE | 0x03, value) ?
EC_ERROR_UNKNOWN : EC_SUCCESS;
rv = sb_read(BATT_FUD_BASE | 0x07, &ymd);
if (rv != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
if (ymd == 0)
return sb_write(BATT_FUD_BASE | 0x07, value) ?
EC_ERROR_UNKNOWN : EC_SUCCESS;
return EC_ERROR_UNKNOWN;
} else {
return EC_ERROR_UNIMPLEMENTED;
}
}
|