Blame view

drivers/power/max17042_battery.c 22.6 KB
359ab9f5b   MyungJoo Ham   power_supply: Add...
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
  /*
   * Fuel gauge driver for Maxim 17042 / 8966 / 8997
   *  Note that Maxim 8966 and 8997 are mfd and this is its subdevice.
   *
   * Copyright (C) 2011 Samsung Electronics
   * MyungJoo Ham <myungjoo.ham@samsung.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   * This driver is based on max17040_battery.c
   */
  
  #include <linux/init.h>
7e6d62db5   Paul Gortmaker   drivers/power: Ad...
26
  #include <linux/module.h>
359ab9f5b   MyungJoo Ham   power_supply: Add...
27
28
  #include <linux/slab.h>
  #include <linux/i2c.h>
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
29
  #include <linux/delay.h>
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
30
  #include <linux/interrupt.h>
48bc17744   Ramakrishna Pallala   max17042_battery:...
31
  #include <linux/pm.h>
359ab9f5b   MyungJoo Ham   power_supply: Add...
32
33
34
  #include <linux/mod_devicetable.h>
  #include <linux/power_supply.h>
  #include <linux/power/max17042_battery.h>
3832246dd   Karol Lewandowski   max17042_battery:...
35
  #include <linux/of.h>
39e7213ed   Jonghwa Lee   max17042_battery:...
36
  #include <linux/regmap.h>
359ab9f5b   MyungJoo Ham   power_supply: Add...
37

f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
38
39
40
41
42
43
44
45
46
47
48
  /* Status register bits */
  #define STATUS_POR_BIT         (1 << 1)
  #define STATUS_BST_BIT         (1 << 3)
  #define STATUS_VMN_BIT         (1 << 8)
  #define STATUS_TMN_BIT         (1 << 9)
  #define STATUS_SMN_BIT         (1 << 10)
  #define STATUS_BI_BIT          (1 << 11)
  #define STATUS_VMX_BIT         (1 << 12)
  #define STATUS_TMX_BIT         (1 << 13)
  #define STATUS_SMX_BIT         (1 << 14)
  #define STATUS_BR_BIT          (1 << 15)
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
49
50
  /* Interrupt mask bits */
  #define CONFIG_ALRT_BIT_ENBL	(1 << 2)
5cdd4d7fa   Ramakrishna Pallala   max17042_battery:...
51
52
  #define STATUS_INTR_SOCMIN_BIT	(1 << 10)
  #define STATUS_INTR_SOCMAX_BIT	(1 << 14)
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
53

f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
54
55
56
57
58
59
60
61
62
63
  #define VFSOC0_LOCK		0x0000
  #define VFSOC0_UNLOCK		0x0080
  #define MODEL_UNLOCK1	0X0059
  #define MODEL_UNLOCK2	0X00C4
  #define MODEL_LOCK1		0X0000
  #define MODEL_LOCK2		0X0000
  
  #define dQ_ACC_DIV	0x4
  #define dP_ACC_100	0x1900
  #define dP_ACC_200	0x3200
9a8422d20   Ramakrishna Pallala   max17042_battery:...
64
65
  #define MAX17042_IC_VERSION	0x0092
  #define MAX17047_IC_VERSION	0x00AC	/* same for max17050 */
359ab9f5b   MyungJoo Ham   power_supply: Add...
66
67
  struct max17042_chip {
  	struct i2c_client *client;
39e7213ed   Jonghwa Lee   max17042_battery:...
68
  	struct regmap *regmap;
359ab9f5b   MyungJoo Ham   power_supply: Add...
69
  	struct power_supply battery;
9a8422d20   Ramakrishna Pallala   max17042_battery:...
70
  	enum max170xx_chip_type chip_type;
359ab9f5b   MyungJoo Ham   power_supply: Add...
71
  	struct max17042_platform_data *pdata;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
72
73
  	struct work_struct work;
  	int    init_complete;
359ab9f5b   MyungJoo Ham   power_supply: Add...
74
  };
359ab9f5b   MyungJoo Ham   power_supply: Add...
75
  static enum power_supply_property max17042_battery_props[] = {
086ef502c   Donggeun Kim   power_supply: MAX...
76
77
78
79
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_CYCLE_COUNT,
  	POWER_SUPPLY_PROP_VOLTAGE_MAX,
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
359ab9f5b   MyungJoo Ham   power_supply: Add...
80
81
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_VOLTAGE_AVG,
a2ebfe2fc   Ramakrishna Pallala   power_supply: Add...
82
  	POWER_SUPPLY_PROP_VOLTAGE_OCV,
359ab9f5b   MyungJoo Ham   power_supply: Add...
83
  	POWER_SUPPLY_PROP_CAPACITY,
086ef502c   Donggeun Kim   power_supply: MAX...
84
  	POWER_SUPPLY_PROP_CHARGE_FULL,
5fc55bc82   Ramakrishna Pallala   max17042_battery:...
85
  	POWER_SUPPLY_PROP_CHARGE_COUNTER,
086ef502c   Donggeun Kim   power_supply: MAX...
86
87
88
  	POWER_SUPPLY_PROP_TEMP,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CURRENT_AVG,
359ab9f5b   MyungJoo Ham   power_supply: Add...
89
90
91
92
93
94
95
96
  };
  
  static int max17042_get_property(struct power_supply *psy,
  			    enum power_supply_property psp,
  			    union power_supply_propval *val)
  {
  	struct max17042_chip *chip = container_of(psy,
  				struct max17042_chip, battery);
39e7213ed   Jonghwa Lee   max17042_battery:...
97
  	struct regmap *map = chip->regmap;
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
98
  	int ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
99
  	u32 data;
359ab9f5b   MyungJoo Ham   power_supply: Add...
100

f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
101
102
  	if (!chip->init_complete)
  		return -EAGAIN;
359ab9f5b   MyungJoo Ham   power_supply: Add...
103
  	switch (psp) {
086ef502c   Donggeun Kim   power_supply: MAX...
104
  	case POWER_SUPPLY_PROP_PRESENT:
39e7213ed   Jonghwa Lee   max17042_battery:...
105
  		ret = regmap_read(map, MAX17042_STATUS, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
106
107
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
108
  		if (data & MAX17042_STATUS_BattAbsent)
086ef502c   Donggeun Kim   power_supply: MAX...
109
110
111
112
113
  			val->intval = 0;
  		else
  			val->intval = 1;
  		break;
  	case POWER_SUPPLY_PROP_CYCLE_COUNT:
39e7213ed   Jonghwa Lee   max17042_battery:...
114
  		ret = regmap_read(map, MAX17042_Cycles, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
115
116
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
117
  		val->intval = data;
086ef502c   Donggeun Kim   power_supply: MAX...
118
119
  		break;
  	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
39e7213ed   Jonghwa Lee   max17042_battery:...
120
  		ret = regmap_read(map, MAX17042_MinMaxVolt, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
121
122
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
123
  		val->intval = data >> 8;
086ef502c   Donggeun Kim   power_supply: MAX...
124
125
126
  		val->intval *= 20000; /* Units of LSB = 20mV */
  		break;
  	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
9a8422d20   Ramakrishna Pallala   max17042_battery:...
127
  		if (chip->chip_type == MAX17042)
39e7213ed   Jonghwa Lee   max17042_battery:...
128
  			ret = regmap_read(map, MAX17042_V_empty, &data);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
129
  		else
39e7213ed   Jonghwa Lee   max17042_battery:...
130
  			ret = regmap_read(map, MAX17047_V_empty, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
131
132
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
133
  		val->intval = data >> 7;
086ef502c   Donggeun Kim   power_supply: MAX...
134
135
  		val->intval *= 10000; /* Units of LSB = 10mV */
  		break;
359ab9f5b   MyungJoo Ham   power_supply: Add...
136
  	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
39e7213ed   Jonghwa Lee   max17042_battery:...
137
  		ret = regmap_read(map, MAX17042_VCELL, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
138
139
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
140
  		val->intval = data * 625 / 8;
359ab9f5b   MyungJoo Ham   power_supply: Add...
141
142
  		break;
  	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
39e7213ed   Jonghwa Lee   max17042_battery:...
143
  		ret = regmap_read(map, MAX17042_AvgVCELL, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
144
145
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
146
  		val->intval = data * 625 / 8;
359ab9f5b   MyungJoo Ham   power_supply: Add...
147
  		break;
a2ebfe2fc   Ramakrishna Pallala   power_supply: Add...
148
  	case POWER_SUPPLY_PROP_VOLTAGE_OCV:
39e7213ed   Jonghwa Lee   max17042_battery:...
149
  		ret = regmap_read(map, MAX17042_OCVInternal, &data);
a2ebfe2fc   Ramakrishna Pallala   power_supply: Add...
150
151
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
152
  		val->intval = data * 625 / 8;
a2ebfe2fc   Ramakrishna Pallala   power_supply: Add...
153
  		break;
359ab9f5b   MyungJoo Ham   power_supply: Add...
154
  	case POWER_SUPPLY_PROP_CAPACITY:
39e7213ed   Jonghwa Lee   max17042_battery:...
155
  		ret = regmap_read(map, MAX17042_RepSOC, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
156
157
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
158
  		val->intval = data >> 8;
359ab9f5b   MyungJoo Ham   power_supply: Add...
159
  		break;
086ef502c   Donggeun Kim   power_supply: MAX...
160
  	case POWER_SUPPLY_PROP_CHARGE_FULL:
39e7213ed   Jonghwa Lee   max17042_battery:...
161
  		ret = regmap_read(map, MAX17042_FullCAP, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
162
163
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
164
  		val->intval = data * 1000 / 2;
086ef502c   Donggeun Kim   power_supply: MAX...
165
  		break;
5fc55bc82   Ramakrishna Pallala   max17042_battery:...
166
  	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
39e7213ed   Jonghwa Lee   max17042_battery:...
167
  		ret = regmap_read(map, MAX17042_QH, &data);
5fc55bc82   Ramakrishna Pallala   max17042_battery:...
168
169
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
170
  		val->intval = data * 1000 / 2;
5fc55bc82   Ramakrishna Pallala   max17042_battery:...
171
  		break;
086ef502c   Donggeun Kim   power_supply: MAX...
172
  	case POWER_SUPPLY_PROP_TEMP:
39e7213ed   Jonghwa Lee   max17042_battery:...
173
  		ret = regmap_read(map, MAX17042_TEMP, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
174
175
  		if (ret < 0)
  			return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
176
  		val->intval = data;
086ef502c   Donggeun Kim   power_supply: MAX...
177
178
179
180
181
182
183
184
185
186
187
  		/* The value is signed. */
  		if (val->intval & 0x8000) {
  			val->intval = (0x7fff & ~val->intval) + 1;
  			val->intval *= -1;
  		}
  		/* The value is converted into deci-centigrade scale */
  		/* Units of LSB = 1 / 256 degree Celsius */
  		val->intval = val->intval * 10 / 256;
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_NOW:
  		if (chip->pdata->enable_current_sense) {
39e7213ed   Jonghwa Lee   max17042_battery:...
188
  			ret = regmap_read(map, MAX17042_Current, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
189
190
  			if (ret < 0)
  				return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
191
  			val->intval = data;
086ef502c   Donggeun Kim   power_supply: MAX...
192
193
194
195
196
197
  			if (val->intval & 0x8000) {
  				/* Negative */
  				val->intval = ~val->intval & 0x7fff;
  				val->intval++;
  				val->intval *= -1;
  			}
91d8b0d6f   Philip Rakity   max17042_battery:...
198
  			val->intval *= 1562500 / chip->pdata->r_sns;
086ef502c   Donggeun Kim   power_supply: MAX...
199
200
201
202
203
204
  		} else {
  			return -EINVAL;
  		}
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_AVG:
  		if (chip->pdata->enable_current_sense) {
39e7213ed   Jonghwa Lee   max17042_battery:...
205
  			ret = regmap_read(map, MAX17042_AvgCurrent, &data);
60a1f6e44   Ramakrishna Pallala   max17042_battery:...
206
207
  			if (ret < 0)
  				return ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
208
  			val->intval = data;
086ef502c   Donggeun Kim   power_supply: MAX...
209
210
211
212
213
214
215
216
217
218
219
  			if (val->intval & 0x8000) {
  				/* Negative */
  				val->intval = ~val->intval & 0x7fff;
  				val->intval++;
  				val->intval *= -1;
  			}
  			val->intval *= 1562500 / chip->pdata->r_sns;
  		} else {
  			return -EINVAL;
  		}
  		break;
359ab9f5b   MyungJoo Ham   power_supply: Add...
220
221
222
223
224
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
39e7213ed   Jonghwa Lee   max17042_battery:...
225
  static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value)
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
226
227
228
  {
  	int retries = 8;
  	int ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
229
  	u32 read_value;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
230
231
  
  	do {
39e7213ed   Jonghwa Lee   max17042_battery:...
232
233
  		ret = regmap_write(map, reg, value);
  		regmap_read(map, reg, &read_value);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
234
235
236
237
238
239
240
  		if (read_value != value) {
  			ret = -EIO;
  			retries--;
  		}
  	} while (retries && read_value != value);
  
  	if (ret < 0)
39e7213ed   Jonghwa Lee   max17042_battery:...
241
242
  		pr_err("%s: err %d
  ", __func__, ret);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
243
244
245
  
  	return ret;
  }
39e7213ed   Jonghwa Lee   max17042_battery:...
246
247
  static inline void max17042_override_por(struct regmap *map,
  					 u8 reg, u16 value)
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
248
249
  {
  	if (value)
39e7213ed   Jonghwa Lee   max17042_battery:...
250
  		regmap_write(map, reg, value);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
251
252
253
254
  }
  
  static inline void max10742_unlock_model(struct max17042_chip *chip)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
255
256
257
  	struct regmap *map = chip->regmap;
  	regmap_write(map, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
  	regmap_write(map, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
258
259
260
261
  }
  
  static inline void max10742_lock_model(struct max17042_chip *chip)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
262
263
264
265
  	struct regmap *map = chip->regmap;
  
  	regmap_write(map, MAX17042_MLOCKReg1, MODEL_LOCK1);
  	regmap_write(map, MAX17042_MLOCKReg2, MODEL_LOCK2);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
266
267
268
269
270
  }
  
  static inline void max17042_write_model_data(struct max17042_chip *chip,
  					u8 addr, int size)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
271
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
272
273
  	int i;
  	for (i = 0; i < size; i++)
39e7213ed   Jonghwa Lee   max17042_battery:...
274
275
  		regmap_write(map, addr + i,
  			chip->pdata->config_data->cell_char_tbl[i]);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
276
277
278
  }
  
  static inline void max17042_read_model_data(struct max17042_chip *chip,
39e7213ed   Jonghwa Lee   max17042_battery:...
279
  					u8 addr, u32 *data, int size)
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
280
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
281
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
282
283
284
  	int i;
  
  	for (i = 0; i < size; i++)
39e7213ed   Jonghwa Lee   max17042_battery:...
285
  		regmap_read(map, addr + i, &data[i]);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  }
  
  static inline int max17042_model_data_compare(struct max17042_chip *chip,
  					u16 *data1, u16 *data2, int size)
  {
  	int i;
  
  	if (memcmp(data1, data2, size)) {
  		dev_err(&chip->client->dev, "%s compare failed
  ", __func__);
  		for (i = 0; i < size; i++)
  			dev_info(&chip->client->dev, "0x%x, 0x%x",
  				data1[i], data2[i]);
  		dev_info(&chip->client->dev, "
  ");
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static int max17042_init_model(struct max17042_chip *chip)
  {
  	int ret;
1ef3d8fb4   Dan Carpenter   max17042_battery:...
309
  	int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
39e7213ed   Jonghwa Lee   max17042_battery:...
310
  	u32 *temp_data;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
311

1ef3d8fb4   Dan Carpenter   max17042_battery:...
312
  	temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
313
314
315
316
317
318
319
320
321
322
323
324
  	if (!temp_data)
  		return -ENOMEM;
  
  	max10742_unlock_model(chip);
  	max17042_write_model_data(chip, MAX17042_MODELChrTbl,
  				table_size);
  	max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data,
  				table_size);
  
  	ret = max17042_model_data_compare(
  		chip,
  		chip->pdata->config_data->cell_char_tbl,
39e7213ed   Jonghwa Lee   max17042_battery:...
325
  		(u16 *)temp_data,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
326
327
328
329
330
331
332
333
334
335
336
  		table_size);
  
  	max10742_lock_model(chip);
  	kfree(temp_data);
  
  	return ret;
  }
  
  static int max17042_verify_model_lock(struct max17042_chip *chip)
  {
  	int i;
1ef3d8fb4   Dan Carpenter   max17042_battery:...
337
  	int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
39e7213ed   Jonghwa Lee   max17042_battery:...
338
  	u32 *temp_data;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
339
  	int ret = 0;
1ef3d8fb4   Dan Carpenter   max17042_battery:...
340
  	temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  	if (!temp_data)
  		return -ENOMEM;
  
  	max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data,
  				table_size);
  	for (i = 0; i < table_size; i++)
  		if (temp_data[i])
  			ret = -EINVAL;
  
  	kfree(temp_data);
  	return ret;
  }
  
  static void max17042_write_config_regs(struct max17042_chip *chip)
  {
  	struct max17042_config_data *config = chip->pdata->config_data;
39e7213ed   Jonghwa Lee   max17042_battery:...
357
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
358

39e7213ed   Jonghwa Lee   max17042_battery:...
359
360
361
  	regmap_write(map, MAX17042_CONFIG, config->config);
  	regmap_write(map, MAX17042_LearnCFG, config->learn_cfg);
  	regmap_write(map, MAX17042_FilterCFG,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
362
  			config->filter_cfg);
39e7213ed   Jonghwa Lee   max17042_battery:...
363
  	regmap_write(map, MAX17042_RelaxCFG, config->relax_cfg);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
364
  	if (chip->chip_type == MAX17047)
39e7213ed   Jonghwa Lee   max17042_battery:...
365
  		regmap_write(map, MAX17047_FullSOCThr,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
366
  						config->full_soc_thresh);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
367
368
369
370
371
  }
  
  static void  max17042_write_custom_regs(struct max17042_chip *chip)
  {
  	struct max17042_config_data *config = chip->pdata->config_data;
39e7213ed   Jonghwa Lee   max17042_battery:...
372
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
373

39e7213ed   Jonghwa Lee   max17042_battery:...
374
375
376
  	max17042_write_verify_reg(map, MAX17042_RCOMP0, config->rcomp0);
  	max17042_write_verify_reg(map, MAX17042_TempCo,	config->tcompc0);
  	max17042_write_verify_reg(map, MAX17042_ICHGTerm, config->ichgt_term);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
377
  	if (chip->chip_type == MAX17042) {
39e7213ed   Jonghwa Lee   max17042_battery:...
378
379
  		regmap_write(map, MAX17042_EmptyTempCo,	config->empty_tempco);
  		max17042_write_verify_reg(map, MAX17042_K_empty0,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
380
381
  					config->kempty0);
  	} else {
39e7213ed   Jonghwa Lee   max17042_battery:...
382
  		max17042_write_verify_reg(map, MAX17047_QRTbl00,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
383
  						config->qrtbl00);
39e7213ed   Jonghwa Lee   max17042_battery:...
384
  		max17042_write_verify_reg(map, MAX17047_QRTbl10,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
385
  						config->qrtbl10);
39e7213ed   Jonghwa Lee   max17042_battery:...
386
  		max17042_write_verify_reg(map, MAX17047_QRTbl20,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
387
  						config->qrtbl20);
39e7213ed   Jonghwa Lee   max17042_battery:...
388
  		max17042_write_verify_reg(map, MAX17047_QRTbl30,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
389
390
  						config->qrtbl30);
  	}
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
391
392
393
394
395
  }
  
  static void max17042_update_capacity_regs(struct max17042_chip *chip)
  {
  	struct max17042_config_data *config = chip->pdata->config_data;
39e7213ed   Jonghwa Lee   max17042_battery:...
396
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
397

39e7213ed   Jonghwa Lee   max17042_battery:...
398
  	max17042_write_verify_reg(map, MAX17042_FullCAP,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
399
  				config->fullcap);
39e7213ed   Jonghwa Lee   max17042_battery:...
400
401
  	regmap_write(map, MAX17042_DesignCap, config->design_cap);
  	max17042_write_verify_reg(map, MAX17042_FullCAPNom,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
402
403
404
405
406
  				config->fullcapnom);
  }
  
  static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
407
408
  	unsigned int vfSoc;
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
409

39e7213ed   Jonghwa Lee   max17042_battery:...
410
411
412
413
  	regmap_read(map, MAX17042_VFSOC, &vfSoc);
  	regmap_write(map, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK);
  	max17042_write_verify_reg(map, MAX17042_VFSOC0, vfSoc);
  	regmap_write(map, MAX17042_VFSOC0Enable, VFSOC0_LOCK);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
414
415
416
417
  }
  
  static void max17042_load_new_capacity_params(struct max17042_chip *chip)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
418
  	u32 full_cap0, rep_cap, dq_acc, vfSoc;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
419
420
421
  	u32 rem_cap;
  
  	struct max17042_config_data *config = chip->pdata->config_data;
39e7213ed   Jonghwa Lee   max17042_battery:...
422
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
423

39e7213ed   Jonghwa Lee   max17042_battery:...
424
425
  	regmap_read(map, MAX17042_FullCAP0, &full_cap0);
  	regmap_read(map, MAX17042_VFSOC, &vfSoc);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
426
427
428
429
430
431
  
  	/* fg_vfSoc needs to shifted by 8 bits to get the
  	 * perc in 1% accuracy, to get the right rem_cap multiply
  	 * full_cap0, fg_vfSoc and devide by 100
  	 */
  	rem_cap = ((vfSoc >> 8) * full_cap0) / 100;
39e7213ed   Jonghwa Lee   max17042_battery:...
432
  	max17042_write_verify_reg(map, MAX17042_RemCap, rem_cap);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
433

39e7213ed   Jonghwa Lee   max17042_battery:...
434
435
  	rep_cap = rem_cap;
  	max17042_write_verify_reg(map, MAX17042_RepCap, rep_cap);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
436
437
438
  
  	/* Write dQ_acc to 200% of Capacity and dP_acc to 200% */
  	dq_acc = config->fullcap / dQ_ACC_DIV;
39e7213ed   Jonghwa Lee   max17042_battery:...
439
440
  	max17042_write_verify_reg(map, MAX17042_dQacc, dq_acc);
  	max17042_write_verify_reg(map, MAX17042_dPacc, dP_ACC_200);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
441

39e7213ed   Jonghwa Lee   max17042_battery:...
442
  	max17042_write_verify_reg(map, MAX17042_FullCAP,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
443
  			config->fullcap);
39e7213ed   Jonghwa Lee   max17042_battery:...
444
  	regmap_write(map, MAX17042_DesignCap,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
445
  			config->design_cap);
39e7213ed   Jonghwa Lee   max17042_battery:...
446
  	max17042_write_verify_reg(map, MAX17042_FullCAPNom,
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
447
  			config->fullcapnom);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
448
  	/* Update SOC register with new SOC */
39e7213ed   Jonghwa Lee   max17042_battery:...
449
  	regmap_write(map, MAX17042_RepSOC, vfSoc);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
450
451
452
453
454
455
456
457
458
  }
  
  /*
   * Block write all the override values coming from platform data.
   * This function MUST be called before the POR initialization proceedure
   * specified by maxim.
   */
  static inline void max17042_override_por_values(struct max17042_chip *chip)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
459
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
460
  	struct max17042_config_data *config = chip->pdata->config_data;
39e7213ed   Jonghwa Lee   max17042_battery:...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  	max17042_override_por(map, MAX17042_TGAIN, config->tgain);
  	max17042_override_por(map, MAx17042_TOFF, config->toff);
  	max17042_override_por(map, MAX17042_CGAIN, config->cgain);
  	max17042_override_por(map, MAX17042_COFF, config->coff);
  
  	max17042_override_por(map, MAX17042_VALRT_Th, config->valrt_thresh);
  	max17042_override_por(map, MAX17042_TALRT_Th, config->talrt_thresh);
  	max17042_override_por(map, MAX17042_SALRT_Th,
  						config->soc_alrt_thresh);
  	max17042_override_por(map, MAX17042_CONFIG, config->config);
  	max17042_override_por(map, MAX17042_SHDNTIMER, config->shdntimer);
  
  	max17042_override_por(map, MAX17042_DesignCap, config->design_cap);
  	max17042_override_por(map, MAX17042_ICHGTerm, config->ichgt_term);
  
  	max17042_override_por(map, MAX17042_AtRate, config->at_rate);
  	max17042_override_por(map, MAX17042_LearnCFG, config->learn_cfg);
  	max17042_override_por(map, MAX17042_FilterCFG, config->filter_cfg);
  	max17042_override_por(map, MAX17042_RelaxCFG, config->relax_cfg);
  	max17042_override_por(map, MAX17042_MiscCFG, config->misc_cfg);
  	max17042_override_por(map, MAX17042_MaskSOC, config->masksoc);
  
  	max17042_override_por(map, MAX17042_FullCAP, config->fullcap);
  	max17042_override_por(map, MAX17042_FullCAPNom, config->fullcapnom);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
485
  	if (chip->chip_type == MAX17042)
39e7213ed   Jonghwa Lee   max17042_battery:...
486
  		max17042_override_por(map, MAX17042_SOC_empty,
9a8422d20   Ramakrishna Pallala   max17042_battery:...
487
  						config->socempty);
39e7213ed   Jonghwa Lee   max17042_battery:...
488
489
490
  	max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty);
  	max17042_override_por(map, MAX17042_dQacc, config->dqacc);
  	max17042_override_por(map, MAX17042_dPacc, config->dpacc);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
491

9a8422d20   Ramakrishna Pallala   max17042_battery:...
492
  	if (chip->chip_type == MAX17042)
39e7213ed   Jonghwa Lee   max17042_battery:...
493
  		max17042_override_por(map, MAX17042_V_empty, config->vempty);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
494
  	else
39e7213ed   Jonghwa Lee   max17042_battery:...
495
496
497
498
499
500
  		max17042_override_por(map, MAX17047_V_empty, config->vempty);
  	max17042_override_por(map, MAX17042_TempNom, config->temp_nom);
  	max17042_override_por(map, MAX17042_TempLim, config->temp_lim);
  	max17042_override_por(map, MAX17042_FCTC, config->fctc);
  	max17042_override_por(map, MAX17042_RCOMP0, config->rcomp0);
  	max17042_override_por(map, MAX17042_TempCo, config->tcompc0);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
501
  	if (chip->chip_type) {
39e7213ed   Jonghwa Lee   max17042_battery:...
502
503
504
505
  		max17042_override_por(map, MAX17042_EmptyTempCo,
  						config->empty_tempco);
  		max17042_override_por(map, MAX17042_K_empty0,
  						config->kempty0);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
506
  	}
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
507
508
509
510
  }
  
  static int max17042_init_chip(struct max17042_chip *chip)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
511
  	struct regmap *map = chip->regmap;
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
  	int ret;
  	int val;
  
  	max17042_override_por_values(chip);
  	/* After Power up, the MAX17042 requires 500mS in order
  	 * to perform signal debouncing and initial SOC reporting
  	 */
  	msleep(500);
  
  	/* Initialize configaration */
  	max17042_write_config_regs(chip);
  
  	/* write cell characterization data */
  	ret = max17042_init_model(chip);
  	if (ret) {
  		dev_err(&chip->client->dev, "%s init failed
  ",
  			__func__);
  		return -EIO;
  	}
a879f19fe   Alan Cox   max17042_battery:...
532
533
  
  	ret = max17042_verify_model_lock(chip);
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
  	if (ret) {
  		dev_err(&chip->client->dev, "%s lock verify failed
  ",
  			__func__);
  		return -EIO;
  	}
  	/* write custom parameters */
  	max17042_write_custom_regs(chip);
  
  	/* update capacity params */
  	max17042_update_capacity_regs(chip);
  
  	/* delay must be atleast 350mS to allow VFSOC
  	 * to be calculated from the new configuration
  	 */
  	msleep(350);
  
  	/* reset vfsoc0 reg */
  	max17042_reset_vfsoc0_reg(chip);
  
  	/* load new capacity params */
  	max17042_load_new_capacity_params(chip);
  
  	/* Init complete, Clear the POR bit */
39e7213ed   Jonghwa Lee   max17042_battery:...
558
559
  	regmap_read(map, MAX17042_STATUS, &val);
  	regmap_write(map, MAX17042_STATUS, val & (~STATUS_POR_BIT));
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
560
561
  	return 0;
  }
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
562
563
  static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
  {
39e7213ed   Jonghwa Lee   max17042_battery:...
564
565
  	struct regmap *map = chip->regmap;
  	u32 soc, soc_tr;
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
566
567
568
569
  
  	/* program interrupt thesholds such that we should
  	 * get interrupt for every 'off' perc change in the soc
  	 */
39e7213ed   Jonghwa Lee   max17042_battery:...
570
571
  	regmap_read(map, MAX17042_RepSOC, &soc);
  	soc >>= 8;
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
572
573
  	soc_tr = (soc + off) << 8;
  	soc_tr |= (soc - off);
39e7213ed   Jonghwa Lee   max17042_battery:...
574
  	regmap_write(map, MAX17042_SALRT_Th, soc_tr);
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
575
  }
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
576
577
578
  static irqreturn_t max17042_thread_handler(int id, void *dev)
  {
  	struct max17042_chip *chip = dev;
39e7213ed   Jonghwa Lee   max17042_battery:...
579
  	u32 val;
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
580

39e7213ed   Jonghwa Lee   max17042_battery:...
581
  	regmap_read(chip->regmap, MAX17042_STATUS, &val);
5cdd4d7fa   Ramakrishna Pallala   max17042_battery:...
582
583
  	if ((val & STATUS_INTR_SOCMIN_BIT) ||
  		(val & STATUS_INTR_SOCMAX_BIT)) {
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
584
585
586
587
588
589
590
591
  		dev_info(&chip->client->dev, "SOC threshold INTR
  ");
  		max17042_set_soc_threshold(chip, 1);
  	}
  
  	power_supply_changed(&chip->battery);
  	return IRQ_HANDLED;
  }
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  
  static void max17042_init_worker(struct work_struct *work)
  {
  	struct max17042_chip *chip = container_of(work,
  				struct max17042_chip, work);
  	int ret;
  
  	/* Initialize registers according to values from the platform data */
  	if (chip->pdata->enable_por_init && chip->pdata->config_data) {
  		ret = max17042_init_chip(chip);
  		if (ret)
  			return;
  	}
  
  	chip->init_complete = 1;
  }
3832246dd   Karol Lewandowski   max17042_battery:...
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  #ifdef CONFIG_OF
  static struct max17042_platform_data *
  max17042_get_pdata(struct device *dev)
  {
  	struct device_node *np = dev->of_node;
  	u32 prop;
  	struct max17042_platform_data *pdata;
  
  	if (!np)
  		return dev->platform_data;
  
  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  	if (!pdata)
  		return NULL;
  
  	/*
  	 * Require current sense resistor value to be specified for
  	 * current-sense functionality to be enabled at all.
  	 */
  	if (of_property_read_u32(np, "maxim,rsns-microohm", &prop) == 0) {
  		pdata->r_sns = prop;
  		pdata->enable_current_sense = true;
  	}
  
  	return pdata;
  }
  #else
  static struct max17042_platform_data *
  max17042_get_pdata(struct device *dev)
  {
  	return dev->platform_data;
  }
  #endif
39e7213ed   Jonghwa Lee   max17042_battery:...
641
642
643
644
645
  static struct regmap_config max17042_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 16,
  	.val_format_endian = REGMAP_ENDIAN_NATIVE,
  };
c8afa6406   Bill Pemberton   power: remove use...
646
  static int max17042_probe(struct i2c_client *client,
359ab9f5b   MyungJoo Ham   power_supply: Add...
647
648
649
650
651
  			const struct i2c_device_id *id)
  {
  	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
  	struct max17042_chip *chip;
  	int ret;
39e7213ed   Jonghwa Lee   max17042_battery:...
652
653
  	int i;
  	u32 val;
359ab9f5b   MyungJoo Ham   power_supply: Add...
654
655
656
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
  		return -EIO;
2f3b43423   Karol Lewandowski   max17042_battery:...
657
  	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
359ab9f5b   MyungJoo Ham   power_supply: Add...
658
659
660
661
  	if (!chip)
  		return -ENOMEM;
  
  	chip->client = client;
39e7213ed   Jonghwa Lee   max17042_battery:...
662
663
664
665
666
667
  	chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
  	if (IS_ERR(chip->regmap)) {
  		dev_err(&client->dev, "Failed to initialize regmap
  ");
  		return -EINVAL;
  	}
3832246dd   Karol Lewandowski   max17042_battery:...
668
669
670
671
672
673
  	chip->pdata = max17042_get_pdata(&client->dev);
  	if (!chip->pdata) {
  		dev_err(&client->dev, "no platform data provided
  ");
  		return -EINVAL;
  	}
359ab9f5b   MyungJoo Ham   power_supply: Add...
674
675
  
  	i2c_set_clientdata(client, chip);
39e7213ed   Jonghwa Lee   max17042_battery:...
676
677
  	regmap_read(chip->regmap, MAX17042_DevName, &val);
  	if (val == MAX17042_IC_VERSION) {
9a8422d20   Ramakrishna Pallala   max17042_battery:...
678
679
680
  		dev_dbg(&client->dev, "chip type max17042 detected
  ");
  		chip->chip_type = MAX17042;
39e7213ed   Jonghwa Lee   max17042_battery:...
681
  	} else if (val == MAX17047_IC_VERSION) {
9a8422d20   Ramakrishna Pallala   max17042_battery:...
682
683
684
685
  		dev_dbg(&client->dev, "chip type max17047/50 detected
  ");
  		chip->chip_type = MAX17047;
  	} else {
39e7213ed   Jonghwa Lee   max17042_battery:...
686
687
  		dev_err(&client->dev, "device version mismatch: %x
  ", val);
9a8422d20   Ramakrishna Pallala   max17042_battery:...
688
689
690
691
  		return -EIO;
  	}
  
  	chip->battery.name		= "max170xx_battery";
359ab9f5b   MyungJoo Ham   power_supply: Add...
692
693
694
695
  	chip->battery.type		= POWER_SUPPLY_TYPE_BATTERY;
  	chip->battery.get_property	= max17042_get_property;
  	chip->battery.properties	= max17042_battery_props;
  	chip->battery.num_properties	= ARRAY_SIZE(max17042_battery_props);
086ef502c   Donggeun Kim   power_supply: MAX...
696
697
698
699
  	/* When current is not measured,
  	 * CURRENT_NOW and CURRENT_AVG properties should be invisible. */
  	if (!chip->pdata->enable_current_sense)
  		chip->battery.num_properties -= 2;
4cfa892c0   Philip Rakity   max17042_battery:...
700
701
  	if (chip->pdata->r_sns == 0)
  		chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
086ef502c   Donggeun Kim   power_supply: MAX...
702
  	if (chip->pdata->init_data)
39e7213ed   Jonghwa Lee   max17042_battery:...
703
704
705
706
  		for (i = 0; i < chip->pdata->num_init_data; i++)
  			regmap_write(chip->regmap,
  					chip->pdata->init_data[i].addr,
  					chip->pdata->init_data[i].data);
086ef502c   Donggeun Kim   power_supply: MAX...
707

359ab9f5b   MyungJoo Ham   power_supply: Add...
708
  	if (!chip->pdata->enable_current_sense) {
39e7213ed   Jonghwa Lee   max17042_battery:...
709
710
711
  		regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000);
  		regmap_write(chip->regmap, MAX17042_MiscCFG, 0x0003);
  		regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
359ab9f5b   MyungJoo Ham   power_supply: Add...
712
  	}
243e3527f   Ramakrishna Pallala   max17042_battery:...
713
714
715
716
717
718
  	ret = power_supply_register(&client->dev, &chip->battery);
  	if (ret) {
  		dev_err(&client->dev, "failed: power supply register
  ");
  		return ret;
  	}
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
719
  	if (client->irq) {
5cdd4d7fa   Ramakrishna Pallala   max17042_battery:...
720
  		ret = request_threaded_irq(client->irq, NULL,
26740dbb5   Jonghwa Lee   max17042_battery:...
721
722
723
  					max17042_thread_handler,
  					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  					chip->battery.name, chip);
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
724
  		if (!ret) {
39e7213ed   Jonghwa Lee   max17042_battery:...
725
726
727
  			regmap_read(chip->regmap, MAX17042_CONFIG, &val);
  			val |= CONFIG_ALRT_BIT_ENBL;
  			regmap_write(chip->regmap, MAX17042_CONFIG, val);
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
728
  			max17042_set_soc_threshold(chip, 1);
e5ba50bc3   Ramakrishna Pallala   max17042_battery:...
729
730
  		} else {
  			client->irq = 0;
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
731
732
733
  			dev_err(&client->dev, "%s(): cannot get IRQ
  ",
  				__func__);
e5ba50bc3   Ramakrishna Pallala   max17042_battery:...
734
  		}
e5f3872d2   Ramakrishna Pallala   max17042: Add sup...
735
  	}
39e7213ed   Jonghwa Lee   max17042_battery:...
736
737
  	regmap_read(chip->regmap, MAX17042_STATUS, &val);
  	if (val & STATUS_POR_BIT) {
f3a71a6eb   Ramakrishna Pallala   max17042: Add POR...
738
739
740
741
742
  		INIT_WORK(&chip->work, max17042_init_worker);
  		schedule_work(&chip->work);
  	} else {
  		chip->init_complete = 1;
  	}
243e3527f   Ramakrishna Pallala   max17042_battery:...
743
  	return 0;
359ab9f5b   MyungJoo Ham   power_supply: Add...
744
  }
415ec69fb   Bill Pemberton   power: remove use...
745
  static int max17042_remove(struct i2c_client *client)
359ab9f5b   MyungJoo Ham   power_supply: Add...
746
747
  {
  	struct max17042_chip *chip = i2c_get_clientdata(client);
bb28da90f   Ramakrishna Pallala   max17042_battery:...
748
749
  	if (client->irq)
  		free_irq(client->irq, chip);
359ab9f5b   MyungJoo Ham   power_supply: Add...
750
  	power_supply_unregister(&chip->battery);
359ab9f5b   MyungJoo Ham   power_supply: Add...
751
752
  	return 0;
  }
3d23c7f45   Manish Badarkhe   max17042_battery:...
753
  #ifdef CONFIG_PM_SLEEP
48bc17744   Ramakrishna Pallala   max17042_battery:...
754
755
756
  static int max17042_suspend(struct device *dev)
  {
  	struct max17042_chip *chip = dev_get_drvdata(dev);
48e41c70c   Anton Vorontsov   max17042_battery:...
757
758
  	/*
  	 * disable the irq and enable irq_wake
48bc17744   Ramakrishna Pallala   max17042_battery:...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
  	 * capability to the interrupt line.
  	 */
  	if (chip->client->irq) {
  		disable_irq(chip->client->irq);
  		enable_irq_wake(chip->client->irq);
  	}
  
  	return 0;
  }
  
  static int max17042_resume(struct device *dev)
  {
  	struct max17042_chip *chip = dev_get_drvdata(dev);
  
  	if (chip->client->irq) {
  		disable_irq_wake(chip->client->irq);
  		enable_irq(chip->client->irq);
  		/* re-program the SOC thresholds to 1% change */
  		max17042_set_soc_threshold(chip, 1);
  	}
  
  	return 0;
  }
48bc17744   Ramakrishna Pallala   max17042_battery:...
782
  #endif
3d23c7f45   Manish Badarkhe   max17042_battery:...
783
784
  static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
  			max17042_resume);
3832246dd   Karol Lewandowski   max17042_battery:...
785
786
787
  #ifdef CONFIG_OF
  static const struct of_device_id max17042_dt_match[] = {
  	{ .compatible = "maxim,max17042" },
9a8422d20   Ramakrishna Pallala   max17042_battery:...
788
789
  	{ .compatible = "maxim,max17047" },
  	{ .compatible = "maxim,max17050" },
3832246dd   Karol Lewandowski   max17042_battery:...
790
791
792
793
  	{ },
  };
  MODULE_DEVICE_TABLE(of, max17042_dt_match);
  #endif
359ab9f5b   MyungJoo Ham   power_supply: Add...
794
795
  static const struct i2c_device_id max17042_id[] = {
  	{ "max17042", 0 },
9a8422d20   Ramakrishna Pallala   max17042_battery:...
796
797
  	{ "max17047", 1 },
  	{ "max17050", 2 },
359ab9f5b   MyungJoo Ham   power_supply: Add...
798
799
800
801
802
803
804
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, max17042_id);
  
  static struct i2c_driver max17042_i2c_driver = {
  	.driver	= {
  		.name	= "max17042",
3832246dd   Karol Lewandowski   max17042_battery:...
805
  		.of_match_table = of_match_ptr(max17042_dt_match),
3d23c7f45   Manish Badarkhe   max17042_battery:...
806
  		.pm	= &max17042_pm_ops,
359ab9f5b   MyungJoo Ham   power_supply: Add...
807
808
  	},
  	.probe		= max17042_probe,
28ea73f4c   Bill Pemberton   power: remove use...
809
  	.remove		= max17042_remove,
359ab9f5b   MyungJoo Ham   power_supply: Add...
810
811
  	.id_table	= max17042_id,
  };
5ff92e7ab   Axel Lin   power_supply: Con...
812
  module_i2c_driver(max17042_i2c_driver);
359ab9f5b   MyungJoo Ham   power_supply: Add...
813
814
815
816
  
  MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
  MODULE_DESCRIPTION("MAX17042 Fuel Gauge");
  MODULE_LICENSE("GPL");