2 * Copyright (C) 2018 Marvell International Ltd.
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
8 #include <common/debug.h>
9 #include <drivers/delay_timer.h>
10 #include <drivers/marvell/thermal.h>
13 #include <mvebu_def.h>
15 #define THERMAL_TIMEOUT 1200
17 #define THERMAL_SEN_CTRL_LSB_STRT_OFFSET 0
18 #define THERMAL_SEN_CTRL_LSB_STRT_MASK \
19 (0x1 << THERMAL_SEN_CTRL_LSB_STRT_OFFSET)
20 #define THERMAL_SEN_CTRL_LSB_RST_OFFSET 1
21 #define THERMAL_SEN_CTRL_LSB_RST_MASK \
22 (0x1 << THERMAL_SEN_CTRL_LSB_RST_OFFSET)
23 #define THERMAL_SEN_CTRL_LSB_EN_OFFSET 2
24 #define THERMAL_SEN_CTRL_LSB_EN_MASK \
25 (0x1 << THERMAL_SEN_CTRL_LSB_EN_OFFSET)
27 #define THERMAL_SEN_CTRL_STATS_VALID_OFFSET 16
28 #define THERMAL_SEN_CTRL_STATS_VALID_MASK \
29 (0x1 << THERMAL_SEN_CTRL_STATS_VALID_OFFSET)
30 #define THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET 0
31 #define THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK \
32 (0x3FF << THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET)
34 #define THERMAL_SEN_OUTPUT_MSB 512
35 #define THERMAL_SEN_OUTPUT_COMP 1024
38 uint32_t ext_tsen_ctrl_lsb
;
39 uint32_t ext_tsen_ctrl_msb
;
40 uint32_t ext_tsen_status
;
43 static int ext_tsen_probe(struct tsen_config
*tsen_cfg
)
45 uint32_t reg
, timeout
= 0;
46 struct tsen_regs
*base
;
48 if (tsen_cfg
== NULL
&& tsen_cfg
->regs_base
== NULL
) {
49 ERROR("initial thermal sensor configuration is missing\n");
52 base
= (struct tsen_regs
*)tsen_cfg
->regs_base
;
54 INFO("initializing thermal sensor\n");
56 /* initialize thermal sensor hardware reset once */
57 reg
= mmio_read_32((uintptr_t)&base
->ext_tsen_ctrl_lsb
);
58 reg
&= ~THERMAL_SEN_CTRL_LSB_RST_OFFSET
; /* de-assert TSEN_RESET */
59 reg
|= THERMAL_SEN_CTRL_LSB_EN_MASK
; /* set TSEN_EN to 1 */
60 reg
|= THERMAL_SEN_CTRL_LSB_STRT_MASK
; /* set TSEN_START to 1 */
61 mmio_write_32((uintptr_t)&base
->ext_tsen_ctrl_lsb
, reg
);
63 reg
= mmio_read_32((uintptr_t)&base
->ext_tsen_status
);
64 while ((reg
& THERMAL_SEN_CTRL_STATS_VALID_MASK
) == 0 &&
65 timeout
< THERMAL_TIMEOUT
) {
67 reg
= mmio_read_32((uintptr_t)&base
->ext_tsen_status
);
71 if ((reg
& THERMAL_SEN_CTRL_STATS_VALID_MASK
) == 0) {
72 ERROR("thermal sensor is not ready\n");
76 tsen_cfg
->tsen_ready
= 1;
78 VERBOSE("thermal sensor was initialized\n");
83 static int ext_tsen_read(struct tsen_config
*tsen_cfg
, int *temp
)
86 struct tsen_regs
*base
;
88 if (tsen_cfg
== NULL
&& !tsen_cfg
->tsen_ready
) {
89 ERROR("thermal sensor was not initialized\n");
92 base
= (struct tsen_regs
*)tsen_cfg
->regs_base
;
94 reg
= mmio_read_32((uintptr_t)&base
->ext_tsen_status
);
95 reg
= ((reg
& THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK
) >>
96 THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET
);
99 * TSEN output format is signed as a 2s complement number
100 * ranging from-512 to +511. when MSB is set, need to
101 * calculate the complement number
103 if (reg
>= THERMAL_SEN_OUTPUT_MSB
)
104 reg
-= THERMAL_SEN_OUTPUT_COMP
;
106 if (tsen_cfg
->tsen_divisor
== 0) {
107 ERROR("thermal sensor divisor cannot be zero\n");
111 *temp
= ((tsen_cfg
->tsen_gain
* ((int)reg
)) +
112 tsen_cfg
->tsen_offset
) / tsen_cfg
->tsen_divisor
;
117 static struct tsen_config tsen_cfg
= {
118 .tsen_offset
= 153400,
120 .tsen_divisor
= 1000,
122 .regs_base
= (void *)MVEBU_AP_EXT_TSEN_BASE
,
123 .ptr_tsen_probe
= ext_tsen_probe
,
124 .ptr_tsen_read
= ext_tsen_read
127 struct tsen_config
*marvell_thermal_config_get(void)