aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/max17042_battery.c
diff options
context:
space:
mode:
authorRamakrishna Pallala <ramakrishna.pallala@intel.com>2012-03-13 14:03:52 -0400
committerAnton Vorontsov <anton.vorontsov@linaro.org>2012-03-26 12:37:35 -0400
commitf3a71a6eb13b71cc8a3dc5b6e5692e3db66b92f0 (patch)
tree8657e58127d2b72d97df5d4d89fdb6372fe02d67 /drivers/power/max17042_battery.c
parentf42c2b45b139b7b21c0c2eca70c82ce8d4104815 (diff)
max17042: Add POR init procedure from Maxim appnote
Add power on reset (POR) init procedure defined by the maxim appnote. Using this procedure ensures that the part is configured/initialized correctly at POR and improves early accuracy of the fuel gauge and informs the fuel gauge with the battery characterization parameters. The battery characterization parameters come from the maxim characterization procedure. Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Diffstat (limited to 'drivers/power/max17042_battery.c')
-rw-r--r--drivers/power/max17042_battery.c386
1 files changed, 376 insertions, 10 deletions
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 86acee2f9889..fde7ccd62953 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -26,14 +26,40 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/i2c.h> 28#include <linux/i2c.h>
29#include <linux/delay.h>
29#include <linux/mod_devicetable.h> 30#include <linux/mod_devicetable.h>
30#include <linux/power_supply.h> 31#include <linux/power_supply.h>
31#include <linux/power/max17042_battery.h> 32#include <linux/power/max17042_battery.h>
32 33
34/* Status register bits */
35#define STATUS_POR_BIT (1 << 1)
36#define STATUS_BST_BIT (1 << 3)
37#define STATUS_VMN_BIT (1 << 8)
38#define STATUS_TMN_BIT (1 << 9)
39#define STATUS_SMN_BIT (1 << 10)
40#define STATUS_BI_BIT (1 << 11)
41#define STATUS_VMX_BIT (1 << 12)
42#define STATUS_TMX_BIT (1 << 13)
43#define STATUS_SMX_BIT (1 << 14)
44#define STATUS_BR_BIT (1 << 15)
45
46#define VFSOC0_LOCK 0x0000
47#define VFSOC0_UNLOCK 0x0080
48#define MODEL_UNLOCK1 0X0059
49#define MODEL_UNLOCK2 0X00C4
50#define MODEL_LOCK1 0X0000
51#define MODEL_LOCK2 0X0000
52
53#define dQ_ACC_DIV 0x4
54#define dP_ACC_100 0x1900
55#define dP_ACC_200 0x3200
56
33struct max17042_chip { 57struct max17042_chip {
34 struct i2c_client *client; 58 struct i2c_client *client;
35 struct power_supply battery; 59 struct power_supply battery;
36 struct max17042_platform_data *pdata; 60 struct max17042_platform_data *pdata;
61 struct work_struct work;
62 int init_complete;
37}; 63};
38 64
39static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value) 65static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value)
@@ -87,6 +113,9 @@ static int max17042_get_property(struct power_supply *psy,
87 struct max17042_chip, battery); 113 struct max17042_chip, battery);
88 int ret; 114 int ret;
89 115
116 if (!chip->init_complete)
117 return -EAGAIN;
118
90 switch (psp) { 119 switch (psp) {
91 case POWER_SUPPLY_PROP_PRESENT: 120 case POWER_SUPPLY_PROP_PRESENT:
92 ret = max17042_read_reg(chip->client, MAX17042_STATUS); 121 ret = max17042_read_reg(chip->client, MAX17042_STATUS);
@@ -210,12 +239,343 @@ static int max17042_get_property(struct power_supply *psy,
210 return 0; 239 return 0;
211} 240}
212 241
242static int max17042_write_verify_reg(struct i2c_client *client,
243 u8 reg, u16 value)
244{
245 int retries = 8;
246 int ret;
247 u16 read_value;
248
249 do {
250 ret = i2c_smbus_write_word_data(client, reg, value);
251 read_value = max17042_read_reg(client, reg);
252 if (read_value != value) {
253 ret = -EIO;
254 retries--;
255 }
256 } while (retries && read_value != value);
257
258 if (ret < 0)
259 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
260
261 return ret;
262}
263
264static inline void max17042_override_por(
265 struct i2c_client *client, u8 reg, u16 value)
266{
267 if (value)
268 max17042_write_reg(client, reg, value);
269}
270
271static inline void max10742_unlock_model(struct max17042_chip *chip)
272{
273 struct i2c_client *client = chip->client;
274 max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
275 max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
276}
277
278static inline void max10742_lock_model(struct max17042_chip *chip)
279{
280 struct i2c_client *client = chip->client;
281 max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_LOCK1);
282 max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_LOCK2);
283}
284
285static inline void max17042_write_model_data(struct max17042_chip *chip,
286 u8 addr, int size)
287{
288 struct i2c_client *client = chip->client;
289 int i;
290 for (i = 0; i < size; i++)
291 max17042_write_reg(client, addr + i,
292 chip->pdata->config_data->cell_char_tbl[i]);
293}
294
295static inline void max17042_read_model_data(struct max17042_chip *chip,
296 u8 addr, u16 *data, int size)
297{
298 struct i2c_client *client = chip->client;
299 int i;
300
301 for (i = 0; i < size; i++)
302 data[i] = max17042_read_reg(client, addr + i);
303}
304
305static inline int max17042_model_data_compare(struct max17042_chip *chip,
306 u16 *data1, u16 *data2, int size)
307{
308 int i;
309
310 if (memcmp(data1, data2, size)) {
311 dev_err(&chip->client->dev, "%s compare failed\n", __func__);
312 for (i = 0; i < size; i++)
313 dev_info(&chip->client->dev, "0x%x, 0x%x",
314 data1[i], data2[i]);
315 dev_info(&chip->client->dev, "\n");
316 return -EINVAL;
317 }
318 return 0;
319}
320
321static int max17042_init_model(struct max17042_chip *chip)
322{
323 int ret;
324 int table_size =
325 sizeof(chip->pdata->config_data->cell_char_tbl)/sizeof(u16);
326 u16 *temp_data;
327
328 temp_data = kzalloc(table_size, GFP_KERNEL);
329 if (!temp_data)
330 return -ENOMEM;
331
332 max10742_unlock_model(chip);
333 max17042_write_model_data(chip, MAX17042_MODELChrTbl,
334 table_size);
335 max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data,
336 table_size);
337
338 ret = max17042_model_data_compare(
339 chip,
340 chip->pdata->config_data->cell_char_tbl,
341 temp_data,
342 table_size);
343
344 max10742_lock_model(chip);
345 kfree(temp_data);
346
347 return ret;
348}
349
350static int max17042_verify_model_lock(struct max17042_chip *chip)
351{
352 int i;
353 int table_size =
354 sizeof(chip->pdata->config_data->cell_char_tbl);
355 u16 *temp_data;
356 int ret = 0;
357
358 temp_data = kzalloc(table_size, GFP_KERNEL);
359 if (!temp_data)
360 return -ENOMEM;
361
362 max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data,
363 table_size);
364 for (i = 0; i < table_size; i++)
365 if (temp_data[i])
366 ret = -EINVAL;
367
368 kfree(temp_data);
369 return ret;
370}
371
372static void max17042_write_config_regs(struct max17042_chip *chip)
373{
374 struct max17042_config_data *config = chip->pdata->config_data;
375
376 max17042_write_reg(chip->client, MAX17042_CONFIG, config->config);
377 max17042_write_reg(chip->client, MAX17042_LearnCFG, config->learn_cfg);
378 max17042_write_reg(chip->client, MAX17042_FilterCFG,
379 config->filter_cfg);
380 max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg);
381}
382
383static void max17042_write_custom_regs(struct max17042_chip *chip)
384{
385 struct max17042_config_data *config = chip->pdata->config_data;
386
387 max17042_write_verify_reg(chip->client, MAX17042_RCOMP0,
388 config->rcomp0);
389 max17042_write_verify_reg(chip->client, MAX17042_TempCo,
390 config->tcompc0);
391 max17042_write_reg(chip->client, MAX17042_EmptyTempCo,
392 config->empty_tempco);
393 max17042_write_verify_reg(chip->client, MAX17042_K_empty0,
394 config->kempty0);
395 max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm,
396 config->ichgt_term);
397}
398
399static void max17042_update_capacity_regs(struct max17042_chip *chip)
400{
401 struct max17042_config_data *config = chip->pdata->config_data;
402
403 max17042_write_verify_reg(chip->client, MAX17042_FullCAP,
404 config->fullcap);
405 max17042_write_reg(chip->client, MAX17042_DesignCap,
406 config->design_cap);
407 max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom,
408 config->fullcapnom);
409}
410
411static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip)
412{
413 u16 vfSoc;
414
415 vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC);
416 max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK);
417 max17042_write_verify_reg(chip->client, MAX17042_VFSOC0, vfSoc);
418 max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_LOCK);
419}
420
421static void max17042_load_new_capacity_params(struct max17042_chip *chip)
422{
423 u16 full_cap0, rep_cap, dq_acc, vfSoc;
424 u32 rem_cap;
425
426 struct max17042_config_data *config = chip->pdata->config_data;
427
428 full_cap0 = max17042_read_reg(chip->client, MAX17042_FullCAP0);
429 vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC);
430
431 /* fg_vfSoc needs to shifted by 8 bits to get the
432 * perc in 1% accuracy, to get the right rem_cap multiply
433 * full_cap0, fg_vfSoc and devide by 100
434 */
435 rem_cap = ((vfSoc >> 8) * full_cap0) / 100;
436 max17042_write_verify_reg(chip->client, MAX17042_RemCap, (u16)rem_cap);
437
438 rep_cap = (u16)rem_cap;
439 max17042_write_verify_reg(chip->client, MAX17042_RepCap, rep_cap);
440
441 /* Write dQ_acc to 200% of Capacity and dP_acc to 200% */
442 dq_acc = config->fullcap / dQ_ACC_DIV;
443 max17042_write_verify_reg(chip->client, MAX17042_dQacc, dq_acc);
444 max17042_write_verify_reg(chip->client, MAX17042_dPacc, dP_ACC_200);
445
446 max17042_write_verify_reg(chip->client, MAX17042_FullCAP,
447 config->fullcap);
448 max17042_write_reg(chip->client, MAX17042_DesignCap,
449 config->design_cap);
450 max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom,
451 config->fullcapnom);
452}
453
454/*
455 * Block write all the override values coming from platform data.
456 * This function MUST be called before the POR initialization proceedure
457 * specified by maxim.
458 */
459static inline void max17042_override_por_values(struct max17042_chip *chip)
460{
461 struct i2c_client *client = chip->client;
462 struct max17042_config_data *config = chip->pdata->config_data;
463
464 max17042_override_por(client, MAX17042_TGAIN, config->tgain);
465 max17042_override_por(client, MAx17042_TOFF, config->toff);
466 max17042_override_por(client, MAX17042_CGAIN, config->cgain);
467 max17042_override_por(client, MAX17042_COFF, config->coff);
468
469 max17042_override_por(client, MAX17042_VALRT_Th, config->valrt_thresh);
470 max17042_override_por(client, MAX17042_TALRT_Th, config->talrt_thresh);
471 max17042_override_por(client, MAX17042_SALRT_Th,
472 config->soc_alrt_thresh);
473 max17042_override_por(client, MAX17042_CONFIG, config->config);
474 max17042_override_por(client, MAX17042_SHDNTIMER, config->shdntimer);
475
476 max17042_override_por(client, MAX17042_DesignCap, config->design_cap);
477 max17042_override_por(client, MAX17042_ICHGTerm, config->ichgt_term);
478
479 max17042_override_por(client, MAX17042_AtRate, config->at_rate);
480 max17042_override_por(client, MAX17042_LearnCFG, config->learn_cfg);
481 max17042_override_por(client, MAX17042_FilterCFG, config->filter_cfg);
482 max17042_override_por(client, MAX17042_RelaxCFG, config->relax_cfg);
483 max17042_override_por(client, MAX17042_MiscCFG, config->misc_cfg);
484 max17042_override_por(client, MAX17042_MaskSOC, config->masksoc);
485
486 max17042_override_por(client, MAX17042_FullCAP, config->fullcap);
487 max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom);
488 max17042_override_por(client, MAX17042_SOC_empty, config->socempty);
489 max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty);
490 max17042_override_por(client, MAX17042_dQacc, config->dqacc);
491 max17042_override_por(client, MAX17042_dPacc, config->dpacc);
492
493 max17042_override_por(client, MAX17042_V_empty, config->vempty);
494 max17042_override_por(client, MAX17042_TempNom, config->temp_nom);
495 max17042_override_por(client, MAX17042_TempLim, config->temp_lim);
496 max17042_override_por(client, MAX17042_FCTC, config->fctc);
497 max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0);
498 max17042_override_por(client, MAX17042_TempCo, config->tcompc0);
499 max17042_override_por(client, MAX17042_EmptyTempCo,
500 config->empty_tempco);
501 max17042_override_por(client, MAX17042_K_empty0, config->kempty0);
502}
503
504static int max17042_init_chip(struct max17042_chip *chip)
505{
506 int ret;
507 int val;
508
509 max17042_override_por_values(chip);
510 /* After Power up, the MAX17042 requires 500mS in order
511 * to perform signal debouncing and initial SOC reporting
512 */
513 msleep(500);
514
515 /* Initialize configaration */
516 max17042_write_config_regs(chip);
517
518 /* write cell characterization data */
519 ret = max17042_init_model(chip);
520 if (ret) {
521 dev_err(&chip->client->dev, "%s init failed\n",
522 __func__);
523 return -EIO;
524 }
525 max17042_verify_model_lock(chip);
526 if (ret) {
527 dev_err(&chip->client->dev, "%s lock verify failed\n",
528 __func__);
529 return -EIO;
530 }
531 /* write custom parameters */
532 max17042_write_custom_regs(chip);
533
534 /* update capacity params */
535 max17042_update_capacity_regs(chip);
536
537 /* delay must be atleast 350mS to allow VFSOC
538 * to be calculated from the new configuration
539 */
540 msleep(350);
541
542 /* reset vfsoc0 reg */
543 max17042_reset_vfsoc0_reg(chip);
544
545 /* load new capacity params */
546 max17042_load_new_capacity_params(chip);
547
548 /* Init complete, Clear the POR bit */
549 val = max17042_read_reg(chip->client, MAX17042_STATUS);
550 max17042_write_reg(chip->client, MAX17042_STATUS,
551 val & (~STATUS_POR_BIT));
552 return 0;
553}
554
555
556static void max17042_init_worker(struct work_struct *work)
557{
558 struct max17042_chip *chip = container_of(work,
559 struct max17042_chip, work);
560 int ret;
561
562 /* Initialize registers according to values from the platform data */
563 if (chip->pdata->enable_por_init && chip->pdata->config_data) {
564 ret = max17042_init_chip(chip);
565 if (ret)
566 return;
567 }
568
569 chip->init_complete = 1;
570}
571
213static int __devinit max17042_probe(struct i2c_client *client, 572static int __devinit max17042_probe(struct i2c_client *client,
214 const struct i2c_device_id *id) 573 const struct i2c_device_id *id)
215{ 574{
216 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 575 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
217 struct max17042_chip *chip; 576 struct max17042_chip *chip;
218 int ret; 577 int ret;
578 int reg;
219 579
220 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) 580 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
221 return -EIO; 581 return -EIO;
@@ -243,17 +603,9 @@ static int __devinit max17042_probe(struct i2c_client *client,
243 if (chip->pdata->r_sns == 0) 603 if (chip->pdata->r_sns == 0)
244 chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; 604 chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
245 605
246 ret = power_supply_register(&client->dev, &chip->battery);
247 if (ret) {
248 dev_err(&client->dev, "failed: power supply register\n");
249 kfree(chip);
250 return ret;
251 }
252
253 /* Initialize registers according to values from the platform data */
254 if (chip->pdata->init_data) 606 if (chip->pdata->init_data)
255 max17042_set_reg(client, chip->pdata->init_data, 607 max17042_set_reg(client, chip->pdata->init_data,
256 chip->pdata->num_init_data); 608 chip->pdata->num_init_data);
257 609
258 if (!chip->pdata->enable_current_sense) { 610 if (!chip->pdata->enable_current_sense) {
259 max17042_write_reg(client, MAX17042_CGAIN, 0x0000); 611 max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
@@ -261,7 +613,21 @@ static int __devinit max17042_probe(struct i2c_client *client,
261 max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); 613 max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
262 } 614 }
263 615
264 return 0; 616 reg = max17042_read_reg(chip->client, MAX17042_STATUS);
617
618 if (reg & STATUS_POR_BIT) {
619 INIT_WORK(&chip->work, max17042_init_worker);
620 schedule_work(&chip->work);
621 } else {
622 chip->init_complete = 1;
623 }
624
625 ret = power_supply_register(&client->dev, &chip->battery);
626 if (ret) {
627 dev_err(&client->dev, "failed: power supply register\n");
628 kfree(chip);
629 }
630 return ret;
265} 631}
266 632
267static int __devexit max17042_remove(struct i2c_client *client) 633static int __devexit max17042_remove(struct i2c_client *client)