aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2017-11-02 04:31:52 -0400
committerZhang Rui <rui.zhang@intel.com>2017-11-02 04:31:52 -0400
commitfe9ba5bc73af01f7d53bb6b2b31204f799dd09be (patch)
treead68935d28d4616eefdefb95b4e10d3d85f11b29
parentb2fd708ffa7f43ce8680271924e1771e26a3ec91 (diff)
parent531fcdeb71f0be1d4c77838b1a4694c317b1eb98 (diff)
Merge branch 'imx-nvmem' into thermal-soc
-rw-r--r--Documentation/devicetree/bindings/thermal/imx-thermal.txt7
-rw-r--r--drivers/thermal/Kconfig1
-rw-r--r--drivers/thermal/imx_thermal.c104
3 files changed, 82 insertions, 30 deletions
diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.txt b/Documentation/devicetree/bindings/thermal/imx-thermal.txt
index 3c67bd50aa10..28be51afdb6a 100644
--- a/Documentation/devicetree/bindings/thermal/imx-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/imx-thermal.txt
@@ -7,10 +7,17 @@ Required properties:
7 is higher than panic threshold, system will auto reboot by SRC module. 7 is higher than panic threshold, system will auto reboot by SRC module.
8- fsl,tempmon : phandle pointer to system controller that contains TEMPMON 8- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
9 control registers, e.g. ANATOP on imx6q. 9 control registers, e.g. ANATOP on imx6q.
10- nvmem-cells: A phandle to the calibration cells provided by ocotp.
11- nvmem-cell-names: Should be "calib", "temp_grade".
12
13Deprecated properties:
10- fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON 14- fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON
11 calibration data, e.g. OCOTP on imx6q. The details about calibration data 15 calibration data, e.g. OCOTP on imx6q. The details about calibration data
12 can be found in SoC Reference Manual. 16 can be found in SoC Reference Manual.
13 17
18Direct access to OCOTP via fsl,tempmon-data is incorrect on some newer chips
19because it does not handle OCOTP clock requirements.
20
14Optional properties: 21Optional properties:
15- clocks : thermal sensor's clock source. 22- clocks : thermal sensor's clock source.
16 23
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c70f6bfd9e85..315ae2926e20 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -206,6 +206,7 @@ config HISI_THERMAL
206config IMX_THERMAL 206config IMX_THERMAL
207 tristate "Temperature sensor driver for Freescale i.MX SoCs" 207 tristate "Temperature sensor driver for Freescale i.MX SoCs"
208 depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST 208 depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
209 depends on NVMEM || !NVMEM
209 depends on MFD_SYSCON 210 depends on MFD_SYSCON
210 depends on OF 211 depends on OF
211 help 212 help
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 4798b4b1fd77..e7d4ffc3de7f 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -25,6 +25,7 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/thermal.h> 26#include <linux/thermal.h>
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/nvmem-consumer.h>
28 29
29#define REG_SET 0x4 30#define REG_SET 0x4
30#define REG_CLR 0x8 31#define REG_CLR 0x8
@@ -94,7 +95,7 @@ struct imx_thermal_data {
94 struct thermal_cooling_device *cdev; 95 struct thermal_cooling_device *cdev;
95 enum thermal_device_mode mode; 96 enum thermal_device_mode mode;
96 struct regmap *tempmon; 97 struct regmap *tempmon;
97 u32 c1, c2; /* See formula in imx_get_sensor_data() */ 98 u32 c1, c2; /* See formula in imx_init_calib() */
98 int temp_passive; 99 int temp_passive;
99 int temp_critical; 100 int temp_critical;
100 int temp_max; 101 int temp_max;
@@ -177,7 +178,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
177 178
178 n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; 179 n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
179 180
180 /* See imx_get_sensor_data() for formula derivation */ 181 /* See imx_init_calib() for formula derivation */
181 *temp = data->c2 - n_meas * data->c1; 182 *temp = data->c2 - n_meas * data->c1;
182 183
183 /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ 184 /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
@@ -346,29 +347,12 @@ static struct thermal_zone_device_ops imx_tz_ops = {
346 .set_trip_temp = imx_set_trip_temp, 347 .set_trip_temp = imx_set_trip_temp,
347}; 348};
348 349
349static int imx_get_sensor_data(struct platform_device *pdev) 350static int imx_init_calib(struct platform_device *pdev, u32 val)
350{ 351{
351 struct imx_thermal_data *data = platform_get_drvdata(pdev); 352 struct imx_thermal_data *data = platform_get_drvdata(pdev);
352 struct regmap *map;
353 int t1, n1; 353 int t1, n1;
354 int ret;
355 u32 val;
356 u64 temp64; 354 u64 temp64;
357 355
358 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
359 "fsl,tempmon-data");
360 if (IS_ERR(map)) {
361 ret = PTR_ERR(map);
362 dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
363 return ret;
364 }
365
366 ret = regmap_read(map, OCOTP_ANA1, &val);
367 if (ret) {
368 dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
369 return ret;
370 }
371
372 if (val == 0 || val == ~0) { 356 if (val == 0 || val == ~0) {
373 dev_err(&pdev->dev, "invalid sensor calibration data\n"); 357 dev_err(&pdev->dev, "invalid sensor calibration data\n");
374 return -EINVAL; 358 return -EINVAL;
@@ -405,12 +389,12 @@ static int imx_get_sensor_data(struct platform_device *pdev)
405 data->c1 = temp64; 389 data->c1 = temp64;
406 data->c2 = n1 * data->c1 + 1000 * t1; 390 data->c2 = n1 * data->c1 + 1000 * t1;
407 391
408 /* use OTP for thermal grade */ 392 return 0;
409 ret = regmap_read(map, OCOTP_MEM0, &val); 393}
410 if (ret) { 394
411 dev_err(&pdev->dev, "failed to read temp grade: %d\n", ret); 395static void imx_init_temp_grade(struct platform_device *pdev, u32 val)
412 return ret; 396{
413 } 397 struct imx_thermal_data *data = platform_get_drvdata(pdev);
414 398
415 /* The maximum die temp is specified by the Temperature Grade */ 399 /* The maximum die temp is specified by the Temperature Grade */
416 switch ((val >> 6) & 0x3) { 400 switch ((val >> 6) & 0x3) {
@@ -438,6 +422,55 @@ static int imx_get_sensor_data(struct platform_device *pdev)
438 */ 422 */
439 data->temp_critical = data->temp_max - (1000 * 5); 423 data->temp_critical = data->temp_max - (1000 * 5);
440 data->temp_passive = data->temp_max - (1000 * 10); 424 data->temp_passive = data->temp_max - (1000 * 10);
425}
426
427static int imx_init_from_tempmon_data(struct platform_device *pdev)
428{
429 struct regmap *map;
430 int ret;
431 u32 val;
432
433 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
434 "fsl,tempmon-data");
435 if (IS_ERR(map)) {
436 ret = PTR_ERR(map);
437 dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
438 return ret;
439 }
440
441 ret = regmap_read(map, OCOTP_ANA1, &val);
442 if (ret) {
443 dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
444 return ret;
445 }
446 ret = imx_init_calib(pdev, val);
447 if (ret)
448 return ret;
449
450 ret = regmap_read(map, OCOTP_MEM0, &val);
451 if (ret) {
452 dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
453 return ret;
454 }
455 imx_init_temp_grade(pdev, val);
456
457 return 0;
458}
459
460static int imx_init_from_nvmem_cells(struct platform_device *pdev)
461{
462 int ret;
463 u32 val;
464
465 ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val);
466 if (ret)
467 return ret;
468 imx_init_calib(pdev, val);
469
470 ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val);
471 if (ret)
472 return ret;
473 imx_init_temp_grade(pdev, val);
441 474
442 return 0; 475 return 0;
443} 476}
@@ -514,10 +547,21 @@ static int imx_thermal_probe(struct platform_device *pdev)
514 547
515 platform_set_drvdata(pdev, data); 548 platform_set_drvdata(pdev, data);
516 549
517 ret = imx_get_sensor_data(pdev); 550 if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
518 if (ret) { 551 ret = imx_init_from_nvmem_cells(pdev);
519 dev_err(&pdev->dev, "failed to get sensor data\n"); 552 if (ret == -EPROBE_DEFER)
520 return ret; 553 return ret;
554 if (ret) {
555 dev_err(&pdev->dev, "failed to init from nvmem: %d\n",
556 ret);
557 return ret;
558 }
559 } else {
560 ret = imx_init_from_tempmon_data(pdev);
561 if (ret) {
562 dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n");
563 return ret;
564 }
521 } 565 }
522 566
523 /* Make sure sensor is in known good state for measurements */ 567 /* Make sure sensor is in known good state for measurements */