linux/drivers/power/supply/generic-adc-battery.c
<<
>>
Prefs
   1/*
   2 * Generic battery driver code using IIO
   3 * Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
   4 * based on jz4740-battery.c
   5 * based on s3c_adc_battery.c
   6 *
   7 * This file is subject to the terms and conditions of the GNU General Public
   8 * License.  See the file COPYING in the main directory of this archive for
   9 * more details.
  10 *
  11 */
  12#include <linux/interrupt.h>
  13#include <linux/platform_device.h>
  14#include <linux/power_supply.h>
  15#include <linux/gpio.h>
  16#include <linux/err.h>
  17#include <linux/timer.h>
  18#include <linux/jiffies.h>
  19#include <linux/errno.h>
  20#include <linux/init.h>
  21#include <linux/module.h>
  22#include <linux/slab.h>
  23#include <linux/iio/consumer.h>
  24#include <linux/iio/types.h>
  25#include <linux/power/generic-adc-battery.h>
  26
  27#define JITTER_DEFAULT 10 /* hope 10ms is enough */
  28
  29enum gab_chan_type {
  30        GAB_VOLTAGE = 0,
  31        GAB_CURRENT,
  32        GAB_POWER,
  33        GAB_MAX_CHAN_TYPE
  34};
  35
  36/*
  37 * gab_chan_name suggests the standard channel names for commonly used
  38 * channel types.
  39 */
  40static const char *const gab_chan_name[] = {
  41        [GAB_VOLTAGE]   = "voltage",
  42        [GAB_CURRENT]   = "current",
  43        [GAB_POWER]             = "power",
  44};
  45
  46struct gab {
  47        struct power_supply             *psy;
  48        struct power_supply_desc        psy_desc;
  49        struct iio_channel      *channel[GAB_MAX_CHAN_TYPE];
  50        struct gab_platform_data        *pdata;
  51        struct delayed_work bat_work;
  52        int     level;
  53        int     status;
  54        bool cable_plugged;
  55};
  56
  57static struct gab *to_generic_bat(struct power_supply *psy)
  58{
  59        return power_supply_get_drvdata(psy);
  60}
  61
  62static void gab_ext_power_changed(struct power_supply *psy)
  63{
  64        struct gab *adc_bat = to_generic_bat(psy);
  65
  66        schedule_delayed_work(&adc_bat->bat_work, msecs_to_jiffies(0));
  67}
  68
  69static const enum power_supply_property gab_props[] = {
  70        POWER_SUPPLY_PROP_STATUS,
  71        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  72        POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
  73        POWER_SUPPLY_PROP_CHARGE_NOW,
  74        POWER_SUPPLY_PROP_VOLTAGE_NOW,
  75        POWER_SUPPLY_PROP_CURRENT_NOW,
  76        POWER_SUPPLY_PROP_TECHNOLOGY,
  77        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  78        POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
  79        POWER_SUPPLY_PROP_MODEL_NAME,
  80};
  81
  82/*
  83 * This properties are set based on the received platform data and this
  84 * should correspond one-to-one with enum chan_type.
  85 */
  86static const enum power_supply_property gab_dyn_props[] = {
  87        POWER_SUPPLY_PROP_VOLTAGE_NOW,
  88        POWER_SUPPLY_PROP_CURRENT_NOW,
  89        POWER_SUPPLY_PROP_POWER_NOW,
  90};
  91
  92static bool gab_charge_finished(struct gab *adc_bat)
  93{
  94        struct gab_platform_data *pdata = adc_bat->pdata;
  95        bool ret = gpio_get_value(pdata->gpio_charge_finished);
  96        bool inv = pdata->gpio_inverted;
  97
  98        if (!gpio_is_valid(pdata->gpio_charge_finished))
  99                return false;
 100        return ret ^ inv;
 101}
 102
 103static int gab_get_status(struct gab *adc_bat)
 104{
 105        struct gab_platform_data *pdata = adc_bat->pdata;
 106        struct power_supply_info *bat_info;
 107
 108        bat_info = &pdata->battery_info;
 109        if (adc_bat->level == bat_info->charge_full_design)
 110                return POWER_SUPPLY_STATUS_FULL;
 111        return adc_bat->status;
 112}
 113
 114static enum gab_chan_type gab_prop_to_chan(enum power_supply_property psp)
 115{
 116        switch (psp) {
 117        case POWER_SUPPLY_PROP_POWER_NOW:
 118                return GAB_POWER;
 119        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 120                return GAB_VOLTAGE;
 121        case POWER_SUPPLY_PROP_CURRENT_NOW:
 122                return GAB_CURRENT;
 123        default:
 124                WARN_ON(1);
 125                break;
 126        }
 127        return GAB_POWER;
 128}
 129
 130static int read_channel(struct gab *adc_bat, enum power_supply_property psp,
 131                int *result)
 132{
 133        int ret;
 134        int chan_index;
 135
 136        chan_index = gab_prop_to_chan(psp);
 137        ret = iio_read_channel_processed(adc_bat->channel[chan_index],
 138                        result);
 139        if (ret < 0)
 140                pr_err("read channel error\n");
 141        return ret;
 142}
 143
 144static int gab_get_property(struct power_supply *psy,
 145                enum power_supply_property psp, union power_supply_propval *val)
 146{
 147        struct gab *adc_bat;
 148        struct gab_platform_data *pdata;
 149        struct power_supply_info *bat_info;
 150        int result = 0;
 151        int ret = 0;
 152
 153        adc_bat = to_generic_bat(psy);
 154        if (!adc_bat) {
 155                dev_err(&psy->dev, "no battery infos ?!\n");
 156                return -EINVAL;
 157        }
 158        pdata = adc_bat->pdata;
 159        bat_info = &pdata->battery_info;
 160
 161        switch (psp) {
 162        case POWER_SUPPLY_PROP_STATUS:
 163                val->intval = gab_get_status(adc_bat);
 164                break;
 165        case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
 166                val->intval = 0;
 167                break;
 168        case POWER_SUPPLY_PROP_CHARGE_NOW:
 169                val->intval = pdata->cal_charge(result);
 170                break;
 171        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 172        case POWER_SUPPLY_PROP_CURRENT_NOW:
 173        case POWER_SUPPLY_PROP_POWER_NOW:
 174                ret = read_channel(adc_bat, psp, &result);
 175                if (ret < 0)
 176                        goto err;
 177                val->intval = result;
 178                break;
 179        case POWER_SUPPLY_PROP_TECHNOLOGY:
 180                val->intval = bat_info->technology;
 181                break;
 182        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
 183                val->intval = bat_info->voltage_min_design;
 184                break;
 185        case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
 186                val->intval = bat_info->voltage_max_design;
 187                break;
 188        case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 189                val->intval = bat_info->charge_full_design;
 190                break;
 191        case POWER_SUPPLY_PROP_MODEL_NAME:
 192                val->strval = bat_info->name;
 193                break;
 194        default:
 195                return -EINVAL;
 196        }
 197err:
 198        return ret;
 199}
 200
 201static void gab_work(struct work_struct *work)
 202{
 203        struct gab *adc_bat;
 204        struct delayed_work *delayed_work;
 205        bool is_plugged;
 206        int status;
 207
 208        delayed_work = to_delayed_work(work);
 209        adc_bat = container_of(delayed_work, struct gab, bat_work);
 210        status = adc_bat->status;
 211
 212        is_plugged = power_supply_am_i_supplied(adc_bat->psy);
 213        adc_bat->cable_plugged = is_plugged;
 214
 215        if (!is_plugged)
 216                adc_bat->status =  POWER_SUPPLY_STATUS_DISCHARGING;
 217        else if (gab_charge_finished(adc_bat))
 218                adc_bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
 219        else
 220                adc_bat->status = POWER_SUPPLY_STATUS_CHARGING;
 221
 222        if (status != adc_bat->status)
 223                power_supply_changed(adc_bat->psy);
 224}
 225
 226static irqreturn_t gab_charged(int irq, void *dev_id)
 227{
 228        struct gab *adc_bat = dev_id;
 229        struct gab_platform_data *pdata = adc_bat->pdata;
 230        int delay;
 231
 232        delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT;
 233        schedule_delayed_work(&adc_bat->bat_work,
 234                        msecs_to_jiffies(delay));
 235        return IRQ_HANDLED;
 236}
 237
 238static int gab_probe(struct platform_device *pdev)
 239{
 240        struct gab *adc_bat;
 241        struct power_supply_desc *psy_desc;
 242        struct power_supply_config psy_cfg = {};
 243        struct gab_platform_data *pdata = pdev->dev.platform_data;
 244        enum power_supply_property *properties;
 245        int ret = 0;
 246        int chan;
 247        int index = 0;
 248
 249        adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL);
 250        if (!adc_bat) {
 251                dev_err(&pdev->dev, "failed to allocate memory\n");
 252                return -ENOMEM;
 253        }
 254
 255        psy_cfg.drv_data = adc_bat;
 256        psy_desc = &adc_bat->psy_desc;
 257        psy_desc->name = pdata->battery_info.name;
 258
 259        /* bootup default values for the battery */
 260        adc_bat->cable_plugged = false;
 261        adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
 262        psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
 263        psy_desc->get_property = gab_get_property;
 264        psy_desc->external_power_changed = gab_ext_power_changed;
 265        adc_bat->pdata = pdata;
 266
 267        /*
 268         * copying the static properties and allocating extra memory for holding
 269         * the extra configurable properties received from platform data.
 270         */
 271        psy_desc->properties = kcalloc(ARRAY_SIZE(gab_props) +
 272                                        ARRAY_SIZE(gab_chan_name),
 273                                        sizeof(*psy_desc->properties),
 274                                        GFP_KERNEL);
 275        if (!psy_desc->properties) {
 276                ret = -ENOMEM;
 277                goto first_mem_fail;
 278        }
 279
 280        memcpy(psy_desc->properties, gab_props, sizeof(gab_props));
 281        properties = (enum power_supply_property *)
 282                        ((char *)psy_desc->properties + sizeof(gab_props));
 283
 284        /*
 285         * getting channel from iio and copying the battery properties
 286         * based on the channel supported by consumer device.
 287         */
 288        for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
 289                adc_bat->channel[chan] = iio_channel_get(&pdev->dev,
 290                                                         gab_chan_name[chan]);
 291                if (IS_ERR(adc_bat->channel[chan])) {
 292                        ret = PTR_ERR(adc_bat->channel[chan]);
 293                        adc_bat->channel[chan] = NULL;
 294                } else {
 295                        /* copying properties for supported channels only */
 296                        memcpy(properties + sizeof(*(psy_desc->properties)) * index,
 297                                        &gab_dyn_props[chan],
 298                                        sizeof(gab_dyn_props[chan]));
 299                        index++;
 300                }
 301        }
 302
 303        /* none of the channels are supported so let's bail out */
 304        if (index == 0) {
 305                ret = -ENODEV;
 306                goto second_mem_fail;
 307        }
 308
 309        /*
 310         * Total number of properties is equal to static properties
 311         * plus the dynamic properties.Some properties may not be set
 312         * as come channels may be not be supported by the device.So
 313         * we need to take care of that.
 314         */
 315        psy_desc->num_properties = ARRAY_SIZE(gab_props) + index;
 316
 317        adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
 318        if (IS_ERR(adc_bat->psy)) {
 319                ret = PTR_ERR(adc_bat->psy);
 320                goto err_reg_fail;
 321        }
 322
 323        INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work);
 324
 325        if (gpio_is_valid(pdata->gpio_charge_finished)) {
 326                int irq;
 327                ret = gpio_request(pdata->gpio_charge_finished, "charged");
 328                if (ret)
 329                        goto gpio_req_fail;
 330
 331                irq = gpio_to_irq(pdata->gpio_charge_finished);
 332                ret = request_any_context_irq(irq, gab_charged,
 333                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 334                                "battery charged", adc_bat);
 335                if (ret < 0)
 336                        goto err_gpio;
 337        }
 338
 339        platform_set_drvdata(pdev, adc_bat);
 340
 341        /* Schedule timer to check current status */
 342        schedule_delayed_work(&adc_bat->bat_work,
 343                        msecs_to_jiffies(0));
 344        return 0;
 345
 346err_gpio:
 347        gpio_free(pdata->gpio_charge_finished);
 348gpio_req_fail:
 349        power_supply_unregister(adc_bat->psy);
 350err_reg_fail:
 351        for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
 352                if (adc_bat->channel[chan])
 353                        iio_channel_release(adc_bat->channel[chan]);
 354        }
 355second_mem_fail:
 356        kfree(psy_desc->properties);
 357first_mem_fail:
 358        return ret;
 359}
 360
 361static int gab_remove(struct platform_device *pdev)
 362{
 363        int chan;
 364        struct gab *adc_bat = platform_get_drvdata(pdev);
 365        struct gab_platform_data *pdata = adc_bat->pdata;
 366
 367        power_supply_unregister(adc_bat->psy);
 368
 369        if (gpio_is_valid(pdata->gpio_charge_finished)) {
 370                free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat);
 371                gpio_free(pdata->gpio_charge_finished);
 372        }
 373
 374        for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
 375                if (adc_bat->channel[chan])
 376                        iio_channel_release(adc_bat->channel[chan]);
 377        }
 378
 379        kfree(adc_bat->psy_desc.properties);
 380        cancel_delayed_work(&adc_bat->bat_work);
 381        return 0;
 382}
 383
 384static int __maybe_unused gab_suspend(struct device *dev)
 385{
 386        struct gab *adc_bat = dev_get_drvdata(dev);
 387
 388        cancel_delayed_work_sync(&adc_bat->bat_work);
 389        adc_bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
 390        return 0;
 391}
 392
 393static int __maybe_unused gab_resume(struct device *dev)
 394{
 395        struct gab *adc_bat = dev_get_drvdata(dev);
 396        struct gab_platform_data *pdata = adc_bat->pdata;
 397        int delay;
 398
 399        delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT;
 400
 401        /* Schedule timer to check current status */
 402        schedule_delayed_work(&adc_bat->bat_work,
 403                        msecs_to_jiffies(delay));
 404        return 0;
 405}
 406
 407static SIMPLE_DEV_PM_OPS(gab_pm_ops, gab_suspend, gab_resume);
 408
 409static struct platform_driver gab_driver = {
 410        .driver         = {
 411                .name   = "generic-adc-battery",
 412                .pm     = &gab_pm_ops,
 413        },
 414        .probe          = gab_probe,
 415        .remove         = gab_remove,
 416};
 417module_platform_driver(gab_driver);
 418
 419MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>");
 420MODULE_DESCRIPTION("generic battery driver using IIO");
 421MODULE_LICENSE("GPL");
 422