]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/thermal/samsung/exynos_tmu.c
thermal: exynos: remove threshold_code checking from exynos4210_tmu_initialize()
[mirror_ubuntu-hirsute-kernel.git] / drivers / thermal / samsung / exynos_tmu.c
CommitLineData
9d97e5c8 1/*
59dfa54c 2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
9d97e5c8 3 *
3b6a1a80
LM
4 * Copyright (C) 2014 Samsung Electronics
5 * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
6 * Lukasz Majewski <l.majewski@samsung.com>
7 *
9d97e5c8
DK
8 * Copyright (C) 2011 Samsung Electronics
9 * Donggeun Kim <dg77.kim@samsung.com>
c48cbba6 10 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
9d97e5c8
DK
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
9d97e5c8 28#include <linux/clk.h>
9d97e5c8 29#include <linux/io.h>
1b678641
ADK
30#include <linux/interrupt.h>
31#include <linux/module.h>
fee88e2b 32#include <linux/of_device.h>
cebe7373
ADK
33#include <linux/of_address.h>
34#include <linux/of_irq.h>
1b678641 35#include <linux/platform_device.h>
498d22f6 36#include <linux/regulator/consumer.h>
1b678641 37
7efd18a2
BZ
38#include <dt-bindings/thermal/thermal_exynos.h>
39
3b6a1a80 40#include "../thermal_core.h"
2845f6ec
BZ
41
42/* Exynos generic registers */
43#define EXYNOS_TMU_REG_TRIMINFO 0x0
44#define EXYNOS_TMU_REG_CONTROL 0x20
45#define EXYNOS_TMU_REG_STATUS 0x28
46#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
47#define EXYNOS_TMU_REG_INTEN 0x70
48#define EXYNOS_TMU_REG_INTSTAT 0x74
49#define EXYNOS_TMU_REG_INTCLEAR 0x78
50
51#define EXYNOS_TMU_TEMP_MASK 0xff
52#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
53#define EXYNOS_TMU_REF_VOLTAGE_MASK 0x1f
54#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK 0xf
55#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT 8
56#define EXYNOS_TMU_CORE_EN_SHIFT 0
57
58/* Exynos3250 specific registers */
59#define EXYNOS_TMU_TRIMINFO_CON1 0x10
60
61/* Exynos4210 specific registers */
62#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
63#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
64
65/* Exynos5250, Exynos4412, Exynos3250 specific registers */
66#define EXYNOS_TMU_TRIMINFO_CON2 0x14
67#define EXYNOS_THD_TEMP_RISE 0x50
68#define EXYNOS_THD_TEMP_FALL 0x54
69#define EXYNOS_EMUL_CON 0x80
70
71#define EXYNOS_TRIMINFO_RELOAD_ENABLE 1
72#define EXYNOS_TRIMINFO_25_SHIFT 0
73#define EXYNOS_TRIMINFO_85_SHIFT 8
74#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
75#define EXYNOS_TMU_TRIP_MODE_MASK 0x7
76#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12
77
78#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
79#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
80#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
81#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
82#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
83
84#define EXYNOS_EMUL_TIME 0x57F0
85#define EXYNOS_EMUL_TIME_MASK 0xffff
86#define EXYNOS_EMUL_TIME_SHIFT 16
87#define EXYNOS_EMUL_DATA_SHIFT 8
88#define EXYNOS_EMUL_DATA_MASK 0xFF
89#define EXYNOS_EMUL_ENABLE 0x1
90
91/* Exynos5260 specific */
92#define EXYNOS5260_TMU_REG_INTEN 0xC0
93#define EXYNOS5260_TMU_REG_INTSTAT 0xC4
94#define EXYNOS5260_TMU_REG_INTCLEAR 0xC8
95#define EXYNOS5260_EMUL_CON 0x100
96
97/* Exynos4412 specific */
98#define EXYNOS4412_MUX_ADDR_VALUE 6
99#define EXYNOS4412_MUX_ADDR_SHIFT 20
100
488c7455
CC
101/* Exynos5433 specific registers */
102#define EXYNOS5433_TMU_REG_CONTROL1 0x024
103#define EXYNOS5433_TMU_SAMPLING_INTERVAL 0x02c
104#define EXYNOS5433_TMU_COUNTER_VALUE0 0x030
105#define EXYNOS5433_TMU_COUNTER_VALUE1 0x034
106#define EXYNOS5433_TMU_REG_CURRENT_TEMP1 0x044
107#define EXYNOS5433_THD_TEMP_RISE3_0 0x050
108#define EXYNOS5433_THD_TEMP_RISE7_4 0x054
109#define EXYNOS5433_THD_TEMP_FALL3_0 0x060
110#define EXYNOS5433_THD_TEMP_FALL7_4 0x064
111#define EXYNOS5433_TMU_REG_INTEN 0x0c0
112#define EXYNOS5433_TMU_REG_INTPEND 0x0c8
113#define EXYNOS5433_TMU_EMUL_CON 0x110
114#define EXYNOS5433_TMU_PD_DET_EN 0x130
115
116#define EXYNOS5433_TRIMINFO_SENSOR_ID_SHIFT 16
117#define EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT 23
118#define EXYNOS5433_TRIMINFO_SENSOR_ID_MASK \
119 (0xf << EXYNOS5433_TRIMINFO_SENSOR_ID_SHIFT)
120#define EXYNOS5433_TRIMINFO_CALIB_SEL_MASK BIT(23)
121
122#define EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING 0
123#define EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING 1
124
125#define EXYNOS5433_PD_DET_EN 1
126
61020d18
BZ
127#define EXYNOS5433_G3D_BASE 0x10070000
128
6c247393
AK
129/* Exynos7 specific registers */
130#define EXYNOS7_THD_TEMP_RISE7_6 0x50
131#define EXYNOS7_THD_TEMP_FALL7_6 0x60
132#define EXYNOS7_TMU_REG_INTEN 0x110
133#define EXYNOS7_TMU_REG_INTPEND 0x118
134#define EXYNOS7_TMU_REG_EMUL_CON 0x160
135
136#define EXYNOS7_TMU_TEMP_MASK 0x1ff
137#define EXYNOS7_PD_DET_EN_SHIFT 23
138#define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0
139#define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1
140#define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2
141#define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3
142#define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4
143#define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5
144#define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6
145#define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7
146#define EXYNOS7_EMUL_DATA_SHIFT 7
147#define EXYNOS7_EMUL_DATA_MASK 0x1ff
148
718b4ca1
BZ
149#define EXYNOS_FIRST_POINT_TRIM 25
150#define EXYNOS_SECOND_POINT_TRIM 85
151
09d29426
BZ
152#define EXYNOS_NOISE_CANCEL_MODE 4
153
3b6a1a80 154#define MCELSIUS 1000
7efd18a2
BZ
155
156enum soc_type {
157 SOC_ARCH_EXYNOS3250 = 1,
158 SOC_ARCH_EXYNOS4210,
159 SOC_ARCH_EXYNOS4412,
160 SOC_ARCH_EXYNOS5250,
161 SOC_ARCH_EXYNOS5260,
162 SOC_ARCH_EXYNOS5420,
163 SOC_ARCH_EXYNOS5420_TRIMINFO,
164 SOC_ARCH_EXYNOS5433,
7efd18a2
BZ
165 SOC_ARCH_EXYNOS7,
166};
167
cebe7373
ADK
168/**
169 * struct exynos_tmu_data : A structure to hold the private data of the TMU
170 driver
171 * @id: identifier of the one instance of the TMU controller.
cebe7373 172 * @base: base address of the single instance of the TMU controller.
9025d563 173 * @base_second: base address of the common registers of the TMU controller.
cebe7373
ADK
174 * @irq: irq number of the TMU controller.
175 * @soc: id of the SOC type.
176 * @irq_work: pointer to the irq work structure.
177 * @lock: lock to implement synchronization.
178 * @clk: pointer to the clock structure.
14a11dc7 179 * @clk_sec: pointer to the clock structure for accessing the base_second.
6c247393 180 * @sclk: pointer to the clock structure for accessing the tmu special clk.
199b3e3c 181 * @cal_type: calibration type for temperature
e3ed3649
BZ
182 * @efuse_value: SoC defined fuse value
183 * @min_efuse_value: minimum valid trimming data
184 * @max_efuse_value: maximum valid trimming data
cebe7373
ADK
185 * @temp_error1: fused value of the first point trim.
186 * @temp_error2: fused value of the second point trim.
fccfe099
BZ
187 * @gain: gain of amplifier in the positive-TC generator block
188 * 0 < gain <= 15
61020d18
BZ
189 * @reference_voltage: reference voltage of amplifier
190 * in the positive-TC generator block
191 * 0 < reference_voltage <= 31
498d22f6 192 * @regulator: pointer to the TMU regulator structure.
cebe7373 193 * @reg_conf: pointer to structure to register with core thermal.
3a3a5f15 194 * @ntrip: number of supported trip points.
0eb875d8 195 * @enabled: current status of TMU device
72d1100b 196 * @tmu_initialize: SoC specific TMU initialization method
37f9034f 197 * @tmu_control: SoC specific TMU control method
b79985ca 198 * @tmu_read: SoC specific TMU temperature read method
285d994a 199 * @tmu_set_emulation: SoC specific TMU emulation setting method
a7331f72 200 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
cebe7373 201 */
f22d9c03 202struct exynos_tmu_data {
cebe7373 203 int id;
9d97e5c8 204 void __iomem *base;
9025d563 205 void __iomem *base_second;
9d97e5c8 206 int irq;
f22d9c03 207 enum soc_type soc;
9d97e5c8
DK
208 struct work_struct irq_work;
209 struct mutex lock;
6c247393 210 struct clk *clk, *clk_sec, *sclk;
199b3e3c 211 u32 cal_type;
e3ed3649
BZ
212 u32 efuse_value;
213 u32 min_efuse_value;
214 u32 max_efuse_value;
6c247393 215 u16 temp_error1, temp_error2;
fccfe099 216 u8 gain;
61020d18 217 u8 reference_voltage;
498d22f6 218 struct regulator *regulator;
3b6a1a80 219 struct thermal_zone_device *tzd;
3a3a5f15 220 unsigned int ntrip;
0eb875d8 221 bool enabled;
3b6a1a80 222
72d1100b 223 int (*tmu_initialize)(struct platform_device *pdev);
37f9034f 224 void (*tmu_control)(struct platform_device *pdev, bool on);
b79985ca 225 int (*tmu_read)(struct exynos_tmu_data *data);
17e8351a 226 void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
a7331f72 227 void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
9d97e5c8
DK
228};
229
3b6a1a80
LM
230static void exynos_report_trigger(struct exynos_tmu_data *p)
231{
232 char data[10], *envp[] = { data, NULL };
233 struct thermal_zone_device *tz = p->tzd;
17e8351a 234 int temp;
3b6a1a80
LM
235 unsigned int i;
236
eccb6014
LM
237 if (!tz) {
238 pr_err("No thermal zone device defined\n");
3b6a1a80
LM
239 return;
240 }
241
0e70f466 242 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
3b6a1a80
LM
243
244 mutex_lock(&tz->lock);
245 /* Find the level for which trip happened */
246 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
247 tz->ops->get_trip_temp(tz, i, &temp);
248 if (tz->last_temperature < temp)
249 break;
250 }
251
252 snprintf(data, sizeof(data), "%u", i);
253 kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, envp);
254 mutex_unlock(&tz->lock);
255}
256
9d97e5c8
DK
257/*
258 * TMU treats temperature as a mapped temperature code.
259 * The temperature is converted differently depending on the calibration type.
260 */
f22d9c03 261static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
9d97e5c8 262{
199b3e3c 263 if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
718b4ca1 264 return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM;
9c933b1b 265
718b4ca1 266 return (temp - EXYNOS_FIRST_POINT_TRIM) *
9c933b1b 267 (data->temp_error2 - data->temp_error1) /
718b4ca1 268 (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) +
9c933b1b 269 data->temp_error1;
9d97e5c8
DK
270}
271
272/*
273 * Calculate a temperature value from a temperature code.
274 * The unit of the temperature is degree Celsius.
275 */
6c247393 276static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
9d97e5c8 277{
199b3e3c 278 if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
718b4ca1 279 return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM;
ddb31d43 280
9c933b1b 281 return (temp_code - data->temp_error1) *
718b4ca1 282 (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) /
9c933b1b 283 (data->temp_error2 - data->temp_error1) +
718b4ca1 284 EXYNOS_FIRST_POINT_TRIM;
9d97e5c8
DK
285}
286
8328a4b1 287static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
9d97e5c8 288{
aef27b65
BZ
289 u16 tmu_temp_mask =
290 (data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK
291 : EXYNOS_TMU_TEMP_MASK;
292
293 data->temp_error1 = trim_info & tmu_temp_mask;
99d67fb9 294 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
b8d582b9 295 EXYNOS_TMU_TEMP_MASK);
f22d9c03 296
5000806c 297 if (!data->temp_error1 ||
e3ed3649
BZ
298 (data->min_efuse_value > data->temp_error1) ||
299 (data->temp_error1 > data->max_efuse_value))
300 data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK;
5000806c
ADK
301
302 if (!data->temp_error2)
303 data->temp_error2 =
e3ed3649 304 (data->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
5000806c 305 EXYNOS_TMU_TEMP_MASK;
8328a4b1 306}
f22d9c03 307
fe87789c
BZ
308static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
309{
3b6a1a80
LM
310 struct thermal_zone_device *tz = data->tzd;
311 const struct thermal_trip * const trips =
312 of_thermal_get_trip_points(tz);
313 unsigned long temp;
3c265134 314 int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip);
c65d3473 315
3c265134 316 for (i = 0; i < ntrips; i++) {
3b6a1a80
LM
317 if (trips[i].type == THERMAL_TRIP_CRITICAL)
318 continue;
319
320 temp = trips[i].temperature / MCELSIUS;
fe87789c 321 if (falling)
3b6a1a80 322 temp -= (trips[i].hysteresis / MCELSIUS);
fe87789c
BZ
323 else
324 threshold &= ~(0xff << 8 * i);
f22d9c03 325
fe87789c 326 threshold |= temp_to_code(data, temp) << 8 * i;
9d97e5c8 327 }
fe87789c
BZ
328
329 return threshold;
330}
331
f22d9c03 332static int exynos_tmu_initialize(struct platform_device *pdev)
9d97e5c8 333{
f22d9c03 334 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
75e0f100
BZ
335 struct thermal_zone_device *tzd = data->tzd;
336 const struct thermal_trip * const trips =
337 of_thermal_get_trip_points(tzd);
97b3881b 338 unsigned int status;
8f1c404b 339 int ret = 0, temp;
9d97e5c8 340
75e0f100
BZ
341 if (!trips) {
342 dev_err(&pdev->dev,
343 "Cannot get trip points from device tree!\n");
344 return -ENODEV;
345 }
346
8f1c404b
BZ
347 if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */
348 ret = tzd->ops->get_crit_temp(tzd, &temp);
349 if (ret) {
350 dev_err(&pdev->dev,
351 "No CRITICAL trip point defined in device tree!\n");
352 goto out;
353 }
354
75e0f100 355 if (of_thermal_get_ntrips(tzd) > data->ntrip) {
3a3a5f15
KK
356 dev_info(&pdev->dev,
357 "More trip points than supported by this TMU.\n");
358 dev_info(&pdev->dev,
359 "%d trip points should be configured in polling mode.\n",
75e0f100 360 (of_thermal_get_ntrips(tzd) - data->ntrip));
3a3a5f15
KK
361 }
362
9d97e5c8
DK
363 mutex_lock(&data->lock);
364 clk_enable(data->clk);
14a11dc7
NKC
365 if (!IS_ERR(data->clk_sec))
366 clk_enable(data->clk_sec);
97b3881b
BZ
367
368 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
369 if (!status)
370 ret = -EBUSY;
371 else
372 ret = data->tmu_initialize(pdev);
373
9d97e5c8
DK
374 clk_disable(data->clk);
375 mutex_unlock(&data->lock);
14a11dc7
NKC
376 if (!IS_ERR(data->clk_sec))
377 clk_disable(data->clk_sec);
8f1c404b 378out:
9d97e5c8
DK
379 return ret;
380}
381
d00671c3 382static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
9d97e5c8 383{
7575983c
BZ
384 if (data->soc == SOC_ARCH_EXYNOS4412 ||
385 data->soc == SOC_ARCH_EXYNOS3250)
386 con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT);
86f5362e 387
99d67fb9 388 con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
61020d18 389 con |= data->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
d0a0ce3e 390
99d67fb9 391 con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
fccfe099 392 con |= (data->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
d0a0ce3e 393
09d29426
BZ
394 con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
395 con |= (EXYNOS_NOISE_CANCEL_MODE << EXYNOS_TMU_TRIP_MODE_SHIFT);
f22d9c03 396
d00671c3
BZ
397 return con;
398}
399
400static void exynos_tmu_control(struct platform_device *pdev, bool on)
401{
402 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
9d97e5c8 403
d00671c3
BZ
404 mutex_lock(&data->lock);
405 clk_enable(data->clk);
37f9034f 406 data->tmu_control(pdev, on);
0eb875d8 407 data->enabled = on;
9d97e5c8
DK
408 clk_disable(data->clk);
409 mutex_unlock(&data->lock);
410}
411
72d1100b 412static int exynos4210_tmu_initialize(struct platform_device *pdev)
9d97e5c8 413{
72d1100b 414 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
3b6a1a80
LM
415 struct thermal_zone_device *tz = data->tzd;
416 const struct thermal_trip * const trips =
417 of_thermal_get_trip_points(tz);
72d1100b 418 int ret = 0, threshold_code, i;
3b6a1a80 419 unsigned long reference, temp;
9d97e5c8 420
72d1100b 421 sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
9d97e5c8 422
72d1100b 423 /* Write temperature code for threshold */
3b6a1a80
LM
424 reference = trips[0].temperature / MCELSIUS;
425 threshold_code = temp_to_code(data, reference);
72d1100b
BZ
426 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
427
3b6a1a80
LM
428 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
429 temp = trips[i].temperature / MCELSIUS;
430 writeb(temp - reference, data->base +
72d1100b 431 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
3b6a1a80 432 }
72d1100b 433
a7331f72 434 data->tmu_clear_irqs(data);
0a79ba52 435
72d1100b
BZ
436 return ret;
437}
438
439static int exynos4412_tmu_initialize(struct platform_device *pdev)
440{
441 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
3b6a1a80
LM
442 const struct thermal_trip * const trips =
443 of_thermal_get_trip_points(data->tzd);
97b3881b 444 unsigned int trim_info, con, ctrl, rising_threshold;
72d1100b 445 int ret = 0, threshold_code, i;
3b6a1a80 446 unsigned long crit_temp = 0;
72d1100b 447
72d1100b
BZ
448 if (data->soc == SOC_ARCH_EXYNOS3250 ||
449 data->soc == SOC_ARCH_EXYNOS4412 ||
450 data->soc == SOC_ARCH_EXYNOS5250) {
451 if (data->soc == SOC_ARCH_EXYNOS3250) {
452 ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
453 ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
454 writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
ddb31d43 455 }
72d1100b
BZ
456 ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
457 ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
458 writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
459 }
ddb31d43 460
72d1100b
BZ
461 /* On exynos5420 the triminfo register is in the shared space */
462 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
463 trim_info = readl(data->base_second + EXYNOS_TMU_REG_TRIMINFO);
464 else
465 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
466
467 sanitize_temp_error(data, trim_info);
468
469 /* Write temperature code for rising and falling threshold */
470 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
471 rising_threshold = get_th_reg(data, rising_threshold, false);
472 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
473 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
474
a7331f72 475 data->tmu_clear_irqs(data);
72d1100b
BZ
476
477 /* if last threshold limit is also present */
3b6a1a80
LM
478 for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) {
479 if (trips[i].type == THERMAL_TRIP_CRITICAL) {
480 crit_temp = trips[i].temperature;
481 break;
482 }
72d1100b 483 }
3b6a1a80 484
3b6a1a80
LM
485 threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
486 /* 1-4 level to be assigned in th0 reg */
487 rising_threshold &= ~(0xff << 8 * i);
488 rising_threshold |= threshold_code << 8 * i;
489 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
490 con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
491 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
492 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
493
72d1100b
BZ
494 return ret;
495}
9d97e5c8 496
488c7455
CC
497static int exynos5433_tmu_initialize(struct platform_device *pdev)
498{
499 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
488c7455 500 struct thermal_zone_device *tz = data->tzd;
97b3881b 501 unsigned int trim_info;
488c7455 502 unsigned int rising_threshold = 0, falling_threshold = 0;
17e8351a 503 int temp, temp_hist;
488c7455
CC
504 int ret = 0, threshold_code, i, sensor_id, cal_type;
505
488c7455
CC
506 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
507 sanitize_temp_error(data, trim_info);
508
509 /* Read the temperature sensor id */
510 sensor_id = (trim_info & EXYNOS5433_TRIMINFO_SENSOR_ID_MASK)
511 >> EXYNOS5433_TRIMINFO_SENSOR_ID_SHIFT;
512 dev_info(&pdev->dev, "Temperature sensor ID: 0x%x\n", sensor_id);
513
514 /* Read the calibration mode */
515 writel(trim_info, data->base + EXYNOS_TMU_REG_TRIMINFO);
516 cal_type = (trim_info & EXYNOS5433_TRIMINFO_CALIB_SEL_MASK)
517 >> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT;
518
519 switch (cal_type) {
488c7455 520 case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING:
199b3e3c 521 data->cal_type = TYPE_TWO_POINT_TRIMMING;
488c7455 522 break;
199b3e3c 523 case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING:
488c7455 524 default:
199b3e3c 525 data->cal_type = TYPE_ONE_POINT_TRIMMING;
488c7455 526 break;
baba1ebb 527 }
488c7455
CC
528
529 dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
530 cal_type ? 2 : 1);
531
532 /* Write temperature code for rising and falling threshold */
533 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
534 int rising_reg_offset, falling_reg_offset;
535 int j = 0;
536
537 switch (i) {
538 case 0:
539 case 1:
540 case 2:
541 case 3:
542 rising_reg_offset = EXYNOS5433_THD_TEMP_RISE3_0;
543 falling_reg_offset = EXYNOS5433_THD_TEMP_FALL3_0;
544 j = i;
545 break;
546 case 4:
547 case 5:
548 case 6:
549 case 7:
550 rising_reg_offset = EXYNOS5433_THD_TEMP_RISE7_4;
551 falling_reg_offset = EXYNOS5433_THD_TEMP_FALL7_4;
552 j = i - 4;
553 break;
554 default:
555 continue;
556 }
557
558 /* Write temperature code for rising threshold */
559 tz->ops->get_trip_temp(tz, i, &temp);
560 temp /= MCELSIUS;
561 threshold_code = temp_to_code(data, temp);
562
563 rising_threshold = readl(data->base + rising_reg_offset);
8bfc218d 564 rising_threshold &= ~(0xff << j * 8);
488c7455
CC
565 rising_threshold |= (threshold_code << j * 8);
566 writel(rising_threshold, data->base + rising_reg_offset);
567
568 /* Write temperature code for falling threshold */
569 tz->ops->get_trip_hyst(tz, i, &temp_hist);
570 temp_hist = temp - (temp_hist / MCELSIUS);
571 threshold_code = temp_to_code(data, temp_hist);
572
573 falling_threshold = readl(data->base + falling_reg_offset);
574 falling_threshold &= ~(0xff << j * 8);
575 falling_threshold |= (threshold_code << j * 8);
576 writel(falling_threshold, data->base + falling_reg_offset);
577 }
578
579 data->tmu_clear_irqs(data);
97b3881b 580
488c7455
CC
581 return ret;
582}
583
6c247393
AK
584static int exynos7_tmu_initialize(struct platform_device *pdev)
585{
586 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
587 struct thermal_zone_device *tz = data->tzd;
97b3881b 588 unsigned int trim_info;
6c247393
AK
589 unsigned int rising_threshold = 0, falling_threshold = 0;
590 int ret = 0, threshold_code, i;
17e8351a 591 int temp, temp_hist;
6c247393
AK
592 unsigned int reg_off, bit_off;
593
6c247393 594 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
aef27b65 595 sanitize_temp_error(data, trim_info);
6c247393
AK
596
597 /* Write temperature code for rising and falling threshold */
598 for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) {
599 /*
600 * On exynos7 there are 4 rising and 4 falling threshold
601 * registers (0x50-0x5c and 0x60-0x6c respectively). Each
602 * register holds the value of two threshold levels (at bit
603 * offsets 0 and 16). Based on the fact that there are atmost
604 * eight possible trigger levels, calculate the register and
605 * bit offsets where the threshold levels are to be written.
606 *
607 * e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50)
608 * [24:16] - Threshold level 7
609 * [8:0] - Threshold level 6
610 * e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54)
611 * [24:16] - Threshold level 5
612 * [8:0] - Threshold level 4
613 *
614 * and similarly for falling thresholds.
615 *
616 * Based on the above, calculate the register and bit offsets
617 * for rising/falling threshold levels and populate them.
618 */
619 reg_off = ((7 - i) / 2) * 4;
620 bit_off = ((8 - i) % 2);
621
622 tz->ops->get_trip_temp(tz, i, &temp);
623 temp /= MCELSIUS;
624
625 tz->ops->get_trip_hyst(tz, i, &temp_hist);
626 temp_hist = temp - (temp_hist / MCELSIUS);
627
628 /* Set 9-bit temperature code for rising threshold levels */
629 threshold_code = temp_to_code(data, temp);
630 rising_threshold = readl(data->base +
631 EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
632 rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
633 rising_threshold |= threshold_code << (16 * bit_off);
634 writel(rising_threshold,
635 data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
636
637 /* Set 9-bit temperature code for falling threshold levels */
638 threshold_code = temp_to_code(data, temp_hist);
639 falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
640 falling_threshold |= threshold_code << (16 * bit_off);
641 writel(falling_threshold,
642 data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
643 }
644
645 data->tmu_clear_irqs(data);
97b3881b 646
6c247393
AK
647 return ret;
648}
649
37f9034f 650static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
bffd1f8a 651{
37f9034f 652 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
3b6a1a80 653 struct thermal_zone_device *tz = data->tzd;
37f9034f 654 unsigned int con, interrupt_en;
bffd1f8a 655
37f9034f 656 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
bffd1f8a 657
37f9034f
BZ
658 if (on) {
659 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
660 interrupt_en =
3b6a1a80
LM
661 (of_thermal_is_trip_valid(tz, 3)
662 << EXYNOS_TMU_INTEN_RISE3_SHIFT) |
663 (of_thermal_is_trip_valid(tz, 2)
664 << EXYNOS_TMU_INTEN_RISE2_SHIFT) |
665 (of_thermal_is_trip_valid(tz, 1)
666 << EXYNOS_TMU_INTEN_RISE1_SHIFT) |
667 (of_thermal_is_trip_valid(tz, 0)
668 << EXYNOS_TMU_INTEN_RISE0_SHIFT);
669
e0761533 670 if (data->soc != SOC_ARCH_EXYNOS4210)
37f9034f
BZ
671 interrupt_en |=
672 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
673 } else {
674 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
675 interrupt_en = 0; /* Disable all interrupts */
676 }
677 writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
678 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
679}
680
488c7455
CC
681static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
682{
683 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
684 struct thermal_zone_device *tz = data->tzd;
685 unsigned int con, interrupt_en, pd_det_en;
686
687 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
688
689 if (on) {
690 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
691 interrupt_en =
692 (of_thermal_is_trip_valid(tz, 7)
693 << EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
694 (of_thermal_is_trip_valid(tz, 6)
695 << EXYNOS7_TMU_INTEN_RISE6_SHIFT) |
696 (of_thermal_is_trip_valid(tz, 5)
697 << EXYNOS7_TMU_INTEN_RISE5_SHIFT) |
698 (of_thermal_is_trip_valid(tz, 4)
699 << EXYNOS7_TMU_INTEN_RISE4_SHIFT) |
700 (of_thermal_is_trip_valid(tz, 3)
701 << EXYNOS7_TMU_INTEN_RISE3_SHIFT) |
702 (of_thermal_is_trip_valid(tz, 2)
703 << EXYNOS7_TMU_INTEN_RISE2_SHIFT) |
704 (of_thermal_is_trip_valid(tz, 1)
705 << EXYNOS7_TMU_INTEN_RISE1_SHIFT) |
706 (of_thermal_is_trip_valid(tz, 0)
707 << EXYNOS7_TMU_INTEN_RISE0_SHIFT);
708
709 interrupt_en |=
710 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
711 } else {
712 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
713 interrupt_en = 0; /* Disable all interrupts */
714 }
715
716 pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0;
717
718 writel(pd_det_en, data->base + EXYNOS5433_TMU_PD_DET_EN);
719 writel(interrupt_en, data->base + EXYNOS5433_TMU_REG_INTEN);
720 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
721}
722
6c247393
AK
723static void exynos7_tmu_control(struct platform_device *pdev, bool on)
724{
725 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
726 struct thermal_zone_device *tz = data->tzd;
727 unsigned int con, interrupt_en;
728
729 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
730
731 if (on) {
732 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
42b696e8 733 con |= (1 << EXYNOS7_PD_DET_EN_SHIFT);
6c247393
AK
734 interrupt_en =
735 (of_thermal_is_trip_valid(tz, 7)
736 << EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
737 (of_thermal_is_trip_valid(tz, 6)
738 << EXYNOS7_TMU_INTEN_RISE6_SHIFT) |
739 (of_thermal_is_trip_valid(tz, 5)
740 << EXYNOS7_TMU_INTEN_RISE5_SHIFT) |
741 (of_thermal_is_trip_valid(tz, 4)
742 << EXYNOS7_TMU_INTEN_RISE4_SHIFT) |
743 (of_thermal_is_trip_valid(tz, 3)
744 << EXYNOS7_TMU_INTEN_RISE3_SHIFT) |
745 (of_thermal_is_trip_valid(tz, 2)
746 << EXYNOS7_TMU_INTEN_RISE2_SHIFT) |
747 (of_thermal_is_trip_valid(tz, 1)
748 << EXYNOS7_TMU_INTEN_RISE1_SHIFT) |
749 (of_thermal_is_trip_valid(tz, 0)
750 << EXYNOS7_TMU_INTEN_RISE0_SHIFT);
751
752 interrupt_en |=
753 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
754 } else {
755 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
42b696e8 756 con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT);
6c247393
AK
757 interrupt_en = 0; /* Disable all interrupts */
758 }
6c247393
AK
759
760 writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
761 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
762}
763
17e8351a 764static int exynos_get_temp(void *p, int *temp)
9d97e5c8 765{
3b6a1a80 766 struct exynos_tmu_data *data = p;
08d725cd 767 int value, ret = 0;
3b6a1a80 768
0eb875d8 769 if (!data || !data->tmu_read || !data->enabled)
3b6a1a80 770 return -EINVAL;
bffd1f8a
ADK
771
772 mutex_lock(&data->lock);
773 clk_enable(data->clk);
3b6a1a80 774
08d725cd
MS
775 value = data->tmu_read(data);
776 if (value < 0)
777 ret = value;
778 else
779 *temp = code_to_temp(data, value) * MCELSIUS;
3b6a1a80 780
9d97e5c8
DK
781 clk_disable(data->clk);
782 mutex_unlock(&data->lock);
bffd1f8a 783
08d725cd 784 return ret;
9d97e5c8 785}
bffd1f8a 786
bffd1f8a 787#ifdef CONFIG_THERMAL_EMULATION
154013ea 788static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
17e8351a 789 int temp)
154013ea 790{
bffd1f8a
ADK
791 if (temp) {
792 temp /= MCELSIUS;
793
8014220d
KK
794 val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
795 val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
6c247393
AK
796 if (data->soc == SOC_ARCH_EXYNOS7) {
797 val &= ~(EXYNOS7_EMUL_DATA_MASK <<
798 EXYNOS7_EMUL_DATA_SHIFT);
799 val |= (temp_to_code(data, temp) <<
800 EXYNOS7_EMUL_DATA_SHIFT) |
801 EXYNOS_EMUL_ENABLE;
802 } else {
803 val &= ~(EXYNOS_EMUL_DATA_MASK <<
804 EXYNOS_EMUL_DATA_SHIFT);
805 val |= (temp_to_code(data, temp) <<
806 EXYNOS_EMUL_DATA_SHIFT) |
807 EXYNOS_EMUL_ENABLE;
808 }
bffd1f8a 809 } else {
b8d582b9 810 val &= ~EXYNOS_EMUL_ENABLE;
bffd1f8a
ADK
811 }
812
154013ea
BZ
813 return val;
814}
815
285d994a 816static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
17e8351a 817 int temp)
285d994a
BZ
818{
819 unsigned int val;
820 u32 emul_con;
821
822 if (data->soc == SOC_ARCH_EXYNOS5260)
823 emul_con = EXYNOS5260_EMUL_CON;
b28fec13 824 else if (data->soc == SOC_ARCH_EXYNOS5433)
488c7455 825 emul_con = EXYNOS5433_TMU_EMUL_CON;
6c247393
AK
826 else if (data->soc == SOC_ARCH_EXYNOS7)
827 emul_con = EXYNOS7_TMU_REG_EMUL_CON;
285d994a
BZ
828 else
829 emul_con = EXYNOS_EMUL_CON;
830
831 val = readl(data->base + emul_con);
832 val = get_emul_con_reg(data, val, temp);
833 writel(val, data->base + emul_con);
834}
835
17e8351a 836static int exynos_tmu_set_emulation(void *drv_data, int temp)
bffd1f8a
ADK
837{
838 struct exynos_tmu_data *data = drv_data;
bffd1f8a
ADK
839 int ret = -EINVAL;
840
ef3f80fc 841 if (data->soc == SOC_ARCH_EXYNOS4210)
bffd1f8a 842 goto out;
bffd1f8a 843
bffd1f8a
ADK
844 if (temp && temp < MCELSIUS)
845 goto out;
846
847 mutex_lock(&data->lock);
848 clk_enable(data->clk);
285d994a 849 data->tmu_set_emulation(data, temp);
bffd1f8a
ADK
850 clk_disable(data->clk);
851 mutex_unlock(&data->lock);
852 return 0;
853out:
854 return ret;
855}
856#else
285d994a 857#define exynos4412_tmu_set_emulation NULL
17e8351a 858static int exynos_tmu_set_emulation(void *drv_data, int temp)
bffd1f8a 859 { return -EINVAL; }
afae1442 860#endif /* CONFIG_THERMAL_EMULATION */
bffd1f8a 861
b79985ca
BZ
862static int exynos4210_tmu_read(struct exynos_tmu_data *data)
863{
864 int ret = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
865
866 /* "temp_code" should range between 75 and 175 */
867 return (ret < 75 || ret > 175) ? -ENODATA : ret;
868}
869
870static int exynos4412_tmu_read(struct exynos_tmu_data *data)
871{
872 return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
873}
874
6c247393
AK
875static int exynos7_tmu_read(struct exynos_tmu_data *data)
876{
877 return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) &
878 EXYNOS7_TMU_TEMP_MASK;
879}
880
f22d9c03 881static void exynos_tmu_work(struct work_struct *work)
9d97e5c8 882{
f22d9c03
ADK
883 struct exynos_tmu_data *data = container_of(work,
884 struct exynos_tmu_data, irq_work);
a0395eee 885
14a11dc7
NKC
886 if (!IS_ERR(data->clk_sec))
887 clk_enable(data->clk_sec);
14a11dc7
NKC
888 if (!IS_ERR(data->clk_sec))
889 clk_disable(data->clk_sec);
9d97e5c8 890
3b6a1a80 891 exynos_report_trigger(data);
9d97e5c8
DK
892 mutex_lock(&data->lock);
893 clk_enable(data->clk);
b8d582b9 894
a4463c4f 895 /* TODO: take action based on particular interrupt */
a7331f72 896 data->tmu_clear_irqs(data);
b8d582b9 897
9d97e5c8
DK
898 clk_disable(data->clk);
899 mutex_unlock(&data->lock);
f22d9c03 900 enable_irq(data->irq);
9d97e5c8
DK
901}
902
a7331f72
BZ
903static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
904{
905 unsigned int val_irq;
906 u32 tmu_intstat, tmu_intclear;
907
908 if (data->soc == SOC_ARCH_EXYNOS5260) {
909 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
910 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
6c247393
AK
911 } else if (data->soc == SOC_ARCH_EXYNOS7) {
912 tmu_intstat = EXYNOS7_TMU_REG_INTPEND;
913 tmu_intclear = EXYNOS7_TMU_REG_INTPEND;
488c7455
CC
914 } else if (data->soc == SOC_ARCH_EXYNOS5433) {
915 tmu_intstat = EXYNOS5433_TMU_REG_INTPEND;
916 tmu_intclear = EXYNOS5433_TMU_REG_INTPEND;
a7331f72
BZ
917 } else {
918 tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
919 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
920 }
921
922 val_irq = readl(data->base + tmu_intstat);
923 /*
924 * Clear the interrupts. Please note that the documentation for
925 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
926 * states that INTCLEAR register has a different placing of bits
927 * responsible for FALL IRQs than INTSTAT register. Exynos5420
928 * and Exynos5440 documentation is correct (Exynos4210 doesn't
929 * support FALL IRQs at all).
930 */
931 writel(val_irq, data->base + tmu_intclear);
932}
933
f22d9c03 934static irqreturn_t exynos_tmu_irq(int irq, void *id)
9d97e5c8 935{
f22d9c03 936 struct exynos_tmu_data *data = id;
9d97e5c8
DK
937
938 disable_irq_nosync(irq);
939 schedule_work(&data->irq_work);
940
941 return IRQ_HANDLED;
942}
17be868e 943
17be868e 944static const struct of_device_id exynos_tmu_match[] = {
fee88e2b
MP
945 {
946 .compatible = "samsung,exynos3250-tmu",
947 .data = (const void *)SOC_ARCH_EXYNOS3250,
948 }, {
949 .compatible = "samsung,exynos4210-tmu",
950 .data = (const void *)SOC_ARCH_EXYNOS4210,
951 }, {
952 .compatible = "samsung,exynos4412-tmu",
953 .data = (const void *)SOC_ARCH_EXYNOS4412,
954 }, {
955 .compatible = "samsung,exynos5250-tmu",
956 .data = (const void *)SOC_ARCH_EXYNOS5250,
957 }, {
958 .compatible = "samsung,exynos5260-tmu",
959 .data = (const void *)SOC_ARCH_EXYNOS5260,
960 }, {
961 .compatible = "samsung,exynos5420-tmu",
962 .data = (const void *)SOC_ARCH_EXYNOS5420,
963 }, {
964 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
965 .data = (const void *)SOC_ARCH_EXYNOS5420_TRIMINFO,
966 }, {
967 .compatible = "samsung,exynos5433-tmu",
968 .data = (const void *)SOC_ARCH_EXYNOS5433,
fee88e2b
MP
969 }, {
970 .compatible = "samsung,exynos7-tmu",
971 .data = (const void *)SOC_ARCH_EXYNOS7,
972 },
973 { },
17be868e
ADK
974};
975MODULE_DEVICE_TABLE(of, exynos_tmu_match);
17be868e 976
cebe7373 977static int exynos_map_dt_data(struct platform_device *pdev)
9d97e5c8 978{
cebe7373 979 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
cebe7373
ADK
980 struct resource res;
981
73b5b1d7 982 if (!data || !pdev->dev.of_node)
cebe7373 983 return -ENODEV;
9d97e5c8 984
cebe7373
ADK
985 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
986 if (data->id < 0)
987 data->id = 0;
17be868e 988
cebe7373
ADK
989 data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
990 if (data->irq <= 0) {
991 dev_err(&pdev->dev, "failed to get IRQ\n");
992 return -ENODEV;
993 }
994
995 if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
996 dev_err(&pdev->dev, "failed to get Resource 0\n");
997 return -ENODEV;
998 }
999
1000 data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
1001 if (!data->base) {
1002 dev_err(&pdev->dev, "Failed to ioremap memory\n");
1003 return -EADDRNOTAVAIL;
1004 }
1005
fee88e2b 1006 data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev);
56adb9ef
BZ
1007
1008 switch (data->soc) {
1009 case SOC_ARCH_EXYNOS4210:
1010 data->tmu_initialize = exynos4210_tmu_initialize;
1011 data->tmu_control = exynos4210_tmu_control;
1012 data->tmu_read = exynos4210_tmu_read;
1013 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
3a3a5f15 1014 data->ntrip = 4;
fccfe099 1015 data->gain = 15;
61020d18 1016 data->reference_voltage = 7;
e3ed3649
BZ
1017 data->efuse_value = 55;
1018 data->min_efuse_value = 40;
1019 data->max_efuse_value = 100;
56adb9ef
BZ
1020 break;
1021 case SOC_ARCH_EXYNOS3250:
1022 case SOC_ARCH_EXYNOS4412:
1023 case SOC_ARCH_EXYNOS5250:
1024 case SOC_ARCH_EXYNOS5260:
1025 case SOC_ARCH_EXYNOS5420:
1026 case SOC_ARCH_EXYNOS5420_TRIMINFO:
1027 data->tmu_initialize = exynos4412_tmu_initialize;
1028 data->tmu_control = exynos4210_tmu_control;
1029 data->tmu_read = exynos4412_tmu_read;
1030 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
1031 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
3a3a5f15 1032 data->ntrip = 4;
fccfe099 1033 data->gain = 8;
61020d18 1034 data->reference_voltage = 16;
e3ed3649
BZ
1035 data->efuse_value = 55;
1036 if (data->soc != SOC_ARCH_EXYNOS5420 &&
1037 data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
1038 data->min_efuse_value = 40;
1039 else
1040 data->min_efuse_value = 0;
1041 data->max_efuse_value = 100;
56adb9ef 1042 break;
488c7455
CC
1043 case SOC_ARCH_EXYNOS5433:
1044 data->tmu_initialize = exynos5433_tmu_initialize;
1045 data->tmu_control = exynos5433_tmu_control;
1046 data->tmu_read = exynos4412_tmu_read;
1047 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
1048 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
3a3a5f15 1049 data->ntrip = 8;
fccfe099 1050 data->gain = 8;
61020d18
BZ
1051 if (res.start == EXYNOS5433_G3D_BASE)
1052 data->reference_voltage = 23;
1053 else
1054 data->reference_voltage = 16;
e3ed3649
BZ
1055 data->efuse_value = 75;
1056 data->min_efuse_value = 40;
1057 data->max_efuse_value = 150;
488c7455 1058 break;
6c247393
AK
1059 case SOC_ARCH_EXYNOS7:
1060 data->tmu_initialize = exynos7_tmu_initialize;
1061 data->tmu_control = exynos7_tmu_control;
1062 data->tmu_read = exynos7_tmu_read;
1063 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
1064 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
3a3a5f15 1065 data->ntrip = 8;
fccfe099 1066 data->gain = 9;
61020d18 1067 data->reference_voltage = 17;
e3ed3649
BZ
1068 data->efuse_value = 75;
1069 data->min_efuse_value = 15;
1070 data->max_efuse_value = 100;
6c247393 1071 break;
56adb9ef
BZ
1072 default:
1073 dev_err(&pdev->dev, "Platform not supported\n");
1074 return -EINVAL;
1075 }
1076
199b3e3c
BZ
1077 data->cal_type = TYPE_ONE_POINT_TRIMMING;
1078
d9b6ee14
ADK
1079 /*
1080 * Check if the TMU shares some registers and then try to map the
1081 * memory of common registers.
1082 */
8014220d 1083 if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
d9b6ee14
ADK
1084 return 0;
1085
1086 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
1087 dev_err(&pdev->dev, "failed to get Resource 1\n");
1088 return -ENODEV;
1089 }
1090
9025d563 1091 data->base_second = devm_ioremap(&pdev->dev, res.start,
d9b6ee14 1092 resource_size(&res));
9025d563 1093 if (!data->base_second) {
d9b6ee14
ADK
1094 dev_err(&pdev->dev, "Failed to ioremap memory\n");
1095 return -ENOMEM;
1096 }
cebe7373
ADK
1097
1098 return 0;
1099}
1100
c3c04d9d 1101static const struct thermal_zone_of_device_ops exynos_sensor_ops = {
3b6a1a80
LM
1102 .get_temp = exynos_get_temp,
1103 .set_emul_temp = exynos_tmu_set_emulation,
1104};
1105
cebe7373
ADK
1106static int exynos_tmu_probe(struct platform_device *pdev)
1107{
3b6a1a80
LM
1108 struct exynos_tmu_data *data;
1109 int ret;
cebe7373 1110
79e093c3
ADK
1111 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
1112 GFP_KERNEL);
2a9675b3 1113 if (!data)
9d97e5c8 1114 return -ENOMEM;
9d97e5c8 1115
cebe7373
ADK
1116 platform_set_drvdata(pdev, data);
1117 mutex_init(&data->lock);
9d97e5c8 1118
824ead03
KK
1119 /*
1120 * Try enabling the regulator if found
1121 * TODO: Add regulator as an SOC feature, so that regulator enable
1122 * is a compulsory call.
1123 */
4d3583cd 1124 data->regulator = devm_regulator_get_optional(&pdev->dev, "vtmu");
824ead03
KK
1125 if (!IS_ERR(data->regulator)) {
1126 ret = regulator_enable(data->regulator);
1127 if (ret) {
1128 dev_err(&pdev->dev, "failed to enable vtmu\n");
1129 return ret;
1130 }
1131 } else {
ccb361d2
JMC
1132 if (PTR_ERR(data->regulator) == -EPROBE_DEFER)
1133 return -EPROBE_DEFER;
824ead03 1134 dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
3b6a1a80 1135 }
824ead03 1136
cebe7373
ADK
1137 ret = exynos_map_dt_data(pdev);
1138 if (ret)
3b6a1a80 1139 goto err_sensor;
9d97e5c8 1140
cebe7373 1141 INIT_WORK(&data->irq_work, exynos_tmu_work);
9d97e5c8 1142
2a16279c 1143 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
9d97e5c8 1144 if (IS_ERR(data->clk)) {
9d97e5c8 1145 dev_err(&pdev->dev, "Failed to get clock\n");
3b6a1a80
LM
1146 ret = PTR_ERR(data->clk);
1147 goto err_sensor;
9d97e5c8
DK
1148 }
1149
14a11dc7
NKC
1150 data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
1151 if (IS_ERR(data->clk_sec)) {
1152 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
1153 dev_err(&pdev->dev, "Failed to get triminfo clock\n");
3b6a1a80
LM
1154 ret = PTR_ERR(data->clk_sec);
1155 goto err_sensor;
14a11dc7
NKC
1156 }
1157 } else {
1158 ret = clk_prepare(data->clk_sec);
1159 if (ret) {
1160 dev_err(&pdev->dev, "Failed to get clock\n");
3b6a1a80 1161 goto err_sensor;
14a11dc7
NKC
1162 }
1163 }
1164
2a16279c 1165 ret = clk_prepare(data->clk);
14a11dc7
NKC
1166 if (ret) {
1167 dev_err(&pdev->dev, "Failed to get clock\n");
1168 goto err_clk_sec;
1169 }
2a16279c 1170
488c7455
CC
1171 switch (data->soc) {
1172 case SOC_ARCH_EXYNOS5433:
1173 case SOC_ARCH_EXYNOS7:
6c247393
AK
1174 data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
1175 if (IS_ERR(data->sclk)) {
1176 dev_err(&pdev->dev, "Failed to get sclk\n");
1177 goto err_clk;
1178 } else {
1179 ret = clk_prepare_enable(data->sclk);
1180 if (ret) {
1181 dev_err(&pdev->dev, "Failed to enable sclk\n");
1182 goto err_clk;
1183 }
1184 }
488c7455
CC
1185 break;
1186 default:
1187 break;
baba1ebb 1188 }
6c247393 1189
9e4249b4
KK
1190 /*
1191 * data->tzd must be registered before calling exynos_tmu_initialize(),
1192 * requesting irq and calling exynos_tmu_control().
1193 */
1194 data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
1195 &exynos_sensor_ops);
1196 if (IS_ERR(data->tzd)) {
1197 ret = PTR_ERR(data->tzd);
1198 dev_err(&pdev->dev, "Failed to register sensor: %d\n", ret);
1199 goto err_sclk;
1200 }
6c247393 1201
f22d9c03 1202 ret = exynos_tmu_initialize(pdev);
9d97e5c8
DK
1203 if (ret) {
1204 dev_err(&pdev->dev, "Failed to initialize TMU\n");
9e4249b4 1205 goto err_thermal;
9d97e5c8
DK
1206 }
1207
cebe7373
ADK
1208 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
1209 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
1210 if (ret) {
1211 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
9e4249b4 1212 goto err_thermal;
cebe7373 1213 }
bbf63be4 1214
3b6a1a80 1215 exynos_tmu_control(pdev, true);
9d97e5c8 1216 return 0;
9e4249b4
KK
1217
1218err_thermal:
1219 thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
6c247393
AK
1220err_sclk:
1221 clk_disable_unprepare(data->sclk);
9d97e5c8 1222err_clk:
2a16279c 1223 clk_unprepare(data->clk);
14a11dc7
NKC
1224err_clk_sec:
1225 if (!IS_ERR(data->clk_sec))
1226 clk_unprepare(data->clk_sec);
3b6a1a80 1227err_sensor:
bfa26838 1228 if (!IS_ERR(data->regulator))
5f09a5cb 1229 regulator_disable(data->regulator);
3b6a1a80 1230
9d97e5c8
DK
1231 return ret;
1232}
1233
4eab7a9e 1234static int exynos_tmu_remove(struct platform_device *pdev)
9d97e5c8 1235{
f22d9c03 1236 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
3b6a1a80 1237 struct thermal_zone_device *tzd = data->tzd;
9d97e5c8 1238
3b6a1a80 1239 thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
4215688e
BZ
1240 exynos_tmu_control(pdev, false);
1241
6c247393 1242 clk_disable_unprepare(data->sclk);
2a16279c 1243 clk_unprepare(data->clk);
14a11dc7
NKC
1244 if (!IS_ERR(data->clk_sec))
1245 clk_unprepare(data->clk_sec);
9d97e5c8 1246
498d22f6
ADK
1247 if (!IS_ERR(data->regulator))
1248 regulator_disable(data->regulator);
1249
9d97e5c8
DK
1250 return 0;
1251}
1252
08cd6753 1253#ifdef CONFIG_PM_SLEEP
f22d9c03 1254static int exynos_tmu_suspend(struct device *dev)
9d97e5c8 1255{
f22d9c03 1256 exynos_tmu_control(to_platform_device(dev), false);
9d97e5c8
DK
1257
1258 return 0;
1259}
1260
f22d9c03 1261static int exynos_tmu_resume(struct device *dev)
9d97e5c8 1262{
08cd6753
RW
1263 struct platform_device *pdev = to_platform_device(dev);
1264
f22d9c03
ADK
1265 exynos_tmu_initialize(pdev);
1266 exynos_tmu_control(pdev, true);
9d97e5c8
DK
1267
1268 return 0;
1269}
08cd6753 1270
f22d9c03
ADK
1271static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
1272 exynos_tmu_suspend, exynos_tmu_resume);
1273#define EXYNOS_TMU_PM (&exynos_tmu_pm)
9d97e5c8 1274#else
f22d9c03 1275#define EXYNOS_TMU_PM NULL
9d97e5c8
DK
1276#endif
1277
f22d9c03 1278static struct platform_driver exynos_tmu_driver = {
9d97e5c8 1279 .driver = {
f22d9c03 1280 .name = "exynos-tmu",
f22d9c03 1281 .pm = EXYNOS_TMU_PM,
73b5b1d7 1282 .of_match_table = exynos_tmu_match,
9d97e5c8 1283 },
f22d9c03 1284 .probe = exynos_tmu_probe,
4eab7a9e 1285 .remove = exynos_tmu_remove,
9d97e5c8
DK
1286};
1287
f22d9c03 1288module_platform_driver(exynos_tmu_driver);
9d97e5c8 1289
f22d9c03 1290MODULE_DESCRIPTION("EXYNOS TMU Driver");
9d97e5c8
DK
1291MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
1292MODULE_LICENSE("GPL");
f22d9c03 1293MODULE_ALIAS("platform:exynos-tmu");