aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal/exynos_thermal.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 22:48:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 22:48:26 -0500
commit2af78448fff61e13392daf4f770cfbcf9253316a (patch)
tree6c0494284dd1dd737d5f76ee19c553618e8d0e54 /drivers/thermal/exynos_thermal.c
parent5e04f4b4290e03deb91b074087ae8d7c169d947d (diff)
parentf5b6d45f8cf688f51140fd21f1da3b90562762a9 (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui: "Highlights: - introduction of Dove thermal sensor driver. - introduction of Kirkwood thermal sensor driver. - introduction of intel_powerclamp thermal cooling device driver. - add interrupt and DT support for rcar thermal driver. - add thermal emulation support which allows platform thermal driver to do software/hardware emulation for thermal issues." * 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (36 commits) thermal: rcar: remove __devinitconst thermal: return an error on failure to register thermal class Thermal: rename thermal governor Kconfig option to avoid generic naming thermal: exynos: Use the new thermal trend type for quick cooling action. Thermal: exynos: Add support for temperature falling interrupt. Thermal: Dove: Add Themal sensor support for Dove. thermal: Add support for the thermal sensor on Kirkwood SoCs thermal: rcar: add Device Tree support thermal: rcar: remove machine_power_off() from rcar_thermal_notify() thermal: rcar: add interrupt support thermal: rcar: add read/write functions for common/priv data thermal: rcar: multi channel support thermal: rcar: use mutex lock instead of spin lock thermal: rcar: enable CPCTL to use hardware TSC deciding thermal: rcar: use parenthesis on macro Thermal: fix a build warning when CONFIG_THERMAL_EMULATION cleared Thermal: fix a wrong comment thermal: sysfs: Add a new sysfs node emul_temp for thermal emulation PM: intel_powerclamp: off by one in start_power_clamp() thermal: exynos: Miscellaneous fixes to support falling threshold interrupt ...
Diffstat (limited to 'drivers/thermal/exynos_thermal.c')
-rw-r--r--drivers/thermal/exynos_thermal.c211
1 files changed, 164 insertions, 47 deletions
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index bada1308318b..e04ebd8671ac 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -82,7 +82,7 @@
82 82
83#define EXYNOS_TRIMINFO_RELOAD 0x1 83#define EXYNOS_TRIMINFO_RELOAD 0x1
84#define EXYNOS_TMU_CLEAR_RISE_INT 0x111 84#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
85#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 16) 85#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12)
86#define EXYNOS_MUX_ADDR_VALUE 6 86#define EXYNOS_MUX_ADDR_VALUE 6
87#define EXYNOS_MUX_ADDR_SHIFT 20 87#define EXYNOS_MUX_ADDR_SHIFT 20
88#define EXYNOS_TMU_TRIP_MODE_SHIFT 13 88#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
@@ -94,11 +94,20 @@
94#define SENSOR_NAME_LEN 16 94#define SENSOR_NAME_LEN 16
95#define MAX_TRIP_COUNT 8 95#define MAX_TRIP_COUNT 8
96#define MAX_COOLING_DEVICE 4 96#define MAX_COOLING_DEVICE 4
97#define MAX_THRESHOLD_LEVS 4
97 98
98#define ACTIVE_INTERVAL 500 99#define ACTIVE_INTERVAL 500
99#define IDLE_INTERVAL 10000 100#define IDLE_INTERVAL 10000
100#define MCELSIUS 1000 101#define MCELSIUS 1000
101 102
103#ifdef CONFIG_EXYNOS_THERMAL_EMUL
104#define EXYNOS_EMUL_TIME 0x57F0
105#define EXYNOS_EMUL_TIME_SHIFT 16
106#define EXYNOS_EMUL_DATA_SHIFT 8
107#define EXYNOS_EMUL_DATA_MASK 0xFF
108#define EXYNOS_EMUL_ENABLE 0x1
109#endif /* CONFIG_EXYNOS_THERMAL_EMUL */
110
102/* CPU Zone information */ 111/* CPU Zone information */
103#define PANIC_ZONE 4 112#define PANIC_ZONE 4
104#define WARN_ZONE 3 113#define WARN_ZONE 3
@@ -125,6 +134,7 @@ struct exynos_tmu_data {
125struct thermal_trip_point_conf { 134struct thermal_trip_point_conf {
126 int trip_val[MAX_TRIP_COUNT]; 135 int trip_val[MAX_TRIP_COUNT];
127 int trip_count; 136 int trip_count;
137 u8 trigger_falling;
128}; 138};
129 139
130struct thermal_cooling_conf { 140struct thermal_cooling_conf {
@@ -174,7 +184,8 @@ static int exynos_set_mode(struct thermal_zone_device *thermal,
174 184
175 mutex_lock(&th_zone->therm_dev->lock); 185 mutex_lock(&th_zone->therm_dev->lock);
176 186
177 if (mode == THERMAL_DEVICE_ENABLED) 187 if (mode == THERMAL_DEVICE_ENABLED &&
188 !th_zone->sensor_conf->trip_data.trigger_falling)
178 th_zone->therm_dev->polling_delay = IDLE_INTERVAL; 189 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
179 else 190 else
180 th_zone->therm_dev->polling_delay = 0; 191 th_zone->therm_dev->polling_delay = 0;
@@ -284,7 +295,7 @@ static int exynos_bind(struct thermal_zone_device *thermal,
284 case MONITOR_ZONE: 295 case MONITOR_ZONE:
285 case WARN_ZONE: 296 case WARN_ZONE:
286 if (thermal_zone_bind_cooling_device(thermal, i, cdev, 297 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
287 level, level)) { 298 level, 0)) {
288 pr_err("error binding cdev inst %d\n", i); 299 pr_err("error binding cdev inst %d\n", i);
289 ret = -EINVAL; 300 ret = -EINVAL;
290 } 301 }
@@ -362,10 +373,17 @@ static int exynos_get_temp(struct thermal_zone_device *thermal,
362static int exynos_get_trend(struct thermal_zone_device *thermal, 373static int exynos_get_trend(struct thermal_zone_device *thermal,
363 int trip, enum thermal_trend *trend) 374 int trip, enum thermal_trend *trend)
364{ 375{
365 if (thermal->temperature >= trip) 376 int ret;
366 *trend = THERMAL_TREND_RAISING; 377 unsigned long trip_temp;
378
379 ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
380 if (ret < 0)
381 return ret;
382
383 if (thermal->temperature >= trip_temp)
384 *trend = THERMAL_TREND_RAISE_FULL;
367 else 385 else
368 *trend = THERMAL_TREND_DROPPING; 386 *trend = THERMAL_TREND_DROP_FULL;
369 387
370 return 0; 388 return 0;
371} 389}
@@ -413,7 +431,8 @@ static void exynos_report_trigger(void)
413 break; 431 break;
414 } 432 }
415 433
416 if (th_zone->mode == THERMAL_DEVICE_ENABLED) { 434 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
435 !th_zone->sensor_conf->trip_data.trigger_falling) {
417 if (i > 0) 436 if (i > 0)
418 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL; 437 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
419 else 438 else
@@ -452,7 +471,8 @@ static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
452 471
453 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name, 472 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
454 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0, 473 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
455 IDLE_INTERVAL); 474 sensor_conf->trip_data.trigger_falling ?
475 0 : IDLE_INTERVAL);
456 476
457 if (IS_ERR(th_zone->therm_dev)) { 477 if (IS_ERR(th_zone->therm_dev)) {
458 pr_err("Failed to register thermal zone device\n"); 478 pr_err("Failed to register thermal zone device\n");
@@ -559,8 +579,9 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
559{ 579{
560 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 580 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
561 struct exynos_tmu_platform_data *pdata = data->pdata; 581 struct exynos_tmu_platform_data *pdata = data->pdata;
562 unsigned int status, trim_info, rising_threshold; 582 unsigned int status, trim_info;
563 int ret = 0, threshold_code; 583 unsigned int rising_threshold = 0, falling_threshold = 0;
584 int ret = 0, threshold_code, i, trigger_levs = 0;
564 585
565 mutex_lock(&data->lock); 586 mutex_lock(&data->lock);
566 clk_enable(data->clk); 587 clk_enable(data->clk);
@@ -585,6 +606,11 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
585 (data->temp_error2 != 0)) 606 (data->temp_error2 != 0))
586 data->temp_error1 = pdata->efuse_value; 607 data->temp_error1 = pdata->efuse_value;
587 608
609 /* Count trigger levels to be enabled */
610 for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
611 if (pdata->trigger_levels[i])
612 trigger_levs++;
613
588 if (data->soc == SOC_ARCH_EXYNOS4210) { 614 if (data->soc == SOC_ARCH_EXYNOS4210) {
589 /* Write temperature code for threshold */ 615 /* Write temperature code for threshold */
590 threshold_code = temp_to_code(data, pdata->threshold); 616 threshold_code = temp_to_code(data, pdata->threshold);
@@ -594,44 +620,38 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
594 } 620 }
595 writeb(threshold_code, 621 writeb(threshold_code,
596 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); 622 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
597 623 for (i = 0; i < trigger_levs; i++)
598 writeb(pdata->trigger_levels[0], 624 writeb(pdata->trigger_levels[i],
599 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0); 625 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
600 writeb(pdata->trigger_levels[1],
601 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL1);
602 writeb(pdata->trigger_levels[2],
603 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL2);
604 writeb(pdata->trigger_levels[3],
605 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL3);
606 626
607 writel(EXYNOS4210_TMU_INTCLEAR_VAL, 627 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
608 data->base + EXYNOS_TMU_REG_INTCLEAR); 628 data->base + EXYNOS_TMU_REG_INTCLEAR);
609 } else if (data->soc == SOC_ARCH_EXYNOS) { 629 } else if (data->soc == SOC_ARCH_EXYNOS) {
610 /* Write temperature code for threshold */ 630 /* Write temperature code for rising and falling threshold */
611 threshold_code = temp_to_code(data, pdata->trigger_levels[0]); 631 for (i = 0; i < trigger_levs; i++) {
612 if (threshold_code < 0) { 632 threshold_code = temp_to_code(data,
613 ret = threshold_code; 633 pdata->trigger_levels[i]);
614 goto out; 634 if (threshold_code < 0) {
615 } 635 ret = threshold_code;
616 rising_threshold = threshold_code; 636 goto out;
617 threshold_code = temp_to_code(data, pdata->trigger_levels[1]); 637 }
618 if (threshold_code < 0) { 638 rising_threshold |= threshold_code << 8 * i;
619 ret = threshold_code; 639 if (pdata->threshold_falling) {
620 goto out; 640 threshold_code = temp_to_code(data,
621 } 641 pdata->trigger_levels[i] -
622 rising_threshold |= (threshold_code << 8); 642 pdata->threshold_falling);
623 threshold_code = temp_to_code(data, pdata->trigger_levels[2]); 643 if (threshold_code > 0)
624 if (threshold_code < 0) { 644 falling_threshold |=
625 ret = threshold_code; 645 threshold_code << 8 * i;
626 goto out; 646 }
627 } 647 }
628 rising_threshold |= (threshold_code << 16);
629 648
630 writel(rising_threshold, 649 writel(rising_threshold,
631 data->base + EXYNOS_THD_TEMP_RISE); 650 data->base + EXYNOS_THD_TEMP_RISE);
632 writel(0, data->base + EXYNOS_THD_TEMP_FALL); 651 writel(falling_threshold,
652 data->base + EXYNOS_THD_TEMP_FALL);
633 653
634 writel(EXYNOS_TMU_CLEAR_RISE_INT|EXYNOS_TMU_CLEAR_FALL_INT, 654 writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
635 data->base + EXYNOS_TMU_REG_INTCLEAR); 655 data->base + EXYNOS_TMU_REG_INTCLEAR);
636 } 656 }
637out: 657out:
@@ -664,6 +684,8 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
664 pdata->trigger_level2_en << 8 | 684 pdata->trigger_level2_en << 8 |
665 pdata->trigger_level1_en << 4 | 685 pdata->trigger_level1_en << 4 |
666 pdata->trigger_level0_en; 686 pdata->trigger_level0_en;
687 if (pdata->threshold_falling)
688 interrupt_en |= interrupt_en << 16;
667 } else { 689 } else {
668 con |= EXYNOS_TMU_CORE_OFF; 690 con |= EXYNOS_TMU_CORE_OFF;
669 interrupt_en = 0; /* Disable all interrupts */ 691 interrupt_en = 0; /* Disable all interrupts */
@@ -697,20 +719,19 @@ static void exynos_tmu_work(struct work_struct *work)
697 struct exynos_tmu_data *data = container_of(work, 719 struct exynos_tmu_data *data = container_of(work,
698 struct exynos_tmu_data, irq_work); 720 struct exynos_tmu_data, irq_work);
699 721
722 exynos_report_trigger();
700 mutex_lock(&data->lock); 723 mutex_lock(&data->lock);
701 clk_enable(data->clk); 724 clk_enable(data->clk);
702
703
704 if (data->soc == SOC_ARCH_EXYNOS) 725 if (data->soc == SOC_ARCH_EXYNOS)
705 writel(EXYNOS_TMU_CLEAR_RISE_INT, 726 writel(EXYNOS_TMU_CLEAR_RISE_INT |
727 EXYNOS_TMU_CLEAR_FALL_INT,
706 data->base + EXYNOS_TMU_REG_INTCLEAR); 728 data->base + EXYNOS_TMU_REG_INTCLEAR);
707 else 729 else
708 writel(EXYNOS4210_TMU_INTCLEAR_VAL, 730 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
709 data->base + EXYNOS_TMU_REG_INTCLEAR); 731 data->base + EXYNOS_TMU_REG_INTCLEAR);
710
711 clk_disable(data->clk); 732 clk_disable(data->clk);
712 mutex_unlock(&data->lock); 733 mutex_unlock(&data->lock);
713 exynos_report_trigger(); 734
714 enable_irq(data->irq); 735 enable_irq(data->irq);
715} 736}
716 737
@@ -759,6 +780,7 @@ static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
759 780
760#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412) 781#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
761static struct exynos_tmu_platform_data const exynos_default_tmu_data = { 782static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
783 .threshold_falling = 10,
762 .trigger_levels[0] = 85, 784 .trigger_levels[0] = 85,
763 .trigger_levels[1] = 103, 785 .trigger_levels[1] = 103,
764 .trigger_levels[2] = 110, 786 .trigger_levels[2] = 110,
@@ -800,8 +822,6 @@ static const struct of_device_id exynos_tmu_match[] = {
800 {}, 822 {},
801}; 823};
802MODULE_DEVICE_TABLE(of, exynos_tmu_match); 824MODULE_DEVICE_TABLE(of, exynos_tmu_match);
803#else
804#define exynos_tmu_match NULL
805#endif 825#endif
806 826
807static struct platform_device_id exynos_tmu_driver_ids[] = { 827static struct platform_device_id exynos_tmu_driver_ids[] = {
@@ -832,6 +852,94 @@ static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
832 return (struct exynos_tmu_platform_data *) 852 return (struct exynos_tmu_platform_data *)
833 platform_get_device_id(pdev)->driver_data; 853 platform_get_device_id(pdev)->driver_data;
834} 854}
855
856#ifdef CONFIG_EXYNOS_THERMAL_EMUL
857static ssize_t exynos_tmu_emulation_show(struct device *dev,
858 struct device_attribute *attr,
859 char *buf)
860{
861 struct platform_device *pdev = container_of(dev,
862 struct platform_device, dev);
863 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
864 unsigned int reg;
865 u8 temp_code;
866 int temp = 0;
867
868 if (data->soc == SOC_ARCH_EXYNOS4210)
869 goto out;
870
871 mutex_lock(&data->lock);
872 clk_enable(data->clk);
873 reg = readl(data->base + EXYNOS_EMUL_CON);
874 clk_disable(data->clk);
875 mutex_unlock(&data->lock);
876
877 if (reg & EXYNOS_EMUL_ENABLE) {
878 reg >>= EXYNOS_EMUL_DATA_SHIFT;
879 temp_code = reg & EXYNOS_EMUL_DATA_MASK;
880 temp = code_to_temp(data, temp_code);
881 }
882out:
883 return sprintf(buf, "%d\n", temp * MCELSIUS);
884}
885
886static ssize_t exynos_tmu_emulation_store(struct device *dev,
887 struct device_attribute *attr,
888 const char *buf, size_t count)
889{
890 struct platform_device *pdev = container_of(dev,
891 struct platform_device, dev);
892 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
893 unsigned int reg;
894 int temp;
895
896 if (data->soc == SOC_ARCH_EXYNOS4210)
897 goto out;
898
899 if (!sscanf(buf, "%d\n", &temp) || temp < 0)
900 return -EINVAL;
901
902 mutex_lock(&data->lock);
903 clk_enable(data->clk);
904
905 reg = readl(data->base + EXYNOS_EMUL_CON);
906
907 if (temp) {
908 /* Both CELSIUS and MCELSIUS type are available for input */
909 if (temp > MCELSIUS)
910 temp /= MCELSIUS;
911
912 reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
913 (temp_to_code(data, (temp / MCELSIUS))
914 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
915 } else {
916 reg &= ~EXYNOS_EMUL_ENABLE;
917 }
918
919 writel(reg, data->base + EXYNOS_EMUL_CON);
920
921 clk_disable(data->clk);
922 mutex_unlock(&data->lock);
923
924out:
925 return count;
926}
927
928static DEVICE_ATTR(emulation, 0644, exynos_tmu_emulation_show,
929 exynos_tmu_emulation_store);
930static int create_emulation_sysfs(struct device *dev)
931{
932 return device_create_file(dev, &dev_attr_emulation);
933}
934static void remove_emulation_sysfs(struct device *dev)
935{
936 device_remove_file(dev, &dev_attr_emulation);
937}
938#else
939static inline int create_emulation_sysfs(struct device *dev) { return 0; }
940static inline void remove_emulation_sysfs(struct device *dev) {}
941#endif
942
835static int exynos_tmu_probe(struct platform_device *pdev) 943static int exynos_tmu_probe(struct platform_device *pdev)
836{ 944{
837 struct exynos_tmu_data *data; 945 struct exynos_tmu_data *data;
@@ -914,6 +1022,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
914 exynos_sensor_conf.trip_data.trip_val[i] = 1022 exynos_sensor_conf.trip_data.trip_val[i] =
915 pdata->threshold + pdata->trigger_levels[i]; 1023 pdata->threshold + pdata->trigger_levels[i];
916 1024
1025 exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
1026
917 exynos_sensor_conf.cooling_data.freq_clip_count = 1027 exynos_sensor_conf.cooling_data.freq_clip_count =
918 pdata->freq_tab_count; 1028 pdata->freq_tab_count;
919 for (i = 0; i < pdata->freq_tab_count; i++) { 1029 for (i = 0; i < pdata->freq_tab_count; i++) {
@@ -928,6 +1038,11 @@ static int exynos_tmu_probe(struct platform_device *pdev)
928 dev_err(&pdev->dev, "Failed to register thermal interface\n"); 1038 dev_err(&pdev->dev, "Failed to register thermal interface\n");
929 goto err_clk; 1039 goto err_clk;
930 } 1040 }
1041
1042 ret = create_emulation_sysfs(&pdev->dev);
1043 if (ret)
1044 dev_err(&pdev->dev, "Failed to create emulation mode sysfs node\n");
1045
931 return 0; 1046 return 0;
932err_clk: 1047err_clk:
933 platform_set_drvdata(pdev, NULL); 1048 platform_set_drvdata(pdev, NULL);
@@ -939,6 +1054,8 @@ static int exynos_tmu_remove(struct platform_device *pdev)
939{ 1054{
940 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1055 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
941 1056
1057 remove_emulation_sysfs(&pdev->dev);
1058
942 exynos_tmu_control(pdev, false); 1059 exynos_tmu_control(pdev, false);
943 1060
944 exynos_unregister_thermal(); 1061 exynos_unregister_thermal();
@@ -980,7 +1097,7 @@ static struct platform_driver exynos_tmu_driver = {
980 .name = "exynos-tmu", 1097 .name = "exynos-tmu",
981 .owner = THIS_MODULE, 1098 .owner = THIS_MODULE,
982 .pm = EXYNOS_TMU_PM, 1099 .pm = EXYNOS_TMU_PM,
983 .of_match_table = exynos_tmu_match, 1100 .of_match_table = of_match_ptr(exynos_tmu_match),
984 }, 1101 },
985 .probe = exynos_tmu_probe, 1102 .probe = exynos_tmu_probe,
986 .remove = exynos_tmu_remove, 1103 .remove = exynos_tmu_remove,