aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2010-05-24 13:55:27 -0400
committerLars-Peter Clausen <lars@metafoo.de>2011-02-22 05:02:42 -0500
commit7fb7ba588c0f276609609565b21fcc853284a9a0 (patch)
tree68a47743764b763ba73572cfaf752d1ddecaccfb /drivers/power
parenta40402ef0bf3b6e53a7dfd396e9487eb2f613e19 (diff)
bq27x00: Add bq27000 support
This patch adds support for the bq27000 battery to the bq27x00 driver. The bq27000 is similar to the bq27200 except that it uses the HDQ bus instead of I2C to communicate with the host system. The driver is implemented as a platform driver. The driver expects to be provided with a read callback function through its platform data. The read function is assumed to do the lowlevel HDQ handling and read out the value of a certain register. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Tested-by: Grazvydas Ignotas <notasas@gmail.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/Kconfig14
-rw-r--r--drivers/power/bq27x00_battery.c184
2 files changed, 183 insertions, 15 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 61bf5d724139..52a462fc6b84 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -117,10 +117,24 @@ config BATTERY_BQ20Z75
117 117
118config BATTERY_BQ27x00 118config BATTERY_BQ27x00
119 tristate "BQ27x00 battery driver" 119 tristate "BQ27x00 battery driver"
120 help
121 Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
122
123config BATTERY_BQ27X00_I2C
124 bool "BQ27200/BQ27500 support"
125 depends on BATTERY_BQ27x00
120 depends on I2C 126 depends on I2C
127 default y
121 help 128 help
122 Say Y here to enable support for batteries with BQ27x00 (I2C) chips. 129 Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
123 130
131config BATTERY_BQ27X00_PLATFORM
132 bool "BQ27000 support"
133 depends on BATTERY_BQ27x00
134 default y
135 help
136 Say Y here to enable support for batteries with BQ27000 (HDQ) chips.
137
124config BATTERY_DA9030 138config BATTERY_DA9030
125 tristate "DA9030 battery driver" 139 tristate "DA9030 battery driver"
126 depends on PMIC_DA903X 140 depends on PMIC_DA903X
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index def951d8fc2b..44bc76be0780 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> 4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> 5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
6 * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
6 * 7 *
7 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. 8 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
8 * 9 *
@@ -27,6 +28,8 @@
27#include <linux/slab.h> 28#include <linux/slab.h>
28#include <asm/unaligned.h> 29#include <asm/unaligned.h>
29 30
31#include <linux/power/bq27x00_battery.h>
32
30#define DRIVER_VERSION "1.1.0" 33#define DRIVER_VERSION "1.1.0"
31 34
32#define BQ27x00_REG_TEMP 0x06 35#define BQ27x00_REG_TEMP 0x06
@@ -46,12 +49,6 @@
46 49
47#define BQ27000_RS 20 /* Resistor sense */ 50#define BQ27000_RS 20 /* Resistor sense */
48 51
49/* If the system has several batteries we need a different name for each
50 * of them...
51 */
52static DEFINE_IDR(battery_id);
53static DEFINE_MUTEX(battery_mutex);
54
55struct bq27x00_device_info; 52struct bq27x00_device_info;
56struct bq27x00_access_methods { 53struct bq27x00_access_methods {
57 int (*read)(struct bq27x00_device_info *, u8 reg, int *rt_value, 54 int (*read)(struct bq27x00_device_info *, u8 reg, int *rt_value,
@@ -317,9 +314,15 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
317 return 0; 314 return 0;
318} 315}
319 316
320/* 317
321 * i2c specific code 318/* i2c specific code */
319#ifdef CONFIG_BATTERY_BQ27X00_I2C
320
321/* If the system has several batteries we need a different name for each
322 * of them...
322 */ 323 */
324static DEFINE_IDR(battery_id);
325static DEFINE_MUTEX(battery_mutex);
323 326
324static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, 327static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg,
325 int *rt_value, bool single) 328 int *rt_value, bool single)
@@ -434,10 +437,6 @@ static int bq27x00_battery_remove(struct i2c_client *client)
434 return 0; 437 return 0;
435} 438}
436 439
437/*
438 * Module stuff
439 */
440
441static const struct i2c_device_id bq27x00_id[] = { 440static const struct i2c_device_id bq27x00_id[] = {
442 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ 441 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */
443 { "bq27500", BQ27500 }, 442 { "bq27500", BQ27500 },
@@ -453,13 +452,167 @@ static struct i2c_driver bq27x00_battery_driver = {
453 .id_table = bq27x00_id, 452 .id_table = bq27x00_id,
454}; 453};
455 454
455static inline int bq27x00_battery_i2c_init(void)
456{
457 int ret = i2c_add_driver(&bq27x00_battery_driver);
458 if (ret)
459 printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n");
460
461 return ret;
462}
463
464static inline void bq27x00_battery_i2c_exit(void)
465{
466 i2c_del_driver(&bq27x00_battery_driver);
467}
468
469#else
470
471static inline int bq27x00_battery_i2c_init(void) { return 0; }
472static inline void bq27x00_battery_i2c_exit(void) {};
473
474#endif
475
476/* platform specific code */
477#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
478
479static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
480 int *rt_value, bool single)
481{
482 struct device *dev = di->dev;
483 struct bq27000_platform_data *pdata = dev->platform_data;
484 unsigned int timeout = 3;
485 int upper, lower;
486 int temp;
487
488 if (!single) {
489 /* Make sure the value has not changed in between reading the
490 * lower and the upper part */
491 upper = pdata->read(dev, reg + 1);
492 do {
493 temp = upper;
494 if (upper < 0)
495 return upper;
496
497 lower = pdata->read(dev, reg);
498 if (lower < 0)
499 return lower;
500
501 upper = pdata->read(dev, reg + 1);
502 } while (temp != upper && --timeout);
503
504 if (timeout == 0)
505 return -EIO;
506
507 *rt_value = (upper << 8) | lower;
508 } else {
509 lower = pdata->read(dev, reg);
510 if (lower < 0)
511 return lower;
512 *rt_value = lower;
513 }
514 return 0;
515}
516
517static int __devinit bq27000_battery_probe(struct platform_device *pdev)
518{
519 struct bq27x00_device_info *di;
520 struct bq27000_platform_data *pdata = pdev->dev.platform_data;
521 int ret;
522
523 if (!pdata) {
524 dev_err(&pdev->dev, "no platform_data supplied\n");
525 return -EINVAL;
526 }
527
528 if (!pdata->read) {
529 dev_err(&pdev->dev, "no hdq read callback supplied\n");
530 return -EINVAL;
531 }
532
533 di = kzalloc(sizeof(*di), GFP_KERNEL);
534 if (!di) {
535 dev_err(&pdev->dev, "failed to allocate device info data\n");
536 return -ENOMEM;
537 }
538
539 platform_set_drvdata(pdev, di);
540
541 di->dev = &pdev->dev;
542 di->chip = BQ27000;
543
544 di->bat.name = pdata->name ?: dev_name(&pdev->dev);
545 di->bus.read = &bq27000_read_platform;
546
547 ret = bq27x00_powersupply_init(di);
548 if (ret)
549 goto err_free;
550
551 return 0;
552
553err_free:
554 platform_set_drvdata(pdev, NULL);
555 kfree(di);
556
557 return ret;
558}
559
560static int __devexit bq27000_battery_remove(struct platform_device *pdev)
561{
562 struct bq27x00_device_info *di = platform_get_drvdata(pdev);
563
564 power_supply_unregister(&di->bat);
565 platform_set_drvdata(pdev, NULL);
566 kfree(di);
567
568 return 0;
569}
570
571static struct platform_driver bq27000_battery_driver = {
572 .probe = bq27000_battery_probe,
573 .remove = __devexit_p(bq27000_battery_remove),
574 .driver = {
575 .name = "bq27000-battery",
576 .owner = THIS_MODULE,
577 },
578};
579
580static inline int bq27x00_battery_platform_init(void)
581{
582 int ret = platform_driver_register(&bq27000_battery_driver);
583 if (ret)
584 printk(KERN_ERR "Unable to register BQ27000 platform driver\n");
585
586 return ret;
587}
588
589static inline void bq27x00_battery_platform_exit(void)
590{
591 platform_driver_unregister(&bq27000_battery_driver);
592}
593
594#else
595
596static inline int bq27x00_battery_platform_init(void) { return 0; }
597static inline void bq27x00_battery_platform_exit(void) {};
598
599#endif
600
601/*
602 * Module stuff
603 */
604
456static int __init bq27x00_battery_init(void) 605static int __init bq27x00_battery_init(void)
457{ 606{
458 int ret; 607 int ret;
459 608
460 ret = i2c_add_driver(&bq27x00_battery_driver); 609 ret = bq27x00_battery_i2c_init();
610 if (ret)
611 return ret;
612
613 ret = bq27x00_battery_platform_init();
461 if (ret) 614 if (ret)
462 printk(KERN_ERR "Unable to register BQ27x00 driver\n"); 615 bq27x00_battery_i2c_exit();
463 616
464 return ret; 617 return ret;
465} 618}
@@ -467,7 +620,8 @@ module_init(bq27x00_battery_init);
467 620
468static void __exit bq27x00_battery_exit(void) 621static void __exit bq27x00_battery_exit(void)
469{ 622{
470 i2c_del_driver(&bq27x00_battery_driver); 623 bq27x00_battery_platform_exit();
624 bq27x00_battery_i2c_exit();
471} 625}
472module_exit(bq27x00_battery_exit); 626module_exit(bq27x00_battery_exit);
473 627