aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorJonghwa Lee <jonghwa3.lee@samsung.com>2013-02-07 20:13:06 -0500
committerZhang Rui <rui.zhang@intel.com>2013-02-08 07:26:07 -0500
commit4f0a6847815837b63b05fc23878ba391701d8f6a (patch)
treefd8364491e2f69887f50ee2b81d60e87b2f1b16a /drivers/thermal
parent74ffa64c23616706381c30064a47888382bba30f (diff)
Thermal: exynos: Add support for temperature falling interrupt.
This patch introduces using temperature falling interrupt in exynos thermal driver. Former patch, it only use polling way to check whether if system themperature is fallen. However, exynos SOC also provides temperature falling interrupt way to do same things by hw. This feature is not supported in exynos4210. Acked-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Jonghwa Lee <jonghwa3.lee@samsung.com> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/exynos_thermal.c81
1 files changed, 46 insertions, 35 deletions
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index cd71e24194b1..f4dd68a25022 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -94,6 +94,7 @@
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
@@ -133,6 +134,7 @@ struct exynos_tmu_data {
133struct thermal_trip_point_conf { 134struct thermal_trip_point_conf {
134 int trip_val[MAX_TRIP_COUNT]; 135 int trip_val[MAX_TRIP_COUNT];
135 int trip_count; 136 int trip_count;
137 u8 trigger_falling;
136}; 138};
137 139
138struct thermal_cooling_conf { 140struct thermal_cooling_conf {
@@ -182,7 +184,8 @@ static int exynos_set_mode(struct thermal_zone_device *thermal,
182 184
183 mutex_lock(&th_zone->therm_dev->lock); 185 mutex_lock(&th_zone->therm_dev->lock);
184 186
185 if (mode == THERMAL_DEVICE_ENABLED) 187 if (mode == THERMAL_DEVICE_ENABLED &&
188 !th_zone->sensor_conf->trip_data.trigger_falling)
186 th_zone->therm_dev->polling_delay = IDLE_INTERVAL; 189 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
187 else 190 else
188 th_zone->therm_dev->polling_delay = 0; 191 th_zone->therm_dev->polling_delay = 0;
@@ -428,7 +431,8 @@ static void exynos_report_trigger(void)
428 break; 431 break;
429 } 432 }
430 433
431 if (th_zone->mode == THERMAL_DEVICE_ENABLED) { 434 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
435 !th_zone->sensor_conf->trip_data.trigger_falling) {
432 if (i > 0) 436 if (i > 0)
433 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL; 437 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
434 else 438 else
@@ -467,7 +471,8 @@ static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
467 471
468 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name, 472 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
469 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0, 473 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
470 IDLE_INTERVAL); 474 sensor_conf->trip_data.trigger_falling ?
475 0 : IDLE_INTERVAL);
471 476
472 if (IS_ERR(th_zone->therm_dev)) { 477 if (IS_ERR(th_zone->therm_dev)) {
473 pr_err("Failed to register thermal zone device\n"); 478 pr_err("Failed to register thermal zone device\n");
@@ -574,8 +579,9 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
574{ 579{
575 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 580 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
576 struct exynos_tmu_platform_data *pdata = data->pdata; 581 struct exynos_tmu_platform_data *pdata = data->pdata;
577 unsigned int status, trim_info, rising_threshold; 582 unsigned int status, trim_info;
578 int ret = 0, threshold_code; 583 unsigned int rising_threshold = 0, falling_threshold = 0;
584 int ret = 0, threshold_code, i, trigger_levs = 0;
579 585
580 mutex_lock(&data->lock); 586 mutex_lock(&data->lock);
581 clk_enable(data->clk); 587 clk_enable(data->clk);
@@ -600,6 +606,11 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
600 (data->temp_error2 != 0)) 606 (data->temp_error2 != 0))
601 data->temp_error1 = pdata->efuse_value; 607 data->temp_error1 = pdata->efuse_value;
602 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
603 if (data->soc == SOC_ARCH_EXYNOS4210) { 614 if (data->soc == SOC_ARCH_EXYNOS4210) {
604 /* Write temperature code for threshold */ 615 /* Write temperature code for threshold */
605 threshold_code = temp_to_code(data, pdata->threshold); 616 threshold_code = temp_to_code(data, pdata->threshold);
@@ -609,44 +620,38 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
609 } 620 }
610 writeb(threshold_code, 621 writeb(threshold_code,
611 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); 622 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
612 623 for (i = 0; i < trigger_levs; i++)
613 writeb(pdata->trigger_levels[0], 624 writeb(pdata->trigger_levels[i],
614 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0); 625 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
615 writeb(pdata->trigger_levels[1],
616 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL1);
617 writeb(pdata->trigger_levels[2],
618 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL2);
619 writeb(pdata->trigger_levels[3],
620 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL3);
621 626
622 writel(EXYNOS4210_TMU_INTCLEAR_VAL, 627 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
623 data->base + EXYNOS_TMU_REG_INTCLEAR); 628 data->base + EXYNOS_TMU_REG_INTCLEAR);
624 } else if (data->soc == SOC_ARCH_EXYNOS) { 629 } else if (data->soc == SOC_ARCH_EXYNOS) {
625 /* Write temperature code for threshold */ 630 /* Write temperature code for rising and falling threshold */
626 threshold_code = temp_to_code(data, pdata->trigger_levels[0]); 631 for (i = 0; i < trigger_levs; i++) {
627 if (threshold_code < 0) { 632 threshold_code = temp_to_code(data,
628 ret = threshold_code; 633 pdata->trigger_levels[i]);
629 goto out; 634 if (threshold_code < 0) {
630 } 635 ret = threshold_code;
631 rising_threshold = threshold_code; 636 goto out;
632 threshold_code = temp_to_code(data, pdata->trigger_levels[1]); 637 }
633 if (threshold_code < 0) { 638 rising_threshold |= threshold_code << 8 * i;
634 ret = threshold_code; 639 if (pdata->threshold_falling) {
635 goto out; 640 threshold_code = temp_to_code(data,
636 } 641 pdata->trigger_levels[i] -
637 rising_threshold |= (threshold_code << 8); 642 pdata->threshold_falling);
638 threshold_code = temp_to_code(data, pdata->trigger_levels[2]); 643 if (threshold_code > 0)
639 if (threshold_code < 0) { 644 falling_threshold |=
640 ret = threshold_code; 645 threshold_code << 8 * i;
641 goto out; 646 }
642 } 647 }
643 rising_threshold |= (threshold_code << 16);
644 648
645 writel(rising_threshold, 649 writel(rising_threshold,
646 data->base + EXYNOS_THD_TEMP_RISE); 650 data->base + EXYNOS_THD_TEMP_RISE);
647 writel(0, data->base + EXYNOS_THD_TEMP_FALL); 651 writel(falling_threshold,
652 data->base + EXYNOS_THD_TEMP_FALL);
648 653
649 writel(EXYNOS_TMU_CLEAR_RISE_INT|EXYNOS_TMU_CLEAR_FALL_INT, 654 writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
650 data->base + EXYNOS_TMU_REG_INTCLEAR); 655 data->base + EXYNOS_TMU_REG_INTCLEAR);
651 } 656 }
652out: 657out:
@@ -679,6 +684,8 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
679 pdata->trigger_level2_en << 8 | 684 pdata->trigger_level2_en << 8 |
680 pdata->trigger_level1_en << 4 | 685 pdata->trigger_level1_en << 4 |
681 pdata->trigger_level0_en; 686 pdata->trigger_level0_en;
687 if (pdata->threshold_falling)
688 interrupt_en |= interrupt_en << 16;
682 } else { 689 } else {
683 con |= EXYNOS_TMU_CORE_OFF; 690 con |= EXYNOS_TMU_CORE_OFF;
684 interrupt_en = 0; /* Disable all interrupts */ 691 interrupt_en = 0; /* Disable all interrupts */
@@ -716,7 +723,8 @@ static void exynos_tmu_work(struct work_struct *work)
716 mutex_lock(&data->lock); 723 mutex_lock(&data->lock);
717 clk_enable(data->clk); 724 clk_enable(data->clk);
718 if (data->soc == SOC_ARCH_EXYNOS) 725 if (data->soc == SOC_ARCH_EXYNOS)
719 writel(EXYNOS_TMU_CLEAR_RISE_INT, 726 writel(EXYNOS_TMU_CLEAR_RISE_INT |
727 EXYNOS_TMU_CLEAR_FALL_INT,
720 data->base + EXYNOS_TMU_REG_INTCLEAR); 728 data->base + EXYNOS_TMU_REG_INTCLEAR);
721 else 729 else
722 writel(EXYNOS4210_TMU_INTCLEAR_VAL, 730 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
@@ -772,6 +780,7 @@ static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
772 780
773#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412) 781#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
774static 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,
775 .trigger_levels[0] = 85, 784 .trigger_levels[0] = 85,
776 .trigger_levels[1] = 103, 785 .trigger_levels[1] = 103,
777 .trigger_levels[2] = 110, 786 .trigger_levels[2] = 110,
@@ -1015,6 +1024,8 @@ static int __devinit exynos_tmu_probe(struct platform_device *pdev)
1015 exynos_sensor_conf.trip_data.trip_val[i] = 1024 exynos_sensor_conf.trip_data.trip_val[i] =
1016 pdata->threshold + pdata->trigger_levels[i]; 1025 pdata->threshold + pdata->trigger_levels[i];
1017 1026
1027 exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
1028
1018 exynos_sensor_conf.cooling_data.freq_clip_count = 1029 exynos_sensor_conf.cooling_data.freq_clip_count =
1019 pdata->freq_tab_count; 1030 pdata->freq_tab_count;
1020 for (i = 0; i < pdata->freq_tab_count; i++) { 1031 for (i = 0; i < pdata->freq_tab_count; i++) {