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(TWL4030_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(TWL4030_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 * value is stored
 215 * Returns the number of successfully read channels.
 216 */
 217static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
 218                                      u8 reg_base, unsigned
 219                                                long channels, int *buf)
 220{
 221        int count = 0, count_req = 0, i;
 222        u8 reg;
 223
 224        for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
 225                reg = reg_base + 2 * i;
 226                buf[i] = twl4030_madc_channel_raw_read(madc, reg);
 227                if (buf[i] < 0) {
 228                        dev_err(madc->dev,
 229                                "Unable to read register 0x%X\n", reg);
 230                        count_req++;
 231                        continue;
 232                }
 233                switch (i) {
 234                case 10:
 235                        buf[i] = twl4030battery_current(buf[i]);
 236                        if (buf[i] < 0) {
 237                                dev_err(madc->dev, "err reading current\n");
 238                                count_req++;
 239                        } else {
 240                                count++;
 241                                buf[i] = buf[i] - 750;
 242                        }
 243                        break;
 244                case 1:
 245                        buf[i] = twl4030battery_temperature(buf[i]);
 246                        if (buf[i] < 0) {
 247                                dev_err(madc->dev, "err reading temperature\n");
 248                                count_req++;
 249                        } else {
 250                                buf[i] -= 3;
 251                                count++;
 252                        }
 253                        break;
 254                default:
 255                        count++;
 256                        /* Analog Input (V) = conv_result * step_size / R
 257                         * conv_result = decimal value of 10-bit conversion
 258                         *               result
 259                         * step size = 1.5 / (2 ^ 10 -1)
 260                         * R = Prescaler ratio for input channels.
 261                         * Result given in mV hence multiplied by 1000.
 262                         */
 263                        buf[i] = (buf[i] * 3 * 1000 *
 264                                 twl4030_divider_ratios[i].denominator)
 265                                / (2 * 1023 *
 266                                twl4030_divider_ratios[i].numerator);
 267                }
 268        }
 269        if (count_req)
 270                dev_err(madc->dev, "%d channel conversion failed\n", count_req);
 271
 272        return count;
 273}
 274
 275/*
 276 * Enables irq.
 277 * @madc - pointer to twl4030_madc_data struct
 278 * @id - irq number to be enabled
 279 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
 280 * corresponding to RT, SW1, SW2 conversion requests.
 281 * If the i2c read fails it returns an error else returns 0.
 282 */
 283static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
 284{
 285        u8 val;
 286        int ret;
 287
 288        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
 289        if (ret) {
 290                dev_err(madc->dev, "unable to read imr register 0x%X\n",
 291                        madc->imr);
 292                return ret;
 293        }
 294        val &= ~(1 << id);
 295        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
 296        if (ret) {
 297                dev_err(madc->dev,
 298                        "unable to write imr register 0x%X\n", madc->imr);
 299                return ret;
 300
 301        }
 302
 303        return 0;
 304}
 305
 306/*
 307 * Disables irq.
 308 * @madc - pointer to twl4030_madc_data struct
 309 * @id - irq number to be disabled
 310 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
 311 * corresponding to RT, SW1, SW2 conversion requests.
 312 * Returns error if i2c read/write fails.
 313 */
 314static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
 315{
 316        u8 val;
 317        int ret;
 318
 319        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
 320        if (ret) {
 321                dev_err(madc->dev, "unable to read imr register 0x%X\n",
 322                        madc->imr);
 323                return ret;
 324        }
 325        val |= (1 << id);
 326        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
 327        if (ret) {
 328                dev_err(madc->dev,
 329                        "unable to write imr register 0x%X\n", madc->imr);
 330                return ret;
 331        }
 332
 333        return 0;
 334}
 335
 336static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
 337{
 338        struct twl4030_madc_data *madc = _madc;
 339        const struct twl4030_madc_conversion_method *method;
 340        u8 isr_val, imr_val;
 341        int i, len, ret;
 342        struct twl4030_madc_request *r;
 343
 344        mutex_lock(&madc->lock);
 345        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
 346        if (ret) {
 347                dev_err(madc->dev, "unable to read isr register 0x%X\n",
 348                        madc->isr);
 349                goto err_i2c;
 350        }
 351        ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
 352        if (ret) {
 353                dev_err(madc->dev, "unable to read imr register 0x%X\n",
 354                        madc->imr);
 355                goto err_i2c;
 356        }
 357        isr_val &= ~imr_val;
 358        for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
 359                if (!(isr_val & (1 << i)))
 360                        continue;
 361                ret = twl4030_madc_disable_irq(madc, i);
 362                if (ret < 0)
 363                        dev_dbg(madc->dev, "Disable interrupt failed%d\n", i);
 364                madc->requests[i].result_pending = 1;
 365        }
 366        for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
 367                r = &madc->requests[i];
 368                /* No pending results for this method, move to next one */
 369                if (!r->result_pending)
 370                        continue;
 371                method = &twl4030_conversion_methods[r->method];
 372                /* Read results */
 373                len = twl4030_madc_read_channels(madc, method->rbase,
 374                                                 r->channels, r->rbuf);
 375                /* Return results to caller */
 376                if (r->func_cb != NULL) {
 377                        r->func_cb(len, r->channels, r->rbuf);
 378                        r->func_cb = NULL;
 379                }
 380                /* Free request */
 381                r->result_pending = 0;
 382                r->active = 0;
 383        }
 384        mutex_unlock(&madc->lock);
 385
 386        return IRQ_HANDLED;
 387
 388err_i2c:
 389        /*
 390         * In case of error check whichever request is active
 391         * and service the same.
 392         */
 393        for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
 394                r = &madc->requests[i];
 395                if (r->active == 0)
 396                        continue;
 397                method = &twl4030_conversion_methods[r->method];
 398                /* Read results */
 399                len = twl4030_madc_read_channels(madc, method->rbase,
 400                                                 r->channels, r->rbuf);
 401                /* Return results to caller */
 402                if (r->func_cb != NULL) {
 403                        r->func_cb(len, r->channels, r->rbuf);
 404                        r->func_cb = NULL;
 405                }
 406                /* Free request */
 407                r->result_pending = 0;
 408                r->active = 0;
 409        }
 410        mutex_unlock(&madc->lock);
 411
 412        return IRQ_HANDLED;
 413}
 414
 415static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
 416                                struct twl4030_madc_request *req)
 417{
 418        struct twl4030_madc_request *p;
 419        int ret;
 420
 421        p = &madc->requests[req->method];
 422        memcpy(p, req, sizeof(*req));
 423        ret = twl4030_madc_enable_irq(madc, req->method);
 424        if (ret < 0) {
 425                dev_err(madc->dev, "enable irq failed!!\n");
 426                return ret;
 427        }
 428
 429        return 0;
 430}
 431
 432/*
 433 * Function which enables the madc conversion
 434 * by writing to the control register.
 435 * @madc - pointer to twl4030_madc_data struct
 436 * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
 437 * corresponding to RT SW1 or SW2 conversion methods.
 438 * Returns 0 if succeeds else a negative error value
 439 */
 440static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
 441                                         int conv_method)
 442{
 443        const struct twl4030_madc_conversion_method *method;
 444        int ret = 0;
 445        method = &twl4030_conversion_methods[conv_method];
 446        switch (conv_method) {
 447        case TWL4030_MADC_SW1:
 448        case TWL4030_MADC_SW2:
 449                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
 450                                       TWL4030_MADC_SW_START, method->ctrl);
 451                if (ret) {
 452                        dev_err(madc->dev,
 453                                "unable to write ctrl register 0x%X\n",
 454                                method->ctrl);
 455                        return ret;
 456                }
 457                break;
 458        default:
 459                break;
 460        }
 461
 462        return 0;
 463}
 464
 465/*
 466 * Function that waits for conversion to be ready
 467 * @madc - pointer to twl4030_madc_data struct
 468 * @timeout_ms - timeout value in milliseconds
 469 * @status_reg - ctrl register
 470 * returns 0 if succeeds else a negative error value
 471 */
 472static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
 473                                              unsigned int timeout_ms,
 474                                              u8 status_reg)
 475{
 476        unsigned long timeout;
 477        int ret;
 478
 479        timeout = jiffies + msecs_to_jiffies(timeout_ms);
 480        do {
 481                u8 reg;
 482
 483                ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
 484                if (ret) {
 485                        dev_err(madc->dev,
 486                                "unable to read status register 0x%X\n",
 487                                status_reg);
 488                        return ret;
 489                }
 490                if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
 491                        return 0;
 492                usleep_range(500, 2000);
 493        } while (!time_after(jiffies, timeout));
 494        dev_err(madc->dev, "conversion timeout!\n");
 495
 496        return -EAGAIN;
 497}
 498
 499/*
 500 * An exported function which can be called from other kernel drivers.
 501 * @req twl4030_madc_request structure
 502 * req->rbuf will be filled with read values of channels based on the
 503 * channel index. If a particular channel reading fails there will
 504 * be a negative error value in the corresponding array element.
 505 * returns 0 if succeeds else error value
 506 */
 507int twl4030_madc_conversion(struct twl4030_madc_request *req)
 508{
 509        const struct twl4030_madc_conversion_method *method;
 510        u8 ch_msb, ch_lsb;
 511        int ret;
 512
 513        if (!req || !twl4030_madc)
 514                return -EINVAL;
 515
 516        mutex_lock(&twl4030_madc->lock);
 517        if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
 518                ret = -EINVAL;
 519                goto out;
 520        }
 521        /* Do we have a conversion request ongoing */
 522        if (twl4030_madc->requests[req->method].active) {
 523                ret = -EBUSY;
 524                goto out;
 525        }
 526        ch_msb = (req->channels >> 8) & 0xff;
 527        ch_lsb = req->channels & 0xff;
 528        method = &twl4030_conversion_methods[req->method];
 529        /* Select channels to be converted */
 530        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1);
 531        if (ret) {
 532                dev_err(twl4030_madc->dev,
 533                        "unable to write sel register 0x%X\n", method->sel + 1);
 534                goto out;
 535        }
 536        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
 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        /* Select averaging for all channels if do_avg is set */
 543        if (req->do_avg) {
 544                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
 545                                       ch_msb, method->avg + 1);
 546                if (ret) {
 547                        dev_err(twl4030_madc->dev,
 548                                "unable to write avg register 0x%X\n",
 549                                method->avg + 1);
 550                        goto out;
 551                }
 552                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
 553                                       ch_lsb, method->avg);
 554                if (ret) {
 555                        dev_err(twl4030_madc->dev,
 556                                "unable to write sel reg 0x%X\n",
 557                                method->sel + 1);
 558                        goto out;
 559                }
 560        }
 561        if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
 562                ret = twl4030_madc_set_irq(twl4030_madc, req);
 563                if (ret < 0)
 564                        goto out;
 565                ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
 566                if (ret < 0)
 567                        goto out;
 568                twl4030_madc->requests[req->method].active = 1;
 569                ret = 0;
 570                goto out;
 571        }
 572        /* With RT method we should not be here anymore */
 573        if (req->method == TWL4030_MADC_RT) {
 574                ret = -EINVAL;
 575                goto out;
 576        }
 577        ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
 578        if (ret < 0)
 579                goto out;
 580        twl4030_madc->requests[req->method].active = 1;
 581        /* Wait until conversion is ready (ctrl register returns EOC) */
 582        ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
 583        if (ret) {
 584                twl4030_madc->requests[req->method].active = 0;
 585                goto out;
 586        }
 587        ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
 588                                         req->channels, req->rbuf);
 589        twl4030_madc->requests[req->method].active = 0;
 590
 591out:
 592        mutex_unlock(&twl4030_madc->lock);
 593
 594        return ret;
 595}
 596EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
 597
 598/*
 599 * Return channel value
 600 * Or < 0 on failure.
 601 */
 602int twl4030_get_madc_conversion(int channel_no)
 603{
 604        struct twl4030_madc_request req;
 605        int temp = 0;
 606        int ret;
 607
 608        req.channels = (1 << channel_no);
 609        req.method = TWL4030_MADC_SW2;
 610        req.active = 0;
 611        req.func_cb = NULL;
 612        ret = twl4030_madc_conversion(&req);
 613        if (ret < 0)
 614                return ret;
 615        if (req.rbuf[channel_no] > 0)
 616                temp = req.rbuf[channel_no];
 617
 618        return temp;
 619}
 620EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
 621
 622/*
 623 * Function to enable or disable bias current for
 624 * main battery type reading or temperature sensing
 625 * @madc - pointer to twl4030_madc_data struct
 626 * @chan - can be one of the two values
 627 * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading
 628 * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature
 629 * sensing
 630 * @on - enable or disable chan.
 631 */
 632static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
 633                                              int chan, int on)
 634{
 635        int ret;
 636        u8 regval;
 637
 638        ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
 639                              &regval, TWL4030_BCI_BCICTL1);
 640        if (ret) {
 641                dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
 642                        TWL4030_BCI_BCICTL1);
 643                return ret;
 644        }
 645        if (on)
 646                regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
 647        else
 648                regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
 649        ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
 650                               regval, TWL4030_BCI_BCICTL1);
 651        if (ret) {
 652                dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
 653                        TWL4030_BCI_BCICTL1);
 654                return ret;
 655        }
 656
 657        return 0;
 658}
 659
 660/*
 661 * Function that sets MADC software power on bit to enable MADC
 662 * @madc - pointer to twl4030_madc_data struct
 663 * @on - Enable or disable MADC software powen on bit.
 664 * returns error if i2c read/write fails else 0
 665 */
 666static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
 667{
 668        u8 regval;
 669        int ret;
 670
 671        ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
 672                              &regval, TWL4030_MADC_CTRL1);
 673        if (ret) {
 674                dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
 675                        TWL4030_MADC_CTRL1);
 676                return ret;
 677        }
 678        if (on)
 679                regval |= TWL4030_MADC_MADCON;
 680        else
 681                regval &= ~TWL4030_MADC_MADCON;
 682        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
 683        if (ret) {
 684                dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
 685                        TWL4030_MADC_CTRL1);
 686                return ret;
 687        }
 688
 689        return 0;
 690}
 691
 692/*
 693 * Initialize MADC and request for threaded irq
 694 */
 695static int __devinit twl4030_madc_probe(struct platform_device *pdev)
 696{
 697        struct twl4030_madc_data *madc;
 698        struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
 699        int ret;
 700        u8 regval;
 701
 702        if (!pdata) {
 703                dev_err(&pdev->dev, "platform_data not available\n");
 704                return -EINVAL;
 705        }
 706        madc = kzalloc(sizeof(*madc), GFP_KERNEL);
 707        if (!madc)
 708                return -ENOMEM;
 709
 710        madc->dev = &pdev->dev;
 711
 712        /*
 713         * Phoenix provides 2 interrupt lines. The first one is connected to
 714         * the OMAP. The other one can be connected to the other processor such
 715         * as modem. Hence two separate ISR and IMR registers.
 716         */
 717        madc->imr = (pdata->irq_line == 1) ?
 718            TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
 719        madc->isr = (pdata->irq_line == 1) ?
 720            TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
 721        ret = twl4030_madc_set_power(madc, 1);
 722        if (ret < 0)
 723                goto err_power;
 724        ret = twl4030_madc_set_current_generator(madc, 0, 1);
 725        if (ret < 0)
 726                goto err_current_generator;
 727
 728        ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
 729                              &regval, TWL4030_BCI_BCICTL1);
 730        if (ret) {
 731                dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
 732                        TWL4030_BCI_BCICTL1);
 733                goto err_i2c;
 734        }
 735        regval |= TWL4030_BCI_MESBAT;
 736        ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
 737                               regval, TWL4030_BCI_BCICTL1);
 738        if (ret) {
 739                dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
 740                        TWL4030_BCI_BCICTL1);
 741                goto err_i2c;
 742        }
 743
 744        /* Check that MADC clock is on */
 745        ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
 746        if (ret) {
 747                dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
 748                                TWL4030_REG_GPBR1);
 749                goto err_i2c;
 750        }
 751
 752        /* If MADC clk is not on, turn it on */
 753        if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
 754                dev_info(&pdev->dev, "clk disabled, enabling\n");
 755                regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
 756                ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
 757                                       TWL4030_REG_GPBR1);
 758                if (ret) {
 759                        dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
 760                                        TWL4030_REG_GPBR1);
 761                        goto err_i2c;
 762                }
 763        }
 764
 765        platform_set_drvdata(pdev, madc);
 766        mutex_init(&madc->lock);
 767        ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
 768                                   twl4030_madc_threaded_irq_handler,
 769                                   IRQF_TRIGGER_RISING, "twl4030_madc", madc);
 770        if (ret) {
 771                dev_dbg(&pdev->dev, "could not request irq\n");
 772                goto err_irq;
 773        }
 774        twl4030_madc = madc;
 775        return 0;
 776err_irq:
 777        platform_set_drvdata(pdev, NULL);
 778err_i2c:
 779        twl4030_madc_set_current_generator(madc, 0, 0);
 780err_current_generator:
 781        twl4030_madc_set_power(madc, 0);
 782err_power:
 783        kfree(madc);
 784
 785        return ret;
 786}
 787
 788static int __devexit twl4030_madc_remove(struct platform_device *pdev)
 789{
 790        struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
 791
 792        free_irq(platform_get_irq(pdev, 0), madc);
 793        platform_set_drvdata(pdev, NULL);
 794        twl4030_madc_set_current_generator(madc, 0, 0);
 795        twl4030_madc_set_power(madc, 0);
 796        kfree(madc);
 797
 798        return 0;
 799}
 800
 801static struct platform_driver twl4030_madc_driver = {
 802        .probe = twl4030_madc_probe,
 803        .remove = __exit_p(twl4030_madc_remove),
 804        .driver = {
 805                   .name = "twl4030_madc",
 806                   .owner = THIS_MODULE,
 807                   },
 808};
 809
 810module_platform_driver(twl4030_madc_driver);
 811
 812MODULE_DESCRIPTION("TWL4030 ADC driver");
 813MODULE_LICENSE("GPL");
 814MODULE_AUTHOR("J Keerthy");
 815MODULE_ALIAS("platform:twl4030_madc");
 816
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.