linux/drivers/power/supply/max8997_charger.c
<<
>>
Prefs
   1/*
   2 * max8997_charger.c - Power supply consumer driver for the Maxim 8997/8966
   3 *
   4 *  Copyright (C) 2011 Samsung Electronics
   5 *  MyungJoo Ham <myungjoo.ham@samsung.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21
  22#include <linux/err.h>
  23#include <linux/module.h>
  24#include <linux/slab.h>
  25#include <linux/platform_device.h>
  26#include <linux/power_supply.h>
  27#include <linux/mfd/max8997.h>
  28#include <linux/mfd/max8997-private.h>
  29
  30struct charger_data {
  31        struct device *dev;
  32        struct max8997_dev *iodev;
  33        struct power_supply *battery;
  34};
  35
  36static enum power_supply_property max8997_battery_props[] = {
  37        POWER_SUPPLY_PROP_STATUS, /* "FULL" or "NOT FULL" only. */
  38        POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */
  39        POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */
  40};
  41
  42/* Note that the charger control is done by a current regulator "CHARGER" */
  43static int max8997_battery_get_property(struct power_supply *psy,
  44                enum power_supply_property psp,
  45                union power_supply_propval *val)
  46{
  47        struct charger_data *charger = power_supply_get_drvdata(psy);
  48        struct i2c_client *i2c = charger->iodev->i2c;
  49        int ret;
  50        u8 reg;
  51
  52        switch (psp) {
  53        case POWER_SUPPLY_PROP_STATUS:
  54                val->intval = 0;
  55                ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
  56                if (ret)
  57                        return ret;
  58                if ((reg & (1 << 0)) == 0x1)
  59                        val->intval = POWER_SUPPLY_STATUS_FULL;
  60
  61                break;
  62        case POWER_SUPPLY_PROP_PRESENT:
  63                val->intval = 0;
  64                ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
  65                if (ret)
  66                        return ret;
  67                if ((reg & (1 << 2)) == 0x0)
  68                        val->intval = 1;
  69
  70                break;
  71        case POWER_SUPPLY_PROP_ONLINE:
  72                val->intval = 0;
  73                ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
  74                if (ret)
  75                        return ret;
  76                /* DCINOK */
  77                if (reg & (1 << 1))
  78                        val->intval = 1;
  79
  80                break;
  81        default:
  82                return -EINVAL;
  83        }
  84
  85        return 0;
  86}
  87
  88static const struct power_supply_desc max8997_battery_desc = {
  89        .name           = "max8997_pmic",
  90        .type           = POWER_SUPPLY_TYPE_BATTERY,
  91        .get_property   = max8997_battery_get_property,
  92        .properties     = max8997_battery_props,
  93        .num_properties = ARRAY_SIZE(max8997_battery_props),
  94};
  95
  96static int max8997_battery_probe(struct platform_device *pdev)
  97{
  98        int ret = 0;
  99        struct charger_data *charger;
 100        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 101        struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
 102        struct power_supply_config psy_cfg = {};
 103
 104        if (!pdata)
 105                return -EINVAL;
 106
 107        if (pdata->eoc_mA) {
 108                int val = (pdata->eoc_mA - 50) / 10;
 109                if (val < 0)
 110                        val = 0;
 111                if (val > 0xf)
 112                        val = 0xf;
 113
 114                ret = max8997_update_reg(iodev->i2c,
 115                                MAX8997_REG_MBCCTRL5, val, 0xf);
 116                if (ret < 0) {
 117                        dev_err(&pdev->dev, "Cannot use i2c bus.\n");
 118                        return ret;
 119                }
 120        }
 121
 122        switch (pdata->timeout) {
 123        case 5:
 124                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 125                                0x2 << 4, 0x7 << 4);
 126                break;
 127        case 6:
 128                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 129                                0x3 << 4, 0x7 << 4);
 130                break;
 131        case 7:
 132                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 133                                0x4 << 4, 0x7 << 4);
 134                break;
 135        case 0:
 136                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 137                                0x7 << 4, 0x7 << 4);
 138                break;
 139        default:
 140                dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
 141                                pdata->timeout);
 142                return -EINVAL;
 143        }
 144        if (ret < 0) {
 145                dev_err(&pdev->dev, "Cannot use i2c bus.\n");
 146                return ret;
 147        }
 148
 149        charger = devm_kzalloc(&pdev->dev, sizeof(struct charger_data),
 150                                GFP_KERNEL);
 151        if (!charger)
 152                return -ENOMEM;
 153
 154        platform_set_drvdata(pdev, charger);
 155
 156
 157        charger->dev = &pdev->dev;
 158        charger->iodev = iodev;
 159
 160        psy_cfg.drv_data = charger;
 161
 162        charger->battery = devm_power_supply_register(&pdev->dev,
 163                                                 &max8997_battery_desc,
 164                                                 &psy_cfg);
 165        if (IS_ERR(charger->battery)) {
 166                dev_err(&pdev->dev, "failed: power supply register\n");
 167                return PTR_ERR(charger->battery);
 168        }
 169
 170        return 0;
 171}
 172
 173static const struct platform_device_id max8997_battery_id[] = {
 174        { "max8997-battery", 0 },
 175        { }
 176};
 177MODULE_DEVICE_TABLE(platform, max8997_battery_id);
 178
 179static struct platform_driver max8997_battery_driver = {
 180        .driver = {
 181                .name = "max8997-battery",
 182        },
 183        .probe = max8997_battery_probe,
 184        .id_table = max8997_battery_id,
 185};
 186
 187static int __init max8997_battery_init(void)
 188{
 189        return platform_driver_register(&max8997_battery_driver);
 190}
 191subsys_initcall(max8997_battery_init);
 192
 193static void __exit max8997_battery_cleanup(void)
 194{
 195        platform_driver_unregister(&max8997_battery_driver);
 196}
 197module_exit(max8997_battery_cleanup);
 198
 199MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver");
 200MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 201MODULE_LICENSE("GPL");
 202