blob: 23c32b9593e5f68fe147cc2ce00247c813167e5c [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (C) 2018 MediaTek Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#include <asm/page.h>
14#include <linux/device.h>
15#include <linux/module.h>
16#include <linux/string.h>
17#include <linux/fs.h>
18#include <linux/kernel.h>
19#include <linux/syscalls.h>
20#include <linux/mm.h>
21/* #include <asm/uaccess.h> */
22#include <linux/uaccess.h>
23#include <linux/hrtimer.h>
24
25#include "met_drv.h"
26#include "trace.h"
27#include "core_plf_trace.h"
28#include "core_plf_init.h"
29
30/*define if the thermal sensor driver use its own timer to sampling the code , otherwise undefine it */
31/*define it is better for sampling jitter if thermal sensor driver supports */
32/* this define is phase out */
33/* #define MET_USE_THERMALDRIVER_TIMER */
34
35noinline void ms_th(const unsigned char cnt, unsigned int *value)
36{
37 char *SOB, *EOB;
38
39 MET_TRACE_GETBUF(&SOB, &EOB);
40 EOB = ms_formatD_EOL(EOB, cnt, value);
41 MET_TRACE_PUTBUF(SOB, EOB);
42}
43
44static unsigned int CheckAvailableThermalSensor(unsigned int a_u4DoCheck)
45{
46 static unsigned int u4AvailableSensor;
47
48 unsigned int u4Index;
49
50 if (!a_u4DoCheck)
51 return u4AvailableSensor;
52
53 /*Do check */
54 if (MTK_THERMAL_SENSOR_COUNT > 32)
55 return 0;
56
57 if (mtk_thermal_get_temp_symbol == NULL)
58 return 0;
59
60 u4AvailableSensor = 0;
61
62 for (u4Index = 0; u4Index < MTK_THERMAL_SENSOR_COUNT; u4Index++) {
63 if (mtk_thermal_get_temp_symbol(u4Index) == (-127000) || mtk_thermal_get_temp_symbol(u4Index) < 0)
64 u4AvailableSensor &= (~(1 << u4Index));
65 else
66 u4AvailableSensor |= (1 << u4Index);
67 }
68
69 return u4AvailableSensor;
70}
71
72static int do_thermal(void)
73{
74 static int do_thermal = -1;
75
76 if (do_thermal != -1)
77 return do_thermal;
78
79 if (met_thermal.mode == 0)
80 do_thermal = 0;
81 else
82 do_thermal = met_thermal.mode;
83 return do_thermal;
84}
85
86static unsigned int get_thermal(unsigned int *value)
87{
88 int j = -1;
89 int i;
90 unsigned int u4ValidSensors = 0;
91
92 /*Do check */
93 if (mtk_thermal_get_temp_symbol == NULL)
94 return 0;
95
96 u4ValidSensors = CheckAvailableThermalSensor(0);
97
98 for (i = 0; i < MTK_THERMAL_SENSOR_COUNT; i++) {
99 if (u4ValidSensors & (1 << i))
100 value[++j] = mtk_thermal_get_temp_symbol(i);
101 }
102
103 return j + 1;
104}
105
106static void wq_get_thermal(struct work_struct *work)
107{
108 unsigned char count = 0;
109 unsigned int thermal_value[MTK_THERMAL_SENSOR_COUNT]; /*Note here */
110
111 int cpu;
112
113 cpu = smp_processor_id();
114 if (do_thermal()) {
115 count = get_thermal(thermal_value);
116 if (count)
117 ms_th(count, thermal_value);
118 }
119}
120
121#ifdef MET_USE_THERMALDRIVER_TIMER
122
123static void thermal_start(void)
124{
125 CheckAvailableThermalSensor(1);
126 /* get extern symbol by symbol_get */
127 if (mt_thermalsampler_registerCB_symbol)
128 mt_thermalsampler_registerCB_symbol(wq_get_thermal);
129}
130
131static void thermal_stop(void)
132{
133 if (mt_thermalsampler_registerCB_symbol)
134 mt_thermalsampler_registerCB_symbol(NULL);
135}
136
137#else
138
139struct delayed_work dwork;
140static void thermal_start(void)
141{
142 CheckAvailableThermalSensor(1);
143 /*pr_debug("Thermal Sample:0x%x\n",CheckAvailableThermalSensor(0)); */
144 INIT_DELAYED_WORK(&dwork, wq_get_thermal);
145}
146
147static void thermal_stop(void)
148{
149 cancel_delayed_work_sync(&dwork);
150}
151
152static void thermal_polling(unsigned long long stamp, int cpu)
153{
154 schedule_delayed_work(&dwork, 0);
155}
156
157#endif
158
159static const char help[] = " --thermal monitor thermal\n";
160static int thermal_print_help(char *buf, int len)
161{
162 return snprintf(buf, PAGE_SIZE, help);
163}
164
165static const char g_pThermalHeader[] = "met-info [000] 0.0: thermal_header: ms_th";
166
167static int thermal_print_header(char *buf, int len)
168{
169 char buffer[256];
170 char ts_buf[8] = {0};
171 unsigned long u4Cnt = 0;
172 unsigned int u4ValidSensor = 0;
173 int i = 0, ts_sz = 0;
174
175 u4ValidSensor = CheckAvailableThermalSensor(0);
176
177 strncpy(buffer, g_pThermalHeader, 256 - 1);
178
179 ts_sz = sizeof(ts_buf);
180
181 for ( i = 0 ; i < MTK_THERMAL_SENSOR_COUNT ; i++) {
182 if ((1 << i) & u4ValidSensor) {
183 snprintf(ts_buf, ts_sz, ",tab_%d", (i + 1));
184 strncat(buffer, ts_buf, 256 - 1);
185 u4Cnt += 1;
186 }
187 memset(ts_buf, '\0', ts_sz);
188 }
189
190 strncat(buffer, "\n", 256 - 1);
191
192 return snprintf(buf, PAGE_SIZE, "%s", buffer);
193}
194
195struct metdevice met_thermal = {
196 .name = "thermal",
197 .owner = THIS_MODULE,
198 .type = MET_TYPE_BUS,
199 .cpu_related = 0,
200 .ondiemet_mode = 0,
201 .start = thermal_start,
202 .stop = thermal_stop,
203#ifdef MET_USE_THERMALDRIVER_TIMER
204#else
205 .polling_interval = 50, /* ms */
206 .timed_polling = thermal_polling,
207 .tagged_polling = thermal_polling,
208#endif
209 .print_help = thermal_print_help,
210 .print_header = thermal_print_header,
211};
212
213
214
215/*CPU sensors */
216static unsigned int CheckAvailableCPUThermalSensor(unsigned int a_u4DoCheck)
217{
218 static unsigned int u4AvailableSensor;
219
220 unsigned int u4Index;
221
222 if (tscpu_get_cpu_temp_met_symbol == NULL)
223 return 0;
224
225 if (!a_u4DoCheck)
226 return u4AvailableSensor;
227
228 u4AvailableSensor = 0;
229
230 for (u4Index = 0; u4Index < MTK_THERMAL_SENSOR_CPU_COUNT; u4Index++) {
231 if (u4Index == ATM_GPU_LIMIT)
232 continue;
233
234 if (tscpu_get_cpu_temp_met_symbol(u4Index) == (-127000) || tscpu_get_cpu_temp_met_symbol(u4Index) < 0)
235 u4AvailableSensor &= (~(1 << u4Index));
236 else
237 u4AvailableSensor |= (1 << u4Index);
238 }
239
240 return u4AvailableSensor;
241}
242
243noinline void CPUTS(void)
244{
245 unsigned int u4Index1 = 0, u4Index2 = 0;
246 unsigned int u4ValidSensors = 0;
247 int i4TSValue[MTK_THERMAL_SENSOR_CPU_COUNT];
248 int i = 0, len = 0, total_len = 0, sz;
249 char str_buff[128] = {0};
250
251 sz = sizeof(str_buff);
252
253 if (tscpu_get_cpu_temp_met_symbol == NULL)
254 return;
255
256 memset(i4TSValue, 0, sizeof(int) * MTK_THERMAL_SENSOR_CPU_COUNT);
257
258 u4ValidSensors = CheckAvailableCPUThermalSensor(0);
259
260 for (; u4Index1 < MTK_THERMAL_SENSOR_CPU_COUNT; u4Index1++) {
261 if (u4ValidSensors & (1 << u4Index1)) {
262 i4TSValue[u4Index2] = tscpu_get_cpu_temp_met_symbol(u4Index1);
263 u4Index2 += 1;
264 }
265 }
266
267 len = snprintf(str_buff + total_len, 8, "%d", i4TSValue[0]);
268 if (len >= 0 && len < sz)
269 total_len += len;
270
271 for (i = 1 ; i < u4Index2 ; i++) {
272 len = snprintf(str_buff + total_len, 8, ",%d", i4TSValue[i]);
273 if (len >= 0 && len < sz)
274 total_len += len;
275 }
276
277 MET_TRACE("%s\n", str_buff);
278}
279
280static void thermal_CPU_start(void)
281{
282 CheckAvailableCPUThermalSensor(1);
283
284 /* get extern symbol by symbol_get */
285 if (mt_thermalsampler_registerCB_symbol)
286 mt_thermalsampler_registerCB_symbol(CPUTS);
287}
288
289static void thermal_CPU_stop(void)
290{
291 /* release extern symbol by symbol_put */
292 if (mt_thermalsampler_registerCB_symbol)
293 mt_thermalsampler_registerCB_symbol(NULL);
294}
295
296static const char help_cpu[] = " --thermal-cpu monitor cpu temperature\n";
297static int thermal_CPU_print_help(char *buf, int len)
298{
299 return snprintf(buf, PAGE_SIZE, help_cpu);
300}
301
302static const char g_pCPUThermalHeader[] = "met-info [000] 0.0: thermal_cpu_header: CPUTS";
303
304static int thermal_CPU_print_header(char *buf, int len)
305{
306 char buffer[256];
307 char ts_buf[8] = {0} ;
308 unsigned long u4Cnt = 0;
309 unsigned int u4ValidSensor = 0;
310 int i = 0, ts_sz = 0;
311
312 u4ValidSensor = CheckAvailableCPUThermalSensor(0);
313
314 strncpy(buffer, g_pCPUThermalHeader, 256 - 1);
315
316 ts_sz = sizeof(ts_buf);
317
318 for ( i = 0 ; i < MTK_THERMAL_SENSOR_CPU_COUNT ; i++) {
319 if ((1 << i) & u4ValidSensor) {
320 snprintf(ts_buf, ts_sz, ",tab_%d", (i + 1));
321 strncat(buffer, ts_buf, 256 - 1);
322 u4Cnt += 1;
323 }
324 memset(ts_buf, '\0', ts_sz);
325 }
326
327 strncat(buffer, "\n", 256 - 1);
328
329 return snprintf(buf, PAGE_SIZE, "%s", buffer);
330}
331
332struct metdevice met_thermal_cpu = {
333 .name = "thermal-cpu",
334 .owner = THIS_MODULE,
335 .type = MET_TYPE_BUS,
336 .cpu_related = 0,
337 .start = thermal_CPU_start,
338 .stop = thermal_CPU_stop,
339 .print_help = thermal_CPU_print_help,
340 .print_header = thermal_CPU_print_header,
341 .ondiemet_mode = 0,
342};