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
|
From efc0041ca08e73f97e68cbab5e7eff8d30fef7b9 Mon Sep 17 00:00:00 2001
From: Stephen Just <stephenjust@gmail.com>
Date: Tue, 28 Jun 2016 23:37:11 -0600
Subject: [PATCH 2/2] power: surface3_power: Improve battery capacity reporting
Read additional registers from the battery device to get more
accurate status reading. Also properly report battery (dis)charge
state and current.
---
drivers/power/supply/surface3_power.c | 55 ++++++++++++++++++++++++++++++-----
1 file changed, 48 insertions(+), 7 deletions(-)
diff --git a/drivers/power/supply/surface3_power.c b/drivers/power/supply/surface3_power.c
index eee21d3..ac8155b 100644
--- a/drivers/power/supply/surface3_power.c
+++ b/drivers/power/supply/surface3_power.c
@@ -61,6 +61,7 @@ struct mshw0011_data {
bool charging;
bool bat_charging;
u8 trip_point;
+ s32 full_capacity;
};
struct mshw0011_lookup {
@@ -122,6 +123,10 @@ struct gsb_buffer {
} __packed;
} __packed;
+#define ACPI_BATTERY_STATE_DISCHARGING 0x1
+#define ACPI_BATTERY_STATE_CHARGING 0x2
+#define ACPI_BATTERY_STATE_CRITICAL 0x4
+
#define MSHW0011_CMD_DEST_BAT0 0x01
#define MSHW0011_CMD_DEST_ADP1 0x03
@@ -140,11 +145,14 @@ struct gsb_buffer {
#define MSHW0011_NOTIFY_GET_VERSION 0x00
#define MSHW0011_NOTIFY_ADP1 0x01
-#define MSHW0011_NOTIFY_BAT0 0x02
+#define MSHW0011_NOTIFY_BAT0_BST 0x02
+#define MSHW0011_NOTIFY_BAT0_BIX 0x05
#define MSHW0011_ADP1_REG_PSR 0x03
-#define MSHW0011_BAT0_REG_CAPACITY 0x0c
+#define MSHW0011_BAT0_REG_CAPACITY 0x0c
+#define MSHW0011_BAT0_REG_FULL_CHG_CAPACITY 0x0e
+#define MSHW0011_BAT0_REG_DESIGN_CAPACITY 0x40
#define MSHW0011_BAT0_REG_VOLTAGE 0x08
#define MSHW0011_BAT0_REG_RATE 0x14
#define MSHW0011_BAT0_REG_OEM 0x45
@@ -235,6 +243,22 @@ static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix)
*bix = default_bix;
+ /* get design capacity */
+ ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_DESIGN_CAPACITY);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error reading design capacity: %d\n", ret);
+ return ret;
+ }
+ bix->design_capacity = le16_to_cpu(ret);
+
+ /* get last full charge capacity */
+ ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_FULL_CHG_CAPACITY);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error reading last full charge capacity: %d\n", ret);
+ return ret;
+ }
+ bix->last_full_charg_capacity = le16_to_cpu(ret);
+
/* get serial number */
ret = mshw0011_i2c_read_block(client, MSHW0011_BAT0_REG_SERIAL_NO,
buf, 10);
@@ -269,7 +293,7 @@ static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix)
static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst)
{
struct i2c_client *client = cdata->bat0;
- int rate, capacity, voltage;
+ int rate, capacity, voltage, state;
s16 tmp;
rate = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_RATE);
@@ -285,8 +309,15 @@ static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst)
return voltage;
tmp = le16_to_cpu(rate);
- bst->battery_present_rate = (s32)tmp;
- bst->battery_state = bst->battery_present_rate < 0 ? 0x01 : 0x02;
+ bst->battery_present_rate = abs((s32)tmp);
+
+ state = 0;
+ if ((s32) tmp > 0)
+ state |= ACPI_BATTERY_STATE_CHARGING;
+ else if ((s32) tmp < 0)
+ state |= ACPI_BATTERY_STATE_DISCHARGING;
+ bst->battery_state = state;
+
bst->battery_remaining_capacity = le16_to_cpu(capacity);
bst->battery_present_voltage = le16_to_cpu(voltage);
@@ -308,6 +339,7 @@ static int mshw0011_adp_psr(struct mshw0011_data *cdata)
static int mshw0011_isr(struct mshw0011_data *cdata)
{
struct bst bst;
+ struct bix bix;
int ret;
bool status, bat_status;
@@ -327,14 +359,23 @@ static int mshw0011_isr(struct mshw0011_data *cdata)
if (ret < 0)
return ret;
- bat_status = bst.battery_present_rate >= 0;
+ bat_status = bst.battery_state;
if (bat_status != cdata->bat_charging)
mshw0011_notify(cdata, cdata->notify_version,
- MSHW0011_NOTIFY_BAT0, &ret);
+ MSHW0011_NOTIFY_BAT0_BST, &ret);
cdata->bat_charging = bat_status;
+ ret = mshw0011_bix(cdata, &bix);
+ if (ret < 0)
+ return ret;
+ if (bix.last_full_charg_capacity != cdata->full_capacity)
+ mshw0011_notify(cdata, cdata->notify_version,
+ MSHW0011_NOTIFY_BAT0_BIX, &ret);
+
+ cdata->full_capacity = bix.last_full_charg_capacity;
+
return 0;
}
--
2.9.3
|