summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Cherry <tcherry@nvidia.com>2011-01-05 11:51:13 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:43:08 -0800
commit88a2475142fe6044acb50781a44e368782622af8 (patch)
treeb5397122c9a6fc6a21eb4efe5ee50e8d6dd257f6
parent0e5eec3307ce47cb03f9405b1c227b400611b24b (diff)
max8907c Charger Driver
max8907c Charger Driver from maxim plus nvidia modifications Integration from http://git-master/r/#change,15043 Original-Change-Id: I8143fee9c99b43ad1089613236410dc8ad5bbca0 Reviewed-on: http://git-master/r/16134 Tested-by: Thomas Cherry <tcherry@nvidia.com> Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Rebase-Id: R14961f2b240e4d3019836231b1be9e719b5f478b
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/max8907c-charger.c228
-rw-r--r--include/linux/power/max8907c-charger.h64
4 files changed, 300 insertions, 0 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 57de051a74b3..c12421d688d7 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -36,6 +36,13 @@ config MAX8925_POWER
Say Y here to enable support for the battery charger in the Maxim
MAX8925 PMIC.
+config MAX8907C_CHARGER
+ tristate "MAX8907c charger support"
+ depends on MFD_MAX8907C
+ help
+ Say Y here to enable support for the charger in the Maxim
+ MAX8907c PMIC.
+
config WM831X_BACKUP
tristate "WM831X backup battery charger support"
depends on MFD_WM831X
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b4af13dd8b66..72124bbf6776 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
+obj-$(CONFIG_MAX8907C_CHARGER) += max8907c-charger.o
diff --git a/drivers/power/max8907c-charger.c b/drivers/power/max8907c-charger.c
new file mode 100644
index 000000000000..64855c589b15
--- /dev/null
+++ b/drivers/power/max8907c-charger.c
@@ -0,0 +1,228 @@
+/*
+ * Battery driver for Maxim MAX8907C
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/max8907c.h>
+#include <linux/power/max8907c-charger.h>
+#include <linux/slab.h>
+
+struct max8907c_charger {
+ struct max8907c_charger_pdata *pdata;
+ struct max8907c *chip;
+ struct i2c_client *i2c;
+ int online;
+};
+
+static void max8907c_set_charger(struct max8907c_charger *charger)
+{
+ struct max8907c_charger_pdata *pdata = charger->pdata;
+ int ret;
+ if (charger->online) {
+ ret = max8907c_reg_write(charger->i2c, MAX8907C_REG_CHG_CNTL1,
+ (pdata->topoff_threshold << 5) |
+ (pdata->restart_hysteresis << 3) |
+ (pdata->fast_charging_current));
+ if (unlikely(ret != 0))
+ pr_err("Failed to set CHG_CNTL1: %d\n", ret);
+
+ ret = max8907c_set_bits(charger->i2c, MAX8907C_REG_CHG_CNTL2,
+ 0x30, pdata->fast_charger_time << 4);
+ if (unlikely(ret != 0))
+ pr_err("Failed to set CHG_CNTL2: %d\n", ret);
+ } else {
+ ret = max8907c_set_bits(charger->i2c, MAX8907C_REG_CHG_CNTL1, 0x80, 0x1);
+ if (unlikely(ret != 0))
+ pr_err("Failed to set CHG_CNTL1: %d\n", ret);
+ }
+}
+
+static irqreturn_t max8907c_charger_isr(int irq, void *dev_id)
+{
+ struct max8907c_charger *charger = dev_id;
+ struct max8907c *chip = charger->chip;
+
+ switch (irq - chip->irq_base) {
+ case MAX8907C_IRQ_VCHG_DC_R:
+ charger->online = 1;
+ max8907c_set_charger(charger);
+ break;
+ case MAX8907C_IRQ_VCHG_DC_F:
+ charger->online = 0;
+ max8907c_set_charger(charger);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int max8907c_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ const static int types[] = {
+ POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
+ POWER_SUPPLY_CHARGE_TYPE_FAST,
+ POWER_SUPPLY_CHARGE_TYPE_FAST,
+ POWER_SUPPLY_CHARGE_TYPE_NONE,
+ };
+ int ret = -ENODEV;
+ int status;
+
+ struct max8907c_charger *charger = dev_get_drvdata(psy->dev->parent);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = charger->online;
+ ret = 0;
+ break;
+
+ case POWER_SUPPLY_PROP_STATUS:
+ /* Get charger status from CHG_EN_STAT */
+ status = max8907c_reg_read(charger->i2c, MAX8907C_REG_CHG_STAT);
+ val->intval = ((status & 0x10) == 0x10) ?
+ POWER_SUPPLY_STATUS_CHARGING :
+ POWER_SUPPLY_STATUS_NOT_CHARGING;
+ ret = 0;
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ /* Get charging type from CHG_MODE */
+ status = max8907c_reg_read(charger->i2c, MAX8907C_REG_CHG_STAT);
+ val->intval = types[(status & 0x0C) >> 2];
+ ret = 0;
+ break;
+
+ default:
+ val->intval = 0;
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property max8907c_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+};
+
+static struct power_supply max8907c_charger_ps = {
+ .name = "charger",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = max8907c_charger_props,
+ .num_properties = ARRAY_SIZE(max8907c_charger_props),
+ .get_property = max8907c_charger_get_property,
+};
+
+static __devinit int max8907c_charger_probe(struct platform_device *pdev)
+{
+ struct max8907c_charger_pdata *pdata = pdev->dev.platform_data;
+ struct max8907c_charger *charger = 0;
+ struct max8907c *chip = dev_get_drvdata(pdev->dev.parent);
+ int ret;
+
+ charger = kzalloc(sizeof(*charger), GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ charger->pdata = pdata;
+ charger->online = 0;
+ charger->chip = chip;
+ charger->i2c = chip->i2c_power;
+
+ platform_set_drvdata(pdev, charger);
+
+ ret = max8907c_reg_read(charger->i2c, MAX8907C_REG_CHG_STAT);
+ if (ret & (1 << 7)) {
+ charger->online = 1;
+ max8907c_set_charger(charger);
+ }
+
+ ret = request_threaded_irq(chip->irq_base + MAX8907C_IRQ_VCHG_DC_F, NULL,
+ max8907c_charger_isr, IRQF_ONESHOT,
+ "power-remove", charger);
+ if (unlikely(ret < 0)) {
+ pr_debug("max8907c: failed to request IRQ %X\n", ret);
+ goto out;
+ }
+
+ ret = request_threaded_irq(chip->irq_base + MAX8907C_IRQ_VCHG_DC_R, NULL,
+ max8907c_charger_isr, IRQF_ONESHOT,
+ "power-insert", charger);
+ if (unlikely(ret < 0)) {
+ pr_debug("max8907c: failed to request IRQ %X\n", ret);
+ goto out1;
+ }
+
+
+ ret = power_supply_register(&pdev->dev, &max8907c_charger_ps);
+ if (unlikely(ret != 0)) {
+ pr_err("Failed to register max8907c_charger driver: %d\n", ret);
+ goto out2;
+ }
+
+ return 0;
+out2:
+ free_irq(chip->irq_base + MAX8907C_IRQ_VCHG_DC_R, charger);
+out1:
+ free_irq(chip->irq_base + MAX8907C_IRQ_VCHG_DC_F, charger);
+out:
+ kfree(charger);
+ return ret;
+}
+
+static __devexit int max8907c_charger_remove(struct platform_device *pdev)
+{
+ struct max8907c_charger *charger = platform_get_drvdata(pdev);
+ struct max8907c *chip = charger->chip;
+ int ret;
+
+ ret = max8907c_reg_write(charger->i2c, MAX8907C_REG_CHG_IRQ1_MASK, 0xFF);
+ if (unlikely(ret != 0)) {
+ pr_err("Failed to set IRQ1_MASK: %d\n", ret);
+ goto out;
+ }
+
+ free_irq(chip->irq_base + MAX8907C_IRQ_VCHG_DC_R, charger);
+ free_irq(chip->irq_base + MAX8907C_IRQ_VCHG_DC_F, charger);
+ power_supply_unregister(&max8907c_charger_ps);
+out:
+ kfree(charger);
+ return 0;
+}
+
+static struct platform_driver max8907c_charger_driver = {
+ .probe = max8907c_charger_probe,
+ .remove = __devexit_p(max8907c_charger_remove),
+ .driver = {
+ .name = "max8907c-charger",
+ },
+};
+
+static int __init max8907c_charger_init(void)
+{
+ return platform_driver_register(&max8907c_charger_driver);
+}
+module_init(max8907c_charger_init);
+
+static void __exit max8907c_charger_exit(void)
+{
+ platform_driver_unregister(&max8907c_charger_driver);
+}
+module_exit(max8907c_charger_exit);
+
+MODULE_DESCRIPTION("Charger driver for MAX8907C");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/power/max8907c-charger.h b/include/linux/power/max8907c-charger.h
new file mode 100644
index 000000000000..2cebad768b0d
--- /dev/null
+++ b/include/linux/power/max8907c-charger.h
@@ -0,0 +1,64 @@
+/* linux/power/max8907c-charger.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MAX8907C_CHARGER_H
+#define __LINUX_MAX8907C_CHARGER_H
+
+/* interrupt */
+#define MAX8907C_VCHG_OVP (1 << 0)
+#define MAX8907C_VCHG_F (1 << 1)
+#define MAX8907C_VCHG_R (1 << 2)
+#define MAX8907C_THM_OK_R (1 << 8)
+#define MAX8907C_THM_OK_F (1 << 9)
+#define MAX8907C_MBATTLOW_F (1 << 10)
+#define MAX8907C_MBATTLOW_R (1 << 11)
+#define MAX8907C_CHG_RST (1 << 12)
+#define MAX8907C_CHG_DONE (1 << 13)
+#define MAX8907C_CHG_TOPOFF (1 << 14)
+#define MAX8907C_CHK_TMR_FAULT (1 << 15)
+
+enum max8907c_charger_topoff_threshold {
+ MAX8907C_TOPOFF_5PERCENT = 0x00,
+ MAX8907C_TOPOFF_10PERCENT = 0x01,
+ MAX8907C_TOPOFF_15PERCENT = 0x02,
+ MAX8907C_TOPOFF_20PERCENT = 0x03,
+};
+
+enum max8907c_charger_restart_hysteresis {
+ MAX8907C_RESTART_100MV = 0x00,
+ MAX8907C_RESTART_150MV = 0x01,
+ MAX8907C_RESTART_200MV = 0x02,
+ MAX8907C_RESTART_FLOAT = 0x03,
+};
+
+enum max8907c_fast_charging_current {
+ MAX8907C_FASTCHARGE_90MA = 0x00,
+ MAX8907C_FASTCHARGE_300MA = 0x01,
+ MAX8907C_FASTCHARGE_460MA = 0x02,
+ MAX8907C_FASTCHARGE_600MA = 0x03,
+ MAX8907C_FASTCHARGE_700MA = 0x04,
+ MAX8907C_FASTCHARGE_800MA = 0x05,
+ MAX8907C_FASTCHARGE_900MA = 0x06,
+ MAX8907C_FASTCHARGE_1000MA = 0x07,
+};
+
+enum max8907c_fast_charger_time {
+ MAX8907C_FCHARGE_TM_8H = 0x00,
+ MAX8907C_FCHARGE_TM_12H = 0x01,
+ MAX8907C_FCHARGE_TM_16H = 0x02,
+ MAX8907C_FCHARGE_TM_OFF = 0x03,
+};
+
+struct max8907c_charger_pdata {
+ int irq;
+ enum max8907c_charger_topoff_threshold topoff_threshold;
+ enum max8907c_charger_restart_hysteresis restart_hysteresis;
+ enum max8907c_charger_restart_hysteresis fast_charging_current;
+ enum max8907c_fast_charger_time fast_charger_time;
+};
+
+#endif