linux/drivers/power/supply/ab8500_btemp.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) ST-Ericsson SA 2012
   3 *
   4 * Battery temperature driver for AB8500
   5 *
   6 * License Terms: GNU General Public License v2
   7 * Author:
   8 *      Johan Palsson <johan.palsson@stericsson.com>
   9 *      Karl Komierowski <karl.komierowski@stericsson.com>
  10 *      Arun R Murthy <arun.murthy@stericsson.com>
  11 */
  12
  13#include <linux/init.h>
  14#include <linux/module.h>
  15#include <linux/device.h>
  16#include <linux/interrupt.h>
  17#include <linux/delay.h>
  18#include <linux/slab.h>
  19#include <linux/platform_device.h>
  20#include <linux/power_supply.h>
  21#include <linux/completion.h>
  22#include <linux/workqueue.h>
  23#include <linux/jiffies.h>
  24#include <linux/of.h>
  25#include <linux/mfd/core.h>
  26#include <linux/mfd/abx500.h>
  27#include <linux/mfd/abx500/ab8500.h>
  28#include <linux/mfd/abx500/ab8500-bm.h>
  29#include <linux/mfd/abx500/ab8500-gpadc.h>
  30
  31#define VTVOUT_V                        1800
  32
  33#define BTEMP_THERMAL_LOW_LIMIT         -10
  34#define BTEMP_THERMAL_MED_LIMIT         0
  35#define BTEMP_THERMAL_HIGH_LIMIT_52     52
  36#define BTEMP_THERMAL_HIGH_LIMIT_57     57
  37#define BTEMP_THERMAL_HIGH_LIMIT_62     62
  38
  39#define BTEMP_BATCTRL_CURR_SRC_7UA      7
  40#define BTEMP_BATCTRL_CURR_SRC_20UA     20
  41
  42#define BTEMP_BATCTRL_CURR_SRC_16UA     16
  43#define BTEMP_BATCTRL_CURR_SRC_18UA     18
  44
  45#define BTEMP_BATCTRL_CURR_SRC_60UA     60
  46#define BTEMP_BATCTRL_CURR_SRC_120UA    120
  47
  48/**
  49 * struct ab8500_btemp_interrupts - ab8500 interrupts
  50 * @name:       name of the interrupt
  51 * @isr         function pointer to the isr
  52 */
  53struct ab8500_btemp_interrupts {
  54        char *name;
  55        irqreturn_t (*isr)(int irq, void *data);
  56};
  57
  58struct ab8500_btemp_events {
  59        bool batt_rem;
  60        bool btemp_high;
  61        bool btemp_medhigh;
  62        bool btemp_lowmed;
  63        bool btemp_low;
  64        bool ac_conn;
  65        bool usb_conn;
  66};
  67
  68struct ab8500_btemp_ranges {
  69        int btemp_high_limit;
  70        int btemp_med_limit;
  71        int btemp_low_limit;
  72};
  73
  74/**
  75 * struct ab8500_btemp - ab8500 BTEMP device information
  76 * @dev:                Pointer to the structure device
  77 * @node:               List of AB8500 BTEMPs, hence prepared for reentrance
  78 * @curr_source:        What current source we use, in uA
  79 * @bat_temp:           Dispatched battery temperature in degree Celcius
  80 * @prev_bat_temp       Last measured battery temperature in degree Celcius
  81 * @parent:             Pointer to the struct ab8500
  82 * @gpadc:              Pointer to the struct gpadc
  83 * @fg:                 Pointer to the struct fg
  84 * @bm:                 Platform specific battery management information
  85 * @btemp_psy:          Structure for BTEMP specific battery properties
  86 * @events:             Structure for information about events triggered
  87 * @btemp_ranges:       Battery temperature range structure
  88 * @btemp_wq:           Work queue for measuring the temperature periodically
  89 * @btemp_periodic_work:        Work for measuring the temperature periodically
  90 * @initialized:        True if battery id read.
  91 */
  92struct ab8500_btemp {
  93        struct device *dev;
  94        struct list_head node;
  95        int curr_source;
  96        int bat_temp;
  97        int prev_bat_temp;
  98        struct ab8500 *parent;
  99        struct ab8500_gpadc *gpadc;
 100        struct ab8500_fg *fg;
 101        struct abx500_bm_data *bm;
 102        struct power_supply *btemp_psy;
 103        struct ab8500_btemp_events events;
 104        struct ab8500_btemp_ranges btemp_ranges;
 105        struct workqueue_struct *btemp_wq;
 106        struct delayed_work btemp_periodic_work;
 107        bool initialized;
 108};
 109
 110/* BTEMP power supply properties */
 111static enum power_supply_property ab8500_btemp_props[] = {
 112        POWER_SUPPLY_PROP_PRESENT,
 113        POWER_SUPPLY_PROP_ONLINE,
 114        POWER_SUPPLY_PROP_TECHNOLOGY,
 115        POWER_SUPPLY_PROP_TEMP,
 116};
 117
 118static LIST_HEAD(ab8500_btemp_list);
 119
 120/**
 121 * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP
 122 * (i.e. the first BTEMP in the instance list)
 123 */
 124struct ab8500_btemp *ab8500_btemp_get(void)
 125{
 126        struct ab8500_btemp *btemp;
 127        btemp = list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node);
 128
 129        return btemp;
 130}
 131EXPORT_SYMBOL(ab8500_btemp_get);
 132
 133/**
 134 * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
 135 * @di:         pointer to the ab8500_btemp structure
 136 * @v_batctrl:  measured batctrl voltage
 137 * @inst_curr:  measured instant current
 138 *
 139 * This function returns the battery resistance that is
 140 * derived from the BATCTRL voltage.
 141 * Returns value in Ohms.
 142 */
 143static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
 144        int v_batctrl, int inst_curr)
 145{
 146        int rbs;
 147
 148        if (is_ab8500_1p1_or_earlier(di->parent)) {
 149                /*
 150                 * For ABB cut1.0 and 1.1 BAT_CTRL is internally
 151                 * connected to 1.8V through a 450k resistor
 152                 */
 153                return (450000 * (v_batctrl)) / (1800 - v_batctrl);
 154        }
 155
 156        if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
 157                /*
 158                 * If the battery has internal NTC, we use the current
 159                 * source to calculate the resistance.
 160                 */
 161                rbs = (v_batctrl * 1000
 162                       - di->bm->gnd_lift_resistance * inst_curr)
 163                      / di->curr_source;
 164        } else {
 165                /*
 166                 * BAT_CTRL is internally
 167                 * connected to 1.8V through a 80k resistor
 168                 */
 169                rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl);
 170        }
 171
 172        return rbs;
 173}
 174
 175/**
 176 * ab8500_btemp_read_batctrl_voltage() - measure batctrl voltage
 177 * @di:         pointer to the ab8500_btemp structure
 178 *
 179 * This function returns the voltage on BATCTRL. Returns value in mV.
 180 */
 181static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di)
 182{
 183        int vbtemp;
 184        static int prev;
 185
 186        vbtemp = ab8500_gpadc_convert(di->gpadc, BAT_CTRL);
 187        if (vbtemp < 0) {
 188                dev_err(di->dev,
 189                        "%s gpadc conversion failed, using previous value",
 190                        __func__);
 191                return prev;
 192        }
 193        prev = vbtemp;
 194        return vbtemp;
 195}
 196
 197/**
 198 * ab8500_btemp_curr_source_enable() - enable/disable batctrl current source
 199 * @di:         pointer to the ab8500_btemp structure
 200 * @enable:     enable or disable the current source
 201 *
 202 * Enable or disable the current sources for the BatCtrl AD channel
 203 */
 204static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
 205        bool enable)
 206{
 207        int curr;
 208        int ret = 0;
 209
 210        /*
 211         * BATCTRL current sources are included on AB8500 cut2.0
 212         * and future versions
 213         */
 214        if (is_ab8500_1p1_or_earlier(di->parent))
 215                return 0;
 216
 217        /* Only do this for batteries with internal NTC */
 218        if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
 219
 220                if (is_ab8540(di->parent)) {
 221                        if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA)
 222                                curr = BAT_CTRL_60U_ENA;
 223                        else
 224                                curr = BAT_CTRL_120U_ENA;
 225                } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 226                        if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
 227                                curr = BAT_CTRL_16U_ENA;
 228                        else
 229                                curr = BAT_CTRL_18U_ENA;
 230                } else {
 231                        if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
 232                                curr = BAT_CTRL_7U_ENA;
 233                        else
 234                                curr = BAT_CTRL_20U_ENA;
 235                }
 236
 237                dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source);
 238
 239                ret = abx500_mask_and_set_register_interruptible(di->dev,
 240                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 241                        FORCE_BAT_CTRL_CMP_HIGH, FORCE_BAT_CTRL_CMP_HIGH);
 242                if (ret) {
 243                        dev_err(di->dev, "%s failed setting cmp_force\n",
 244                                __func__);
 245                        return ret;
 246                }
 247
 248                /*
 249                 * We have to wait one 32kHz cycle before enabling
 250                 * the current source, since ForceBatCtrlCmpHigh needs
 251                 * to be written in a separate cycle
 252                 */
 253                udelay(32);
 254
 255                ret = abx500_set_register_interruptible(di->dev,
 256                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 257                        FORCE_BAT_CTRL_CMP_HIGH | curr);
 258                if (ret) {
 259                        dev_err(di->dev, "%s failed enabling current source\n",
 260                                __func__);
 261                        goto disable_curr_source;
 262                }
 263        } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
 264                dev_dbg(di->dev, "Disable BATCTRL curr source\n");
 265
 266                if (is_ab8540(di->parent)) {
 267                        /* Write 0 to the curr bits */
 268                        ret = abx500_mask_and_set_register_interruptible(
 269                                di->dev,
 270                                AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 271                                BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
 272                                ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
 273                } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 274                        /* Write 0 to the curr bits */
 275                        ret = abx500_mask_and_set_register_interruptible(
 276                                di->dev,
 277                                AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 278                                BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
 279                                ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
 280                } else {
 281                        /* Write 0 to the curr bits */
 282                        ret = abx500_mask_and_set_register_interruptible(
 283                                di->dev,
 284                                AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 285                                BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
 286                                ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
 287                }
 288
 289                if (ret) {
 290                        dev_err(di->dev, "%s failed disabling current source\n",
 291                                __func__);
 292                        goto disable_curr_source;
 293                }
 294
 295                /* Enable Pull-Up and comparator */
 296                ret = abx500_mask_and_set_register_interruptible(di->dev,
 297                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 298                        BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
 299                        BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
 300                if (ret) {
 301                        dev_err(di->dev, "%s failed enabling PU and comp\n",
 302                                __func__);
 303                        goto enable_pu_comp;
 304                }
 305
 306                /*
 307                 * We have to wait one 32kHz cycle before disabling
 308                 * ForceBatCtrlCmpHigh since this needs to be written
 309                 * in a separate cycle
 310                 */
 311                udelay(32);
 312
 313                /* Disable 'force comparator' */
 314                ret = abx500_mask_and_set_register_interruptible(di->dev,
 315                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 316                        FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
 317                if (ret) {
 318                        dev_err(di->dev, "%s failed disabling force comp\n",
 319                                __func__);
 320                        goto disable_force_comp;
 321                }
 322        }
 323        return ret;
 324
 325        /*
 326         * We have to try unsetting FORCE_BAT_CTRL_CMP_HIGH one more time
 327         * if we got an error above
 328         */
 329disable_curr_source:
 330        if (is_ab8540(di->parent)) {
 331                /* Write 0 to the curr bits */
 332                ret = abx500_mask_and_set_register_interruptible(di->dev,
 333                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 334                        BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
 335                        ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
 336        } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 337                /* Write 0 to the curr bits */
 338                ret = abx500_mask_and_set_register_interruptible(di->dev,
 339                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 340                        BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
 341                        ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
 342        } else {
 343                /* Write 0 to the curr bits */
 344                ret = abx500_mask_and_set_register_interruptible(di->dev,
 345                        AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 346                        BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
 347                        ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
 348        }
 349
 350        if (ret) {
 351                dev_err(di->dev, "%s failed disabling current source\n",
 352                        __func__);
 353                return ret;
 354        }
 355enable_pu_comp:
 356        /* Enable Pull-Up and comparator */
 357        ret = abx500_mask_and_set_register_interruptible(di->dev,
 358                AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 359                BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
 360                BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
 361        if (ret) {
 362                dev_err(di->dev, "%s failed enabling PU and comp\n",
 363                        __func__);
 364                return ret;
 365        }
 366
 367disable_force_comp:
 368        /*
 369         * We have to wait one 32kHz cycle before disabling
 370         * ForceBatCtrlCmpHigh since this needs to be written
 371         * in a separate cycle
 372         */
 373        udelay(32);
 374
 375        /* Disable 'force comparator' */
 376        ret = abx500_mask_and_set_register_interruptible(di->dev,
 377                AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
 378                FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
 379        if (ret) {
 380                dev_err(di->dev, "%s failed disabling force comp\n",
 381                        __func__);
 382                return ret;
 383        }
 384
 385        return ret;
 386}
 387
 388/**
 389 * ab8500_btemp_get_batctrl_res() - get battery resistance
 390 * @di:         pointer to the ab8500_btemp structure
 391 *
 392 * This function returns the battery pack identification resistance.
 393 * Returns value in Ohms.
 394 */
 395static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
 396{
 397        int ret;
 398        int batctrl = 0;
 399        int res;
 400        int inst_curr;
 401        int i;
 402
 403        /*
 404         * BATCTRL current sources are included on AB8500 cut2.0
 405         * and future versions
 406         */
 407        ret = ab8500_btemp_curr_source_enable(di, true);
 408        if (ret) {
 409                dev_err(di->dev, "%s curr source enabled failed\n", __func__);
 410                return ret;
 411        }
 412
 413        if (!di->fg)
 414                di->fg = ab8500_fg_get();
 415        if (!di->fg) {
 416                dev_err(di->dev, "No fg found\n");
 417                return -EINVAL;
 418        }
 419
 420        ret = ab8500_fg_inst_curr_start(di->fg);
 421
 422        if (ret) {
 423                dev_err(di->dev, "Failed to start current measurement\n");
 424                return ret;
 425        }
 426
 427        do {
 428                msleep(20);
 429        } while (!ab8500_fg_inst_curr_started(di->fg));
 430
 431        i = 0;
 432
 433        do {
 434                batctrl += ab8500_btemp_read_batctrl_voltage(di);
 435                i++;
 436                msleep(20);
 437        } while (!ab8500_fg_inst_curr_done(di->fg));
 438        batctrl /= i;
 439
 440        ret = ab8500_fg_inst_curr_finalize(di->fg, &inst_curr);
 441        if (ret) {
 442                dev_err(di->dev, "Failed to finalize current measurement\n");
 443                return ret;
 444        }
 445
 446        res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr);
 447
 448        ret = ab8500_btemp_curr_source_enable(di, false);
 449        if (ret) {
 450                dev_err(di->dev, "%s curr source disable failed\n", __func__);
 451                return ret;
 452        }
 453
 454        dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n",
 455                __func__, batctrl, res, inst_curr, i);
 456
 457        return res;
 458}
 459
 460/**
 461 * ab8500_btemp_res_to_temp() - resistance to temperature
 462 * @di:         pointer to the ab8500_btemp structure
 463 * @tbl:        pointer to the resiatance to temperature table
 464 * @tbl_size:   size of the resistance to temperature table
 465 * @res:        resistance to calculate the temperature from
 466 *
 467 * This function returns the battery temperature in degrees Celcius
 468 * based on the NTC resistance.
 469 */
 470static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
 471        const struct abx500_res_to_temp *tbl, int tbl_size, int res)
 472{
 473        int i, temp;
 474        /*
 475         * Calculate the formula for the straight line
 476         * Simple interpolation if we are within
 477         * the resistance table limits, extrapolate
 478         * if resistance is outside the limits.
 479         */
 480        if (res > tbl[0].resist)
 481                i = 0;
 482        else if (res <= tbl[tbl_size - 1].resist)
 483                i = tbl_size - 2;
 484        else {
 485                i = 0;
 486                while (!(res <= tbl[i].resist &&
 487                        res > tbl[i + 1].resist))
 488                        i++;
 489        }
 490
 491        temp = tbl[i].temp + ((tbl[i + 1].temp - tbl[i].temp) *
 492                (res - tbl[i].resist)) / (tbl[i + 1].resist - tbl[i].resist);
 493        return temp;
 494}
 495
 496/**
 497 * ab8500_btemp_measure_temp() - measure battery temperature
 498 * @di:         pointer to the ab8500_btemp structure
 499 *
 500 * Returns battery temperature (on success) else the previous temperature
 501 */
 502static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
 503{
 504        int temp;
 505        static int prev;
 506        int rbat, rntc, vntc;
 507        u8 id;
 508
 509        id = di->bm->batt_id;
 510
 511        if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
 512                        id != BATTERY_UNKNOWN) {
 513
 514                rbat = ab8500_btemp_get_batctrl_res(di);
 515                if (rbat < 0) {
 516                        dev_err(di->dev, "%s get batctrl res failed\n",
 517                                __func__);
 518                        /*
 519                         * Return out-of-range temperature so that
 520                         * charging is stopped
 521                         */
 522                        return BTEMP_THERMAL_LOW_LIMIT;
 523                }
 524
 525                temp = ab8500_btemp_res_to_temp(di,
 526                        di->bm->bat_type[id].r_to_t_tbl,
 527                        di->bm->bat_type[id].n_temp_tbl_elements, rbat);
 528        } else {
 529                vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
 530                if (vntc < 0) {
 531                        dev_err(di->dev,
 532                                "%s gpadc conversion failed,"
 533                                " using previous value\n", __func__);
 534                        return prev;
 535                }
 536                /*
 537                 * The PCB NTC is sourced from VTVOUT via a 230kOhm
 538                 * resistor.
 539                 */
 540                rntc = 230000 * vntc / (VTVOUT_V - vntc);
 541
 542                temp = ab8500_btemp_res_to_temp(di,
 543                        di->bm->bat_type[id].r_to_t_tbl,
 544                        di->bm->bat_type[id].n_temp_tbl_elements, rntc);
 545                prev = temp;
 546        }
 547        dev_dbg(di->dev, "Battery temperature is %d\n", temp);
 548        return temp;
 549}
 550
 551/**
 552 * ab8500_btemp_id() - Identify the connected battery
 553 * @di:         pointer to the ab8500_btemp structure
 554 *
 555 * This function will try to identify the battery by reading the ID
 556 * resistor. Some brands use a combined ID resistor with a NTC resistor to
 557 * both be able to identify and to read the temperature of it.
 558 */
 559static int ab8500_btemp_id(struct ab8500_btemp *di)
 560{
 561        int res;
 562        u8 i;
 563        if (is_ab8540(di->parent))
 564                di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
 565        else if (is_ab9540(di->parent) || is_ab8505(di->parent))
 566                di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
 567        else
 568                di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
 569
 570        di->bm->batt_id = BATTERY_UNKNOWN;
 571
 572        res =  ab8500_btemp_get_batctrl_res(di);
 573        if (res < 0) {
 574                dev_err(di->dev, "%s get batctrl res failed\n", __func__);
 575                return -ENXIO;
 576        }
 577
 578        /* BATTERY_UNKNOWN is defined on position 0, skip it! */
 579        for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
 580                if ((res <= di->bm->bat_type[i].resis_high) &&
 581                        (res >= di->bm->bat_type[i].resis_low)) {
 582                        dev_dbg(di->dev, "Battery detected on %s"
 583                                " low %d < res %d < high: %d"
 584                                " index: %d\n",
 585                                di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
 586                                "BATCTRL" : "BATTEMP",
 587                                di->bm->bat_type[i].resis_low, res,
 588                                di->bm->bat_type[i].resis_high, i);
 589
 590                        di->bm->batt_id = i;
 591                        break;
 592                }
 593        }
 594
 595        if (di->bm->batt_id == BATTERY_UNKNOWN) {
 596                dev_warn(di->dev, "Battery identified as unknown"
 597                        ", resistance %d Ohm\n", res);
 598                return -ENXIO;
 599        }
 600
 601        /*
 602         * We only have to change current source if the
 603         * detected type is Type 1.
 604         */
 605        if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
 606            di->bm->batt_id == 1) {
 607                if (is_ab8540(di->parent)) {
 608                        dev_dbg(di->dev,
 609                                "Set BATCTRL current source to 60uA\n");
 610                        di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
 611                } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 612                        dev_dbg(di->dev,
 613                                "Set BATCTRL current source to 16uA\n");
 614                        di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
 615                } else {
 616                        dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
 617                        di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
 618                }
 619        }
 620
 621        return di->bm->batt_id;
 622}
 623
 624/**
 625 * ab8500_btemp_periodic_work() - Measuring the temperature periodically
 626 * @work:       pointer to the work_struct structure
 627 *
 628 * Work function for measuring the temperature periodically
 629 */
 630static void ab8500_btemp_periodic_work(struct work_struct *work)
 631{
 632        int interval;
 633        int bat_temp;
 634        struct ab8500_btemp *di = container_of(work,
 635                struct ab8500_btemp, btemp_periodic_work.work);
 636
 637        if (!di->initialized) {
 638                /* Identify the battery */
 639                if (ab8500_btemp_id(di) < 0)
 640                        dev_warn(di->dev, "failed to identify the battery\n");
 641        }
 642
 643        bat_temp = ab8500_btemp_measure_temp(di);
 644        /*
 645         * Filter battery temperature.
 646         * Allow direct updates on temperature only if two samples result in
 647         * same temperature. Else only allow 1 degree change from previous
 648         * reported value in the direction of the new measurement.
 649         */
 650        if ((bat_temp == di->prev_bat_temp) || !di->initialized) {
 651                if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
 652                        di->initialized = true;
 653                        di->bat_temp = bat_temp;
 654                        power_supply_changed(di->btemp_psy);
 655                }
 656        } else if (bat_temp < di->prev_bat_temp) {
 657                di->bat_temp--;
 658                power_supply_changed(di->btemp_psy);
 659        } else if (bat_temp > di->prev_bat_temp) {
 660                di->bat_temp++;
 661                power_supply_changed(di->btemp_psy);
 662        }
 663        di->prev_bat_temp = bat_temp;
 664
 665        if (di->events.ac_conn || di->events.usb_conn)
 666                interval = di->bm->temp_interval_chg;
 667        else
 668                interval = di->bm->temp_interval_nochg;
 669
 670        /* Schedule a new measurement */
 671        queue_delayed_work(di->btemp_wq,
 672                &di->btemp_periodic_work,
 673                round_jiffies(interval * HZ));
 674}
 675
 676/**
 677 * ab8500_btemp_batctrlindb_handler() - battery removal detected
 678 * @irq:       interrupt number
 679 * @_di:       void pointer that has to address of ab8500_btemp
 680 *
 681 * Returns IRQ status(IRQ_HANDLED)
 682 */
 683static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di)
 684{
 685        struct ab8500_btemp *di = _di;
 686        dev_err(di->dev, "Battery removal detected!\n");
 687
 688        di->events.batt_rem = true;
 689        power_supply_changed(di->btemp_psy);
 690
 691        return IRQ_HANDLED;
 692}
 693
 694/**
 695 * ab8500_btemp_templow_handler() - battery temp lower than 10 degrees
 696 * @irq:       interrupt number
 697 * @_di:       void pointer that has to address of ab8500_btemp
 698 *
 699 * Returns IRQ status(IRQ_HANDLED)
 700 */
 701static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di)
 702{
 703        struct ab8500_btemp *di = _di;
 704
 705        if (is_ab8500_3p3_or_earlier(di->parent)) {
 706                dev_dbg(di->dev, "Ignore false btemp low irq"
 707                        " for ABB cut 1.0, 1.1, 2.0 and 3.3\n");
 708        } else {
 709                dev_crit(di->dev, "Battery temperature lower than -10deg c\n");
 710
 711                di->events.btemp_low = true;
 712                di->events.btemp_high = false;
 713                di->events.btemp_medhigh = false;
 714                di->events.btemp_lowmed = false;
 715                power_supply_changed(di->btemp_psy);
 716        }
 717
 718        return IRQ_HANDLED;
 719}
 720
 721/**
 722 * ab8500_btemp_temphigh_handler() - battery temp higher than max temp
 723 * @irq:       interrupt number
 724 * @_di:       void pointer that has to address of ab8500_btemp
 725 *
 726 * Returns IRQ status(IRQ_HANDLED)
 727 */
 728static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di)
 729{
 730        struct ab8500_btemp *di = _di;
 731
 732        dev_crit(di->dev, "Battery temperature is higher than MAX temp\n");
 733
 734        di->events.btemp_high = true;
 735        di->events.btemp_medhigh = false;
 736        di->events.btemp_lowmed = false;
 737        di->events.btemp_low = false;
 738        power_supply_changed(di->btemp_psy);
 739
 740        return IRQ_HANDLED;
 741}
 742
 743/**
 744 * ab8500_btemp_lowmed_handler() - battery temp between low and medium
 745 * @irq:       interrupt number
 746 * @_di:       void pointer that has to address of ab8500_btemp
 747 *
 748 * Returns IRQ status(IRQ_HANDLED)
 749 */
 750static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di)
 751{
 752        struct ab8500_btemp *di = _di;
 753
 754        dev_dbg(di->dev, "Battery temperature is between low and medium\n");
 755
 756        di->events.btemp_lowmed = true;
 757        di->events.btemp_medhigh = false;
 758        di->events.btemp_high = false;
 759        di->events.btemp_low = false;
 760        power_supply_changed(di->btemp_psy);
 761
 762        return IRQ_HANDLED;
 763}
 764
 765/**
 766 * ab8500_btemp_medhigh_handler() - battery temp between medium and high
 767 * @irq:       interrupt number
 768 * @_di:       void pointer that has to address of ab8500_btemp
 769 *
 770 * Returns IRQ status(IRQ_HANDLED)
 771 */
 772static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di)
 773{
 774        struct ab8500_btemp *di = _di;
 775
 776        dev_dbg(di->dev, "Battery temperature is between medium and high\n");
 777
 778        di->events.btemp_medhigh = true;
 779        di->events.btemp_lowmed = false;
 780        di->events.btemp_high = false;
 781        di->events.btemp_low = false;
 782        power_supply_changed(di->btemp_psy);
 783
 784        return IRQ_HANDLED;
 785}
 786
 787/**
 788 * ab8500_btemp_periodic() - Periodic temperature measurements
 789 * @di:         pointer to the ab8500_btemp structure
 790 * @enable:     enable or disable periodic temperature measurements
 791 *
 792 * Starts of stops periodic temperature measurements. Periodic measurements
 793 * should only be done when a charger is connected.
 794 */
 795static void ab8500_btemp_periodic(struct ab8500_btemp *di,
 796        bool enable)
 797{
 798        dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n",
 799                enable);
 800        /*
 801         * Make sure a new measurement is done directly by cancelling
 802         * any pending work
 803         */
 804        cancel_delayed_work_sync(&di->btemp_periodic_work);
 805
 806        if (enable)
 807                queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0);
 808}
 809
 810/**
 811 * ab8500_btemp_get_temp() - get battery temperature
 812 * @di:         pointer to the ab8500_btemp structure
 813 *
 814 * Returns battery temperature
 815 */
 816int ab8500_btemp_get_temp(struct ab8500_btemp *di)
 817{
 818        int temp = 0;
 819
 820        /*
 821         * The BTEMP events are not reliabe on AB8500 cut3.3
 822         * and prior versions
 823         */
 824        if (is_ab8500_3p3_or_earlier(di->parent)) {
 825                temp = di->bat_temp * 10;
 826        } else {
 827                if (di->events.btemp_low) {
 828                        if (temp > di->btemp_ranges.btemp_low_limit)
 829                                temp = di->btemp_ranges.btemp_low_limit * 10;
 830                        else
 831                                temp = di->bat_temp * 10;
 832                } else if (di->events.btemp_high) {
 833                        if (temp < di->btemp_ranges.btemp_high_limit)
 834                                temp = di->btemp_ranges.btemp_high_limit * 10;
 835                        else
 836                                temp = di->bat_temp * 10;
 837                } else if (di->events.btemp_lowmed) {
 838                        if (temp > di->btemp_ranges.btemp_med_limit)
 839                                temp = di->btemp_ranges.btemp_med_limit * 10;
 840                        else
 841                                temp = di->bat_temp * 10;
 842                } else if (di->events.btemp_medhigh) {
 843                        if (temp < di->btemp_ranges.btemp_med_limit)
 844                                temp = di->btemp_ranges.btemp_med_limit * 10;
 845                        else
 846                                temp = di->bat_temp * 10;
 847                } else
 848                        temp = di->bat_temp * 10;
 849        }
 850        return temp;
 851}
 852EXPORT_SYMBOL(ab8500_btemp_get_temp);
 853
 854/**
 855 * ab8500_btemp_get_batctrl_temp() - get the temperature
 856 * @btemp:      pointer to the btemp structure
 857 *
 858 * Returns the batctrl temperature in millidegrees
 859 */
 860int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
 861{
 862        return btemp->bat_temp * 1000;
 863}
 864EXPORT_SYMBOL(ab8500_btemp_get_batctrl_temp);
 865
 866/**
 867 * ab8500_btemp_get_property() - get the btemp properties
 868 * @psy:        pointer to the power_supply structure
 869 * @psp:        pointer to the power_supply_property structure
 870 * @val:        pointer to the power_supply_propval union
 871 *
 872 * This function gets called when an application tries to get the btemp
 873 * properties by reading the sysfs files.
 874 * online:      presence of the battery
 875 * present:     presence of the battery
 876 * technology:  battery technology
 877 * temp:        battery temperature
 878 * Returns error code in case of failure else 0(on success)
 879 */
 880static int ab8500_btemp_get_property(struct power_supply *psy,
 881        enum power_supply_property psp,
 882        union power_supply_propval *val)
 883{
 884        struct ab8500_btemp *di = power_supply_get_drvdata(psy);
 885
 886        switch (psp) {
 887        case POWER_SUPPLY_PROP_PRESENT:
 888        case POWER_SUPPLY_PROP_ONLINE:
 889                if (di->events.batt_rem)
 890                        val->intval = 0;
 891                else
 892                        val->intval = 1;
 893                break;
 894        case POWER_SUPPLY_PROP_TECHNOLOGY:
 895                val->intval = di->bm->bat_type[di->bm->batt_id].name;
 896                break;
 897        case POWER_SUPPLY_PROP_TEMP:
 898                val->intval = ab8500_btemp_get_temp(di);
 899                break;
 900        default:
 901                return -EINVAL;
 902        }
 903        return 0;
 904}
 905
 906static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
 907{
 908        struct power_supply *psy;
 909        struct power_supply *ext = dev_get_drvdata(dev);
 910        const char **supplicants = (const char **)ext->supplied_to;
 911        struct ab8500_btemp *di;
 912        union power_supply_propval ret;
 913        int j;
 914
 915        psy = (struct power_supply *)data;
 916        di = power_supply_get_drvdata(psy);
 917
 918        /*
 919         * For all psy where the name of your driver
 920         * appears in any supplied_to
 921         */
 922        j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
 923        if (j < 0)
 924                return 0;
 925
 926        /* Go through all properties for the psy */
 927        for (j = 0; j < ext->desc->num_properties; j++) {
 928                enum power_supply_property prop;
 929                prop = ext->desc->properties[j];
 930
 931                if (power_supply_get_property(ext, prop, &ret))
 932                        continue;
 933
 934                switch (prop) {
 935                case POWER_SUPPLY_PROP_PRESENT:
 936                        switch (ext->desc->type) {
 937                        case POWER_SUPPLY_TYPE_MAINS:
 938                                /* AC disconnected */
 939                                if (!ret.intval && di->events.ac_conn) {
 940                                        di->events.ac_conn = false;
 941                                }
 942                                /* AC connected */
 943                                else if (ret.intval && !di->events.ac_conn) {
 944                                        di->events.ac_conn = true;
 945                                        if (!di->events.usb_conn)
 946                                                ab8500_btemp_periodic(di, true);
 947                                }
 948                                break;
 949                        case POWER_SUPPLY_TYPE_USB:
 950                                /* USB disconnected */
 951                                if (!ret.intval && di->events.usb_conn) {
 952                                        di->events.usb_conn = false;
 953                                }
 954                                /* USB connected */
 955                                else if (ret.intval && !di->events.usb_conn) {
 956                                        di->events.usb_conn = true;
 957                                        if (!di->events.ac_conn)
 958                                                ab8500_btemp_periodic(di, true);
 959                                }
 960                                break;
 961                        default:
 962                                break;
 963                        }
 964                        break;
 965                default:
 966                        break;
 967                }
 968        }
 969        return 0;
 970}
 971
 972/**
 973 * ab8500_btemp_external_power_changed() - callback for power supply changes
 974 * @psy:       pointer to the structure power_supply
 975 *
 976 * This function is pointing to the function pointer external_power_changed
 977 * of the structure power_supply.
 978 * This function gets executed when there is a change in the external power
 979 * supply to the btemp.
 980 */
 981static void ab8500_btemp_external_power_changed(struct power_supply *psy)
 982{
 983        struct ab8500_btemp *di = power_supply_get_drvdata(psy);
 984
 985        class_for_each_device(power_supply_class, NULL,
 986                di->btemp_psy, ab8500_btemp_get_ext_psy_data);
 987}
 988
 989/* ab8500 btemp driver interrupts and their respective isr */
 990static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = {
 991        {"BAT_CTRL_INDB", ab8500_btemp_batctrlindb_handler},
 992        {"BTEMP_LOW", ab8500_btemp_templow_handler},
 993        {"BTEMP_HIGH", ab8500_btemp_temphigh_handler},
 994        {"BTEMP_LOW_MEDIUM", ab8500_btemp_lowmed_handler},
 995        {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler},
 996};
 997
 998#if defined(CONFIG_PM)
 999static int ab8500_btemp_resume(struct platform_device *pdev)
1000{
1001        struct ab8500_btemp *di = platform_get_drvdata(pdev);
1002
1003        ab8500_btemp_periodic(di, true);
1004
1005        return 0;
1006}
1007
1008static int ab8500_btemp_suspend(struct platform_device *pdev,
1009        pm_message_t state)
1010{
1011        struct ab8500_btemp *di = platform_get_drvdata(pdev);
1012
1013        ab8500_btemp_periodic(di, false);
1014
1015        return 0;
1016}
1017#else
1018#define ab8500_btemp_suspend      NULL
1019#define ab8500_btemp_resume       NULL
1020#endif
1021
1022static int ab8500_btemp_remove(struct platform_device *pdev)
1023{
1024        struct ab8500_btemp *di = platform_get_drvdata(pdev);
1025        int i, irq;
1026
1027        /* Disable interrupts */
1028        for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1029                irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1030                free_irq(irq, di);
1031        }
1032
1033        /* Delete the work queue */
1034        destroy_workqueue(di->btemp_wq);
1035
1036        flush_scheduled_work();
1037        power_supply_unregister(di->btemp_psy);
1038
1039        return 0;
1040}
1041
1042static char *supply_interface[] = {
1043        "ab8500_chargalg",
1044        "ab8500_fg",
1045};
1046
1047static const struct power_supply_desc ab8500_btemp_desc = {
1048        .name                   = "ab8500_btemp",
1049        .type                   = POWER_SUPPLY_TYPE_BATTERY,
1050        .properties             = ab8500_btemp_props,
1051        .num_properties         = ARRAY_SIZE(ab8500_btemp_props),
1052        .get_property           = ab8500_btemp_get_property,
1053        .external_power_changed = ab8500_btemp_external_power_changed,
1054};
1055
1056static int ab8500_btemp_probe(struct platform_device *pdev)
1057{
1058        struct device_node *np = pdev->dev.of_node;
1059        struct abx500_bm_data *plat = pdev->dev.platform_data;
1060        struct power_supply_config psy_cfg = {};
1061        struct ab8500_btemp *di;
1062        int irq, i, ret = 0;
1063        u8 val;
1064
1065        di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
1066        if (!di) {
1067                dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
1068                return -ENOMEM;
1069        }
1070
1071        if (!plat) {
1072                dev_err(&pdev->dev, "no battery management data supplied\n");
1073                return -EINVAL;
1074        }
1075        di->bm = plat;
1076
1077        if (np) {
1078                ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
1079                if (ret) {
1080                        dev_err(&pdev->dev, "failed to get battery information\n");
1081                        return ret;
1082                }
1083        }
1084
1085        /* get parent data */
1086        di->dev = &pdev->dev;
1087        di->parent = dev_get_drvdata(pdev->dev.parent);
1088        di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1089
1090        di->initialized = false;
1091
1092        psy_cfg.supplied_to = supply_interface;
1093        psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
1094        psy_cfg.drv_data = di;
1095
1096        /* Create a work queue for the btemp */
1097        di->btemp_wq =
1098                alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0);
1099        if (di->btemp_wq == NULL) {
1100                dev_err(di->dev, "failed to create work queue\n");
1101                return -ENOMEM;
1102        }
1103
1104        /* Init work for measuring temperature periodically */
1105        INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
1106                ab8500_btemp_periodic_work);
1107
1108        /* Set BTEMP thermal limits. Low and Med are fixed */
1109        di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
1110        di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
1111
1112        ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
1113                AB8500_BTEMP_HIGH_TH, &val);
1114        if (ret < 0) {
1115                dev_err(di->dev, "%s ab8500 read failed\n", __func__);
1116                goto free_btemp_wq;
1117        }
1118        switch (val) {
1119        case BTEMP_HIGH_TH_57_0:
1120        case BTEMP_HIGH_TH_57_1:
1121                di->btemp_ranges.btemp_high_limit =
1122                        BTEMP_THERMAL_HIGH_LIMIT_57;
1123                break;
1124        case BTEMP_HIGH_TH_52:
1125                di->btemp_ranges.btemp_high_limit =
1126                        BTEMP_THERMAL_HIGH_LIMIT_52;
1127                break;
1128        case BTEMP_HIGH_TH_62:
1129                di->btemp_ranges.btemp_high_limit =
1130                        BTEMP_THERMAL_HIGH_LIMIT_62;
1131                break;
1132        }
1133
1134        /* Register BTEMP power supply class */
1135        di->btemp_psy = power_supply_register(di->dev, &ab8500_btemp_desc,
1136                                              &psy_cfg);
1137        if (IS_ERR(di->btemp_psy)) {
1138                dev_err(di->dev, "failed to register BTEMP psy\n");
1139                ret = PTR_ERR(di->btemp_psy);
1140                goto free_btemp_wq;
1141        }
1142
1143        /* Register interrupts */
1144        for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1145                irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1146                ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr,
1147                        IRQF_SHARED | IRQF_NO_SUSPEND,
1148                        ab8500_btemp_irq[i].name, di);
1149
1150                if (ret) {
1151                        dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
1152                                , ab8500_btemp_irq[i].name, irq, ret);
1153                        goto free_irq;
1154                }
1155                dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
1156                        ab8500_btemp_irq[i].name, irq, ret);
1157        }
1158
1159        platform_set_drvdata(pdev, di);
1160
1161        /* Kick off periodic temperature measurements */
1162        ab8500_btemp_periodic(di, true);
1163        list_add_tail(&di->node, &ab8500_btemp_list);
1164
1165        return ret;
1166
1167free_irq:
1168        power_supply_unregister(di->btemp_psy);
1169
1170        /* We also have to free all successfully registered irqs */
1171        for (i = i - 1; i >= 0; i--) {
1172                irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1173                free_irq(irq, di);
1174        }
1175free_btemp_wq:
1176        destroy_workqueue(di->btemp_wq);
1177        return ret;
1178}
1179
1180static const struct of_device_id ab8500_btemp_match[] = {
1181        { .compatible = "stericsson,ab8500-btemp", },
1182        { },
1183};
1184
1185static struct platform_driver ab8500_btemp_driver = {
1186        .probe = ab8500_btemp_probe,
1187        .remove = ab8500_btemp_remove,
1188        .suspend = ab8500_btemp_suspend,
1189        .resume = ab8500_btemp_resume,
1190        .driver = {
1191                .name = "ab8500-btemp",
1192                .of_match_table = ab8500_btemp_match,
1193        },
1194};
1195
1196static int __init ab8500_btemp_init(void)
1197{
1198        return platform_driver_register(&ab8500_btemp_driver);
1199}
1200
1201static void __exit ab8500_btemp_exit(void)
1202{
1203        platform_driver_unregister(&ab8500_btemp_driver);
1204}
1205
1206device_initcall(ab8500_btemp_init);
1207module_exit(ab8500_btemp_exit);
1208
1209MODULE_LICENSE("GPL v2");
1210MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
1211MODULE_ALIAS("platform:ab8500-btemp");
1212MODULE_DESCRIPTION("AB8500 battery temperature driver");
1213