root/drivers/platform/x86/intel_mid_thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_msic_die_temp
  2. is_valid_adc
  3. adc_to_temp
  4. mid_read_temp
  5. configure_adc
  6. set_up_therm_channel
  7. reset_stopbit
  8. find_free_channel
  9. mid_initialize_adc
  10. initialize_sensor
  11. mid_thermal_resume
  12. mid_thermal_suspend
  13. read_curr_temp
  14. mid_thermal_probe
  15. mid_thermal_remove

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

/* [<][>][^][v][top][bottom][index][help] */