xref: /OK3568_Linux_fs/kernel/drivers/platform/x86/surface3_power.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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