| .. | .. |
|---|
| 3 | 3 | // Copyright 2013 Freescale Semiconductor, Inc. |
|---|
| 4 | 4 | |
|---|
| 5 | 5 | #include <linux/clk.h> |
|---|
| 6 | | -#include <linux/cpu.h> |
|---|
| 7 | 6 | #include <linux/cpufreq.h> |
|---|
| 8 | 7 | #include <linux/cpu_cooling.h> |
|---|
| 9 | 8 | #include <linux/delay.h> |
|---|
| 10 | | -#include <linux/device.h> |
|---|
| 11 | | -#include <linux/init.h> |
|---|
| 12 | 9 | #include <linux/interrupt.h> |
|---|
| 13 | 10 | #include <linux/io.h> |
|---|
| 14 | | -#include <linux/kernel.h> |
|---|
| 15 | 11 | #include <linux/mfd/syscon.h> |
|---|
| 16 | 12 | #include <linux/module.h> |
|---|
| 17 | 13 | #include <linux/of.h> |
|---|
| 18 | 14 | #include <linux/of_device.h> |
|---|
| 19 | | -#include <linux/platform_device.h> |
|---|
| 20 | 15 | #include <linux/regmap.h> |
|---|
| 21 | | -#include <linux/slab.h> |
|---|
| 22 | 16 | #include <linux/thermal.h> |
|---|
| 23 | | -#include <linux/types.h> |
|---|
| 24 | 17 | #include <linux/nvmem-consumer.h> |
|---|
| 18 | +#include <linux/pm_runtime.h> |
|---|
| 25 | 19 | |
|---|
| 26 | 20 | #define REG_SET 0x4 |
|---|
| 27 | 21 | #define REG_CLR 0x8 |
|---|
| .. | .. |
|---|
| 201 | 195 | }; |
|---|
| 202 | 196 | |
|---|
| 203 | 197 | struct imx_thermal_data { |
|---|
| 198 | + struct device *dev; |
|---|
| 204 | 199 | struct cpufreq_policy *policy; |
|---|
| 205 | 200 | struct thermal_zone_device *tz; |
|---|
| 206 | 201 | struct thermal_cooling_device *cdev; |
|---|
| 207 | | - enum thermal_device_mode mode; |
|---|
| 208 | 202 | struct regmap *tempmon; |
|---|
| 209 | 203 | u32 c1, c2; /* See formula in imx_init_calib() */ |
|---|
| 210 | 204 | int temp_passive; |
|---|
| .. | .. |
|---|
| 260 | 254 | const struct thermal_soc_data *soc_data = data->socdata; |
|---|
| 261 | 255 | struct regmap *map = data->tempmon; |
|---|
| 262 | 256 | unsigned int n_meas; |
|---|
| 263 | | - bool wait; |
|---|
| 264 | 257 | u32 val; |
|---|
| 258 | + int ret; |
|---|
| 265 | 259 | |
|---|
| 266 | | - if (data->mode == THERMAL_DEVICE_ENABLED) { |
|---|
| 267 | | - /* Check if a measurement is currently in progress */ |
|---|
| 268 | | - regmap_read(map, soc_data->temp_data, &val); |
|---|
| 269 | | - wait = !(val & soc_data->temp_valid_mask); |
|---|
| 270 | | - } else { |
|---|
| 271 | | - /* |
|---|
| 272 | | - * Every time we measure the temperature, we will power on the |
|---|
| 273 | | - * temperature sensor, enable measurements, take a reading, |
|---|
| 274 | | - * disable measurements, power off the temperature sensor. |
|---|
| 275 | | - */ |
|---|
| 276 | | - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
|---|
| 277 | | - soc_data->power_down_mask); |
|---|
| 278 | | - regmap_write(map, soc_data->sensor_ctrl + REG_SET, |
|---|
| 279 | | - soc_data->measure_temp_mask); |
|---|
| 280 | | - |
|---|
| 281 | | - wait = true; |
|---|
| 282 | | - } |
|---|
| 283 | | - |
|---|
| 284 | | - /* |
|---|
| 285 | | - * According to the temp sensor designers, it may require up to ~17us |
|---|
| 286 | | - * to complete a measurement. |
|---|
| 287 | | - */ |
|---|
| 288 | | - if (wait) |
|---|
| 289 | | - usleep_range(20, 50); |
|---|
| 260 | + ret = pm_runtime_resume_and_get(data->dev); |
|---|
| 261 | + if (ret < 0) |
|---|
| 262 | + return ret; |
|---|
| 290 | 263 | |
|---|
| 291 | 264 | regmap_read(map, soc_data->temp_data, &val); |
|---|
| 292 | | - |
|---|
| 293 | | - if (data->mode != THERMAL_DEVICE_ENABLED) { |
|---|
| 294 | | - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
|---|
| 295 | | - soc_data->measure_temp_mask); |
|---|
| 296 | | - regmap_write(map, soc_data->sensor_ctrl + REG_SET, |
|---|
| 297 | | - soc_data->power_down_mask); |
|---|
| 298 | | - } |
|---|
| 299 | 265 | |
|---|
| 300 | 266 | if ((val & soc_data->temp_valid_mask) == 0) { |
|---|
| 301 | 267 | dev_dbg(&tz->device, "temp measurement never finished\n"); |
|---|
| .. | .. |
|---|
| 335 | 301 | enable_irq(data->irq); |
|---|
| 336 | 302 | } |
|---|
| 337 | 303 | |
|---|
| 338 | | - return 0; |
|---|
| 339 | | -} |
|---|
| 340 | | - |
|---|
| 341 | | -static int imx_get_mode(struct thermal_zone_device *tz, |
|---|
| 342 | | - enum thermal_device_mode *mode) |
|---|
| 343 | | -{ |
|---|
| 344 | | - struct imx_thermal_data *data = tz->devdata; |
|---|
| 345 | | - |
|---|
| 346 | | - *mode = data->mode; |
|---|
| 304 | + pm_runtime_put(data->dev); |
|---|
| 347 | 305 | |
|---|
| 348 | 306 | return 0; |
|---|
| 349 | 307 | } |
|---|
| 350 | 308 | |
|---|
| 351 | | -static int imx_set_mode(struct thermal_zone_device *tz, |
|---|
| 352 | | - enum thermal_device_mode mode) |
|---|
| 309 | +static int imx_change_mode(struct thermal_zone_device *tz, |
|---|
| 310 | + enum thermal_device_mode mode) |
|---|
| 353 | 311 | { |
|---|
| 354 | 312 | struct imx_thermal_data *data = tz->devdata; |
|---|
| 355 | | - struct regmap *map = data->tempmon; |
|---|
| 356 | | - const struct thermal_soc_data *soc_data = data->socdata; |
|---|
| 357 | 313 | |
|---|
| 358 | 314 | if (mode == THERMAL_DEVICE_ENABLED) { |
|---|
| 359 | | - tz->polling_delay = IMX_POLLING_DELAY; |
|---|
| 360 | | - tz->passive_delay = IMX_PASSIVE_DELAY; |
|---|
| 361 | | - |
|---|
| 362 | | - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
|---|
| 363 | | - soc_data->power_down_mask); |
|---|
| 364 | | - regmap_write(map, soc_data->sensor_ctrl + REG_SET, |
|---|
| 365 | | - soc_data->measure_temp_mask); |
|---|
| 315 | + pm_runtime_get(data->dev); |
|---|
| 366 | 316 | |
|---|
| 367 | 317 | if (!data->irq_enabled) { |
|---|
| 368 | 318 | data->irq_enabled = true; |
|---|
| 369 | 319 | enable_irq(data->irq); |
|---|
| 370 | 320 | } |
|---|
| 371 | 321 | } else { |
|---|
| 372 | | - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
|---|
| 373 | | - soc_data->measure_temp_mask); |
|---|
| 374 | | - regmap_write(map, soc_data->sensor_ctrl + REG_SET, |
|---|
| 375 | | - soc_data->power_down_mask); |
|---|
| 376 | | - |
|---|
| 377 | | - tz->polling_delay = 0; |
|---|
| 378 | | - tz->passive_delay = 0; |
|---|
| 322 | + pm_runtime_put(data->dev); |
|---|
| 379 | 323 | |
|---|
| 380 | 324 | if (data->irq_enabled) { |
|---|
| 381 | 325 | disable_irq(data->irq); |
|---|
| 382 | 326 | data->irq_enabled = false; |
|---|
| 383 | 327 | } |
|---|
| 384 | 328 | } |
|---|
| 385 | | - |
|---|
| 386 | | - data->mode = mode; |
|---|
| 387 | | - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); |
|---|
| 388 | 329 | |
|---|
| 389 | 330 | return 0; |
|---|
| 390 | 331 | } |
|---|
| .. | .. |
|---|
| 419 | 360 | int temp) |
|---|
| 420 | 361 | { |
|---|
| 421 | 362 | struct imx_thermal_data *data = tz->devdata; |
|---|
| 363 | + int ret; |
|---|
| 364 | + |
|---|
| 365 | + ret = pm_runtime_resume_and_get(data->dev); |
|---|
| 366 | + if (ret < 0) |
|---|
| 367 | + return ret; |
|---|
| 422 | 368 | |
|---|
| 423 | 369 | /* do not allow changing critical threshold */ |
|---|
| 424 | 370 | if (trip == IMX_TRIP_CRITICAL) |
|---|
| .. | .. |
|---|
| 431 | 377 | data->temp_passive = temp; |
|---|
| 432 | 378 | |
|---|
| 433 | 379 | imx_set_alarm_temp(data, temp); |
|---|
| 380 | + |
|---|
| 381 | + pm_runtime_put(data->dev); |
|---|
| 434 | 382 | |
|---|
| 435 | 383 | return 0; |
|---|
| 436 | 384 | } |
|---|
| .. | .. |
|---|
| 474 | 422 | .bind = imx_bind, |
|---|
| 475 | 423 | .unbind = imx_unbind, |
|---|
| 476 | 424 | .get_temp = imx_get_temp, |
|---|
| 477 | | - .get_mode = imx_get_mode, |
|---|
| 478 | | - .set_mode = imx_set_mode, |
|---|
| 425 | + .change_mode = imx_change_mode, |
|---|
| 479 | 426 | .get_trip_type = imx_get_trip_type, |
|---|
| 480 | 427 | .get_trip_temp = imx_get_trip_temp, |
|---|
| 481 | 428 | .get_crit_temp = imx_get_crit_temp, |
|---|
| .. | .. |
|---|
| 648 | 595 | }; |
|---|
| 649 | 596 | MODULE_DEVICE_TABLE(of, of_imx_thermal_match); |
|---|
| 650 | 597 | |
|---|
| 598 | +#ifdef CONFIG_CPU_FREQ |
|---|
| 651 | 599 | /* |
|---|
| 652 | 600 | * Create cooling device in case no #cooling-cells property is available in |
|---|
| 653 | 601 | * CPU node |
|---|
| 654 | 602 | */ |
|---|
| 655 | 603 | static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data) |
|---|
| 656 | 604 | { |
|---|
| 657 | | - struct device_node *np = of_get_cpu_node(data->policy->cpu, NULL); |
|---|
| 658 | | - int ret; |
|---|
| 605 | + struct device_node *np; |
|---|
| 606 | + int ret = 0; |
|---|
| 607 | + |
|---|
| 608 | + data->policy = cpufreq_cpu_get(0); |
|---|
| 609 | + if (!data->policy) { |
|---|
| 610 | + pr_debug("%s: CPUFreq policy not found\n", __func__); |
|---|
| 611 | + return -EPROBE_DEFER; |
|---|
| 612 | + } |
|---|
| 613 | + |
|---|
| 614 | + np = of_get_cpu_node(data->policy->cpu, NULL); |
|---|
| 659 | 615 | |
|---|
| 660 | 616 | if (!np || !of_find_property(np, "#cooling-cells", NULL)) { |
|---|
| 661 | 617 | data->cdev = cpufreq_cooling_register(data->policy); |
|---|
| 662 | 618 | if (IS_ERR(data->cdev)) { |
|---|
| 663 | 619 | ret = PTR_ERR(data->cdev); |
|---|
| 664 | 620 | cpufreq_cpu_put(data->policy); |
|---|
| 665 | | - return ret; |
|---|
| 666 | 621 | } |
|---|
| 667 | 622 | } |
|---|
| 668 | 623 | |
|---|
| 624 | + of_node_put(np); |
|---|
| 625 | + |
|---|
| 626 | + return ret; |
|---|
| 627 | +} |
|---|
| 628 | + |
|---|
| 629 | +static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data) |
|---|
| 630 | +{ |
|---|
| 631 | + cpufreq_cooling_unregister(data->cdev); |
|---|
| 632 | + cpufreq_cpu_put(data->policy); |
|---|
| 633 | +} |
|---|
| 634 | + |
|---|
| 635 | +#else |
|---|
| 636 | + |
|---|
| 637 | +static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data) |
|---|
| 638 | +{ |
|---|
| 669 | 639 | return 0; |
|---|
| 670 | 640 | } |
|---|
| 641 | + |
|---|
| 642 | +static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data) |
|---|
| 643 | +{ |
|---|
| 644 | +} |
|---|
| 645 | +#endif |
|---|
| 671 | 646 | |
|---|
| 672 | 647 | static int imx_thermal_probe(struct platform_device *pdev) |
|---|
| 673 | 648 | { |
|---|
| .. | .. |
|---|
| 679 | 654 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
|---|
| 680 | 655 | if (!data) |
|---|
| 681 | 656 | return -ENOMEM; |
|---|
| 657 | + |
|---|
| 658 | + data->dev = &pdev->dev; |
|---|
| 682 | 659 | |
|---|
| 683 | 660 | map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon"); |
|---|
| 684 | 661 | if (IS_ERR(map)) { |
|---|
| .. | .. |
|---|
| 715 | 692 | |
|---|
| 716 | 693 | if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) { |
|---|
| 717 | 694 | ret = imx_init_from_nvmem_cells(pdev); |
|---|
| 718 | | - if (ret == -EPROBE_DEFER) |
|---|
| 719 | | - return ret; |
|---|
| 720 | | - if (ret) { |
|---|
| 721 | | - dev_err(&pdev->dev, "failed to init from nvmem: %d\n", |
|---|
| 722 | | - ret); |
|---|
| 723 | | - return ret; |
|---|
| 724 | | - } |
|---|
| 695 | + if (ret) |
|---|
| 696 | + return dev_err_probe(&pdev->dev, ret, |
|---|
| 697 | + "failed to init from nvmem\n"); |
|---|
| 725 | 698 | } else { |
|---|
| 726 | 699 | ret = imx_init_from_tempmon_data(pdev); |
|---|
| 727 | 700 | if (ret) { |
|---|
| 728 | | - dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n"); |
|---|
| 701 | + dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n"); |
|---|
| 729 | 702 | return ret; |
|---|
| 730 | 703 | } |
|---|
| 731 | 704 | } |
|---|
| .. | .. |
|---|
| 743 | 716 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, |
|---|
| 744 | 717 | data->socdata->power_down_mask); |
|---|
| 745 | 718 | |
|---|
| 746 | | - data->policy = cpufreq_cpu_get(0); |
|---|
| 747 | | - if (!data->policy) { |
|---|
| 748 | | - pr_debug("%s: CPUFreq policy not found\n", __func__); |
|---|
| 749 | | - return -EPROBE_DEFER; |
|---|
| 750 | | - } |
|---|
| 751 | | - |
|---|
| 752 | 719 | ret = imx_thermal_register_legacy_cooling(data); |
|---|
| 753 | | - if (ret) { |
|---|
| 754 | | - dev_err(&pdev->dev, |
|---|
| 755 | | - "failed to register cpufreq cooling device: %d\n", ret); |
|---|
| 756 | | - return ret; |
|---|
| 757 | | - } |
|---|
| 720 | + if (ret) |
|---|
| 721 | + return dev_err_probe(&pdev->dev, ret, |
|---|
| 722 | + "failed to register cpufreq cooling device\n"); |
|---|
| 758 | 723 | |
|---|
| 759 | 724 | data->thermal_clk = devm_clk_get(&pdev->dev, NULL); |
|---|
| 760 | 725 | if (IS_ERR(data->thermal_clk)) { |
|---|
| .. | .. |
|---|
| 762 | 727 | if (ret != -EPROBE_DEFER) |
|---|
| 763 | 728 | dev_err(&pdev->dev, |
|---|
| 764 | 729 | "failed to get thermal clk: %d\n", ret); |
|---|
| 765 | | - cpufreq_cooling_unregister(data->cdev); |
|---|
| 766 | | - cpufreq_cpu_put(data->policy); |
|---|
| 767 | | - return ret; |
|---|
| 730 | + goto legacy_cleanup; |
|---|
| 768 | 731 | } |
|---|
| 769 | 732 | |
|---|
| 770 | 733 | /* |
|---|
| .. | .. |
|---|
| 777 | 740 | ret = clk_prepare_enable(data->thermal_clk); |
|---|
| 778 | 741 | if (ret) { |
|---|
| 779 | 742 | dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret); |
|---|
| 780 | | - cpufreq_cooling_unregister(data->cdev); |
|---|
| 781 | | - cpufreq_cpu_put(data->policy); |
|---|
| 782 | | - return ret; |
|---|
| 743 | + goto legacy_cleanup; |
|---|
| 783 | 744 | } |
|---|
| 784 | 745 | |
|---|
| 785 | 746 | data->tz = thermal_zone_device_register("imx_thermal_zone", |
|---|
| .. | .. |
|---|
| 792 | 753 | ret = PTR_ERR(data->tz); |
|---|
| 793 | 754 | dev_err(&pdev->dev, |
|---|
| 794 | 755 | "failed to register thermal zone device %d\n", ret); |
|---|
| 795 | | - clk_disable_unprepare(data->thermal_clk); |
|---|
| 796 | | - cpufreq_cooling_unregister(data->cdev); |
|---|
| 797 | | - cpufreq_cpu_put(data->policy); |
|---|
| 798 | | - return ret; |
|---|
| 756 | + goto clk_disable; |
|---|
| 799 | 757 | } |
|---|
| 800 | 758 | |
|---|
| 801 | 759 | dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC" |
|---|
| .. | .. |
|---|
| 818 | 776 | data->socdata->power_down_mask); |
|---|
| 819 | 777 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, |
|---|
| 820 | 778 | data->socdata->measure_temp_mask); |
|---|
| 779 | + /* After power up, we need a delay before first access can be done. */ |
|---|
| 780 | + usleep_range(20, 50); |
|---|
| 781 | + |
|---|
| 782 | + /* the core was configured and enabled just before */ |
|---|
| 783 | + pm_runtime_set_active(&pdev->dev); |
|---|
| 784 | + pm_runtime_enable(data->dev); |
|---|
| 785 | + |
|---|
| 786 | + ret = pm_runtime_resume_and_get(data->dev); |
|---|
| 787 | + if (ret < 0) |
|---|
| 788 | + goto disable_runtime_pm; |
|---|
| 821 | 789 | |
|---|
| 822 | 790 | data->irq_enabled = true; |
|---|
| 823 | | - data->mode = THERMAL_DEVICE_ENABLED; |
|---|
| 791 | + ret = thermal_zone_device_enable(data->tz); |
|---|
| 792 | + if (ret) |
|---|
| 793 | + goto thermal_zone_unregister; |
|---|
| 824 | 794 | |
|---|
| 825 | 795 | ret = devm_request_threaded_irq(&pdev->dev, data->irq, |
|---|
| 826 | 796 | imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, |
|---|
| 827 | 797 | 0, "imx_thermal", data); |
|---|
| 828 | 798 | if (ret < 0) { |
|---|
| 829 | 799 | dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); |
|---|
| 830 | | - clk_disable_unprepare(data->thermal_clk); |
|---|
| 831 | | - thermal_zone_device_unregister(data->tz); |
|---|
| 832 | | - cpufreq_cooling_unregister(data->cdev); |
|---|
| 833 | | - cpufreq_cpu_put(data->policy); |
|---|
| 834 | | - return ret; |
|---|
| 800 | + goto thermal_zone_unregister; |
|---|
| 835 | 801 | } |
|---|
| 836 | 802 | |
|---|
| 803 | + pm_runtime_put(data->dev); |
|---|
| 804 | + |
|---|
| 837 | 805 | return 0; |
|---|
| 806 | + |
|---|
| 807 | +thermal_zone_unregister: |
|---|
| 808 | + thermal_zone_device_unregister(data->tz); |
|---|
| 809 | +disable_runtime_pm: |
|---|
| 810 | + pm_runtime_put_noidle(data->dev); |
|---|
| 811 | + pm_runtime_disable(data->dev); |
|---|
| 812 | +clk_disable: |
|---|
| 813 | + clk_disable_unprepare(data->thermal_clk); |
|---|
| 814 | +legacy_cleanup: |
|---|
| 815 | + imx_thermal_unregister_legacy_cooling(data); |
|---|
| 816 | + |
|---|
| 817 | + return ret; |
|---|
| 838 | 818 | } |
|---|
| 839 | 819 | |
|---|
| 840 | 820 | static int imx_thermal_remove(struct platform_device *pdev) |
|---|
| 841 | 821 | { |
|---|
| 842 | 822 | struct imx_thermal_data *data = platform_get_drvdata(pdev); |
|---|
| 843 | | - struct regmap *map = data->tempmon; |
|---|
| 844 | 823 | |
|---|
| 845 | | - /* Disable measurements */ |
|---|
| 846 | | - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, |
|---|
| 847 | | - data->socdata->power_down_mask); |
|---|
| 848 | | - if (!IS_ERR(data->thermal_clk)) |
|---|
| 849 | | - clk_disable_unprepare(data->thermal_clk); |
|---|
| 824 | + pm_runtime_put_noidle(data->dev); |
|---|
| 825 | + pm_runtime_disable(data->dev); |
|---|
| 850 | 826 | |
|---|
| 851 | 827 | thermal_zone_device_unregister(data->tz); |
|---|
| 852 | | - cpufreq_cooling_unregister(data->cdev); |
|---|
| 853 | | - cpufreq_cpu_put(data->policy); |
|---|
| 828 | + imx_thermal_unregister_legacy_cooling(data); |
|---|
| 854 | 829 | |
|---|
| 855 | 830 | return 0; |
|---|
| 856 | 831 | } |
|---|
| 857 | 832 | |
|---|
| 858 | | -#ifdef CONFIG_PM_SLEEP |
|---|
| 859 | | -static int imx_thermal_suspend(struct device *dev) |
|---|
| 833 | +static int __maybe_unused imx_thermal_suspend(struct device *dev) |
|---|
| 860 | 834 | { |
|---|
| 861 | 835 | struct imx_thermal_data *data = dev_get_drvdata(dev); |
|---|
| 862 | | - struct regmap *map = data->tempmon; |
|---|
| 836 | + int ret; |
|---|
| 863 | 837 | |
|---|
| 864 | 838 | /* |
|---|
| 865 | 839 | * Need to disable thermal sensor, otherwise, when thermal core |
|---|
| 866 | 840 | * try to get temperature before thermal sensor resume, a wrong |
|---|
| 867 | 841 | * temperature will be read as the thermal sensor is powered |
|---|
| 868 | | - * down. |
|---|
| 842 | + * down. This is done in change_mode() operation called from |
|---|
| 843 | + * thermal_zone_device_disable() |
|---|
| 869 | 844 | */ |
|---|
| 870 | | - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
|---|
| 871 | | - data->socdata->measure_temp_mask); |
|---|
| 872 | | - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, |
|---|
| 873 | | - data->socdata->power_down_mask); |
|---|
| 874 | | - data->mode = THERMAL_DEVICE_DISABLED; |
|---|
| 845 | + ret = thermal_zone_device_disable(data->tz); |
|---|
| 846 | + if (ret) |
|---|
| 847 | + return ret; |
|---|
| 848 | + |
|---|
| 849 | + return pm_runtime_force_suspend(data->dev); |
|---|
| 850 | +} |
|---|
| 851 | + |
|---|
| 852 | +static int __maybe_unused imx_thermal_resume(struct device *dev) |
|---|
| 853 | +{ |
|---|
| 854 | + struct imx_thermal_data *data = dev_get_drvdata(dev); |
|---|
| 855 | + int ret; |
|---|
| 856 | + |
|---|
| 857 | + ret = pm_runtime_force_resume(data->dev); |
|---|
| 858 | + if (ret) |
|---|
| 859 | + return ret; |
|---|
| 860 | + /* Enabled thermal sensor after resume */ |
|---|
| 861 | + return thermal_zone_device_enable(data->tz); |
|---|
| 862 | +} |
|---|
| 863 | + |
|---|
| 864 | +static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev) |
|---|
| 865 | +{ |
|---|
| 866 | + struct imx_thermal_data *data = dev_get_drvdata(dev); |
|---|
| 867 | + const struct thermal_soc_data *socdata = data->socdata; |
|---|
| 868 | + struct regmap *map = data->tempmon; |
|---|
| 869 | + int ret; |
|---|
| 870 | + |
|---|
| 871 | + ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR, |
|---|
| 872 | + socdata->measure_temp_mask); |
|---|
| 873 | + if (ret) |
|---|
| 874 | + return ret; |
|---|
| 875 | + |
|---|
| 876 | + ret = regmap_write(map, socdata->sensor_ctrl + REG_SET, |
|---|
| 877 | + socdata->power_down_mask); |
|---|
| 878 | + if (ret) |
|---|
| 879 | + return ret; |
|---|
| 880 | + |
|---|
| 875 | 881 | clk_disable_unprepare(data->thermal_clk); |
|---|
| 876 | 882 | |
|---|
| 877 | 883 | return 0; |
|---|
| 878 | 884 | } |
|---|
| 879 | 885 | |
|---|
| 880 | | -static int imx_thermal_resume(struct device *dev) |
|---|
| 886 | +static int __maybe_unused imx_thermal_runtime_resume(struct device *dev) |
|---|
| 881 | 887 | { |
|---|
| 882 | 888 | struct imx_thermal_data *data = dev_get_drvdata(dev); |
|---|
| 889 | + const struct thermal_soc_data *socdata = data->socdata; |
|---|
| 883 | 890 | struct regmap *map = data->tempmon; |
|---|
| 884 | 891 | int ret; |
|---|
| 885 | 892 | |
|---|
| 886 | 893 | ret = clk_prepare_enable(data->thermal_clk); |
|---|
| 887 | 894 | if (ret) |
|---|
| 888 | 895 | return ret; |
|---|
| 889 | | - /* Enabled thermal sensor after resume */ |
|---|
| 890 | | - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
|---|
| 891 | | - data->socdata->power_down_mask); |
|---|
| 892 | | - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, |
|---|
| 893 | | - data->socdata->measure_temp_mask); |
|---|
| 894 | | - data->mode = THERMAL_DEVICE_ENABLED; |
|---|
| 896 | + |
|---|
| 897 | + ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR, |
|---|
| 898 | + socdata->power_down_mask); |
|---|
| 899 | + if (ret) |
|---|
| 900 | + return ret; |
|---|
| 901 | + |
|---|
| 902 | + ret = regmap_write(map, socdata->sensor_ctrl + REG_SET, |
|---|
| 903 | + socdata->measure_temp_mask); |
|---|
| 904 | + if (ret) |
|---|
| 905 | + return ret; |
|---|
| 906 | + |
|---|
| 907 | + /* |
|---|
| 908 | + * According to the temp sensor designers, it may require up to ~17us |
|---|
| 909 | + * to complete a measurement. |
|---|
| 910 | + */ |
|---|
| 911 | + usleep_range(20, 50); |
|---|
| 895 | 912 | |
|---|
| 896 | 913 | return 0; |
|---|
| 897 | 914 | } |
|---|
| 898 | | -#endif |
|---|
| 899 | 915 | |
|---|
| 900 | | -static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops, |
|---|
| 901 | | - imx_thermal_suspend, imx_thermal_resume); |
|---|
| 916 | +static const struct dev_pm_ops imx_thermal_pm_ops = { |
|---|
| 917 | + SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume) |
|---|
| 918 | + SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend, |
|---|
| 919 | + imx_thermal_runtime_resume, NULL) |
|---|
| 920 | +}; |
|---|
| 902 | 921 | |
|---|
| 903 | 922 | static struct platform_driver imx_thermal = { |
|---|
| 904 | 923 | .driver = { |
|---|