1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Supports for the power IC on the Surface 3 tablet.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright 2016-2018 Red Hat, Inc
6*4882a593Smuzhiyun * (C) Copyright 2016-2018 Benjamin Tissoires <benjamin.tissoires@gmail.com>
7*4882a593Smuzhiyun * (C) Copyright 2016 Stephen Just <stephenjust@gmail.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This driver has been reverse-engineered by parsing the DSDT of the Surface 3
10*4882a593Smuzhiyun * and looking at the registers of the chips.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * The DSDT allowed to find out that:
13*4882a593Smuzhiyun * - the driver is required for the ACPI BAT0 device to communicate to the chip
14*4882a593Smuzhiyun * through an operation region.
15*4882a593Smuzhiyun * - the various defines for the operation region functions to communicate with
16*4882a593Smuzhiyun * this driver
17*4882a593Smuzhiyun * - the DSM 3f99e367-6220-4955-8b0f-06ef2ae79412 allows to trigger ACPI
18*4882a593Smuzhiyun * events to BAT0 (the code is all available in the DSDT).
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * Further findings regarding the 2 chips declared in the MSHW0011 are:
21*4882a593Smuzhiyun * - there are 2 chips declared:
22*4882a593Smuzhiyun * . 0x22 seems to control the ADP1 line status (and probably the charger)
23*4882a593Smuzhiyun * . 0x55 controls the battery directly
24*4882a593Smuzhiyun * - the battery chip uses a SMBus protocol (using plain SMBus allows non
25*4882a593Smuzhiyun * destructive commands):
26*4882a593Smuzhiyun * . the commands/registers used are in the range 0x00..0x7F
27*4882a593Smuzhiyun * . if bit 8 (0x80) is set in the SMBus command, the returned value is the
28*4882a593Smuzhiyun * same as when it is not set. There is a high chance this bit is the
29*4882a593Smuzhiyun * read/write
30*4882a593Smuzhiyun * . the various registers semantic as been deduced by observing the register
31*4882a593Smuzhiyun * dumps.
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <linux/acpi.h>
35*4882a593Smuzhiyun #include <linux/bits.h>
36*4882a593Smuzhiyun #include <linux/freezer.h>
37*4882a593Smuzhiyun #include <linux/i2c.h>
38*4882a593Smuzhiyun #include <linux/kernel.h>
39*4882a593Smuzhiyun #include <linux/kthread.h>
40*4882a593Smuzhiyun #include <linux/slab.h>
41*4882a593Smuzhiyun #include <linux/types.h>
42*4882a593Smuzhiyun #include <linux/uuid.h>
43*4882a593Smuzhiyun #include <asm/unaligned.h>
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define SURFACE_3_POLL_INTERVAL (2 * HZ)
46*4882a593Smuzhiyun #define SURFACE_3_STRLEN 10
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun struct mshw0011_data {
49*4882a593Smuzhiyun struct i2c_client *adp1;
50*4882a593Smuzhiyun struct i2c_client *bat0;
51*4882a593Smuzhiyun unsigned short notify_mask;
52*4882a593Smuzhiyun struct task_struct *poll_task;
53*4882a593Smuzhiyun bool kthread_running;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun bool charging;
56*4882a593Smuzhiyun bool bat_charging;
57*4882a593Smuzhiyun u8 trip_point;
58*4882a593Smuzhiyun s32 full_capacity;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun struct mshw0011_handler_data {
62*4882a593Smuzhiyun struct acpi_connection_info info;
63*4882a593Smuzhiyun struct i2c_client *client;
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun struct bix {
67*4882a593Smuzhiyun u32 revision;
68*4882a593Smuzhiyun u32 power_unit;
69*4882a593Smuzhiyun u32 design_capacity;
70*4882a593Smuzhiyun u32 last_full_charg_capacity;
71*4882a593Smuzhiyun u32 battery_technology;
72*4882a593Smuzhiyun u32 design_voltage;
73*4882a593Smuzhiyun u32 design_capacity_of_warning;
74*4882a593Smuzhiyun u32 design_capacity_of_low;
75*4882a593Smuzhiyun u32 cycle_count;
76*4882a593Smuzhiyun u32 measurement_accuracy;
77*4882a593Smuzhiyun u32 max_sampling_time;
78*4882a593Smuzhiyun u32 min_sampling_time;
79*4882a593Smuzhiyun u32 max_average_interval;
80*4882a593Smuzhiyun u32 min_average_interval;
81*4882a593Smuzhiyun u32 battery_capacity_granularity_1;
82*4882a593Smuzhiyun u32 battery_capacity_granularity_2;
83*4882a593Smuzhiyun char model[SURFACE_3_STRLEN];
84*4882a593Smuzhiyun char serial[SURFACE_3_STRLEN];
85*4882a593Smuzhiyun char type[SURFACE_3_STRLEN];
86*4882a593Smuzhiyun char OEM[SURFACE_3_STRLEN];
87*4882a593Smuzhiyun } __packed;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun struct bst {
90*4882a593Smuzhiyun u32 battery_state;
91*4882a593Smuzhiyun s32 battery_present_rate;
92*4882a593Smuzhiyun u32 battery_remaining_capacity;
93*4882a593Smuzhiyun u32 battery_present_voltage;
94*4882a593Smuzhiyun } __packed;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun struct gsb_command {
97*4882a593Smuzhiyun u8 arg0;
98*4882a593Smuzhiyun u8 arg1;
99*4882a593Smuzhiyun u8 arg2;
100*4882a593Smuzhiyun } __packed;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun struct gsb_buffer {
103*4882a593Smuzhiyun u8 status;
104*4882a593Smuzhiyun u8 len;
105*4882a593Smuzhiyun u8 ret;
106*4882a593Smuzhiyun union {
107*4882a593Smuzhiyun struct gsb_command cmd;
108*4882a593Smuzhiyun struct bst bst;
109*4882a593Smuzhiyun struct bix bix;
110*4882a593Smuzhiyun } __packed;
111*4882a593Smuzhiyun } __packed;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun #define ACPI_BATTERY_STATE_DISCHARGING BIT(0)
114*4882a593Smuzhiyun #define ACPI_BATTERY_STATE_CHARGING BIT(1)
115*4882a593Smuzhiyun #define ACPI_BATTERY_STATE_CRITICAL BIT(2)
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun #define MSHW0011_CMD_DEST_BAT0 0x01
118*4882a593Smuzhiyun #define MSHW0011_CMD_DEST_ADP1 0x03
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_STA 0x01
121*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_BIX 0x02
122*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_BCT 0x03
123*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_BTM 0x04
124*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_BST 0x05
125*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_BTP 0x06
126*4882a593Smuzhiyun #define MSHW0011_CMD_ADP1_PSR 0x07
127*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_PSOC 0x09
128*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_PMAX 0x0a
129*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_PSRC 0x0b
130*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_CHGI 0x0c
131*4882a593Smuzhiyun #define MSHW0011_CMD_BAT0_ARTG 0x0d
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun #define MSHW0011_NOTIFY_GET_VERSION 0x00
134*4882a593Smuzhiyun #define MSHW0011_NOTIFY_ADP1 0x01
135*4882a593Smuzhiyun #define MSHW0011_NOTIFY_BAT0_BST 0x02
136*4882a593Smuzhiyun #define MSHW0011_NOTIFY_BAT0_BIX 0x05
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun #define MSHW0011_ADP1_REG_PSR 0x04
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_CAPACITY 0x0c
141*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_FULL_CHG_CAPACITY 0x0e
142*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_DESIGN_CAPACITY 0x40
143*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_VOLTAGE 0x08
144*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_RATE 0x14
145*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_OEM 0x45
146*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_TYPE 0x4e
147*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_SERIAL_NO 0x56
148*4882a593Smuzhiyun #define MSHW0011_BAT0_REG_CYCLE_CNT 0x6e
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #define MSHW0011_EV_2_5_MASK GENMASK(8, 0)
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* 3f99e367-6220-4955-8b0f-06ef2ae79412 */
153*4882a593Smuzhiyun static const guid_t mshw0011_guid =
154*4882a593Smuzhiyun GUID_INIT(0x3F99E367, 0x6220, 0x4955, 0x8B, 0x0F, 0x06, 0xEF,
155*4882a593Smuzhiyun 0x2A, 0xE7, 0x94, 0x12);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun static int
mshw0011_notify(struct mshw0011_data * cdata,u8 arg1,u8 arg2,unsigned int * ret_value)158*4882a593Smuzhiyun mshw0011_notify(struct mshw0011_data *cdata, u8 arg1, u8 arg2,
159*4882a593Smuzhiyun unsigned int *ret_value)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun union acpi_object *obj;
162*4882a593Smuzhiyun struct acpi_device *adev;
163*4882a593Smuzhiyun acpi_handle handle;
164*4882a593Smuzhiyun unsigned int i;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun handle = ACPI_HANDLE(&cdata->adp1->dev);
167*4882a593Smuzhiyun if (!handle || acpi_bus_get_device(handle, &adev))
168*4882a593Smuzhiyun return -ENODEV;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun obj = acpi_evaluate_dsm_typed(handle, &mshw0011_guid, arg1, arg2, NULL,
171*4882a593Smuzhiyun ACPI_TYPE_BUFFER);
172*4882a593Smuzhiyun if (!obj) {
173*4882a593Smuzhiyun dev_err(&cdata->adp1->dev, "device _DSM execution failed\n");
174*4882a593Smuzhiyun return -ENODEV;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun *ret_value = 0;
178*4882a593Smuzhiyun for (i = 0; i < obj->buffer.length; i++)
179*4882a593Smuzhiyun *ret_value |= obj->buffer.pointer[i] << (i * 8);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun ACPI_FREE(obj);
182*4882a593Smuzhiyun return 0;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun static const struct bix default_bix = {
186*4882a593Smuzhiyun .revision = 0x00,
187*4882a593Smuzhiyun .power_unit = 0x01,
188*4882a593Smuzhiyun .design_capacity = 0x1dca,
189*4882a593Smuzhiyun .last_full_charg_capacity = 0x1dca,
190*4882a593Smuzhiyun .battery_technology = 0x01,
191*4882a593Smuzhiyun .design_voltage = 0x10df,
192*4882a593Smuzhiyun .design_capacity_of_warning = 0x8f,
193*4882a593Smuzhiyun .design_capacity_of_low = 0x47,
194*4882a593Smuzhiyun .cycle_count = 0xffffffff,
195*4882a593Smuzhiyun .measurement_accuracy = 0x00015f90,
196*4882a593Smuzhiyun .max_sampling_time = 0x03e8,
197*4882a593Smuzhiyun .min_sampling_time = 0x03e8,
198*4882a593Smuzhiyun .max_average_interval = 0x03e8,
199*4882a593Smuzhiyun .min_average_interval = 0x03e8,
200*4882a593Smuzhiyun .battery_capacity_granularity_1 = 0x45,
201*4882a593Smuzhiyun .battery_capacity_granularity_2 = 0x11,
202*4882a593Smuzhiyun .model = "P11G8M",
203*4882a593Smuzhiyun .serial = "",
204*4882a593Smuzhiyun .type = "LION",
205*4882a593Smuzhiyun .OEM = "",
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun
mshw0011_bix(struct mshw0011_data * cdata,struct bix * bix)208*4882a593Smuzhiyun static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun struct i2c_client *client = cdata->bat0;
211*4882a593Smuzhiyun char buf[SURFACE_3_STRLEN];
212*4882a593Smuzhiyun int ret;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun *bix = default_bix;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* get design capacity */
217*4882a593Smuzhiyun ret = i2c_smbus_read_word_data(client,
218*4882a593Smuzhiyun MSHW0011_BAT0_REG_DESIGN_CAPACITY);
219*4882a593Smuzhiyun if (ret < 0) {
220*4882a593Smuzhiyun dev_err(&client->dev, "Error reading design capacity: %d\n",
221*4882a593Smuzhiyun ret);
222*4882a593Smuzhiyun return ret;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun bix->design_capacity = ret;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /* get last full charge capacity */
227*4882a593Smuzhiyun ret = i2c_smbus_read_word_data(client,
228*4882a593Smuzhiyun MSHW0011_BAT0_REG_FULL_CHG_CAPACITY);
229*4882a593Smuzhiyun if (ret < 0) {
230*4882a593Smuzhiyun dev_err(&client->dev,
231*4882a593Smuzhiyun "Error reading last full charge capacity: %d\n", ret);
232*4882a593Smuzhiyun return ret;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun bix->last_full_charg_capacity = ret;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun /*
237*4882a593Smuzhiyun * Get serial number, on some devices (with unofficial replacement
238*4882a593Smuzhiyun * battery?) reading any of the serial number range addresses gets
239*4882a593Smuzhiyun * nacked in this case just leave the serial number empty.
240*4882a593Smuzhiyun */
241*4882a593Smuzhiyun ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_SERIAL_NO,
242*4882a593Smuzhiyun sizeof(buf), buf);
243*4882a593Smuzhiyun if (ret == -EREMOTEIO) {
244*4882a593Smuzhiyun /* no serial number available */
245*4882a593Smuzhiyun } else if (ret != sizeof(buf)) {
246*4882a593Smuzhiyun dev_err(&client->dev, "Error reading serial no: %d\n", ret);
247*4882a593Smuzhiyun return ret;
248*4882a593Smuzhiyun } else {
249*4882a593Smuzhiyun snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /* get cycle count */
253*4882a593Smuzhiyun ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CYCLE_CNT);
254*4882a593Smuzhiyun if (ret < 0) {
255*4882a593Smuzhiyun dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
256*4882a593Smuzhiyun return ret;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun bix->cycle_count = ret;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun /* get OEM name */
261*4882a593Smuzhiyun ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_OEM,
262*4882a593Smuzhiyun 4, buf);
263*4882a593Smuzhiyun if (ret != 4) {
264*4882a593Smuzhiyun dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
265*4882a593Smuzhiyun return ret;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun snprintf(bix->OEM, ARRAY_SIZE(bix->OEM), "%3pE", buf);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return 0;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
mshw0011_bst(struct mshw0011_data * cdata,struct bst * bst)272*4882a593Smuzhiyun static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun struct i2c_client *client = cdata->bat0;
275*4882a593Smuzhiyun int rate, capacity, voltage, state;
276*4882a593Smuzhiyun s16 tmp;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun rate = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_RATE);
279*4882a593Smuzhiyun if (rate < 0)
280*4882a593Smuzhiyun return rate;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun capacity = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CAPACITY);
283*4882a593Smuzhiyun if (capacity < 0)
284*4882a593Smuzhiyun return capacity;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun voltage = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_VOLTAGE);
287*4882a593Smuzhiyun if (voltage < 0)
288*4882a593Smuzhiyun return voltage;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun tmp = rate;
291*4882a593Smuzhiyun bst->battery_present_rate = abs((s32)tmp);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun state = 0;
294*4882a593Smuzhiyun if ((s32) tmp > 0)
295*4882a593Smuzhiyun state |= ACPI_BATTERY_STATE_CHARGING;
296*4882a593Smuzhiyun else if ((s32) tmp < 0)
297*4882a593Smuzhiyun state |= ACPI_BATTERY_STATE_DISCHARGING;
298*4882a593Smuzhiyun bst->battery_state = state;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun bst->battery_remaining_capacity = capacity;
301*4882a593Smuzhiyun bst->battery_present_voltage = voltage;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun return 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
mshw0011_adp_psr(struct mshw0011_data * cdata)306*4882a593Smuzhiyun static int mshw0011_adp_psr(struct mshw0011_data *cdata)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun return i2c_smbus_read_byte_data(cdata->adp1, MSHW0011_ADP1_REG_PSR);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
mshw0011_isr(struct mshw0011_data * cdata)311*4882a593Smuzhiyun static int mshw0011_isr(struct mshw0011_data *cdata)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun struct bst bst;
314*4882a593Smuzhiyun struct bix bix;
315*4882a593Smuzhiyun int ret;
316*4882a593Smuzhiyun bool status, bat_status;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun ret = mshw0011_adp_psr(cdata);
319*4882a593Smuzhiyun if (ret < 0)
320*4882a593Smuzhiyun return ret;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun status = ret;
323*4882a593Smuzhiyun if (status != cdata->charging)
324*4882a593Smuzhiyun mshw0011_notify(cdata, cdata->notify_mask,
325*4882a593Smuzhiyun MSHW0011_NOTIFY_ADP1, &ret);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun cdata->charging = status;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun ret = mshw0011_bst(cdata, &bst);
330*4882a593Smuzhiyun if (ret < 0)
331*4882a593Smuzhiyun return ret;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun bat_status = bst.battery_state;
334*4882a593Smuzhiyun if (bat_status != cdata->bat_charging)
335*4882a593Smuzhiyun mshw0011_notify(cdata, cdata->notify_mask,
336*4882a593Smuzhiyun MSHW0011_NOTIFY_BAT0_BST, &ret);
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun cdata->bat_charging = bat_status;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun ret = mshw0011_bix(cdata, &bix);
341*4882a593Smuzhiyun if (ret < 0)
342*4882a593Smuzhiyun return ret;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun if (bix.last_full_charg_capacity != cdata->full_capacity)
345*4882a593Smuzhiyun mshw0011_notify(cdata, cdata->notify_mask,
346*4882a593Smuzhiyun MSHW0011_NOTIFY_BAT0_BIX, &ret);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun cdata->full_capacity = bix.last_full_charg_capacity;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun return 0;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
mshw0011_poll_task(void * data)353*4882a593Smuzhiyun static int mshw0011_poll_task(void *data)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct mshw0011_data *cdata = data;
356*4882a593Smuzhiyun int ret = 0;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun cdata->kthread_running = true;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun set_freezable();
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun while (!kthread_should_stop()) {
363*4882a593Smuzhiyun schedule_timeout_interruptible(SURFACE_3_POLL_INTERVAL);
364*4882a593Smuzhiyun try_to_freeze();
365*4882a593Smuzhiyun ret = mshw0011_isr(data);
366*4882a593Smuzhiyun if (ret)
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun cdata->kthread_running = false;
371*4882a593Smuzhiyun return ret;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun static acpi_status
mshw0011_space_handler(u32 function,acpi_physical_address command,u32 bits,u64 * value64,void * handler_context,void * region_context)375*4882a593Smuzhiyun mshw0011_space_handler(u32 function, acpi_physical_address command,
376*4882a593Smuzhiyun u32 bits, u64 *value64,
377*4882a593Smuzhiyun void *handler_context, void *region_context)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
380*4882a593Smuzhiyun struct mshw0011_handler_data *data = handler_context;
381*4882a593Smuzhiyun struct acpi_connection_info *info = &data->info;
382*4882a593Smuzhiyun struct acpi_resource_i2c_serialbus *sb;
383*4882a593Smuzhiyun struct i2c_client *client = data->client;
384*4882a593Smuzhiyun struct mshw0011_data *cdata = i2c_get_clientdata(client);
385*4882a593Smuzhiyun struct acpi_resource *ares;
386*4882a593Smuzhiyun u32 accessor_type = function >> 16;
387*4882a593Smuzhiyun acpi_status ret;
388*4882a593Smuzhiyun int status = 1;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
391*4882a593Smuzhiyun if (ACPI_FAILURE(ret))
392*4882a593Smuzhiyun return ret;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
395*4882a593Smuzhiyun ret = AE_BAD_PARAMETER;
396*4882a593Smuzhiyun goto err;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun sb = &ares->data.i2c_serial_bus;
400*4882a593Smuzhiyun if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
401*4882a593Smuzhiyun ret = AE_BAD_PARAMETER;
402*4882a593Smuzhiyun goto err;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) {
406*4882a593Smuzhiyun ret = AE_BAD_PARAMETER;
407*4882a593Smuzhiyun goto err;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (gsb->cmd.arg0 == MSHW0011_CMD_DEST_ADP1 &&
411*4882a593Smuzhiyun gsb->cmd.arg1 == MSHW0011_CMD_ADP1_PSR) {
412*4882a593Smuzhiyun status = mshw0011_adp_psr(cdata);
413*4882a593Smuzhiyun if (status >= 0) {
414*4882a593Smuzhiyun ret = AE_OK;
415*4882a593Smuzhiyun goto out;
416*4882a593Smuzhiyun } else {
417*4882a593Smuzhiyun ret = AE_ERROR;
418*4882a593Smuzhiyun goto err;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun if (gsb->cmd.arg0 != MSHW0011_CMD_DEST_BAT0) {
423*4882a593Smuzhiyun ret = AE_BAD_PARAMETER;
424*4882a593Smuzhiyun goto err;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun switch (gsb->cmd.arg1) {
428*4882a593Smuzhiyun case MSHW0011_CMD_BAT0_STA:
429*4882a593Smuzhiyun break;
430*4882a593Smuzhiyun case MSHW0011_CMD_BAT0_BIX:
431*4882a593Smuzhiyun ret = mshw0011_bix(cdata, &gsb->bix);
432*4882a593Smuzhiyun break;
433*4882a593Smuzhiyun case MSHW0011_CMD_BAT0_BTP:
434*4882a593Smuzhiyun cdata->trip_point = gsb->cmd.arg2;
435*4882a593Smuzhiyun break;
436*4882a593Smuzhiyun case MSHW0011_CMD_BAT0_BST:
437*4882a593Smuzhiyun ret = mshw0011_bst(cdata, &gsb->bst);
438*4882a593Smuzhiyun break;
439*4882a593Smuzhiyun default:
440*4882a593Smuzhiyun dev_info(&cdata->bat0->dev, "command(0x%02x) is not supported.\n", gsb->cmd.arg1);
441*4882a593Smuzhiyun ret = AE_BAD_PARAMETER;
442*4882a593Smuzhiyun goto err;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun out:
446*4882a593Smuzhiyun gsb->ret = status;
447*4882a593Smuzhiyun gsb->status = 0;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun err:
450*4882a593Smuzhiyun ACPI_FREE(ares);
451*4882a593Smuzhiyun return ret;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
mshw0011_install_space_handler(struct i2c_client * client)454*4882a593Smuzhiyun static int mshw0011_install_space_handler(struct i2c_client *client)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun acpi_handle handle;
457*4882a593Smuzhiyun struct mshw0011_handler_data *data;
458*4882a593Smuzhiyun acpi_status status;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun handle = ACPI_HANDLE(&client->dev);
461*4882a593Smuzhiyun if (!handle)
462*4882a593Smuzhiyun return -ENODEV;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun data = kzalloc(sizeof(struct mshw0011_handler_data),
465*4882a593Smuzhiyun GFP_KERNEL);
466*4882a593Smuzhiyun if (!data)
467*4882a593Smuzhiyun return -ENOMEM;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun data->client = client;
470*4882a593Smuzhiyun status = acpi_bus_attach_private_data(handle, (void *)data);
471*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
472*4882a593Smuzhiyun kfree(data);
473*4882a593Smuzhiyun return -ENOMEM;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun status = acpi_install_address_space_handler(handle,
477*4882a593Smuzhiyun ACPI_ADR_SPACE_GSBUS,
478*4882a593Smuzhiyun &mshw0011_space_handler,
479*4882a593Smuzhiyun NULL,
480*4882a593Smuzhiyun data);
481*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
482*4882a593Smuzhiyun dev_err(&client->dev, "Error installing i2c space handler\n");
483*4882a593Smuzhiyun acpi_bus_detach_private_data(handle);
484*4882a593Smuzhiyun kfree(data);
485*4882a593Smuzhiyun return -ENOMEM;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun acpi_walk_dep_device_list(handle);
489*4882a593Smuzhiyun return 0;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
mshw0011_remove_space_handler(struct i2c_client * client)492*4882a593Smuzhiyun static void mshw0011_remove_space_handler(struct i2c_client *client)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun struct mshw0011_handler_data *data;
495*4882a593Smuzhiyun acpi_handle handle;
496*4882a593Smuzhiyun acpi_status status;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun handle = ACPI_HANDLE(&client->dev);
499*4882a593Smuzhiyun if (!handle)
500*4882a593Smuzhiyun return;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun acpi_remove_address_space_handler(handle,
503*4882a593Smuzhiyun ACPI_ADR_SPACE_GSBUS,
504*4882a593Smuzhiyun &mshw0011_space_handler);
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun status = acpi_bus_get_private_data(handle, (void **)&data);
507*4882a593Smuzhiyun if (ACPI_SUCCESS(status))
508*4882a593Smuzhiyun kfree(data);
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun acpi_bus_detach_private_data(handle);
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
mshw0011_probe(struct i2c_client * client)513*4882a593Smuzhiyun static int mshw0011_probe(struct i2c_client *client)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun struct i2c_board_info board_info;
516*4882a593Smuzhiyun struct device *dev = &client->dev;
517*4882a593Smuzhiyun struct i2c_client *bat0;
518*4882a593Smuzhiyun struct mshw0011_data *data;
519*4882a593Smuzhiyun int error, mask;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
522*4882a593Smuzhiyun if (!data)
523*4882a593Smuzhiyun return -ENOMEM;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun data->adp1 = client;
526*4882a593Smuzhiyun i2c_set_clientdata(client, data);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun memset(&board_info, 0, sizeof(board_info));
529*4882a593Smuzhiyun strlcpy(board_info.type, "MSHW0011-bat0", I2C_NAME_SIZE);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun bat0 = i2c_acpi_new_device(dev, 1, &board_info);
532*4882a593Smuzhiyun if (IS_ERR(bat0))
533*4882a593Smuzhiyun return PTR_ERR(bat0);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun data->bat0 = bat0;
536*4882a593Smuzhiyun i2c_set_clientdata(bat0, data);
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun error = mshw0011_notify(data, 1, MSHW0011_NOTIFY_GET_VERSION, &mask);
539*4882a593Smuzhiyun if (error)
540*4882a593Smuzhiyun goto out_err;
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun data->notify_mask = mask == MSHW0011_EV_2_5_MASK;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun data->poll_task = kthread_run(mshw0011_poll_task, data, "mshw0011_adp");
545*4882a593Smuzhiyun if (IS_ERR(data->poll_task)) {
546*4882a593Smuzhiyun error = PTR_ERR(data->poll_task);
547*4882a593Smuzhiyun dev_err(&client->dev, "Unable to run kthread err %d\n", error);
548*4882a593Smuzhiyun goto out_err;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun error = mshw0011_install_space_handler(client);
552*4882a593Smuzhiyun if (error)
553*4882a593Smuzhiyun goto out_err;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun return 0;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun out_err:
558*4882a593Smuzhiyun if (data->kthread_running)
559*4882a593Smuzhiyun kthread_stop(data->poll_task);
560*4882a593Smuzhiyun i2c_unregister_device(data->bat0);
561*4882a593Smuzhiyun return error;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
mshw0011_remove(struct i2c_client * client)564*4882a593Smuzhiyun static int mshw0011_remove(struct i2c_client *client)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun struct mshw0011_data *cdata = i2c_get_clientdata(client);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun mshw0011_remove_space_handler(client);
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun if (cdata->kthread_running)
571*4882a593Smuzhiyun kthread_stop(cdata->poll_task);
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun i2c_unregister_device(cdata->bat0);
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun return 0;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun static const struct acpi_device_id mshw0011_acpi_match[] = {
579*4882a593Smuzhiyun { "MSHW0011", 0 },
580*4882a593Smuzhiyun { }
581*4882a593Smuzhiyun };
582*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match);
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun static struct i2c_driver mshw0011_driver = {
585*4882a593Smuzhiyun .probe_new = mshw0011_probe,
586*4882a593Smuzhiyun .remove = mshw0011_remove,
587*4882a593Smuzhiyun .driver = {
588*4882a593Smuzhiyun .name = "mshw0011",
589*4882a593Smuzhiyun .acpi_match_table = mshw0011_acpi_match,
590*4882a593Smuzhiyun },
591*4882a593Smuzhiyun };
592*4882a593Smuzhiyun module_i2c_driver(mshw0011_driver);
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
595*4882a593Smuzhiyun MODULE_DESCRIPTION("mshw0011 driver");
596*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
597