linux/drivers/mfd/twl4030-madc.c
<<
>>
Prefs
   1/*
   2 *
   3 * TWL4030 MADC module driver-This driver monitors the real time
   4 * conversion of analog signals like battery temperature,
   5 * battery type, battery level etc.
   6 *
   7 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   8 * J Keerthy <j-keerthy@ti.com>
   9 *
  10 * Based on twl4030-madc.c
  11 * Copyright (C) 2008 Nokia Corporation
  12 * Mikko Ylinen <mikko.k.ylinen@nokia.com>
  13 *
  14 * Amit Kucheria <amit.kucheria@canonical.com>
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License
  18 * version 2 as published by the Free Software Foundation.
  19 *
  20 * This program is distributed in the hope that it will be useful, but
  21 * WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  23 * General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  28 * 02110-1301 USA
  29 *
  30 */
  31
  32#include <linux/init.h>
  33#include <linux/device.h>
  34#include <linux/interrupt.h>
  35#include <linux/kernel.h>
  36#include <linux/delay.h>
  37#include <linux/platform_device.h>
  38#include <linux/slab.h>
  39#include <linux/i2c/twl.h>
  40#include <linux/i2c/twl4030-madc.h>
  41#include <linux/module.h>
  42#include <linux/stddef.h>
  43#include <linux/mutex.h>
  44#include <linux/bitops.h>
  45#include <linux/jiffies.h>
  46#include <linux/types.h>
  47#include <linux/gfp.h>
  48#include <linux/err.h>
  49
  50/*
  51 * struct twl4030_madc_data - a container for madc info
  52 * @dev - pointer to device structure for madc
  53 * @lock - mutex protecting this data structure
  54 * @requests - Array of request struct corresponding to SW1, SW2 and RT
  55 * @imr - Interrupt mask register of MADC
  56 * @isr - Interrupt status register of MADC
  57 */
  58struct twl4030_madc_data {
  59        struct device *dev;
  60        struct mutex lock;      /* mutex protecting this data structure */
  61        struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
  62        int imr;
  63        int isr;
  64};
  65
  66static struct twl4030_madc_data *twl4030_madc;
  67
  68struct twl4030_prescale_divider_ratios {
  69        s16 numerator;
  70        s16 denominator;
  71};
  72
  73static const struct twl4030_prescale_divider_ratios
  74twl4030_divider_ratios[16] = {
  75        {1, 1},         /* CHANNEL 0 No Prescaler */
  76        {1, 1},         /* CHANNEL 1 No Prescaler */
  77        {6, 10},        /* CHANNEL 2 */
  78        {6, 10},        /* CHANNEL 3 */
  79        {6, 10},        /* CHANNEL 4 */
  80        {6, 10},        /* CHANNEL 5 */
  81        {6, 10},        /* CHANNEL 6 */
  82        {6, 10},        /* CHANNEL 7 */
  83        {3, 14},        /* CHANNEL 8 */
  84        {1, 3},         /* CHANNEL 9 */
  85        {1, 1},         /* CHANNEL 10 No Prescaler */
  86        {15, 100},      /* CHANNEL 11 */
  87        {1, 4},         /* CHANNEL 12 */
  88        {1, 1},         /* CHANNEL 13 Reserved channels */
  89        {1, 1},         /* CHANNEL 14 Reseved channels */
  90        {5, 11},        /* CHANNEL 15 */
  91};
  92
  93
  94/*
  95 * Conversion table from -3 to 55 degree Celcius
  96 */
  97static int therm_tbl[] = {
  9830800,  29500,  28300,  27100,
  9926000,  24900,  23900,  22900,  22000,  21100,  20300,  19400,  18700,  17900,
 10017200,  16500,  15900,  15300,  14700,  14100,  13600,  13100,  12600,  12100,
 10111600,  11200,  10800,  10400,  10000,  9630,   9280,   8950,   8620,   8310,
 1028020,   7730,   7460,   7200,   6950,   6710,   6470,   6250,   6040,   5830,
 1035640,   5450,   5260,   5090,   4920,   4760,   4600,   4450,   4310,   4170,
 1044040,   3910,   3790,   3670,   3550
 105};
 106
 107/*
 108 * Structure containing the registers
 109 * of different conversion methods supported by MADC.
 110 * Hardware or RT real time conversion request initiated by external host
 111 * processor for RT Signal conversions.
 112 * External host processors can also request for non RT conversions
 113 * SW1 and SW2 software conversions also called asynchronous or GPC request.
 114 */
 115static
 116const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
 117        [TWL4030_MADC_RT] = {
 118                             .sel = TWL4030_MADC_RTSELECT_LSB,
 119                             .avg = TWL4030_MADC_RTAVERAGE_LSB,
 120                             .rbase = TWL4030_MADC_RTCH0_LSB,
 121                             },
 122        [TWL4030_MADC_SW1] = {
 123                              .sel = TWL4030_MADC_SW1SELECT_LSB,
 124                              .avg = TWL4030_MADC_SW1AVERAGE_LSB,
 125                              .rbase = TWL4030_MADC_GPCH0_LSB,
 126                              .ctrl = TWL4030_MADC_CTRL_SW1,
 127                              },
 128        [TWL4030_MADC_SW2] = {
 129                              .sel = TWL4030_MADC_SW2SELECT_LSB,
 130                              .avg = TWL4030_MADC_SW2AVERAGE_LSB,
 131                              .rbase = TWL4030_MADC_GPCH0_LSB,
 132                              .ctrl = TWL4030_MADC_CTRL_SW2,
 133                              },
 134};
 135
 136/*
 137 * Function to read a particular channel value.
 138 * @madc - pointer to struct twl4030_madc_data
 139 * @reg - lsb of ADC Channel
 140 * If the i2c read fails it returns an error else returns 0.
 141 */
 142static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
 143{
 144        u8 msb, lsb;
 145        int ret;
 146        /*
 147         * For each ADC channel, we have MSB and LSB register pair. MSB address
 148         * is always LSB address+1. reg parameter is the address of LSB register
 149         */
 150        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1);
 151        if (ret) {
 152                dev_err(madc->dev, "unable to read MSB register 0x%X\n",
 153                        reg + 1);
 154                return ret;
 155        }
 156        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg);
 157        if (ret) {
 158                dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg);
 159                return ret;
 160        }
 161
 162        return (int)(((msb << 8) | lsb) >> 6);
 163}
 164
 165/*
 166 * Return battery temperature
 167 * Or < 0 on failure.
 168 */
 169static int twl4030battery_temperature(int raw_volt)
 170{
 171        u8 val;
 172        int temp, curr, volt, res, ret;
 173
 174        volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
 175        /* Getting and calculating the supply current in micro ampers */
 176        ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
 177                REG_BCICTL2);
 178        if (ret < 0)
 179                return ret;
 180        curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
 181        /* Getting and calculating the thermistor resistance in ohms */
 182        res = volt * 1000 / curr;
 183        /* calculating temperature */
 184        for (temp = 58; temp >= 0; temp--) {
 185                int actual = therm_tbl[temp];
 186
 187                if ((actual - res) >= 0)
 188                        break;
 189        }
 190
 191        return temp + 1;
 192}
 193
 194static int twl4030battery_current(int raw_volt)
 195{
 196        int ret;
 197        u8 val;
 198
 199        ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
 200                TWL4030_BCI_BCICTL1);
 201        if (ret)
 202                return ret;
 203        if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
 204                return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
 205        else /* slope of 0.88 mV/mA */
 206                return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
 207}
 208/*
 209 * Function to read channel values
 210 * @madc - pointer to twl4030_madc_data struct
 211 * @reg_base - Base address of the first channel
 212 * @Channels - 16 bit bitmap. If the bit is set, channel value is read
 213 * @buf - The channel values are stored here. if read fails error
 214 * @raw - Return raw values without conversion
 215 * value is stored
 216 * Returns the number of successfully read channels.
 217 */
 218static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
 219                                      u8 reg_base, unsigned
 220                                      long channels, int *buf,
 221                                      bool raw)
 222{
 223        int count = 0, count_req = 0, i;
 224        u8 reg;
 225
 226        for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
 227                reg = reg_base + 2 * i;
 228                buf[i] = twl4030_madc_channel_raw_read(madc, reg);
 229                if (buf[i] < 0) {
 230                        dev_err(madc->dev,
 231                                "Unable to read register 0x%X\n", reg);
 232                        count_req++;
 233                        continue;
 234                }
 235                if (raw) {
 236                        count++;
 237                        continue;
 238                }
 239                switch (i) {
 240                case 10:
 241                        buf[i] = twl4030battery_current(buf[i]);
 242                        if (buf[i] < 0) {
 243                                dev_err(madc->dev, "err reading current\n");
 244                                count_req++;
 245                        } else {
 246                                count++;
 247                                buf[i] = buf[i] - 750;
 248                        }
 249                        break;
 250                case 1:
 251                        buf[i] = twl4030battery_temperature(buf[i]);
 252                        if (buf[i] < 0) {
 253                                dev_err(madc->dev, "err reading temperature\n");
 254                                count_req++;
 255                        } else {
 256                                buf[i] -= 3;
 257                                count++;
 258                        }
 259                        break;
 260                default:
 261                        count++;
 262                        /* Analog Input (V) = conv_result * step_size / R
 263                         * conv_result = decimal value of 10-bit conversion
 264                         *               result
 265                         * step size = 1.5 / (2 ^ 10 -1)
 266                         * R = Prescaler ratio for input channels.
 267                         * Result given in mV hence multiplied by 1000.
 268                         */
 269                        buf[i] = (buf[i] * 3 * 1000 *
 270                                 twl4030_divider_ratios[i].denominator)
 271                                / (2 * 1023 *
 272                                twl4030_divider_ratios[i].numerator);
 273                }
 274        }
 275        if (count_req)
 276                dev_err(madc->dev, "%d channel conversion failed\n", count_req);
 277
 278        return count;
 279}
 280
 281/*
 282 * Enables irq.
 283 * @madc - pointer to twl4030_madc_data struct
 284 * @id - irq number to be enabled
 285 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
 286 * corresponding to RT, SW1, SW2 conversion requests.
 287 * If the i2c read fails it returns an error else returns 0.
 288 */
 289static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
 290{
 291        u8 val;
 292        int ret;
 293
 294        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
 295        if (ret) {
 296                dev_err(madc->dev, "unable to read imr register 0x%X\n",
 297                        madc->imr);
 298                return ret;
 299        }
 300        val &= ~(1 << id);
 301        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
 302        if (ret) {
 303                dev_err(madc->dev,
 304                        "unable to write imr register 0x%X\n", madc->imr);
 305                return ret;
 306
 307        }
 308
 309        return 0;
 310}
 311
 312/*
 313 * Disables irq.
 314 * @madc - pointer to twl4030_madc_data struct
 315 * @id - irq number to be disabled
 316 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
 317 * corresponding to RT, SW1, SW2 conversion requests.
 318 * Returns error if i2c read/write fails.
 319 */
 320static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
 321{
 322        u8 val;
 323        int ret;
 324
 325        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
 326        if (ret) {
 327                dev_err(madc->dev, "unable to read imr register 0x%X\n",
 328                        madc->imr);
 329                return ret;
 330        }
 331        val |= (1 << id);
 332        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
 333        if (ret) {
 334                dev_err(madc->dev,
 335                        "unable to write imr register 0x%X\n", madc->imr);
 336                return ret;
 337        }
 338
 339        return 0;
 340}
 341
 342static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
 343{
 344        struct twl4030_madc_data *madc = _madc;
 345        const struct twl4030_madc_conversion_method *method;
 346        u8 isr_val, imr_val;
 347        int i, len, ret;
 348        struct twl4030_madc_request *r;
 349
 350        mutex_lock(&madc->lock);
 351        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
 352        if (ret) {
 353                dev_err(madc->dev, "unable to read isr register 0x%X\n",
 354                        madc->isr);
 355                goto err_i2c;
 356        }
 357        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
 358        if (ret) {
 359                dev_err(madc->dev, "unable to read imr register 0x%X\n",
 360                        madc->imr);
 361                goto err_i2c;
 362        }
 363        isr_val &= ~imr_val;
 364        for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
 365                if (!(isr_val & (1 << i)))
 366                        continue;
 367                ret = twl4030_madc_disable_irq(madc, i);
 368                if (ret < 0)
 369                        dev_dbg(madc->dev, "Disable interrupt failed%d\n", i);
 370                madc->requests[i].result_pending = 1;
 371        }
 372        for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
 373                r = &madc->requests[i];
 374                /* No pending results for this method, move to next one */
 375                if (!r->result_pending)
 376                        continue;
 377                method = &twl4030_conversion_methods[r->method];
 378                /* Read results */
 379                len = twl4030_madc_read_channels(madc, method->rbase,
 380                                                 r->channels, r->rbuf, r->raw);
 381                /* Return results to caller */
 382                if (r->func_cb != NULL) {
 383                        r->func_cb(len, r->channels, r->rbuf);
 384                        r->func_cb = NULL;
 385                }
 386                /* Free request */
 387                r->result_pending = 0;
 388                r->active = 0;
 389        }
 390        mutex_unlock(&madc->lock);
 391
 392        return IRQ_HANDLED;
 393
 394err_i2c:
 395        /*
 396         * In case of error check whichever request is active
 397         * and service the same.
 398         */
 399        for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
 400                r = &madc->requests[i];
 401                if (r->active == 0)
 402                        continue;
 403                method = &twl4030_conversion_methods[r->method];
 404                /* Read results */
 405                len = twl4030_madc_read_channels(madc, method->rbase,
 406                                                 r->channels, r->rbuf, r->raw);
 407                /* Return results to caller */
 408                if (r->func_cb != NULL) {
 409                        r->func_cb(len, r->channels, r->rbuf);
 410                        r->func_cb = NULL;
 411                }
 412                /* Free request */
 413                r->result_pending = 0;
 414                r->active = 0;
 415        }
 416        mutex_unlock(&madc->lock);
 417
 418        return IRQ_HANDLED;
 419}
 420
 421static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
 422                                struct twl4030_madc_request *req)
 423{
 424        struct twl4030_madc_request *p;
 425        int ret;
 426
 427        p = &madc->requests[req->method];
 428        memcpy(p, req, sizeof(*req));
 429        ret = twl4030_madc_enable_irq(madc, req->method);
 430        if (ret < 0) {
 431                dev_err(madc->dev, "enable irq failed!!\n");
 432                return ret;
 433        }
 434
 435        return 0;
 436}
 437
 438/*
 439 * Function which enables the madc conversion
 440 * by writing to the control register.
 441 * @madc - pointer to twl4030_madc_data struct
 442 * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
 443 * corresponding to RT SW1 or SW2 conversion methods.
 444 * Returns 0 if succeeds else a negative error value
 445 */
 446static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
 447                                         int conv_method)
 448{
 449        const struct twl4030_madc_conversion_method *method;
 450        int ret = 0;
 451        method = &twl4030_conversion_methods[conv_method];
 452        switch (conv_method) {
 453        case TWL4030_MADC_SW1:
 454        case TWL4030_MADC_SW2:
 455                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
 456                                       TWL4030_MADC_SW_START, method->ctrl);
 457                if (ret) {
 458                        dev_err(madc->dev,
 459                                "unable to write ctrl register 0x%X\n",
 460                                method->ctrl);
 461                        return ret;
 462                }
 463                break;
 464        default:
 465                break;
 466        }
 467
 468        return 0;
 469}
 470
 471/*
 472 * Function that waits for conversion to be ready
 473 * @madc - pointer to twl4030_madc_data struct
 474 * @timeout_ms - timeout value in milliseconds
 475 * @status_reg - ctrl register
 476 * returns 0 if succeeds else a negative error value
 477 */
 478static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
 479                                              unsigned int timeout_ms,
 480                                              u8 status_reg)
 481{
 482        unsigned long timeout;
 483        int ret;
 484
 485        timeout = jiffies + msecs_to_jiffies(timeout_ms);
 486        do {
 487                u8 reg;
 488
 489                ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
 490                if (ret) {
 491                        dev_err(madc->dev,
 492                                "unable to read status register 0x%X\n",
 493                                status_reg);
 494                        return ret;
 495                }
 496                if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
 497                        return 0;
 498                usleep_range(500, 2000);
 499        } while (!time_after(jiffies, timeout));
 500        dev_err(madc->dev, "conversion timeout!\n");
 501
 502        return -EAGAIN;
 503}
 504
 505/*
 506 * An exported function which can be called from other kernel drivers.
 507 * @req twl4030_madc_request structure
 508 * req->rbuf will be filled with read values of channels based on the
 509 * channel index. If a particular channel reading fails there will
 510 * be a negative error value in the corresponding array element.
 511 * returns 0 if succeeds else error value
 512 */
 513int twl4030_madc_conversion(struct twl4030_madc_request *req)
 514{
 515        const struct twl4030_madc_conversion_method *method;
 516        u8 ch_msb, ch_lsb;
 517        int ret;
 518
 519        if (!req || !twl4030_madc)
 520                return -EINVAL;
 521
 522        mutex_lock(&twl4030_madc->lock);
 523        if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
 524                ret = -EINVAL;
 525                goto out;
 526        }
 527        /* Do we have a conversion request ongoing */
 528        if (twl4030_madc->requests[req->method].active) {
 529                ret = -EBUSY;
 530                goto out;
 531        }
 532        ch_msb = (req->channels >> 8) & 0xff;
 533        ch_lsb = req->channels & 0xff;
 534        method = &twl4030_conversion_methods[req->method];
 535        /* Select channels to be converted */
 536        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1);
 537        if (ret) {
 538                dev_err(twl4030_madc->dev,
 539                        "unable to write sel register 0x%X\n", method->sel + 1);
 540                goto out;
 541        }
 542        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
 543        if (ret) {
 544                dev_err(twl4030_madc->dev,
 545                        "unable to write sel register 0x%X\n", method->sel + 1);
 546                goto out;
 547        }
 548        /* Select averaging for all channels if do_avg is set */
 549        if (req->do_avg) {
 550                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
 551                                       ch_msb, method->avg + 1);
 552                if (ret) {
 553                        dev_err(twl4030_madc->dev,
 554                                "unable to write avg register 0x%X\n",
 555                                method->avg + 1);
 556                        goto out;
 557                }
 558                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
 559                                       ch_lsb, method->avg);
 560                if (ret) {
 561                        dev_err(twl4030_madc->dev,
 562                                "unable to write sel reg 0x%X\n",
 563                                method->sel + 1);
 564                        goto out;
 565                }
 566        }
 567        if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
 568                ret = twl4030_madc_set_irq(twl4030_madc, req);
 569                if (ret < 0)
 570                        goto out;
 571                ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
 572                if (ret < 0)
 573                        goto out;
 574                twl4030_madc->requests[req->method].active = 1;
 575                ret = 0;
 576                goto out;
 577        }
 578        /* With RT method we should not be here anymore */
 579        if (req->method == TWL4030_MADC_RT) {
 580                ret = -EINVAL;
 581                goto out;
 582        }
 583        ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
 584        if (ret < 0)
 585                goto out;
 586        twl4030_madc->requests[req->method].active = 1;
 587        /* Wait until conversion is ready (ctrl register returns EOC) */
 588        ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
 589        if (ret) {
 590                twl4030_madc->requests[req->method].active = 0;
 591                goto out;
 592        }
 593        ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
 594                                         req->channels, req->rbuf, req->raw);
 595        twl4030_madc->requests[req->method].active = 0;
 596
 597out:
 598        mutex_unlock(&twl4030_madc->lock);
 599
 600        return ret;
 601}
 602EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
 603
 604/*
 605 * Return channel value
 606 * Or < 0 on failure.
 607 */
 608int twl4030_get_madc_conversion(int channel_no)
 609{
 610        struct twl4030_madc_request req;
 611        int temp = 0;
 612        int ret;
 613
 614        req.channels = (1 << channel_no);
 615        req.method = TWL4030_MADC_SW2;
 616        req.active = 0;
 617        req.func_cb = NULL;
 618        ret = twl4030_madc_conversion(&req);
 619        if (ret < 0)
 620                return ret;
 621        if (req.rbuf[channel_no] > 0)
 622                temp = req.rbuf[channel_no];
 623
 624        return temp;
 625}
 626EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
 627
 628/*
 629 * Function to enable or disable bias current for
 630 * main battery type reading or temperature sensing
 631 * @madc - pointer to twl4030_madc_data struct
 632 * @chan - can be one of the two values
 633 * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading
 634 * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature
 635 * sensing
 636 * @on - enable or disable chan.
 637 */
 638static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
 639                                              int chan, int on)
 640{
 641        int ret;
 642        u8 regval;
 643
 644        ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
 645                              &regval, TWL4030_BCI_BCICTL1);
 646        if (ret) {
 647                dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
 648                        TWL4030_BCI_BCICTL1);
 649                return ret;
 650        }
 651        if (on)
 652                regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
 653        else
 654                regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
 655        ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
 656                               regval, TWL4030_BCI_BCICTL1);
 657        if (ret) {
 658                dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
 659                        TWL4030_BCI_BCICTL1);
 660                return ret;
 661        }
 662
 663        return 0;
 664}
 665
 666/*
 667 * Function that sets MADC software power on bit to enable MADC
 668 * @madc - pointer to twl4030_madc_data struct
 669 * @on - Enable or disable MADC software powen on bit.
 670 * returns error if i2c read/write fails else 0
 671 */
 672static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
 673{
 674        u8 regval;
 675        int ret;
 676
 677        ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
 678                              &regval, TWL4030_MADC_CTRL1);
 679        if (ret) {
 680                dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
 681                        TWL4030_MADC_CTRL1);
 682                return ret;
 683        }
 684        if (on)
 685                regval |= TWL4030_MADC_MADCON;
 686        else
 687                regval &= ~TWL4030_MADC_MADCON;
 688        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
 689        if (ret) {
 690                dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
 691                        TWL4030_MADC_CTRL1);
 692                return ret;
 693        }
 694
 695        return 0;
 696}
 697
 698/*
 699 * Initialize MADC and request for threaded irq
 700 */
 701static int twl4030_madc_probe(struct platform_device *pdev)
 702{
 703        struct twl4030_madc_data *madc;
 704        struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
 705        int ret;
 706        u8 regval;
 707
 708        if (!pdata) {
 709                dev_err(&pdev->dev, "platform_data not available\n");
 710                return -EINVAL;
 711        }
 712        madc = kzalloc(sizeof(*madc), GFP_KERNEL);
 713        if (!madc)
 714                return -ENOMEM;
 715
 716        madc->dev = &pdev->dev;
 717
 718        /*
 719         * Phoenix provides 2 interrupt lines. The first one is connected to
 720         * the OMAP. The other one can be connected to the other processor such
 721         * as modem. Hence two separate ISR and IMR registers.
 722         */
 723        madc->imr = (pdata->irq_line == 1) ?
 724            TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
 725        madc->isr = (pdata->irq_line == 1) ?
 726            TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
 727        ret = twl4030_madc_set_power(madc, 1);
 728        if (ret < 0)
 729                goto err_power;
 730        ret = twl4030_madc_set_current_generator(madc, 0, 1);
 731        if (ret < 0)
 732                goto err_current_generator;
 733
 734        ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
 735                              &regval, TWL4030_BCI_BCICTL1);
 736        if (ret) {
 737                dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
 738                        TWL4030_BCI_BCICTL1);
 739                goto err_i2c;
 740        }
 741        regval |= TWL4030_BCI_MESBAT;
 742        ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
 743                               regval, TWL4030_BCI_BCICTL1);
 744        if (ret) {
 745                dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
 746                        TWL4030_BCI_BCICTL1);
 747                goto err_i2c;
 748        }
 749
 750        /* Check that MADC clock is on */
 751        ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
 752        if (ret) {
 753                dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
 754                                TWL4030_REG_GPBR1);
 755                goto err_i2c;
 756        }
 757
 758        /* If MADC clk is not on, turn it on */
 759        if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
 760                dev_info(&pdev->dev, "clk disabled, enabling\n");
 761                regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
 762                ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
 763                                       TWL4030_REG_GPBR1);
 764                if (ret) {
 765                        dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
 766                                        TWL4030_REG_GPBR1);
 767                        goto err_i2c;
 768                }
 769        }
 770
 771        platform_set_drvdata(pdev, madc);
 772        mutex_init(&madc->lock);
 773        ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
 774                                   twl4030_madc_threaded_irq_handler,
 775                                   IRQF_TRIGGER_RISING, "twl4030_madc", madc);
 776        if (ret) {
 777                dev_dbg(&pdev->dev, "could not request irq\n");
 778                goto err_i2c;
 779        }
 780        twl4030_madc = madc;
 781        return 0;
 782err_i2c:
 783        twl4030_madc_set_current_generator(madc, 0, 0);
 784err_current_generator:
 785        twl4030_madc_set_power(madc, 0);
 786err_power:
 787        kfree(madc);
 788
 789        return ret;
 790}
 791
 792static int twl4030_madc_remove(struct platform_device *pdev)
 793{
 794        struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
 795
 796        free_irq(platform_get_irq(pdev, 0), madc);
 797        twl4030_madc_set_current_generator(madc, 0, 0);
 798        twl4030_madc_set_power(madc, 0);
 799        kfree(madc);
 800
 801        return 0;
 802}
 803
 804static struct platform_driver twl4030_madc_driver = {
 805        .probe = twl4030_madc_probe,
 806        .remove = twl4030_madc_remove,
 807        .driver = {
 808                   .name = "twl4030_madc",
 809                   .owner = THIS_MODULE,
 810                   },
 811};
 812
 813module_platform_driver(twl4030_madc_driver);
 814
 815MODULE_DESCRIPTION("TWL4030 ADC driver");
 816MODULE_LICENSE("GPL");
 817MODULE_AUTHOR("J Keerthy");
 818MODULE_ALIAS("platform:twl4030_madc");
 819
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.