aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorJonghwa Lee <jonghwa3.lee@samsung.com>2012-11-20 23:31:01 -0500
committerZhang Rui <rui.zhang@intel.com>2013-01-04 02:22:37 -0500
commitbbf63be4f331358173da26b888a10583fcc92ec0 (patch)
tree6823381e0bae1e601921d33d964a5f24e997f18e /drivers/thermal
parentb8bb6cb999858043489c1ddef08eed2127559169 (diff)
Thermal: exynos: Add sysfs node supporting exynos's emulation mode.
This patch supports exynos's emulation mode with newly created sysfs node. Exynos 4x12 (4212, 4412) and 5 series provide emulation mode for thermal management unit. Thermal emulation mode supports software debug for TMU's operation. User can set temperature manually with software code and TMU will read current temperature from user value not from sensor's value. This patch includes also documentary placed under Documentation/thermal/. Signed-off-by: Jonghwa Lee <jonghwa3.lee@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig9
-rw-r--r--drivers/thermal/exynos_thermal.c103
2 files changed, 112 insertions, 0 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c2c77d1ac499..c31b9e4451a3 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -101,6 +101,15 @@ config EXYNOS_THERMAL
101 If you say yes here you get support for TMU (Thermal Management 101 If you say yes here you get support for TMU (Thermal Management
102 Unit) on SAMSUNG EXYNOS series of SoC. 102 Unit) on SAMSUNG EXYNOS series of SoC.
103 103
104config EXYNOS_THERMAL_EMUL
105 bool "EXYNOS TMU emulation mode support"
106 depends on EXYNOS_THERMAL
107 help
108 Exynos 4412 and 4414 and 5 series has emulation mode on TMU.
109 Enable this option will be make sysfs node in exynos thermal platform
110 device directory to support emulation mode. With emulation mode sysfs
111 node, you can manually input temperature to TMU for simulation purpose.
112
104config DB8500_THERMAL 113config DB8500_THERMAL
105 bool "DB8500 thermal management" 114 bool "DB8500 thermal management"
106 depends on ARCH_U8500 115 depends on ARCH_U8500
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index 7772d1603769..e2ef8a3531ac 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -99,6 +99,14 @@
99#define IDLE_INTERVAL 10000 99#define IDLE_INTERVAL 10000
100#define MCELSIUS 1000 100#define MCELSIUS 1000
101 101
102#ifdef CONFIG_EXYNOS_THERMAL_EMUL
103#define EXYNOS_EMUL_TIME 0x57F0
104#define EXYNOS_EMUL_TIME_SHIFT 16
105#define EXYNOS_EMUL_DATA_SHIFT 8
106#define EXYNOS_EMUL_DATA_MASK 0xFF
107#define EXYNOS_EMUL_ENABLE 0x1
108#endif /* CONFIG_EXYNOS_THERMAL_EMUL */
109
102/* CPU Zone information */ 110/* CPU Zone information */
103#define PANIC_ZONE 4 111#define PANIC_ZONE 4
104#define WARN_ZONE 3 112#define WARN_ZONE 3
@@ -832,6 +840,94 @@ static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
832 return (struct exynos_tmu_platform_data *) 840 return (struct exynos_tmu_platform_data *)
833 platform_get_device_id(pdev)->driver_data; 841 platform_get_device_id(pdev)->driver_data;
834} 842}
843
844#ifdef CONFIG_EXYNOS_THERMAL_EMUL
845static ssize_t exynos_tmu_emulation_show(struct device *dev,
846 struct device_attribute *attr,
847 char *buf)
848{
849 struct platform_device *pdev = container_of(dev,
850 struct platform_device, dev);
851 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
852 unsigned int reg;
853 u8 temp_code;
854 int temp = 0;
855
856 if (data->soc == SOC_ARCH_EXYNOS4210)
857 goto out;
858
859 mutex_lock(&data->lock);
860 clk_enable(data->clk);
861 reg = readl(data->base + EXYNOS_EMUL_CON);
862 clk_disable(data->clk);
863 mutex_unlock(&data->lock);
864
865 if (reg & EXYNOS_EMUL_ENABLE) {
866 reg >>= EXYNOS_EMUL_DATA_SHIFT;
867 temp_code = reg & EXYNOS_EMUL_DATA_MASK;
868 temp = code_to_temp(data, temp_code);
869 }
870out:
871 return sprintf(buf, "%d\n", temp * MCELSIUS);
872}
873
874static ssize_t exynos_tmu_emulation_store(struct device *dev,
875 struct device_attribute *attr,
876 const char *buf, size_t count)
877{
878 struct platform_device *pdev = container_of(dev,
879 struct platform_device, dev);
880 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
881 unsigned int reg;
882 int temp;
883
884 if (data->soc == SOC_ARCH_EXYNOS4210)
885 goto out;
886
887 if (!sscanf(buf, "%d\n", &temp) || temp < 0)
888 return -EINVAL;
889
890 mutex_lock(&data->lock);
891 clk_enable(data->clk);
892
893 reg = readl(data->base + EXYNOS_EMUL_CON);
894
895 if (temp) {
896 /* Both CELSIUS and MCELSIUS type are available for input */
897 if (temp > MCELSIUS)
898 temp /= MCELSIUS;
899
900 reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
901 (temp_to_code(data, (temp / MCELSIUS))
902 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
903 } else {
904 reg &= ~EXYNOS_EMUL_ENABLE;
905 }
906
907 writel(reg, data->base + EXYNOS_EMUL_CON);
908
909 clk_disable(data->clk);
910 mutex_unlock(&data->lock);
911
912out:
913 return count;
914}
915
916static DEVICE_ATTR(emulation, 0644, exynos_tmu_emulation_show,
917 exynos_tmu_emulation_store);
918static int create_emulation_sysfs(struct device *dev)
919{
920 return device_create_file(dev, &dev_attr_emulation);
921}
922static void remove_emulation_sysfs(struct device *dev)
923{
924 device_remove_file(dev, &dev_attr_emulation);
925}
926#else
927static inline int create_emulation_sysfs(struct device *dev) { return 0; }
928static inline void remove_emulation_sysfs(struct device *dev) {}
929#endif
930
835static int __devinit exynos_tmu_probe(struct platform_device *pdev) 931static int __devinit exynos_tmu_probe(struct platform_device *pdev)
836{ 932{
837 struct exynos_tmu_data *data; 933 struct exynos_tmu_data *data;
@@ -930,6 +1026,11 @@ static int __devinit exynos_tmu_probe(struct platform_device *pdev)
930 dev_err(&pdev->dev, "Failed to register thermal interface\n"); 1026 dev_err(&pdev->dev, "Failed to register thermal interface\n");
931 goto err_clk; 1027 goto err_clk;
932 } 1028 }
1029
1030 ret = create_emulation_sysfs(&pdev->dev);
1031 if (ret)
1032 dev_err(&pdev->dev, "Failed to create emulation mode sysfs node\n");
1033
933 return 0; 1034 return 0;
934err_clk: 1035err_clk:
935 platform_set_drvdata(pdev, NULL); 1036 platform_set_drvdata(pdev, NULL);
@@ -941,6 +1042,8 @@ static int __devexit exynos_tmu_remove(struct platform_device *pdev)
941{ 1042{
942 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1043 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
943 1044
1045 remove_emulation_sysfs(&pdev->dev);
1046
944 exynos_tmu_control(pdev, false); 1047 exynos_tmu_control(pdev, false);
945 1048
946 exynos_unregister_thermal(); 1049 exynos_unregister_thermal();