2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 Samsung Electronics
5 * Copyright 2013 Google Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 /* EXYNOS - Thermal Management Unit */
20 #include <console/console.h>
21 #include <soc/power.h>
24 #define TRIMINFO_RELOAD 1
26 #define THERM_TRIP_EN (1 << 12)
29 #define INTEN_RISE1 (1 << 4)
30 #define INTEN_RISE2 (1 << 8)
31 #define INTEN_FALL0 (1 << 16)
32 #define INTEN_FALL1 (1 << 20)
33 #define INTEN_FALL2 (1 << 24)
35 #define TRIM_INFO_MASK 0xff
37 #define INTCLEAR_RISE0 1
38 #define INTCLEAR_RISE1 (1 << 4)
39 #define INTCLEAR_RISE2 (1 << 8)
40 #define INTCLEAR_FALL0 (1 << 16)
41 #define INTCLEAR_FALL1 (1 << 20)
42 #define INTCLEAR_FALL2 (1 << 24)
43 #define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \
44 INTCLEAR_RISE2 | INTCLEAR_FALL0 | \
45 INTCLEAR_FALL1 | INTCLEAR_FALL2)
47 struct tmu_info exynos5420_tmu_info
= {
48 .tmu_base
= 0x10060000,
55 .start_tripping
= 105,
56 .hardware_tripping
= 110,
58 .efuse_min_value
= 40,
60 .efuse_max_value
= 100,
67 * After reading temperature code from register, compensating
68 * its value and calculating celsius temperature,
69 * get current temperature.
71 * @return current temperature of the chip as sensed by TMU
73 static int get_cur_temp(struct tmu_info
*info
)
76 struct tmu_reg
*reg
= (struct tmu_reg
*)info
->tmu_base
;
78 /* Temperature code range between min 25 and max 125 */
79 cur_temp
= read32(®
->current_temp
) & 0xff;
81 /* Calibrate current temperature */
83 cur_temp
= cur_temp
- info
->te1
+ info
->dc_value
;
89 * Monitors status of the TMU device and exynos temperature
92 * @temp pointer to the current temperature value
93 * @return enum tmu_status_t value, code indicating event to execute
95 enum tmu_status_t
tmu_monitor(struct tmu_info
*info
, int *temp
)
97 if (info
->tmu_state
== TMU_STATUS_INIT
)
101 struct tmu_data
*data
= &info
->data
;
103 /* Read current temperature of the SOC */
104 cur_temp
= get_cur_temp(info
);
107 /* Temperature code lies between min 25 and max 125 */
108 if (cur_temp
>= data
->ts
.start_tripping
&&
109 cur_temp
<= data
->ts
.max_val
)
110 return TMU_STATUS_TRIPPED
;
111 else if (cur_temp
>= data
->ts
.start_warning
)
112 return TMU_STATUS_WARNING
;
113 else if (cur_temp
< data
->ts
.start_warning
&&
114 cur_temp
>= data
->ts
.min_val
)
115 return TMU_STATUS_NORMAL
;
116 /* Temperature code does not lie between min 25 and max 125 */
118 info
->tmu_state
= TMU_STATUS_INIT
;
119 printk(BIOS_DEBUG
, "EXYNOS_TMU: Thermal reading failed\n");
126 * Calibrate and calculate threshold values and
127 * enable interrupt levels
129 * @param info pointer to the tmu_info struct
131 static void tmu_setup_parameters(struct tmu_info
*info
)
133 unsigned int te_temp
, con
;
134 unsigned int warning_code
, trip_code
, hwtrip_code
;
135 unsigned int cooling_temp
;
136 unsigned int rising_value
;
137 struct tmu_data
*data
= &info
->data
;
138 struct tmu_reg
*reg
= (struct tmu_reg
*)info
->tmu_base
;
140 /* Must reload for using efuse value at EXYNOS */
141 write32(®
->triminfo_control
, TRIMINFO_RELOAD
);
143 /* Get the compensation parameter */
144 te_temp
= read32(®
->triminfo
);
145 info
->te1
= te_temp
& TRIM_INFO_MASK
;
146 info
->te2
= ((te_temp
>> 8) & TRIM_INFO_MASK
);
148 if ((data
->efuse_min_value
> info
->te1
) ||
149 (info
->te1
> data
->efuse_max_value
)
151 info
->te1
= data
->efuse_value
;
153 /* Get RISING & FALLING Threshold value */
154 warning_code
= data
->ts
.start_warning
155 + info
->te1
- info
->dc_value
;
156 trip_code
= data
->ts
.start_tripping
157 + info
->te1
- info
->dc_value
;
158 hwtrip_code
= data
->ts
.hardware_tripping
159 + info
->te1
- info
->dc_value
;
163 rising_value
= ((warning_code
<< 8) |
165 (hwtrip_code
<< 24));
167 /* Set interrupt level */
168 write32(®
->threshold_temp_rise
, rising_value
);
169 write32(®
->threshold_temp_fall
, cooling_temp
);
172 * Need to init all register settings after getting parameter info
173 * [28:23] vref [11:8] slope - Tuning parameter
175 * WARNING: this slope value writes into many bits in the tmu_control
176 * register, with the default FDT value of 268470274 (0x10008802)
177 * we are using this essentially sets the default register setting
178 * from the TRM for tmu_control.
179 * TODO(bhthompson): rewrite this code such that we are not performing
180 * a hard wipe of tmu_control and re verify functionality.
182 write32(®
->tmu_control
, data
->slope
);
184 write32(®
->intclear
, INTCLEARALL
);
185 /* TMU core enable */
186 con
= read32(®
->tmu_control
);
187 con
|= (info
->tmu_mux
<< 20) | THERM_TRIP_EN
| CORE_EN
;
189 write32(®
->tmu_control
, con
);
191 /* Enable HW thermal trip */
192 power_enable_hw_thermal_trip();
194 /* LEV1 LEV2 interrupt enable */
195 write32(®
->inten
, INTEN_RISE1
| INTEN_RISE2
);
199 * Initialize TMU device
201 * @return int value, 0 for success
203 int tmu_init(struct tmu_info
*info
)
205 info
->tmu_state
= TMU_STATUS_INIT
;
207 tmu_setup_parameters(info
);
208 info
->tmu_state
= TMU_STATUS_NORMAL
;