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