Commit bffd1f8ac87a798515a8aed5f64047b182e049f5

Authored by Amit Daniel Kachhap
Committed by Zhang Rui
1 parent 51d45d2594

thermal: exynos: Adapt to temperature emulation core thermal framework

This removes the driver specific sysfs support of the temperature
emulation and uses the newly added core thermal framework for thermal
emulation. An exynos platform specific handler is added to support this.

In this patch, the exynos senor(tmu) related code and exynos framework
related (thermal zone, cooling devices) code are intentionally kept separate.
So an emulated function pointer is passed from sensor to framework. This is
beneficial in adding more sensor support using the same framework code
which is an ongoing work. The goal is to finally split them totally. Even
the existing read_temperature also follows the same execution method.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>

Showing 3 changed files with 67 additions and 108 deletions Side-by-side Diff

Documentation/thermal/exynos_thermal_emulation
... ... @@ -13,11 +13,11 @@
13 13 manually with software code and TMU will read current temperature from user value not from
14 14 sensor's value.
15 15  
16   -Enabling CONFIG_EXYNOS_THERMAL_EMUL option will make this support in available.
17   -When it's enabled, sysfs node will be created under
18   -/sys/bus/platform/devices/'exynos device name'/ with name of 'emulation'.
  16 +Enabling CONFIG_THERMAL_EMULATION option will make this support available.
  17 +When it's enabled, sysfs node will be created as
  18 +/sys/devices/virtual/thermal/thermal_zone'zone id'/emul_temp.
19 19  
20   -The sysfs node, 'emulation', will contain value 0 for the initial state. When you input any
  20 +The sysfs node, 'emul_node', will contain value 0 for the initial state. When you input any
21 21 temperature you want to update to sysfs node, it automatically enable emulation mode and
22 22 current temperature will be changed into it.
23 23 (Exynos also supports user changable delay time which would be used to delay of
drivers/thermal/Kconfig
... ... @@ -117,15 +117,6 @@
117 117 If you say yes here you get support for TMU (Thermal Management
118 118 Unit) on SAMSUNG EXYNOS series of SoC.
119 119  
120   -config EXYNOS_THERMAL_EMUL
121   - bool "EXYNOS TMU emulation mode support"
122   - depends on EXYNOS_THERMAL
123   - help
124   - Exynos 4412 and 4414 and 5 series has emulation mode on TMU.
125   - Enable this option will be make sysfs node in exynos thermal platform
126   - device directory to support emulation mode. With emulation mode sysfs
127   - node, you can manually input temperature to TMU for simulation purpose.
128   -
129 120 config DOVE_THERMAL
130 121 tristate "Temperature sensor on Marvell Dove SoCs"
131 122 depends on ARCH_DOVE
drivers/thermal/exynos_thermal.c
... ... @@ -100,13 +100,13 @@
100 100 #define IDLE_INTERVAL 10000
101 101 #define MCELSIUS 1000
102 102  
103   -#ifdef CONFIG_EXYNOS_THERMAL_EMUL
  103 +#ifdef CONFIG_THERMAL_EMULATION
104 104 #define EXYNOS_EMUL_TIME 0x57F0
105 105 #define EXYNOS_EMUL_TIME_SHIFT 16
106 106 #define EXYNOS_EMUL_DATA_SHIFT 8
107 107 #define EXYNOS_EMUL_DATA_MASK 0xFF
108 108 #define EXYNOS_EMUL_ENABLE 0x1
109   -#endif /* CONFIG_EXYNOS_THERMAL_EMUL */
  109 +#endif /* CONFIG_THERMAL_EMULATION */
110 110  
111 111 /* CPU Zone information */
112 112 #define PANIC_ZONE 4
... ... @@ -145,6 +145,7 @@
145 145 struct thermal_sensor_conf {
146 146 char name[SENSOR_NAME_LEN];
147 147 int (*read_temperature)(void *data);
  148 + int (*write_emul_temp)(void *drv_data, unsigned long temp);
148 149 struct thermal_trip_point_conf trip_data;
149 150 struct thermal_cooling_conf cooling_data;
150 151 void *private_data;
... ... @@ -349,6 +350,23 @@
349 350 return 0;
350 351 }
351 352  
  353 +/* Get temperature callback functions for thermal zone */
  354 +static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
  355 + unsigned long temp)
  356 +{
  357 + void *data;
  358 + int ret = -EINVAL;
  359 +
  360 + if (!th_zone->sensor_conf) {
  361 + pr_info("Temperature sensor not initialised\n");
  362 + return -EINVAL;
  363 + }
  364 + data = th_zone->sensor_conf->private_data;
  365 + if (th_zone->sensor_conf->write_emul_temp)
  366 + ret = th_zone->sensor_conf->write_emul_temp(data, temp);
  367 + return ret;
  368 +}
  369 +
352 370 /* Get the temperature trend */
353 371 static int exynos_get_trend(struct thermal_zone_device *thermal,
354 372 int trip, enum thermal_trend *trend)
... ... @@ -372,6 +390,7 @@
372 390 .bind = exynos_bind,
373 391 .unbind = exynos_unbind,
374 392 .get_temp = exynos_get_temp,
  393 + .set_emul_temp = exynos_set_emul_temp,
375 394 .get_trend = exynos_get_trend,
376 395 .get_mode = exynos_get_mode,
377 396 .set_mode = exynos_set_mode,
... ... @@ -694,6 +713,47 @@
694 713 return temp;
695 714 }
696 715  
  716 +#ifdef CONFIG_THERMAL_EMULATION
  717 +static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
  718 +{
  719 + struct exynos_tmu_data *data = drv_data;
  720 + unsigned int reg;
  721 + int ret = -EINVAL;
  722 +
  723 + if (data->soc == SOC_ARCH_EXYNOS4210)
  724 + goto out;
  725 +
  726 + if (temp && temp < MCELSIUS)
  727 + goto out;
  728 +
  729 + mutex_lock(&data->lock);
  730 + clk_enable(data->clk);
  731 +
  732 + reg = readl(data->base + EXYNOS_EMUL_CON);
  733 +
  734 + if (temp) {
  735 + temp /= MCELSIUS;
  736 +
  737 + reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
  738 + (temp_to_code(data, temp)
  739 + << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
  740 + } else {
  741 + reg &= ~EXYNOS_EMUL_ENABLE;
  742 + }
  743 +
  744 + writel(reg, data->base + EXYNOS_EMUL_CON);
  745 +
  746 + clk_disable(data->clk);
  747 + mutex_unlock(&data->lock);
  748 + return 0;
  749 +out:
  750 + return ret;
  751 +}
  752 +#else
  753 +static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
  754 + { return -EINVAL; }
  755 +#endif/*CONFIG_THERMAL_EMULATION*/
  756 +
697 757 static void exynos_tmu_work(struct work_struct *work)
698 758 {
699 759 struct exynos_tmu_data *data = container_of(work,
... ... @@ -727,6 +787,7 @@
727 787 static struct thermal_sensor_conf exynos_sensor_conf = {
728 788 .name = "exynos-therm",
729 789 .read_temperature = (int (*)(void *))exynos_tmu_read,
  790 + .write_emul_temp = exynos_tmu_set_emulation,
730 791 };
731 792  
732 793 #if defined(CONFIG_CPU_EXYNOS4210)
... ... @@ -833,93 +894,6 @@
833 894 platform_get_device_id(pdev)->driver_data;
834 895 }
835 896  
836   -#ifdef CONFIG_EXYNOS_THERMAL_EMUL
837   -static ssize_t exynos_tmu_emulation_show(struct device *dev,
838   - struct device_attribute *attr,
839   - char *buf)
840   -{
841   - struct platform_device *pdev = container_of(dev,
842   - struct platform_device, dev);
843   - struct exynos_tmu_data *data = platform_get_drvdata(pdev);
844   - unsigned int reg;
845   - u8 temp_code;
846   - int temp = 0;
847   -
848   - if (data->soc == SOC_ARCH_EXYNOS4210)
849   - goto out;
850   -
851   - mutex_lock(&data->lock);
852   - clk_enable(data->clk);
853   - reg = readl(data->base + EXYNOS_EMUL_CON);
854   - clk_disable(data->clk);
855   - mutex_unlock(&data->lock);
856   -
857   - if (reg & EXYNOS_EMUL_ENABLE) {
858   - reg >>= EXYNOS_EMUL_DATA_SHIFT;
859   - temp_code = reg & EXYNOS_EMUL_DATA_MASK;
860   - temp = code_to_temp(data, temp_code);
861   - }
862   -out:
863   - return sprintf(buf, "%d\n", temp * MCELSIUS);
864   -}
865   -
866   -static ssize_t exynos_tmu_emulation_store(struct device *dev,
867   - struct device_attribute *attr,
868   - const char *buf, size_t count)
869   -{
870   - struct platform_device *pdev = container_of(dev,
871   - struct platform_device, dev);
872   - struct exynos_tmu_data *data = platform_get_drvdata(pdev);
873   - unsigned int reg;
874   - int temp;
875   -
876   - if (data->soc == SOC_ARCH_EXYNOS4210)
877   - goto out;
878   -
879   - if (!sscanf(buf, "%d\n", &temp) || temp < 0)
880   - return -EINVAL;
881   -
882   - mutex_lock(&data->lock);
883   - clk_enable(data->clk);
884   -
885   - reg = readl(data->base + EXYNOS_EMUL_CON);
886   -
887   - if (temp) {
888   - /* Both CELSIUS and MCELSIUS type are available for input */
889   - if (temp > MCELSIUS)
890   - temp /= MCELSIUS;
891   -
892   - reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
893   - (temp_to_code(data, (temp / MCELSIUS))
894   - << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
895   - } else {
896   - reg &= ~EXYNOS_EMUL_ENABLE;
897   - }
898   -
899   - writel(reg, data->base + EXYNOS_EMUL_CON);
900   -
901   - clk_disable(data->clk);
902   - mutex_unlock(&data->lock);
903   -
904   -out:
905   - return count;
906   -}
907   -
908   -static DEVICE_ATTR(emulation, 0644, exynos_tmu_emulation_show,
909   - exynos_tmu_emulation_store);
910   -static int create_emulation_sysfs(struct device *dev)
911   -{
912   - return device_create_file(dev, &dev_attr_emulation);
913   -}
914   -static void remove_emulation_sysfs(struct device *dev)
915   -{
916   - device_remove_file(dev, &dev_attr_emulation);
917   -}
918   -#else
919   -static inline int create_emulation_sysfs(struct device *dev) { return 0; }
920   -static inline void remove_emulation_sysfs(struct device *dev) {}
921   -#endif
922   -
923 897 static int exynos_tmu_probe(struct platform_device *pdev)
924 898 {
925 899 struct exynos_tmu_data *data;
... ... @@ -1019,10 +993,6 @@
1019 993 goto err_clk;
1020 994 }
1021 995  
1022   - ret = create_emulation_sysfs(&pdev->dev);
1023   - if (ret)
1024   - dev_err(&pdev->dev, "Failed to create emulation mode sysfs node\n");
1025   -
1026 996 return 0;
1027 997 err_clk:
1028 998 platform_set_drvdata(pdev, NULL);
... ... @@ -1033,8 +1003,6 @@
1033 1003 static int exynos_tmu_remove(struct platform_device *pdev)
1034 1004 {
1035 1005 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1036   -
1037   - remove_emulation_sysfs(&pdev->dev);
1038 1006  
1039 1007 exynos_tmu_control(pdev, false);
1040 1008