diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/power/max17048_battery.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/power/max17048_battery.c')
-rw-r--r-- | drivers/power/max17048_battery.c | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/drivers/power/max17048_battery.c b/drivers/power/max17048_battery.c new file mode 100644 index 00000000000..44275e329c5 --- /dev/null +++ b/drivers/power/max17048_battery.c | |||
@@ -0,0 +1,579 @@ | |||
1 | /* | ||
2 | * max17048_battery.c | ||
3 | * fuel-gauge systems for lithium-ion (Li+) batteries | ||
4 | * | ||
5 | * Copyright (C) 2012 Nvidia Cooperation | ||
6 | * Chandler Zhang <chazhang@nvidia.com> | ||
7 | * Syed Rafiuddin <srafiuddin@nvidia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <asm/unaligned.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/power_supply.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/max17048_battery.h> | ||
25 | |||
26 | #define MAX17048_VCELL 0x02 | ||
27 | #define MAX17048_SOC 0x04 | ||
28 | #define MAX17048_VER 0x08 | ||
29 | #define MAX17048_HIBRT 0x0A | ||
30 | #define MAX17048_CONFIG 0x0C | ||
31 | #define MAX17048_OCV 0x0E | ||
32 | #define MAX17048_VLRT 0x14 | ||
33 | #define MAX17048_VRESET 0x18 | ||
34 | #define MAX17048_STATUS 0x1A | ||
35 | #define MAX17048_UNLOCK 0x3E | ||
36 | #define MAX17048_TABLE 0x40 | ||
37 | #define MAX17048_RCOMPSEG1 0x80 | ||
38 | #define MAX17048_RCOMPSEG2 0x90 | ||
39 | #define MAX17048_CMD 0xFF | ||
40 | #define MAX17048_UNLOCK_VALUE 0x4a57 | ||
41 | #define MAX17048_RESET_VALUE 0x5400 | ||
42 | #define MAX17048_DELAY 1000 | ||
43 | #define MAX17048_BATTERY_FULL 95 | ||
44 | #define MAX17048_VERSION_NO 0x11 | ||
45 | |||
46 | struct max17048_chip { | ||
47 | struct i2c_client *client; | ||
48 | struct delayed_work work; | ||
49 | struct power_supply battery; | ||
50 | struct power_supply ac; | ||
51 | struct power_supply usb; | ||
52 | struct max17048_battery_model *model_data; | ||
53 | |||
54 | /* State Of Connect */ | ||
55 | int ac_online; | ||
56 | int usb_online; | ||
57 | /* battery voltage */ | ||
58 | int vcell; | ||
59 | /* battery capacity */ | ||
60 | int soc; | ||
61 | /* State Of Charge */ | ||
62 | int status; | ||
63 | |||
64 | int lasttime_vcell; | ||
65 | int lasttime_soc; | ||
66 | int lasttime_status; | ||
67 | }; | ||
68 | |||
69 | uint8_t max17048_custom_data[] = { | ||
70 | 0xAA, 0x00, 0xB1, 0xF0, 0xB7, 0xE0, 0xB9, 0x60, 0xBB, 0x80, | ||
71 | 0xBC, 0x40, 0xBD, 0x30, 0xBD, 0x50, 0xBD, 0xF0, 0xBE, 0x40, | ||
72 | 0xBF, 0xD0, 0xC0, 0x90, 0xC4, 0x30, 0xC7, 0xC0, 0xCA, 0x60, | ||
73 | 0xCF, 0x30, 0x01, 0x20, 0x09, 0xC0, 0x1F, 0xC0, 0x2B, 0xE0, | ||
74 | 0x4F, 0xC0, 0x30, 0x00, 0x47, 0x80, 0x4F, 0xE0, 0x77, 0x00, | ||
75 | 0x15, 0x60, 0x46, 0x20, 0x13, 0x80, 0x1A, 0x60, 0x12, 0x20, | ||
76 | 0x14, 0xA0, 0x14, 0xA0}; | ||
77 | |||
78 | static int max17048_write_word(struct i2c_client *client, int reg, u16 value) | ||
79 | { | ||
80 | int ret; | ||
81 | |||
82 | ret = i2c_smbus_write_word_data(client, reg, swab16(value)); | ||
83 | |||
84 | if (ret < 0) | ||
85 | dev_err(&client->dev, "%s(): Failed in writing register" | ||
86 | "0x%02x err %d\n", __func__, reg, ret); | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static uint16_t max17048_read_word(struct i2c_client *client, int reg) | ||
92 | { | ||
93 | uint16_t ret; | ||
94 | |||
95 | ret = i2c_smbus_read_word_data(client, reg); | ||
96 | |||
97 | if (ret < 0) | ||
98 | dev_err(&client->dev, "%s(): Failed in reading register" | ||
99 | "0x%02x err %d\n", __func__, reg, ret); | ||
100 | |||
101 | return swab16(ret); | ||
102 | } | ||
103 | |||
104 | static int max17048_get_property(struct power_supply *psy, | ||
105 | enum power_supply_property psp, | ||
106 | union power_supply_propval *val) | ||
107 | { | ||
108 | struct max17048_chip *chip = container_of(psy, | ||
109 | struct max17048_chip, battery); | ||
110 | |||
111 | switch (psp) { | ||
112 | case POWER_SUPPLY_PROP_STATUS: | ||
113 | val->intval = chip->status; | ||
114 | break; | ||
115 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
116 | val->intval = chip->vcell; | ||
117 | break; | ||
118 | case POWER_SUPPLY_PROP_CAPACITY: | ||
119 | val->intval = chip->soc; | ||
120 | break; | ||
121 | default: | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int max17048_ac_get_property(struct power_supply *psy, | ||
128 | enum power_supply_property psp, | ||
129 | union power_supply_propval *val) | ||
130 | { | ||
131 | struct max17048_chip *chip = container_of(psy, | ||
132 | struct max17048_chip, ac); | ||
133 | |||
134 | if (psp == POWER_SUPPLY_PROP_ONLINE) | ||
135 | val->intval = chip->ac_online; | ||
136 | else | ||
137 | return -EINVAL; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int max17048_usb_get_property(struct power_supply *psy, | ||
143 | enum power_supply_property psp, | ||
144 | union power_supply_propval *val) | ||
145 | { | ||
146 | struct max17048_chip *chip = container_of(psy, | ||
147 | struct max17048_chip, usb); | ||
148 | |||
149 | if (psp == POWER_SUPPLY_PROP_ONLINE) | ||
150 | val->intval = chip->usb_online; | ||
151 | else | ||
152 | return -EINVAL; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static void max17048_get_vcell(struct i2c_client *client) | ||
158 | { | ||
159 | struct max17048_chip *chip = i2c_get_clientdata(client); | ||
160 | uint16_t vcell; | ||
161 | |||
162 | vcell = max17048_read_word(client, MAX17048_VCELL); | ||
163 | if (vcell < 0) | ||
164 | dev_err(&client->dev, "%s: err %d\n", __func__, vcell); | ||
165 | |||
166 | chip->vcell = vcell; | ||
167 | } | ||
168 | |||
169 | static void max17048_get_soc(struct i2c_client *client) | ||
170 | { | ||
171 | struct max17048_chip *chip = i2c_get_clientdata(client); | ||
172 | uint16_t soc; | ||
173 | |||
174 | soc = max17048_read_word(client, MAX17048_SOC); | ||
175 | if (soc < 0) | ||
176 | dev_err(&client->dev, "%s: err %d\n", __func__, soc); | ||
177 | |||
178 | chip->soc = soc >> 9; | ||
179 | } | ||
180 | |||
181 | static uint16_t max17048_get_version(struct i2c_client *client) | ||
182 | { | ||
183 | return swab16(i2c_smbus_read_word_data(client, MAX17048_VER)); | ||
184 | } | ||
185 | |||
186 | static void max17048_work(struct work_struct *work) | ||
187 | { | ||
188 | struct max17048_chip *chip; | ||
189 | |||
190 | chip = container_of(work, struct max17048_chip, work.work); | ||
191 | |||
192 | max17048_get_vcell(chip->client); | ||
193 | max17048_get_soc(chip->client); | ||
194 | |||
195 | if (chip->vcell != chip->lasttime_vcell || | ||
196 | chip->soc != chip->lasttime_soc || | ||
197 | chip->status != chip->lasttime_status) { | ||
198 | |||
199 | chip->lasttime_vcell = chip->vcell; | ||
200 | chip->lasttime_soc = chip->soc; | ||
201 | |||
202 | power_supply_changed(&chip->battery); | ||
203 | } | ||
204 | schedule_delayed_work(&chip->work, MAX17048_DELAY); | ||
205 | } | ||
206 | |||
207 | static void max17048_battery_status(enum charging_states status, | ||
208 | enum charger_type chrg_type, void *data) | ||
209 | { | ||
210 | struct max17048_chip *chip = data; | ||
211 | |||
212 | chip->ac_online = 0; | ||
213 | chip->usb_online = 0; | ||
214 | |||
215 | if (chrg_type == AC) | ||
216 | chip->ac_online = 1; | ||
217 | else if (chrg_type == USB) | ||
218 | chip->usb_online = 1; | ||
219 | |||
220 | if (status == progress) | ||
221 | chip->status = POWER_SUPPLY_STATUS_CHARGING; | ||
222 | else | ||
223 | chip->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
224 | |||
225 | if (chip->soc > MAX17048_BATTERY_FULL) | ||
226 | chip->status = POWER_SUPPLY_STATUS_FULL; | ||
227 | |||
228 | power_supply_changed(&chip->battery); | ||
229 | power_supply_changed(&chip->usb); | ||
230 | power_supply_changed(&chip->ac); | ||
231 | } | ||
232 | |||
233 | static enum power_supply_property max17048_battery_props[] = { | ||
234 | POWER_SUPPLY_PROP_STATUS, | ||
235 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
236 | POWER_SUPPLY_PROP_CAPACITY, | ||
237 | }; | ||
238 | |||
239 | static enum power_supply_property max17048_ac_props[] = { | ||
240 | POWER_SUPPLY_PROP_ONLINE, | ||
241 | }; | ||
242 | |||
243 | static enum power_supply_property max17048_usb_props[] = { | ||
244 | POWER_SUPPLY_PROP_ONLINE, | ||
245 | }; | ||
246 | |||
247 | static int max17048_write_rcomp_seg(struct i2c_client *client, | ||
248 | uint16_t rcomp_seg) | ||
249 | { | ||
250 | uint8_t rs1, rs2; | ||
251 | int ret; | ||
252 | |||
253 | rs2 = rcomp_seg | 0x00FF; | ||
254 | rs1 = rcomp_seg >> 8; | ||
255 | uint8_t rcomp_seg_table[16] = { rs1, rs2, rs1, rs2, | ||
256 | rs1, rs2, rs1, rs2, | ||
257 | rs1, rs2, rs1, rs2, | ||
258 | rs1, rs2, rs1, rs2}; | ||
259 | |||
260 | ret = i2c_smbus_write_i2c_block_data(client, MAX17048_RCOMPSEG1, | ||
261 | 16, (uint8_t *)rcomp_seg_table); | ||
262 | if (ret < 0) { | ||
263 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | ret = i2c_smbus_write_i2c_block_data(client, MAX17048_RCOMPSEG2, | ||
268 | 16, (uint8_t *)rcomp_seg_table); | ||
269 | if (ret < 0) { | ||
270 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int max17048_load_model_data(struct max17048_chip *chip) | ||
278 | { | ||
279 | struct i2c_client *client = chip->client; | ||
280 | struct max17048_battery_model *mdata = chip->model_data; | ||
281 | uint16_t soc_tst, ocv; | ||
282 | int i, ret = 0; | ||
283 | |||
284 | /* read OCV */ | ||
285 | ocv = max17048_read_word(client, MAX17048_OCV); | ||
286 | if (ocv == 0xffff) { | ||
287 | dev_err(&client->dev, "%s: Failed in unlocking" | ||
288 | "max17048 err: %d\n", __func__, ocv); | ||
289 | return -1; | ||
290 | } | ||
291 | |||
292 | /* write custom model data */ | ||
293 | for (i = 0; i < 4; i += 1) { | ||
294 | if (i2c_smbus_write_i2c_block_data(client, | ||
295 | (MAX17048_TABLE+i*16), 16, | ||
296 | &max17048_custom_data[i*0x10]) < 0) { | ||
297 | dev_err(&client->dev, "%s: error writing model data:\n", | ||
298 | __func__); | ||
299 | return -1; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | /* Write OCV Test value */ | ||
304 | ret = max17048_write_word(client, MAX17048_OCV, mdata->ocvtest); | ||
305 | if (ret < 0) | ||
306 | return ret; | ||
307 | |||
308 | ret = max17048_write_rcomp_seg(client, mdata->rcomp_seg); | ||
309 | if (ret < 0) | ||
310 | return ret; | ||
311 | |||
312 | /* Disable hibernate */ | ||
313 | ret = max17048_write_word(client, MAX17048_HIBRT, 0x0000); | ||
314 | if (ret < 0) | ||
315 | return ret; | ||
316 | |||
317 | /* Lock model access */ | ||
318 | ret = max17048_write_word(client, MAX17048_UNLOCK, 0x0000); | ||
319 | if (ret < 0) | ||
320 | return ret; | ||
321 | |||
322 | /* Delay between 150ms to 600ms */ | ||
323 | mdelay(200); | ||
324 | |||
325 | /* Read SOC Register and compare to expected result */ | ||
326 | soc_tst = max17048_read_word(client, MAX17048_SOC); | ||
327 | if (!((soc_tst >> 8) >= mdata->soccheck_A && | ||
328 | (soc_tst >> 8) <= mdata->soccheck_B)) { | ||
329 | dev_err(&client->dev, "%s: soc comparison failed %d\n", | ||
330 | __func__, ret); | ||
331 | return ret; | ||
332 | } else { | ||
333 | dev_info(&client->dev, "MAX17048 Custom data" | ||
334 | " loading successfull\n"); | ||
335 | } | ||
336 | |||
337 | /* unlock model access */ | ||
338 | ret = max17048_write_word(client, MAX17048_UNLOCK, | ||
339 | MAX17048_UNLOCK_VALUE); | ||
340 | if (ret < 0) | ||
341 | return ret; | ||
342 | |||
343 | /* Restore OCV */ | ||
344 | ret = max17048_write_word(client, MAX17048_OCV, ocv); | ||
345 | if (ret < 0) | ||
346 | return ret; | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static int max17048_initialize(struct max17048_chip *chip) | ||
352 | { | ||
353 | uint8_t ret, config, status; | ||
354 | uint16_t wrt_status; | ||
355 | struct i2c_client *client = chip->client; | ||
356 | struct max17048_battery_model *mdata = chip->model_data; | ||
357 | |||
358 | /* unlock model access */ | ||
359 | ret = max17048_write_word(client, MAX17048_UNLOCK, | ||
360 | MAX17048_UNLOCK_VALUE); | ||
361 | if (ret < 0) | ||
362 | return ret; | ||
363 | |||
364 | /* load model data */ | ||
365 | ret = max17048_load_model_data(chip); | ||
366 | if (ret < 0) { | ||
367 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | if (mdata->bits == 19) | ||
372 | config = 32 - (mdata->alert_threshold * 2); | ||
373 | else if (mdata->bits == 18) | ||
374 | config = 32 - mdata->alert_threshold; | ||
375 | |||
376 | config = mdata->one_percent_alerts | config; | ||
377 | |||
378 | ret = max17048_write_word(client, MAX17048_CONFIG, | ||
379 | ((mdata->rcomp << 8) | config)); | ||
380 | if (ret < 0) | ||
381 | return ret; | ||
382 | |||
383 | /* Voltage Alert configuration */ | ||
384 | ret = max17048_write_word(client, MAX17048_VLRT, mdata->valert); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | /* Hibernate configuration */ | ||
389 | ret = max17048_write_word(client, MAX17048_HIBRT, mdata->hibernate); | ||
390 | if (ret < 0) | ||
391 | return ret; | ||
392 | |||
393 | ret = max17048_write_word(client, MAX17048_VRESET, mdata->vreset); | ||
394 | if (ret < 0) | ||
395 | return ret; | ||
396 | |||
397 | /* clears the reset indicator */ | ||
398 | ret = max17048_read_word(client, MAX17048_STATUS); | ||
399 | if (ret < 0) | ||
400 | return ret; | ||
401 | |||
402 | /* Sets the EnVR bit if selected */ | ||
403 | status = (ret & 0xFE) | mdata->alert_on_reset; | ||
404 | wrt_status = status << 8; | ||
405 | |||
406 | ret = max17048_write_word(client, MAX17048_STATUS, wrt_status); | ||
407 | if (ret < 0) | ||
408 | return ret; | ||
409 | |||
410 | /* Lock model access */ | ||
411 | ret = max17048_write_word(client, MAX17048_UNLOCK, 0x0000); | ||
412 | if (ret < 0) | ||
413 | return ret; | ||
414 | |||
415 | /* Add delay */ | ||
416 | mdelay(200); | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int __devinit max17048_probe(struct i2c_client *client, | ||
421 | const struct i2c_device_id *id) | ||
422 | { | ||
423 | struct max17048_chip *chip; | ||
424 | int ret; | ||
425 | uint16_t version; | ||
426 | |||
427 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
428 | if (!chip) | ||
429 | return -ENOMEM; | ||
430 | |||
431 | chip->client = client; | ||
432 | chip->model_data = client->dev.platform_data; | ||
433 | chip->ac_online = 0; | ||
434 | chip->usb_online = 0; | ||
435 | |||
436 | i2c_set_clientdata(client, chip); | ||
437 | |||
438 | version = max17048_get_version(client); | ||
439 | if (version != MAX17048_VERSION_NO) { | ||
440 | ret = -ENODEV; | ||
441 | goto error2; | ||
442 | } | ||
443 | dev_info(&client->dev, "MAX17048 Fuel-Gauge Ver 0x%x\n", version); | ||
444 | |||
445 | ret = max17048_initialize(chip); | ||
446 | if (ret < 0) { | ||
447 | dev_err(&client->dev, "Error: Initializing fuel-gauge\n"); | ||
448 | goto error2; | ||
449 | } | ||
450 | |||
451 | ret = register_callback(max17048_battery_status, chip); | ||
452 | if (ret < 0) | ||
453 | goto error2; | ||
454 | |||
455 | chip->battery.name = "battery"; | ||
456 | chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
457 | chip->battery.get_property = max17048_get_property; | ||
458 | chip->battery.properties = max17048_battery_props; | ||
459 | chip->battery.num_properties = ARRAY_SIZE(max17048_battery_props); | ||
460 | |||
461 | ret = power_supply_register(&client->dev, &chip->battery); | ||
462 | if (ret) { | ||
463 | dev_err(&client->dev, "failed: power supply register\n"); | ||
464 | goto error2; | ||
465 | } | ||
466 | |||
467 | chip->ac.name = "maxim-ac"; | ||
468 | chip->ac.type = POWER_SUPPLY_TYPE_MAINS; | ||
469 | chip->ac.get_property = max17048_ac_get_property; | ||
470 | chip->ac.properties = max17048_ac_props; | ||
471 | chip->ac.num_properties = ARRAY_SIZE(max17048_ac_props); | ||
472 | |||
473 | ret = power_supply_register(&client->dev, &chip->ac); | ||
474 | if (ret) { | ||
475 | dev_err(&client->dev, "failed: power supply register\n"); | ||
476 | goto error1; | ||
477 | } | ||
478 | |||
479 | chip->usb.name = "maxim-usb"; | ||
480 | chip->usb.type = POWER_SUPPLY_TYPE_USB; | ||
481 | chip->usb.get_property = max17048_usb_get_property; | ||
482 | chip->usb.properties = max17048_usb_props; | ||
483 | chip->usb.num_properties = ARRAY_SIZE(max17048_usb_props); | ||
484 | |||
485 | ret = power_supply_register(&client->dev, &chip->usb); | ||
486 | if (ret) { | ||
487 | dev_err(&client->dev, "failed: power supply register\n"); | ||
488 | goto error; | ||
489 | } | ||
490 | |||
491 | INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17048_work); | ||
492 | schedule_delayed_work(&chip->work, MAX17048_DELAY); | ||
493 | |||
494 | ret = update_charger_status(); | ||
495 | if (ret) { | ||
496 | dev_err(&client->dev, "failed: update_charger_status\n"); | ||
497 | goto error; | ||
498 | } | ||
499 | |||
500 | return 0; | ||
501 | error: | ||
502 | power_supply_unregister(&chip->ac); | ||
503 | error1: | ||
504 | power_supply_unregister(&chip->battery); | ||
505 | error2: | ||
506 | kfree(chip); | ||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | static int __devexit max17048_remove(struct i2c_client *client) | ||
511 | { | ||
512 | struct max17048_chip *chip = i2c_get_clientdata(client); | ||
513 | |||
514 | power_supply_unregister(&chip->battery); | ||
515 | power_supply_unregister(&chip->usb); | ||
516 | power_supply_unregister(&chip->ac); | ||
517 | cancel_delayed_work(&chip->work); | ||
518 | kfree(chip); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | #ifdef CONFIG_PM | ||
523 | |||
524 | static int max17048_suspend(struct i2c_client *client, | ||
525 | pm_message_t state) | ||
526 | { | ||
527 | struct max17048_chip *chip = i2c_get_clientdata(client); | ||
528 | |||
529 | cancel_delayed_work(&chip->work); | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static int max17048_resume(struct i2c_client *client) | ||
534 | { | ||
535 | struct max17048_chip *chip = i2c_get_clientdata(client); | ||
536 | |||
537 | schedule_delayed_work(&chip->work, MAX17048_DELAY); | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | #else | ||
542 | |||
543 | #define max17048_suspend NULL | ||
544 | #define max17048_resume NULL | ||
545 | |||
546 | #endif /* CONFIG_PM */ | ||
547 | |||
548 | static const struct i2c_device_id max17048_id[] = { | ||
549 | { "max17048", 0 }, | ||
550 | { } | ||
551 | }; | ||
552 | MODULE_DEVICE_TABLE(i2c, max17048_id); | ||
553 | |||
554 | static struct i2c_driver max17048_i2c_driver = { | ||
555 | .driver = { | ||
556 | .name = "max17048", | ||
557 | }, | ||
558 | .probe = max17048_probe, | ||
559 | .remove = __devexit_p(max17048_remove), | ||
560 | .suspend = max17048_suspend, | ||
561 | .resume = max17048_resume, | ||
562 | .id_table = max17048_id, | ||
563 | }; | ||
564 | |||
565 | static int __init max17048_init(void) | ||
566 | { | ||
567 | return i2c_add_driver(&max17048_i2c_driver); | ||
568 | } | ||
569 | module_init(max17048_init); | ||
570 | |||
571 | static void __exit max17048_exit(void) | ||
572 | { | ||
573 | i2c_del_driver(&max17048_i2c_driver); | ||
574 | } | ||
575 | module_exit(max17048_exit); | ||
576 | |||
577 | MODULE_AUTHOR("Chandler Zhang <chazhang@nvidia.com>"); | ||
578 | MODULE_DESCRIPTION("MAX17048 Fuel Gauge"); | ||
579 | MODULE_LICENSE("GPL"); | ||