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 */ 69static int channel_index; 70 71struct platform_info { 72 struct platform_device *pdev; 73 struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS]; 74}; 75 76struct 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 */ 89static 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 */ 101static 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 */ 119static 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 */ 161static 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 */ 213static 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 */ 240static 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 */ 274static 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 */ 298static 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 */ 332static 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 */ 386static 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 */ 409static 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 */ 421static 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 432static 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 */ 441static 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 */ 448static 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 */ 459static 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 ret = thermal_zone_device_enable(pinfo->tzd[i]); 497 if (ret) { 498 kfree(td_info); 499 thermal_zone_device_unregister(pinfo->tzd[i]); 500 goto err; 501 } 502 } 503 504 pinfo->pdev = pdev; 505 platform_set_drvdata(pdev, pinfo); 506 return 0; 507 508err: 509 while (--i >= 0) { 510 kfree(pinfo->tzd[i]->devdata); 511 thermal_zone_device_unregister(pinfo->tzd[i]); 512 } 513 configure_adc(0); 514 return ret; 515} 516 517/** 518 * mid_thermal_remove - mfld thermal finalize 519 * @dev: platform device structure 520 * 521 * MLFD thermal remove unregisters all the sensors from the generic 522 * thermal framework. Can sleep. 523 */ 524static int mid_thermal_remove(struct platform_device *pdev) 525{ 526 int i; 527 struct platform_info *pinfo = platform_get_drvdata(pdev); 528 529 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) { 530 kfree(pinfo->tzd[i]->devdata); 531 thermal_zone_device_unregister(pinfo->tzd[i]); 532 } 533 534 /* Stop the ADC */ 535 return configure_adc(0); 536} 537 538#define DRIVER_NAME "msic_thermal" 539 540static const struct platform_device_id therm_id_table[] = { 541 { DRIVER_NAME, 1 }, 542 { } 543}; 544MODULE_DEVICE_TABLE(platform, therm_id_table); 545 546static struct platform_driver mid_thermal_driver = { 547 .driver = { 548 .name = DRIVER_NAME, 549 .pm = &mid_thermal_pm, 550 }, 551 .probe = mid_thermal_probe, 552 .remove = mid_thermal_remove, 553 .id_table = therm_id_table, 554}; 555 556module_platform_driver(mid_thermal_driver); 557 558MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>"); 559MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver"); 560MODULE_LICENSE("GPL v2"); 561