diff options
author | Naveen Krishna Chatradhi <ch.naveen@samsung.com> | 2013-12-19 01:06:31 -0500 |
---|---|---|
committer | Eduardo Valentin <edubezval@gmail.com> | 2014-05-06 14:51:32 -0400 |
commit | 14a11dc7e0dbf4acdd9c7b703ebd088f14def739 (patch) | |
tree | 92b6362dab322f7c2807f2a2f131a1123ad624a0 /drivers/thermal | |
parent | 9025d563cd9bd141a7b7f2095b6a760cd9d83a4e (diff) |
thermal: samsung: Add TMU support for Exynos5420 SoCs
Exynos5420 has 5 TMU channels, the TRIMINFO register is
misplaced for TMU channels 2, 3 and 4
TRIMINFO at 0x1006c000 contains data for TMU channel 3
TRIMINFO at 0x100a0000 contains data for TMU channel 4
TRIMINFO at 0x10068000 contains data for TMU channel 2
This patch
1 Adds the neccessary register changes and arch information
to support Exynos5420 SoCs.
2. Handles the gate clock for misplaced TRIMINFO register
3. Updates the Documentation at
Documentation/devicetree/bindings/thermal/exynos-thermal.txt
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.c | 52 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.h | 1 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu_data.c | 99 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu_data.h | 8 |
4 files changed, 156 insertions, 4 deletions
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index d9e7663fea8c..bc50912a222d 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
@@ -47,6 +47,7 @@ | |||
47 | * @irq_work: pointer to the irq work structure. | 47 | * @irq_work: pointer to the irq work structure. |
48 | * @lock: lock to implement synchronization. | 48 | * @lock: lock to implement synchronization. |
49 | * @clk: pointer to the clock structure. | 49 | * @clk: pointer to the clock structure. |
50 | * @clk_sec: pointer to the clock structure for accessing the base_second. | ||
50 | * @temp_error1: fused value of the first point trim. | 51 | * @temp_error1: fused value of the first point trim. |
51 | * @temp_error2: fused value of the second point trim. | 52 | * @temp_error2: fused value of the second point trim. |
52 | * @regulator: pointer to the TMU regulator structure. | 53 | * @regulator: pointer to the TMU regulator structure. |
@@ -61,7 +62,7 @@ struct exynos_tmu_data { | |||
61 | enum soc_type soc; | 62 | enum soc_type soc; |
62 | struct work_struct irq_work; | 63 | struct work_struct irq_work; |
63 | struct mutex lock; | 64 | struct mutex lock; |
64 | struct clk *clk; | 65 | struct clk *clk, *clk_sec; |
65 | u8 temp_error1, temp_error2; | 66 | u8 temp_error1, temp_error2; |
66 | struct regulator *regulator; | 67 | struct regulator *regulator; |
67 | struct thermal_sensor_conf *reg_conf; | 68 | struct thermal_sensor_conf *reg_conf; |
@@ -152,6 +153,8 @@ static int exynos_tmu_initialize(struct platform_device *pdev) | |||
152 | 153 | ||
153 | mutex_lock(&data->lock); | 154 | mutex_lock(&data->lock); |
154 | clk_enable(data->clk); | 155 | clk_enable(data->clk); |
156 | if (!IS_ERR(data->clk_sec)) | ||
157 | clk_enable(data->clk_sec); | ||
155 | 158 | ||
156 | if (TMU_SUPPORTS(pdata, READY_STATUS)) { | 159 | if (TMU_SUPPORTS(pdata, READY_STATUS)) { |
157 | status = readb(data->base + reg->tmu_status); | 160 | status = readb(data->base + reg->tmu_status); |
@@ -186,7 +189,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev) | |||
186 | EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data); | 189 | EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data); |
187 | } | 190 | } |
188 | } else { | 191 | } else { |
189 | trim_info = readl(data->base + reg->triminfo_data); | 192 | /* On exynos5420 the triminfo register is in the shared space */ |
193 | if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) | ||
194 | trim_info = readl(data->base_second + | ||
195 | reg->triminfo_data); | ||
196 | else | ||
197 | trim_info = readl(data->base + reg->triminfo_data); | ||
190 | } | 198 | } |
191 | data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; | 199 | data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; |
192 | data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) & | 200 | data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) & |
@@ -302,6 +310,8 @@ skip_calib_data: | |||
302 | out: | 310 | out: |
303 | clk_disable(data->clk); | 311 | clk_disable(data->clk); |
304 | mutex_unlock(&data->lock); | 312 | mutex_unlock(&data->lock); |
313 | if (!IS_ERR(data->clk_sec)) | ||
314 | clk_disable(data->clk_sec); | ||
305 | 315 | ||
306 | return ret; | 316 | return ret; |
307 | } | 317 | } |
@@ -453,12 +463,16 @@ static void exynos_tmu_work(struct work_struct *work) | |||
453 | const struct exynos_tmu_registers *reg = pdata->registers; | 463 | const struct exynos_tmu_registers *reg = pdata->registers; |
454 | unsigned int val_irq, val_type; | 464 | unsigned int val_irq, val_type; |
455 | 465 | ||
466 | if (!IS_ERR(data->clk_sec)) | ||
467 | clk_enable(data->clk_sec); | ||
456 | /* Find which sensor generated this interrupt */ | 468 | /* Find which sensor generated this interrupt */ |
457 | if (reg->tmu_irqstatus) { | 469 | if (reg->tmu_irqstatus) { |
458 | val_type = readl(data->base_second + reg->tmu_irqstatus); | 470 | val_type = readl(data->base_second + reg->tmu_irqstatus); |
459 | if (!((val_type >> data->id) & 0x1)) | 471 | if (!((val_type >> data->id) & 0x1)) |
460 | goto out; | 472 | goto out; |
461 | } | 473 | } |
474 | if (!IS_ERR(data->clk_sec)) | ||
475 | clk_disable(data->clk_sec); | ||
462 | 476 | ||
463 | exynos_report_trigger(data->reg_conf); | 477 | exynos_report_trigger(data->reg_conf); |
464 | mutex_lock(&data->lock); | 478 | mutex_lock(&data->lock); |
@@ -499,6 +513,14 @@ static const struct of_device_id exynos_tmu_match[] = { | |||
499 | .data = (void *)EXYNOS5250_TMU_DRV_DATA, | 513 | .data = (void *)EXYNOS5250_TMU_DRV_DATA, |
500 | }, | 514 | }, |
501 | { | 515 | { |
516 | .compatible = "samsung,exynos5420-tmu", | ||
517 | .data = (void *)EXYNOS5420_TMU_DRV_DATA, | ||
518 | }, | ||
519 | { | ||
520 | .compatible = "samsung,exynos5420-tmu-ext-triminfo", | ||
521 | .data = (void *)EXYNOS5420_TMU_DRV_DATA, | ||
522 | }, | ||
523 | { | ||
502 | .compatible = "samsung,exynos5440-tmu", | 524 | .compatible = "samsung,exynos5440-tmu", |
503 | .data = (void *)EXYNOS5440_TMU_DRV_DATA, | 525 | .data = (void *)EXYNOS5440_TMU_DRV_DATA, |
504 | }, | 526 | }, |
@@ -629,13 +651,30 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
629 | return PTR_ERR(data->clk); | 651 | return PTR_ERR(data->clk); |
630 | } | 652 | } |
631 | 653 | ||
654 | data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif"); | ||
655 | if (IS_ERR(data->clk_sec)) { | ||
656 | if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) { | ||
657 | dev_err(&pdev->dev, "Failed to get triminfo clock\n"); | ||
658 | return PTR_ERR(data->clk_sec); | ||
659 | } | ||
660 | } else { | ||
661 | ret = clk_prepare(data->clk_sec); | ||
662 | if (ret) { | ||
663 | dev_err(&pdev->dev, "Failed to get clock\n"); | ||
664 | return ret; | ||
665 | } | ||
666 | } | ||
667 | |||
632 | ret = clk_prepare(data->clk); | 668 | ret = clk_prepare(data->clk); |
633 | if (ret) | 669 | if (ret) { |
634 | return ret; | 670 | dev_err(&pdev->dev, "Failed to get clock\n"); |
671 | goto err_clk_sec; | ||
672 | } | ||
635 | 673 | ||
636 | if (pdata->type == SOC_ARCH_EXYNOS4210 || | 674 | if (pdata->type == SOC_ARCH_EXYNOS4210 || |
637 | pdata->type == SOC_ARCH_EXYNOS4412 || | 675 | pdata->type == SOC_ARCH_EXYNOS4412 || |
638 | pdata->type == SOC_ARCH_EXYNOS5250 || | 676 | pdata->type == SOC_ARCH_EXYNOS5250 || |
677 | pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO || | ||
639 | pdata->type == SOC_ARCH_EXYNOS5440) | 678 | pdata->type == SOC_ARCH_EXYNOS5440) |
640 | data->soc = pdata->type; | 679 | data->soc = pdata->type; |
641 | else { | 680 | else { |
@@ -704,6 +743,9 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
704 | return 0; | 743 | return 0; |
705 | err_clk: | 744 | err_clk: |
706 | clk_unprepare(data->clk); | 745 | clk_unprepare(data->clk); |
746 | err_clk_sec: | ||
747 | if (!IS_ERR(data->clk_sec)) | ||
748 | clk_unprepare(data->clk_sec); | ||
707 | return ret; | 749 | return ret; |
708 | } | 750 | } |
709 | 751 | ||
@@ -716,6 +758,8 @@ static int exynos_tmu_remove(struct platform_device *pdev) | |||
716 | exynos_unregister_thermal(data->reg_conf); | 758 | exynos_unregister_thermal(data->reg_conf); |
717 | 759 | ||
718 | clk_unprepare(data->clk); | 760 | clk_unprepare(data->clk); |
761 | if (!IS_ERR(data->clk_sec)) | ||
762 | clk_unprepare(data->clk_sec); | ||
719 | 763 | ||
720 | if (!IS_ERR(data->regulator)) | 764 | if (!IS_ERR(data->regulator)) |
721 | regulator_disable(data->regulator); | 765 | regulator_disable(data->regulator); |
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 0d6b32fb0a4c..60cce2855fa8 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h | |||
@@ -43,6 +43,7 @@ enum soc_type { | |||
43 | SOC_ARCH_EXYNOS4210 = 1, | 43 | SOC_ARCH_EXYNOS4210 = 1, |
44 | SOC_ARCH_EXYNOS4412, | 44 | SOC_ARCH_EXYNOS4412, |
45 | SOC_ARCH_EXYNOS5250, | 45 | SOC_ARCH_EXYNOS5250, |
46 | SOC_ARCH_EXYNOS5420_TRIMINFO, | ||
46 | SOC_ARCH_EXYNOS5440, | 47 | SOC_ARCH_EXYNOS5440, |
47 | }; | 48 | }; |
48 | 49 | ||
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c index 9816294f7058..e597f61a15f9 100644 --- a/drivers/thermal/samsung/exynos_tmu_data.c +++ b/drivers/thermal/samsung/exynos_tmu_data.c | |||
@@ -194,6 +194,105 @@ struct exynos_tmu_init_data const exynos5250_default_tmu_data = { | |||
194 | }; | 194 | }; |
195 | #endif | 195 | #endif |
196 | 196 | ||
197 | #if defined(CONFIG_SOC_EXYNOS5420) | ||
198 | static const struct exynos_tmu_registers exynos5420_tmu_registers = { | ||
199 | .triminfo_data = EXYNOS_TMU_REG_TRIMINFO, | ||
200 | .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT, | ||
201 | .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT, | ||
202 | .tmu_ctrl = EXYNOS_TMU_REG_CONTROL, | ||
203 | .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT, | ||
204 | .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK, | ||
205 | .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT, | ||
206 | .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK, | ||
207 | .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT, | ||
208 | .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT, | ||
209 | .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK, | ||
210 | .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT, | ||
211 | .tmu_status = EXYNOS_TMU_REG_STATUS, | ||
212 | .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP, | ||
213 | .threshold_th0 = EXYNOS_THD_TEMP_RISE, | ||
214 | .threshold_th1 = EXYNOS_THD_TEMP_FALL, | ||
215 | .tmu_inten = EXYNOS_TMU_REG_INTEN, | ||
216 | .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT, | ||
217 | .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT, | ||
218 | .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT, | ||
219 | /* INTEN_RISE3 Not availble in exynos5420 */ | ||
220 | .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT, | ||
221 | .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT, | ||
222 | .tmu_intstat = EXYNOS_TMU_REG_INTSTAT, | ||
223 | .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR, | ||
224 | .intclr_fall_shift = EXYNOS5420_TMU_CLEAR_FALL_INT_SHIFT, | ||
225 | .intclr_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT, | ||
226 | .intclr_rise_mask = EXYNOS_TMU_RISE_INT_MASK, | ||
227 | .intclr_fall_mask = EXYNOS_TMU_FALL_INT_MASK, | ||
228 | .emul_con = EXYNOS_EMUL_CON, | ||
229 | .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT, | ||
230 | .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT, | ||
231 | .emul_time_mask = EXYNOS_EMUL_TIME_MASK, | ||
232 | }; | ||
233 | |||
234 | #define __EXYNOS5420_TMU_DATA \ | ||
235 | .threshold_falling = 10, \ | ||
236 | .trigger_levels[0] = 85, \ | ||
237 | .trigger_levels[1] = 103, \ | ||
238 | .trigger_levels[2] = 110, \ | ||
239 | .trigger_levels[3] = 120, \ | ||
240 | .trigger_enable[0] = true, \ | ||
241 | .trigger_enable[1] = true, \ | ||
242 | .trigger_enable[2] = true, \ | ||
243 | .trigger_enable[3] = false, \ | ||
244 | .trigger_type[0] = THROTTLE_ACTIVE, \ | ||
245 | .trigger_type[1] = THROTTLE_ACTIVE, \ | ||
246 | .trigger_type[2] = SW_TRIP, \ | ||
247 | .trigger_type[3] = HW_TRIP, \ | ||
248 | .max_trigger_level = 4, \ | ||
249 | .gain = 8, \ | ||
250 | .reference_voltage = 16, \ | ||
251 | .noise_cancel_mode = 4, \ | ||
252 | .cal_type = TYPE_ONE_POINT_TRIMMING, \ | ||
253 | .efuse_value = 55, \ | ||
254 | .min_efuse_value = 40, \ | ||
255 | .max_efuse_value = 100, \ | ||
256 | .first_point_trim = 25, \ | ||
257 | .second_point_trim = 85, \ | ||
258 | .default_temp_offset = 50, \ | ||
259 | .freq_tab[0] = { \ | ||
260 | .freq_clip_max = 800 * 1000, \ | ||
261 | .temp_level = 85, \ | ||
262 | }, \ | ||
263 | .freq_tab[1] = { \ | ||
264 | .freq_clip_max = 200 * 1000, \ | ||
265 | .temp_level = 103, \ | ||
266 | }, \ | ||
267 | .freq_tab_count = 2, \ | ||
268 | .registers = &exynos5420_tmu_registers, \ | ||
269 | |||
270 | #define EXYNOS5420_TMU_DATA \ | ||
271 | __EXYNOS5420_TMU_DATA \ | ||
272 | .type = SOC_ARCH_EXYNOS5250, \ | ||
273 | .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \ | ||
274 | TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \ | ||
275 | TMU_SUPPORT_EMUL_TIME) | ||
276 | |||
277 | #define EXYNOS5420_TMU_DATA_SHARED \ | ||
278 | __EXYNOS5420_TMU_DATA \ | ||
279 | .type = SOC_ARCH_EXYNOS5420_TRIMINFO, \ | ||
280 | .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \ | ||
281 | TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \ | ||
282 | TMU_SUPPORT_EMUL_TIME | TMU_SUPPORT_ADDRESS_MULTIPLE) | ||
283 | |||
284 | struct exynos_tmu_init_data const exynos5420_default_tmu_data = { | ||
285 | .tmu_data = { | ||
286 | { EXYNOS5420_TMU_DATA }, | ||
287 | { EXYNOS5420_TMU_DATA }, | ||
288 | { EXYNOS5420_TMU_DATA_SHARED }, | ||
289 | { EXYNOS5420_TMU_DATA_SHARED }, | ||
290 | { EXYNOS5420_TMU_DATA_SHARED }, | ||
291 | }, | ||
292 | .tmu_count = 5, | ||
293 | }; | ||
294 | #endif | ||
295 | |||
197 | #if defined(CONFIG_SOC_EXYNOS5440) | 296 | #if defined(CONFIG_SOC_EXYNOS5440) |
198 | static const struct exynos_tmu_registers exynos5440_tmu_registers = { | 297 | static const struct exynos_tmu_registers exynos5440_tmu_registers = { |
199 | .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM, | 298 | .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM, |
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h index d9495a441560..41f06dc70849 100644 --- a/drivers/thermal/samsung/exynos_tmu_data.h +++ b/drivers/thermal/samsung/exynos_tmu_data.h | |||
@@ -72,6 +72,7 @@ | |||
72 | #define EXYNOS_TMU_CLEAR_RISE_INT 0x111 | 72 | #define EXYNOS_TMU_CLEAR_RISE_INT 0x111 |
73 | #define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12) | 73 | #define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12) |
74 | #define EXYNOS_TMU_CLEAR_FALL_INT_SHIFT 12 | 74 | #define EXYNOS_TMU_CLEAR_FALL_INT_SHIFT 12 |
75 | #define EXYNOS5420_TMU_CLEAR_FALL_INT_SHIFT 16 | ||
75 | #define EXYNOS5440_TMU_CLEAR_FALL_INT_SHIFT 4 | 76 | #define EXYNOS5440_TMU_CLEAR_FALL_INT_SHIFT 4 |
76 | #define EXYNOS_TMU_TRIP_MODE_SHIFT 13 | 77 | #define EXYNOS_TMU_TRIP_MODE_SHIFT 13 |
77 | #define EXYNOS_TMU_TRIP_MODE_MASK 0x7 | 78 | #define EXYNOS_TMU_TRIP_MODE_MASK 0x7 |
@@ -156,6 +157,13 @@ extern struct exynos_tmu_init_data const exynos5250_default_tmu_data; | |||
156 | #define EXYNOS5250_TMU_DRV_DATA (NULL) | 157 | #define EXYNOS5250_TMU_DRV_DATA (NULL) |
157 | #endif | 158 | #endif |
158 | 159 | ||
160 | #if defined(CONFIG_SOC_EXYNOS5420) | ||
161 | extern struct exynos_tmu_init_data const exynos5420_default_tmu_data; | ||
162 | #define EXYNOS5420_TMU_DRV_DATA (&exynos5420_default_tmu_data) | ||
163 | #else | ||
164 | #define EXYNOS5420_TMU_DRV_DATA (NULL) | ||
165 | #endif | ||
166 | |||
159 | #if defined(CONFIG_SOC_EXYNOS5440) | 167 | #if defined(CONFIG_SOC_EXYNOS5440) |
160 | extern struct exynos_tmu_init_data const exynos5440_default_tmu_data; | 168 | extern struct exynos_tmu_init_data const exynos5440_default_tmu_data; |
161 | #define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data) | 169 | #define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data) |