5
5
* Author: Anson Huang <[email protected] >
6
6
*/
7
7
8
+ #include <linux/bitfield.h>
8
9
#include <linux/clk.h>
9
10
#include <linux/err.h>
10
11
#include <linux/io.h>
11
12
#include <linux/module.h>
12
13
#include <linux/of.h>
13
- #include <linux/of_address .h>
14
+ #include <linux/of_device .h>
14
15
#include <linux/platform_device.h>
15
16
#include <linux/thermal.h>
16
17
17
18
#include "thermal_core.h"
18
19
19
20
#define TER 0x0 /* TMU enable */
21
+ #define TPS 0x4
20
22
#define TRITSR 0x20 /* TMU immediate temp */
21
23
22
24
#define TER_EN BIT(31)
23
- #define TRITSR_VAL_MASK 0xff
25
+ #define TRITSR_TEMP0_VAL_MASK 0xff
26
+ #define TRITSR_TEMP1_VAL_MASK 0xff0000
24
27
25
- #define TEMP_LOW_LIMIT 10
28
+ #define PROBE_SEL_ALL GENMASK(31, 30)
26
29
27
- struct imx8mm_tmu {
30
+ #define probe_status_offset (x ) (30 + x)
31
+ #define SIGN_BIT BIT(7)
32
+ #define TEMP_VAL_MASK GENMASK(6, 0)
33
+
34
+ #define VER1_TEMP_LOW_LIMIT 10000
35
+ #define VER2_TEMP_LOW_LIMIT -40000
36
+ #define VER2_TEMP_HIGH_LIMIT 125000
37
+
38
+ #define TMU_VER1 0x1
39
+ #define TMU_VER2 0x2
40
+
41
+ struct thermal_soc_data {
42
+ u32 num_sensors ;
43
+ u32 version ;
44
+ int (* get_temp )(void * , int * );
45
+ };
46
+
47
+ struct tmu_sensor {
48
+ struct imx8mm_tmu * priv ;
49
+ u32 hw_id ;
28
50
struct thermal_zone_device * tzd ;
51
+ };
52
+
53
+ struct imx8mm_tmu {
29
54
void __iomem * base ;
30
55
struct clk * clk ;
56
+ const struct thermal_soc_data * socdata ;
57
+ struct tmu_sensor sensors [0 ];
31
58
};
32
59
33
- static int tmu_get_temp (void * data , int * temp )
60
+ static int imx8mm_tmu_get_temp (void * data , int * temp )
34
61
{
35
- struct imx8mm_tmu * tmu = data ;
62
+ struct tmu_sensor * sensor = data ;
63
+ struct imx8mm_tmu * tmu = sensor -> priv ;
36
64
u32 val ;
37
65
38
- val = readl_relaxed (tmu -> base + TRITSR ) & TRITSR_VAL_MASK ;
39
- if (val < TEMP_LOW_LIMIT )
66
+ val = readl_relaxed (tmu -> base + TRITSR ) & TRITSR_TEMP0_VAL_MASK ;
67
+ * temp = val * 1000 ;
68
+ if (* temp < VER1_TEMP_LOW_LIMIT )
40
69
return - EAGAIN ;
41
70
71
+ return 0 ;
72
+ }
73
+
74
+ static int imx8mp_tmu_get_temp (void * data , int * temp )
75
+ {
76
+ struct tmu_sensor * sensor = data ;
77
+ struct imx8mm_tmu * tmu = sensor -> priv ;
78
+ bool ready ;
79
+ u32 val ;
80
+
81
+ ready = test_bit (probe_status_offset (sensor -> hw_id ),
82
+ tmu -> base + TRITSR );
83
+ if (!ready )
84
+ return - EAGAIN ;
85
+
86
+ val = readl_relaxed (tmu -> base + TRITSR );
87
+ val = sensor -> hw_id ? FIELD_GET (TRITSR_TEMP1_VAL_MASK , val ) :
88
+ FIELD_GET (TRITSR_TEMP0_VAL_MASK , val );
89
+ if (val & SIGN_BIT ) /* negative */
90
+ val = (~(val & TEMP_VAL_MASK ) + 1 );
91
+
42
92
* temp = val * 1000 ;
93
+ if (* temp < VER2_TEMP_LOW_LIMIT || * temp > VER2_TEMP_HIGH_LIMIT )
94
+ return - EAGAIN ;
43
95
44
96
return 0 ;
45
97
}
46
98
99
+ static int tmu_get_temp (void * data , int * temp )
100
+ {
101
+ struct tmu_sensor * sensor = data ;
102
+ struct imx8mm_tmu * tmu = sensor -> priv ;
103
+
104
+ return tmu -> socdata -> get_temp (data , temp );
105
+ }
106
+
47
107
static struct thermal_zone_of_device_ops tmu_tz_ops = {
48
108
.get_temp = tmu_get_temp ,
49
109
};
50
110
111
+ static void imx8mm_tmu_enable (struct imx8mm_tmu * tmu , bool enable )
112
+ {
113
+ u32 val ;
114
+
115
+ val = readl_relaxed (tmu -> base + TER );
116
+ val = enable ? (val | TER_EN ) : (val & ~TER_EN );
117
+ writel_relaxed (val , tmu -> base + TER );
118
+ }
119
+
120
+ static void imx8mm_tmu_probe_sel_all (struct imx8mm_tmu * tmu )
121
+ {
122
+ u32 val ;
123
+
124
+ val = readl_relaxed (tmu -> base + TPS );
125
+ val |= PROBE_SEL_ALL ;
126
+ writel_relaxed (val , tmu -> base + TPS );
127
+ }
128
+
51
129
static int imx8mm_tmu_probe (struct platform_device * pdev )
52
130
{
131
+ const struct thermal_soc_data * data ;
53
132
struct imx8mm_tmu * tmu ;
54
- u32 val ;
55
133
int ret ;
134
+ int i ;
135
+
136
+ data = of_device_get_match_data (& pdev -> dev );
56
137
57
- tmu = devm_kzalloc (& pdev -> dev , sizeof (struct imx8mm_tmu ), GFP_KERNEL );
138
+ tmu = devm_kzalloc (& pdev -> dev , struct_size (tmu , sensors ,
139
+ data -> num_sensors ), GFP_KERNEL );
58
140
if (!tmu )
59
141
return - ENOMEM ;
60
142
143
+ tmu -> socdata = data ;
144
+
61
145
tmu -> base = devm_platform_ioremap_resource (pdev , 0 );
62
146
if (IS_ERR (tmu -> base ))
63
147
return PTR_ERR (tmu -> base );
@@ -77,42 +161,64 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
77
161
return ret ;
78
162
}
79
163
80
- tmu -> tzd = devm_thermal_zone_of_sensor_register (& pdev -> dev , 0 ,
81
- tmu , & tmu_tz_ops );
82
- if (IS_ERR (tmu -> tzd )) {
83
- dev_err (& pdev -> dev ,
84
- "failed to register thermal zone sensor: %d\n" , ret );
85
- return PTR_ERR (tmu -> tzd );
164
+ /* disable the monitor during initialization */
165
+ imx8mm_tmu_enable (tmu , false);
166
+
167
+ for (i = 0 ; i < data -> num_sensors ; i ++ ) {
168
+ tmu -> sensors [i ].priv = tmu ;
169
+ tmu -> sensors [i ].tzd =
170
+ devm_thermal_zone_of_sensor_register (& pdev -> dev , i ,
171
+ & tmu -> sensors [i ],
172
+ & tmu_tz_ops );
173
+ if (IS_ERR (tmu -> sensors [i ].tzd )) {
174
+ dev_err (& pdev -> dev ,
175
+ "failed to register thermal zone sensor[%d]: %d\n" ,
176
+ i , ret );
177
+ return PTR_ERR (tmu -> sensors [i ].tzd );
178
+ }
179
+ tmu -> sensors [i ].hw_id = i ;
86
180
}
87
181
88
182
platform_set_drvdata (pdev , tmu );
89
183
184
+ /* enable all the probes for V2 TMU */
185
+ if (tmu -> socdata -> version == TMU_VER2 )
186
+ imx8mm_tmu_probe_sel_all (tmu );
187
+
90
188
/* enable the monitor */
91
- val = readl_relaxed (tmu -> base + TER );
92
- val |= TER_EN ;
93
- writel_relaxed (val , tmu -> base + TER );
189
+ imx8mm_tmu_enable (tmu , true);
94
190
95
191
return 0 ;
96
192
}
97
193
98
194
static int imx8mm_tmu_remove (struct platform_device * pdev )
99
195
{
100
196
struct imx8mm_tmu * tmu = platform_get_drvdata (pdev );
101
- u32 val ;
102
197
103
198
/* disable TMU */
104
- val = readl_relaxed (tmu -> base + TER );
105
- val &= ~TER_EN ;
106
- writel_relaxed (val , tmu -> base + TER );
199
+ imx8mm_tmu_enable (tmu , false);
107
200
108
201
clk_disable_unprepare (tmu -> clk );
109
202
platform_set_drvdata (pdev , NULL );
110
203
111
204
return 0 ;
112
205
}
113
206
207
+ static struct thermal_soc_data imx8mm_tmu_data = {
208
+ .num_sensors = 1 ,
209
+ .version = TMU_VER1 ,
210
+ .get_temp = imx8mm_tmu_get_temp ,
211
+ };
212
+
213
+ static struct thermal_soc_data imx8mp_tmu_data = {
214
+ .num_sensors = 2 ,
215
+ .version = TMU_VER2 ,
216
+ .get_temp = imx8mp_tmu_get_temp ,
217
+ };
218
+
114
219
static const struct of_device_id imx8mm_tmu_table [] = {
115
- { .compatible = "fsl,imx8mm-tmu" , },
220
+ { .compatible = "fsl,imx8mm-tmu" , .data = & imx8mm_tmu_data , },
221
+ { .compatible = "fsl,imx8mp-tmu" , .data = & imx8mp_tmu_data , },
116
222
{ },
117
223
};
118
224
0 commit comments