linux/drivers/platform/x86/intel_mid_thermal.c
<<
>>
Prefs
   1/*
   2 * intel_mid_thermal.c - Intel MID platform thermal driver
   3 *
   4 * Copyright (C) 2011 Intel Corporation
   5 *
   6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; version 2 of the License.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along
  18 * with this program; if not, write to the Free Software Foundation, Inc.,
  19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  20 *
  21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  22 * Author: Durgadoss R <durgadoss.r@intel.com>
  23 */
  24
  25#define pr_fmt(fmt) "intel_mid_thermal: " fmt
  26
  27#include <linux/module.h>
  28#include <linux/init.h>
  29#include <linux/err.h>
  30#include <linux/param.h>
  31#include <linux/device.h>
  32#include <linux/platform_device.h>
  33#include <linux/slab.h>
  34#include <linux/pm.h>
  35#include <linux/thermal.h>
  36#include <linux/mfd/intel_msic.h>
  37
  38/* Number of thermal sensors */
  39#define MSIC_THERMAL_SENSORS    4
  40
  41/* ADC1 - thermal registers */
  42#define MSIC_ADC_ENBL           0x10
  43#define MSIC_ADC_START          0x08
  44
  45#define MSIC_ADCTHERM_ENBL      0x04
  46#define MSIC_ADCRRDATA_ENBL     0x05
  47#define MSIC_CHANL_MASK_VAL     0x0F
  48
  49#define MSIC_STOPBIT_MASK       16
  50#define MSIC_ADCTHERM_MASK      4
  51/* Number of ADC channels */
  52#define ADC_CHANLS_MAX          15
  53#define ADC_LOOP_MAX            (ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
  54
  55/* ADC channel code values */
  56#define SKIN_SENSOR0_CODE       0x08
  57#define SKIN_SENSOR1_CODE       0x09
  58#define SYS_SENSOR_CODE         0x0A
  59#define MSIC_DIE_SENSOR_CODE    0x03
  60
  61#define SKIN_THERM_SENSOR0      0
  62#define SKIN_THERM_SENSOR1      1
  63#define SYS_THERM_SENSOR2       2
  64#define MSIC_DIE_THERM_SENSOR3  3
  65
  66/* ADC code range */
  67#define ADC_MAX                 977
  68#define ADC_MIN                 162
  69#define ADC_VAL0C               887
  70#define ADC_VAL20C              720
  71#define ADC_VAL40C              508
  72#define ADC_VAL60C              315
  73
  74/* ADC base addresses */
  75#define ADC_CHNL_START_ADDR     INTEL_MSIC_ADC1ADDR0    /* increments by 1 */
  76#define ADC_DATA_START_ADDR     INTEL_MSIC_ADC1SNS0H    /* increments by 2 */
  77
  78/* MSIC die attributes */
  79#define MSIC_DIE_ADC_MIN        488
  80#define MSIC_DIE_ADC_MAX        1004
  81
  82/* This holds the address of the first free ADC channel,
  83 * among the 15 channels
  84 */
  85static int channel_index;
  86
  87struct platform_info {
  88        struct platform_device *pdev;
  89        struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
  90};
  91
  92struct thermal_device_info {
  93        unsigned int chnl_addr;
  94        int direct;
  95        /* This holds the current temperature in millidegree celsius */
  96        long curr_temp;
  97};
  98
  99/**
 100 * to_msic_die_temp - converts adc_val to msic_die temperature
 101 * @adc_val: ADC value to be converted
 102 *
 103 * Can sleep
 104 */
 105static int to_msic_die_temp(uint16_t adc_val)
 106{
 107        return (368 * (adc_val) / 1000) - 220;
 108}
 109
 110/**
 111 * is_valid_adc - checks whether the adc code is within the defined range
 112 * @min: minimum value for the sensor
 113 * @max: maximum value for the sensor
 114 *
 115 * Can sleep
 116 */
 117static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
 118{
 119        return (adc_val >= min) && (adc_val <= max);
 120}
 121
 122/**
 123 * adc_to_temp - converts the ADC code to temperature in C
 124 * @direct: true if ths channel is direct index
 125 * @adc_val: the adc_val that needs to be converted
 126 * @tp: temperature return value
 127 *
 128 * Linear approximation is used to covert the skin adc value into temperature.
 129 * This technique is used to avoid very long look-up table to get
 130 * the appropriate temp value from ADC value.
 131 * The adc code vs sensor temp curve is split into five parts
 132 * to achieve very close approximate temp value with less than
 133 * 0.5C error
 134 */
 135static int adc_to_temp(int direct, uint16_t adc_val, int *tp)
 136{
 137        int temp;
 138
 139        /* Direct conversion for die temperature */
 140        if (direct) {
 141                if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX)) {
 142                        *tp = to_msic_die_temp(adc_val) * 1000;
 143                        return 0;
 144                }
 145                return -ERANGE;
 146        }
 147
 148        if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
 149                return -ERANGE;
 150
 151        /* Linear approximation for skin temperature */
 152        if (adc_val > ADC_VAL0C)
 153                temp = 177 - (adc_val/5);
 154        else if ((adc_val <= ADC_VAL0C) && (adc_val > ADC_VAL20C))
 155                temp = 111 - (adc_val/8);
 156        else if ((adc_val <= ADC_VAL20C) && (adc_val > ADC_VAL40C))
 157                temp = 92 - (adc_val/10);
 158        else if ((adc_val <= ADC_VAL40C) && (adc_val > ADC_VAL60C))
 159                temp = 91 - (adc_val/10);
 160        else
 161                temp = 112 - (adc_val/6);
 162
 163        /* Convert temperature in celsius to milli degree celsius */
 164        *tp = temp * 1000;
 165        return 0;
 166}
 167
 168/**
 169 * mid_read_temp - read sensors for temperature
 170 * @temp: holds the current temperature for the sensor after reading
 171 *
 172 * reads the adc_code from the channel and converts it to real
 173 * temperature. The converted value is stored in temp.
 174 *
 175 * Can sleep
 176 */
 177static int mid_read_temp(struct thermal_zone_device *tzd, int *temp)
 178{
 179        struct thermal_device_info *td_info = tzd->devdata;
 180        uint16_t adc_val, addr;
 181        uint8_t data = 0;
 182        int ret;
 183        int curr_temp;
 184
 185        addr = td_info->chnl_addr;
 186
 187        /* Enable the msic for conversion before reading */
 188        ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
 189        if (ret)
 190                return ret;
 191
 192        /* Re-toggle the RRDATARD bit (temporary workaround) */
 193        ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
 194        if (ret)
 195                return ret;
 196
 197        /* Read the higher bits of data */
 198        ret = intel_msic_reg_read(addr, &data);
 199        if (ret)
 200                return ret;
 201
 202        /* Shift bits to accommodate the lower two data bits */
 203        adc_val = (data << 2);
 204        addr++;
 205
 206        ret = intel_msic_reg_read(addr, &data);/* Read lower bits */
 207        if (ret)
 208                return ret;
 209
 210        /* Adding lower two bits to the higher bits */
 211        data &= 03;
 212        adc_val += data;
 213
 214        /* Convert ADC value to temperature */
 215        ret = adc_to_temp(td_info->direct, adc_val, &curr_temp);
 216        if (ret == 0)
 217                *temp = td_info->curr_temp = curr_temp;
 218        return ret;
 219}
 220
 221/**
 222 * configure_adc - enables/disables the ADC for conversion
 223 * @val: zero: disables the ADC non-zero:enables the ADC
 224 *
 225 * Enable/Disable the ADC depending on the argument
 226 *
 227 * Can sleep
 228 */
 229static int configure_adc(int val)
 230{
 231        int ret;
 232        uint8_t data;
 233
 234        ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data);
 235        if (ret)
 236                return ret;
 237
 238        if (val) {
 239                /* Enable and start the ADC */
 240                data |= (MSIC_ADC_ENBL | MSIC_ADC_START);
 241        } else {
 242                /* Just stop the ADC */
 243                data &= (~MSIC_ADC_START);
 244        }
 245        return intel_msic_reg_write(INTEL_MSIC_ADC1CNTL1, data);
 246}
 247
 248/**
 249 * set_up_therm_channel - enable thermal channel for conversion
 250 * @base_addr: index of free msic ADC channel
 251 *
 252 * Enable all the three channels for conversion
 253 *
 254 * Can sleep
 255 */
 256static int set_up_therm_channel(u16 base_addr)
 257{
 258        int ret;
 259
 260        /* Enable all the sensor channels */
 261        ret = intel_msic_reg_write(base_addr, SKIN_SENSOR0_CODE);
 262        if (ret)
 263                return ret;
 264
 265        ret = intel_msic_reg_write(base_addr + 1, SKIN_SENSOR1_CODE);
 266        if (ret)
 267                return ret;
 268
 269        ret = intel_msic_reg_write(base_addr + 2, SYS_SENSOR_CODE);
 270        if (ret)
 271                return ret;
 272
 273        /* Since this is the last channel, set the stop bit
 274         * to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
 275        ret = intel_msic_reg_write(base_addr + 3,
 276                        (MSIC_DIE_SENSOR_CODE | 0x10));
 277        if (ret)
 278                return ret;
 279
 280        /* Enable ADC and start it */
 281        return configure_adc(1);
 282}
 283
 284/**
 285 * reset_stopbit - sets the stop bit to 0 on the given channel
 286 * @addr: address of the channel
 287 *
 288 * Can sleep
 289 */
 290static int reset_stopbit(uint16_t addr)
 291{
 292        int ret;
 293        uint8_t data;
 294        ret = intel_msic_reg_read(addr, &data);
 295        if (ret)
 296                return ret;
 297        /* Set the stop bit to zero */
 298        return intel_msic_reg_write(addr, (data & 0xEF));
 299}
 300
 301/**
 302 * find_free_channel - finds an empty channel for conversion
 303 *
 304 * If the ADC is not enabled then start using 0th channel
 305 * itself. Otherwise find an empty channel by looking for a
 306 * channel in which the stopbit is set to 1. returns the index
 307 * of the first free channel if succeeds or an error code.
 308 *
 309 * Context: can sleep
 310 *
 311 * FIXME: Ultimately the channel allocator will move into the intel_scu_ipc
 312 * code.
 313 */
 314static int find_free_channel(void)
 315{
 316        int ret;
 317        int i;
 318        uint8_t data;
 319
 320        /* check whether ADC is enabled */
 321        ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data);
 322        if (ret)
 323                return ret;
 324
 325        if ((data & MSIC_ADC_ENBL) == 0)
 326                return 0;
 327
 328        /* ADC is already enabled; Looking for an empty channel */
 329        for (i = 0; i < ADC_CHANLS_MAX; i++) {
 330                ret = intel_msic_reg_read(ADC_CHNL_START_ADDR + i, &data);
 331                if (ret)
 332                        return ret;
 333
 334                if (data & MSIC_STOPBIT_MASK) {
 335                        ret = i;
 336                        break;
 337                }
 338        }
 339        return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
 340}
 341
 342/**
 343 * mid_initialize_adc - initializing the ADC
 344 * @dev: our device structure
 345 *
 346 * Initialize the ADC for reading thermistor values. Can sleep.
 347 */
 348static int mid_initialize_adc(struct device *dev)
 349{
 350        u8  data;
 351        u16 base_addr;
 352        int ret;
 353
 354        /*
 355         * Ensure that adctherm is disabled before we
 356         * initialize the ADC
 357         */
 358        ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL3, &data);
 359        if (ret)
 360                return ret;
 361
 362        data &= ~MSIC_ADCTHERM_MASK;
 363        ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, data);
 364        if (ret)
 365                return ret;
 366
 367        /* Index of the first channel in which the stop bit is set */
 368        channel_index = find_free_channel();
 369        if (channel_index < 0) {
 370                dev_err(dev, "No free ADC channels");
 371                return channel_index;
 372        }
 373
 374        base_addr = ADC_CHNL_START_ADDR + channel_index;
 375
 376        if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
 377                /* Reset stop bit for channels other than 0 and 12 */
 378                ret = reset_stopbit(base_addr);
 379                if (ret)
 380                        return ret;
 381
 382                /* Index of the first free channel */
 383                base_addr++;
 384                channel_index++;
 385        }
 386
 387        ret = set_up_therm_channel(base_addr);
 388        if (ret) {
 389                dev_err(dev, "unable to enable ADC");
 390                return ret;
 391        }
 392        dev_dbg(dev, "ADC initialization successful");
 393        return ret;
 394}
 395
 396/**
 397 * initialize_sensor - sets default temp and timer ranges
 398 * @index: index of the sensor
 399 *
 400 * Context: can sleep
 401 */
 402static struct thermal_device_info *initialize_sensor(int index)
 403{
 404        struct thermal_device_info *td_info =
 405                kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
 406
 407        if (!td_info)
 408                return NULL;
 409
 410        /* Set the base addr of the channel for this sensor */
 411        td_info->chnl_addr = ADC_DATA_START_ADDR + 2 * (channel_index + index);
 412        /* Sensor 3 is direct conversion */
 413        if (index == 3)
 414                td_info->direct = 1;
 415        return td_info;
 416}
 417
 418/**
 419 * mid_thermal_resume - resume routine
 420 * @dev: device structure
 421 *
 422 * mid thermal resume: re-initializes the adc. Can sleep.
 423 */
 424static int mid_thermal_resume(struct device *dev)
 425{
 426        return mid_initialize_adc(dev);
 427}
 428
 429/**
 430 * mid_thermal_suspend - suspend routine
 431 * @dev: device structure
 432 *
 433 * mid thermal suspend implements the suspend functionality
 434 * by stopping the ADC. Can sleep.
 435 */
 436static int mid_thermal_suspend(struct device *dev)
 437{
 438        /*
 439         * This just stops the ADC and does not disable it.
 440         * temporary workaround until we have a generic ADC driver.
 441         * If 0 is passed, it disables the ADC.
 442         */
 443        return configure_adc(0);
 444}
 445
 446static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
 447                         mid_thermal_suspend, mid_thermal_resume);
 448
 449/**
 450 * read_curr_temp - reads the current temperature and stores in temp
 451 * @temp: holds the current temperature value after reading
 452 *
 453 * Can sleep
 454 */
 455static int read_curr_temp(struct thermal_zone_device *tzd, int *temp)
 456{
 457        WARN_ON(tzd == NULL);
 458        return mid_read_temp(tzd, temp);
 459}
 460
 461/* Can't be const */
 462static struct thermal_zone_device_ops tzd_ops = {
 463        .get_temp = read_curr_temp,
 464};
 465
 466/**
 467 * mid_thermal_probe - mfld thermal initialize
 468 * @pdev: platform device structure
 469 *
 470 * mid thermal probe initializes the hardware and registers
 471 * all the sensors with the generic thermal framework. Can sleep.
 472 */
 473static int mid_thermal_probe(struct platform_device *pdev)
 474{
 475        static char *name[MSIC_THERMAL_SENSORS] = {
 476                "skin0", "skin1", "sys", "msicdie"
 477        };
 478
 479        int ret;
 480        int i;
 481        struct platform_info *pinfo;
 482
 483        pinfo = devm_kzalloc(&pdev->dev, sizeof(struct platform_info),
 484                             GFP_KERNEL);
 485        if (!pinfo)
 486                return -ENOMEM;
 487
 488        /* Initializing the hardware */
 489        ret = mid_initialize_adc(&pdev->dev);
 490        if (ret) {
 491                dev_err(&pdev->dev, "ADC init failed");
 492                return ret;
 493        }
 494
 495        /* Register each sensor with the generic thermal framework*/
 496        for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
 497                struct thermal_device_info *td_info = initialize_sensor(i);
 498
 499                if (!td_info) {
 500                        ret = -ENOMEM;
 501                        goto err;
 502                }
 503                pinfo->tzd[i] = thermal_zone_device_register(name[i],
 504                                0, 0, td_info, &tzd_ops, NULL, 0, 0);
 505                if (IS_ERR(pinfo->tzd[i])) {
 506                        kfree(td_info);
 507                        ret = PTR_ERR(pinfo->tzd[i]);
 508                        goto err;
 509                }
 510        }
 511
 512        pinfo->pdev = pdev;
 513        platform_set_drvdata(pdev, pinfo);
 514        return 0;
 515
 516err:
 517        while (--i >= 0) {
 518                kfree(pinfo->tzd[i]->devdata);
 519                thermal_zone_device_unregister(pinfo->tzd[i]);
 520        }
 521        configure_adc(0);
 522        return ret;
 523}
 524
 525/**
 526 * mid_thermal_remove - mfld thermal finalize
 527 * @dev: platform device structure
 528 *
 529 * MLFD thermal remove unregisters all the sensors from the generic
 530 * thermal framework. Can sleep.
 531 */
 532static int mid_thermal_remove(struct platform_device *pdev)
 533{
 534        int i;
 535        struct platform_info *pinfo = platform_get_drvdata(pdev);
 536
 537        for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
 538                kfree(pinfo->tzd[i]->devdata);
 539                thermal_zone_device_unregister(pinfo->tzd[i]);
 540        }
 541
 542        /* Stop the ADC */
 543        return configure_adc(0);
 544}
 545
 546#define DRIVER_NAME "msic_thermal"
 547
 548static const struct platform_device_id therm_id_table[] = {
 549        { DRIVER_NAME, 1 },
 550        { "msic_thermal", 1 },
 551        { }
 552};
 553
 554static struct platform_driver mid_thermal_driver = {
 555        .driver = {
 556                .name = DRIVER_NAME,
 557                .pm = &mid_thermal_pm,
 558        },
 559        .probe = mid_thermal_probe,
 560        .remove = mid_thermal_remove,
 561        .id_table = therm_id_table,
 562};
 563
 564module_platform_driver(mid_thermal_driver);
 565
 566MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
 567MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
 568MODULE_LICENSE("GPL");
 569