diff options
author | Amit Daniel Kachhap <amit.daniel@samsung.com> | 2013-06-24 06:50:46 -0400 |
---|---|---|
committer | Eduardo Valentin <eduardo.valentin@ti.com> | 2013-08-13 09:52:03 -0400 |
commit | 1928457ea6337043a06ca2acd9b4d01e75810a3f (patch) | |
tree | a99d2cb5cdbed00e05c3ba3eefe846c08037765a /drivers/thermal | |
parent | 5000806c119799715f315e482fb60cc61e2536ea (diff) |
thermal: exynos: Add hardware mode thermal calibration support
This patch adds support for h/w mode calibration in the TMU controller.
Soc's like 5440 support this features. The h/w bits needed for calibration
setting are same as that of enum calibration_type.
Acked-by: Jonghwa Lee <jonghwa3.lee@samsung.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.c | 33 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.h | 8 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu_data.c | 2 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu_data.h | 2 |
4 files changed, 44 insertions, 1 deletions
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 3fac0f92bf91..a6fc3798a6c4 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
@@ -73,6 +73,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) | |||
73 | struct exynos_tmu_platform_data *pdata = data->pdata; | 73 | struct exynos_tmu_platform_data *pdata = data->pdata; |
74 | int temp_code; | 74 | int temp_code; |
75 | 75 | ||
76 | if (pdata->cal_mode == HW_MODE) | ||
77 | return temp; | ||
78 | |||
76 | if (data->soc == SOC_ARCH_EXYNOS4210) | 79 | if (data->soc == SOC_ARCH_EXYNOS4210) |
77 | /* temp should range between 25 and 125 */ | 80 | /* temp should range between 25 and 125 */ |
78 | if (temp < 25 || temp > 125) { | 81 | if (temp < 25 || temp > 125) { |
@@ -107,6 +110,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code) | |||
107 | struct exynos_tmu_platform_data *pdata = data->pdata; | 110 | struct exynos_tmu_platform_data *pdata = data->pdata; |
108 | int temp; | 111 | int temp; |
109 | 112 | ||
113 | if (pdata->cal_mode == HW_MODE) | ||
114 | return temp_code; | ||
115 | |||
110 | if (data->soc == SOC_ARCH_EXYNOS4210) | 116 | if (data->soc == SOC_ARCH_EXYNOS4210) |
111 | /* temp_code should range between 75 and 175 */ | 117 | /* temp_code should range between 75 and 175 */ |
112 | if (temp_code < 75 || temp_code > 175) { | 118 | if (temp_code < 75 || temp_code > 175) { |
@@ -155,6 +161,9 @@ static int exynos_tmu_initialize(struct platform_device *pdev) | |||
155 | if (TMU_SUPPORTS(pdata, TRIM_RELOAD)) | 161 | if (TMU_SUPPORTS(pdata, TRIM_RELOAD)) |
156 | __raw_writel(1, data->base + reg->triminfo_ctrl); | 162 | __raw_writel(1, data->base + reg->triminfo_ctrl); |
157 | 163 | ||
164 | if (pdata->cal_mode == HW_MODE) | ||
165 | goto skip_calib_data; | ||
166 | |||
158 | /* Save trimming info in order to perform calibration */ | 167 | /* Save trimming info in order to perform calibration */ |
159 | if (data->soc == SOC_ARCH_EXYNOS5440) { | 168 | if (data->soc == SOC_ARCH_EXYNOS5440) { |
160 | /* | 169 | /* |
@@ -190,6 +199,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev) | |||
190 | (pdata->efuse_value >> reg->triminfo_85_shift) & | 199 | (pdata->efuse_value >> reg->triminfo_85_shift) & |
191 | EXYNOS_TMU_TEMP_MASK; | 200 | EXYNOS_TMU_TEMP_MASK; |
192 | 201 | ||
202 | skip_calib_data: | ||
193 | if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) { | 203 | if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) { |
194 | dev_err(&pdev->dev, "Invalid max trigger level\n"); | 204 | dev_err(&pdev->dev, "Invalid max trigger level\n"); |
195 | goto out; | 205 | goto out; |
@@ -297,7 +307,7 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) | |||
297 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 307 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
298 | struct exynos_tmu_platform_data *pdata = data->pdata; | 308 | struct exynos_tmu_platform_data *pdata = data->pdata; |
299 | const struct exynos_tmu_registers *reg = pdata->registers; | 309 | const struct exynos_tmu_registers *reg = pdata->registers; |
300 | unsigned int con, interrupt_en; | 310 | unsigned int con, interrupt_en, cal_val; |
301 | 311 | ||
302 | mutex_lock(&data->lock); | 312 | mutex_lock(&data->lock); |
303 | clk_enable(data->clk); | 313 | clk_enable(data->clk); |
@@ -320,6 +330,27 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) | |||
320 | con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift); | 330 | con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift); |
321 | } | 331 | } |
322 | 332 | ||
333 | if (pdata->cal_mode == HW_MODE) { | ||
334 | con &= ~(reg->calib_mode_mask << reg->calib_mode_shift); | ||
335 | cal_val = 0; | ||
336 | switch (pdata->cal_type) { | ||
337 | case TYPE_TWO_POINT_TRIMMING: | ||
338 | cal_val = 3; | ||
339 | break; | ||
340 | case TYPE_ONE_POINT_TRIMMING_85: | ||
341 | cal_val = 2; | ||
342 | break; | ||
343 | case TYPE_ONE_POINT_TRIMMING_25: | ||
344 | cal_val = 1; | ||
345 | break; | ||
346 | case TYPE_NONE: | ||
347 | break; | ||
348 | default: | ||
349 | dev_err(&pdev->dev, "Invalid calibration type, using none\n"); | ||
350 | } | ||
351 | con |= cal_val << reg->calib_mode_shift; | ||
352 | } | ||
353 | |||
323 | if (on) { | 354 | if (on) { |
324 | con |= (1 << reg->core_en_shift); | 355 | con |= (1 << reg->core_en_shift); |
325 | interrupt_en = | 356 | interrupt_en = |
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 25c48d49ad47..b364c9eee701 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | enum calibration_type { | 29 | enum calibration_type { |
30 | TYPE_ONE_POINT_TRIMMING, | 30 | TYPE_ONE_POINT_TRIMMING, |
31 | TYPE_ONE_POINT_TRIMMING_25, | ||
32 | TYPE_ONE_POINT_TRIMMING_85, | ||
31 | TYPE_TWO_POINT_TRIMMING, | 33 | TYPE_TWO_POINT_TRIMMING, |
32 | TYPE_NONE, | 34 | TYPE_NONE, |
33 | }; | 35 | }; |
@@ -90,6 +92,10 @@ enum soc_type { | |||
90 | * @buf_slope_sel_shift: shift bits of amplifier gain value in tmu_ctrl | 92 | * @buf_slope_sel_shift: shift bits of amplifier gain value in tmu_ctrl |
91 | register. | 93 | register. |
92 | * @buf_slope_sel_mask: mask bits of amplifier gain value in tmu_ctrl register. | 94 | * @buf_slope_sel_mask: mask bits of amplifier gain value in tmu_ctrl register. |
95 | * @calib_mode_shift: shift bits of calibration mode value in tmu_ctrl | ||
96 | register. | ||
97 | * @calib_mode_mask: mask bits of calibration mode value in tmu_ctrl | ||
98 | register. | ||
93 | * @therm_trip_tq_en_shift: shift bits of thermal trip enable by TQ pin in | 99 | * @therm_trip_tq_en_shift: shift bits of thermal trip enable by TQ pin in |
94 | tmu_ctrl register. | 100 | tmu_ctrl register. |
95 | * @core_en_shift: shift bits of TMU core enable bit in tmu_ctrl register. | 101 | * @core_en_shift: shift bits of TMU core enable bit in tmu_ctrl register. |
@@ -151,6 +157,8 @@ struct exynos_tmu_registers { | |||
151 | u32 therm_trip_en_shift; | 157 | u32 therm_trip_en_shift; |
152 | u32 buf_slope_sel_shift; | 158 | u32 buf_slope_sel_shift; |
153 | u32 buf_slope_sel_mask; | 159 | u32 buf_slope_sel_mask; |
160 | u32 calib_mode_shift; | ||
161 | u32 calib_mode_mask; | ||
154 | u32 therm_trip_tq_en_shift; | 162 | u32 therm_trip_tq_en_shift; |
155 | u32 core_en_shift; | 163 | u32 core_en_shift; |
156 | 164 | ||
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c index 5952915d249c..9002499c1f69 100644 --- a/drivers/thermal/samsung/exynos_tmu_data.c +++ b/drivers/thermal/samsung/exynos_tmu_data.c | |||
@@ -189,6 +189,8 @@ static const struct exynos_tmu_registers exynos5440_tmu_registers = { | |||
189 | .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT, | 189 | .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT, |
190 | .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT, | 190 | .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT, |
191 | .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK, | 191 | .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK, |
192 | .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT, | ||
193 | .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK, | ||
192 | .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT, | 194 | .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT, |
193 | .tmu_status = EXYNOS5440_TMU_S0_7_STATUS, | 195 | .tmu_status = EXYNOS5440_TMU_S0_7_STATUS, |
194 | .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP, | 196 | .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP, |
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h index 43ce5fb428a8..dc7feb51099b 100644 --- a/drivers/thermal/samsung/exynos_tmu_data.h +++ b/drivers/thermal/samsung/exynos_tmu_data.h | |||
@@ -75,6 +75,8 @@ | |||
75 | #define EXYNOS_TMU_TRIP_MODE_SHIFT 13 | 75 | #define EXYNOS_TMU_TRIP_MODE_SHIFT 13 |
76 | #define EXYNOS_TMU_TRIP_MODE_MASK 0x7 | 76 | #define EXYNOS_TMU_TRIP_MODE_MASK 0x7 |
77 | #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12 | 77 | #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12 |
78 | #define EXYNOS_TMU_CALIB_MODE_SHIFT 4 | ||
79 | #define EXYNOS_TMU_CALIB_MODE_MASK 0x3 | ||
78 | 80 | ||
79 | #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0 | 81 | #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0 |
80 | #define EXYNOS_TMU_INTEN_RISE1_SHIFT 4 | 82 | #define EXYNOS_TMU_INTEN_RISE1_SHIFT 4 |