linux/drivers/power/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 = container_of(psy,
  48                        struct charger_data, battery);
  49        struct i2c_client *i2c = charger->iodev->i2c;
  50        int ret;
  51        u8 reg;
  52
  53        switch (psp) {
  54        case POWER_SUPPLY_PROP_STATUS:
  55                val->intval = 0;
  56                ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
  57                if (ret)
  58                        return ret;
  59                if ((reg & (1 << 0)) == 0x1)
  60                        val->intval = POWER_SUPPLY_STATUS_FULL;
  61
  62                break;
  63        case POWER_SUPPLY_PROP_PRESENT:
  64                val->intval = 0;
  65                ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
  66                if (ret)
  67                        return ret;
  68                if ((reg & (1 << 2)) == 0x0)
  69                        val->intval = 1;
  70
  71                break;
  72        case POWER_SUPPLY_PROP_ONLINE:
  73                val->intval = 0;
  74                ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
  75                if (ret)
  76                        return ret;
  77                /* DCINOK */
  78                if (reg & (1 << 1))
  79                        val->intval = 1;
  80
  81                break;
  82        default:
  83                return -EINVAL;
  84        }
  85
  86        return 0;
  87}
  88
  89static int max8997_battery_probe(struct platform_device *pdev)
  90{
  91        int ret = 0;
  92        struct charger_data *charger;
  93        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
  94        struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
  95
  96        if (!pdata)
  97                return -EINVAL;
  98
  99        if (pdata->eoc_mA) {
 100                int val = (pdata->eoc_mA - 50) / 10;
 101                if (val < 0)
 102                        val = 0;
 103                if (val > 0xf)
 104                        val = 0xf;
 105
 106                ret = max8997_update_reg(iodev->i2c,
 107                                MAX8997_REG_MBCCTRL5, val, 0xf);
 108                if (ret < 0) {
 109                        dev_err(&pdev->dev, "Cannot use i2c bus.\n");
 110                        return ret;
 111                }
 112        }
 113
 114        switch (pdata->timeout) {
 115        case 5:
 116                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 117                                0x2 << 4, 0x7 << 4);
 118                break;
 119        case 6:
 120                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 121                                0x3 << 4, 0x7 << 4);
 122                break;
 123        case 7:
 124                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 125                                0x4 << 4, 0x7 << 4);
 126                break;
 127        case 0:
 128                ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
 129                                0x7 << 4, 0x7 << 4);
 130                break;
 131        default:
 132                dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
 133                                pdata->timeout);
 134                return -EINVAL;
 135        }
 136        if (ret < 0) {
 137                dev_err(&pdev->dev, "Cannot use i2c bus.\n");
 138                return ret;
 139        }
 140
 141        charger = kzalloc(sizeof(struct charger_data), GFP_KERNEL);
 142        if (charger == NULL) {
 143                dev_err(&pdev->dev, "Cannot allocate memory.\n");
 144                return -ENOMEM;
 145        }
 146
 147        platform_set_drvdata(pdev, charger);
 148
 149        charger->battery.name = "max8997_pmic";
 150        charger->battery.type = POWER_SUPPLY_TYPE_BATTERY;
 151        charger->battery.get_property = max8997_battery_get_property;
 152        charger->battery.properties = max8997_battery_props;
 153        charger->battery.num_properties = ARRAY_SIZE(max8997_battery_props);
 154
 155        charger->dev = &pdev->dev;
 156        charger->iodev = iodev;
 157
 158        ret = power_supply_register(&pdev->dev, &charger->battery);
 159        if (ret) {
 160                dev_err(&pdev->dev, "failed: power supply register\n");
 161                goto err;
 162        }
 163
 164        return 0;
 165err:
 166        kfree(charger);
 167        return ret;
 168}
 169
 170static int max8997_battery_remove(struct platform_device *pdev)
 171{
 172        struct charger_data *charger = platform_get_drvdata(pdev);
 173
 174        power_supply_unregister(&charger->battery);
 175        kfree(charger);
 176        return 0;
 177}
 178
 179static const struct platform_device_id max8997_battery_id[] = {
 180        { "max8997-battery", 0 },
 181        { }
 182};
 183
 184static struct platform_driver max8997_battery_driver = {
 185        .driver = {
 186                .name = "max8997-battery",
 187                .owner = THIS_MODULE,
 188        },
 189        .probe = max8997_battery_probe,
 190        .remove = max8997_battery_remove,
 191        .id_table = max8997_battery_id,
 192};
 193
 194static int __init max8997_battery_init(void)
 195{
 196        return platform_driver_register(&max8997_battery_driver);
 197}
 198subsys_initcall(max8997_battery_init);
 199
 200static void __exit max8997_battery_cleanup(void)
 201{
 202        platform_driver_unregister(&max8997_battery_driver);
 203}
 204module_exit(max8997_battery_cleanup);
 205
 206MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver");
 207MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 208MODULE_LICENSE("GPL");
 209
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.