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