diff options
author | Zhang Rui <rui.zhang@intel.com> | 2017-11-02 04:31:52 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2017-11-02 04:31:52 -0400 |
commit | fe9ba5bc73af01f7d53bb6b2b31204f799dd09be (patch) | |
tree | ad68935d28d4616eefdefb95b4e10d3d85f11b29 | |
parent | b2fd708ffa7f43ce8680271924e1771e26a3ec91 (diff) | |
parent | 531fcdeb71f0be1d4c77838b1a4694c317b1eb98 (diff) |
Merge branch 'imx-nvmem' into thermal-soc
-rw-r--r-- | Documentation/devicetree/bindings/thermal/imx-thermal.txt | 7 | ||||
-rw-r--r-- | drivers/thermal/Kconfig | 1 | ||||
-rw-r--r-- | drivers/thermal/imx_thermal.c | 104 |
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 | |||
13 | Deprecated 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 | ||
18 | Direct access to OCOTP via fsl,tempmon-data is incorrect on some newer chips | ||
19 | because it does not handle OCOTP clock requirements. | ||
20 | |||
14 | Optional properties: | 21 | Optional 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 | |||
206 | config IMX_THERMAL | 206 | config 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 | ||
349 | static int imx_get_sensor_data(struct platform_device *pdev) | 350 | static 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); | 395 | static 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 | |||
427 | static 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 | |||
460 | static 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 */ |