xref: /OK3568_Linux_fs/kernel/drivers/thermal/rk_virtual_thermal.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * rk virtual tsadc driver
3  *
4  * Copyright (C) 2017 Rockchip Electronics Co., Ltd
5  * Author: Rocky Hao <rocky.hao@rock-chips.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17 
18 #include <linux/clk.h>
19 #include <linux/module.h>
20 #include <linux/of.h>
21 #include <linux/of_address.h>
22 #include <linux/platform_device.h>
23 #include <linux/thermal.h>
24 #include <linux/timer.h>
25 #include <linux/nvmem-consumer.h>
26 #include <linux/backlight.h>
27 #include <linux/cpufreq.h>
28 #include <linux/power_supply.h>
29 #include <linux/clk-provider.h>
30 #include <dt-bindings/clock/rk3128-cru.h>
31 
32 #define GPU_TEMP_COMPENSION			(6000)
33 #define VPU_TEMP_COMPENSION			(3000)
34 
35 #define LOWEST_TEMP				(-273000)
36 
37 #define BASE					(1024)
38 #define BASE_SHIFT				(10)
39 #define START_DEBOUNCE_COUNT			(100)
40 #define HIGHER_DEBOUNCE_TEMP			(30000)
41 #define LOWER_DEBOUNCE_TEMP			(15000)
42 
43 #define LEAKAGE_INVALID				(0xff)
44 /*20ms as the unit, 60000 * 20ms = 20mins */
45 #define TEMP_STABLE_TIME			(60000)
46 
47 #define MINIMAL_DISCHARGE_CURRENT		(-200000)
48 #define LOWEST_WORKING_TEMP			(-40000)
49 
50 static unsigned int logout;
51 module_param(logout, int, 0644);
52 MODULE_PARM_DESC(logout, "switch to control logout or not");
53 
54 struct temp_frequency_entry {
55 	unsigned int frequency;
56 	s32 time2temp[2];
57 	int time_bound;
58 	s32 time2temp2[2];
59 	int min_temp;
60 	int stable_temp;
61 
62 	s32 temp2time[2];
63 	int temp_bound;
64 	s32 temp2time2[2];
65 };
66 
67 static const struct temp_frequency_entry rk3126_table[] = {
68 	{400000, {18, 446167,}, 6000, {2, 541167,}, 44616, 69000, {555, -23865},
69 	 56000, {5000, -272785},},
70 	{816000, {18, 496167,}, 6000, {2, 591167,}, 49616, 74000, {555, -26640},
71 	 61000, {5000, -297785},},
72 	{912000, {21, 525167,}, 6000, {2, 639167,}, 52516, 80000, {476, -25007},
73 	 65000, {5000, -319067},},
74 	{1008000, {22, 563500,}, 6000, {3, 677500,}, 56350, 100000,
75 	 {454, -25613}, 70000, {3333, -227143},},
76 	{1104000, {33, 570000,}, 6000, {5, 738000,}, 57000, 109000,
77 	 {303, -17272}, 77000, {2000, -147941},},
78 	{1200000, {35, 620167,}, 6000, {5, 800167,}, 61016, 113000,
79 	 {285, -17719}, 83000, {2000, -160064},},
80 	{CPUFREQ_TABLE_END, {0, 0,}, 0, {0, 0,}, 0, 0, {0, 0,}, 0, {0, 0,} },
81 };
82 
83 struct thermal_tuning_info {
84 	int load_slope;
85 	int load_intercept;
86 
87 	int lkg_slope;
88 	int lkg_intercept;
89 
90 	int cur_slope;
91 	int cur_intercept;
92 
93 	int bn_slope;
94 	int bn_intercept;
95 	int bn_offsite;
96 
97 	int vpu_slope;
98 	int gpu_slope;
99 	const struct temp_frequency_entry *map_entries;
100 
101 	int vpu_ajust;
102 	int gpu_ajust;
103 
104 	int fusing_step;
105 };
106 
107 static const struct thermal_tuning_info rk3126_tuning_info = {
108 	.load_slope = 102,
109 	.load_intercept = 61800,
110 
111 	.lkg_slope = 107,
112 	.lkg_intercept = 4713,
113 
114 	.cur_slope = 42,
115 	.cur_intercept = 32661,
116 
117 	.bn_slope = 1517,
118 	.bn_intercept = 199353,
119 	.bn_offsite = 262000,
120 
121 	.vpu_slope = 5,
122 	.gpu_slope = 5,
123 
124 	.map_entries = rk3126_table,
125 
126 	.vpu_ajust = GPU_TEMP_COMPENSION,
127 	.gpu_ajust = VPU_TEMP_COMPENSION,
128 
129 	.fusing_step = 2,
130 };
131 
132 struct virtual_thermal_data {
133 	struct platform_device *pdev;
134 	struct device *dev;
135 	struct thermal_zone_device *tzd;
136 	struct power_supply *psy_bat;
137 	struct power_supply *psy_usb;
138 	struct power_supply *psy_ac;
139 	struct cpufreq_freqs current_freq;
140 	const struct temp_frequency_entry *temp_freq;
141 	int cmp_lkg_temp;
142 	int sigma_time_20ms;
143 	struct kobject virtual_thermal_kobj;
144 	struct thermal_tuning_info *tuning_info;
145 	struct clk *gpu_clk;
146 	struct clk *vpu_clk;
147 };
148 
149 static struct platform_device *platform_dev;
150 
get_temp_by_freq_time(unsigned int freq,int time_20ms)151 static int get_temp_by_freq_time(unsigned int freq, int time_20ms)
152 {
153 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
154 
155 	const struct temp_frequency_entry *table = ctx->tuning_info->map_entries;
156 
157 	int i = 0;
158 	int milli_deg = 0;
159 
160 	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
161 		if (freq < table[i].frequency) {
162 			ctx->temp_freq = &table[i];
163 			break;
164 		}
165 	}
166 	if (table[i].frequency == CPUFREQ_TABLE_END)
167 		ctx->temp_freq = &table[i - 1];
168 
169 	if (time_20ms > TEMP_STABLE_TIME)
170 		return ctx->temp_freq->stable_temp;
171 
172 	if (time_20ms < ctx->temp_freq->time_bound)
173 		milli_deg =
174 		    time_20ms * ctx->temp_freq->time2temp[0] +
175 		    ctx->temp_freq->time2temp[1];
176 	else
177 		milli_deg =
178 		    time_20ms * ctx->temp_freq->time2temp2[0] +
179 		    ctx->temp_freq->time2temp2[1];
180 
181 	if (logout)
182 		dev_info(&platform_dev->dev, "current freq: %u stable_temp: %d milli_deg %d\n",
183 			 freq, ctx->temp_freq->stable_temp, milli_deg / 10);
184 
185 	return milli_deg / 10;
186 }
187 
get_time_by_temp(int milli_deg)188 static int get_time_by_temp(int milli_deg)
189 {
190 	int time_20ms = 0;
191 	int deg = milli_deg / 1000;
192 
193 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
194 
195 	if (milli_deg > ctx->temp_freq->stable_temp)
196 		return TEMP_STABLE_TIME;
197 
198 	if (milli_deg < ctx->temp_freq->temp_bound) {
199 		time_20ms =
200 		    deg * ctx->temp_freq->temp2time[0] +
201 		    ctx->temp_freq->temp2time[1];
202 	} else {
203 		time_20ms =
204 		    deg * ctx->temp_freq->temp2time2[0] +
205 		    ctx->temp_freq->temp2time2[1];
206 	}
207 
208 	if (logout)
209 		dev_info(&platform_dev->dev, "estimate time %d, by milli_deg %d\n",
210 			 time_20ms, milli_deg);
211 
212 	return max(time_20ms, 0);
213 }
214 
get_load(int cpu,int cpu_idx)215 static u32 get_load(int cpu, int cpu_idx)
216 {
217 	static u64 time_in_idle[NR_CPUS] = { 0 };
218 	static u64 time_in_idle_timestamp[NR_CPUS] = { 0 };
219 
220 	u32 load;
221 	u64 now, now_idle, delta_time, delta_idle;
222 
223 	now_idle = get_cpu_idle_time(cpu, &now, 0);
224 	delta_idle = now_idle - time_in_idle[cpu_idx];
225 	delta_time = now - time_in_idle_timestamp[cpu_idx];
226 
227 	if (delta_time <= delta_idle)
228 		load = 0;
229 	else
230 		load = div64_u64(100 * (delta_time - delta_idle), delta_time);
231 
232 	time_in_idle[cpu_idx] = now_idle;
233 	time_in_idle_timestamp[cpu_idx] = now;
234 
235 	return load;
236 }
237 
get_all_load(void)238 static int get_all_load(void)
239 {
240 	u32 total_load = 0;
241 	int cpu;
242 	int i = 0;
243 
244 	for_each_online_cpu(cpu) {
245 		u32 load;
246 
247 		load = get_load(cpu, i);
248 		total_load += load;
249 		if (logout)
250 			dev_info(&platform_dev->dev, "cpu %d, load %d\n", i,
251 				 load);
252 
253 		i++;
254 	}
255 	if (logout)
256 		dev_info(&platform_dev->dev, "total cpu load %d\n", total_load);
257 
258 	return total_load;
259 }
260 
predict_normal_temp(int milli_deg)261 static int predict_normal_temp(int milli_deg)
262 {
263 	int cov_q = 18;
264 	int cov_r = 542;
265 
266 	int gain;
267 	int temp_mid;
268 	int temp_now;
269 	int prob_mid;
270 	int prob_now;
271 	static int temp_last = 50000;
272 	static int prob_last = 20;
273 	static int bounding_cnt;
274 
275 	if (bounding_cnt++ > START_DEBOUNCE_COUNT) {
276 		bounding_cnt = START_DEBOUNCE_COUNT;
277 		if (milli_deg - temp_last > HIGHER_DEBOUNCE_TEMP)
278 			milli_deg = temp_last + HIGHER_DEBOUNCE_TEMP / 3;
279 		if (temp_last - milli_deg > LOWER_DEBOUNCE_TEMP)
280 			milli_deg = temp_last - LOWER_DEBOUNCE_TEMP / 3;
281 	}
282 
283 	temp_mid = temp_last;
284 	prob_mid = prob_last + cov_q;
285 	gain = (prob_mid * BASE) / (prob_mid + cov_r);
286 
287 	temp_now = temp_mid + (gain * (milli_deg - temp_mid) >> BASE_SHIFT);
288 	prob_now = ((BASE - gain) * prob_mid) >> BASE_SHIFT;
289 
290 	prob_last = prob_now;
291 	temp_last = temp_now;
292 
293 	return temp_last;
294 }
295 
predict_cur_temp(int milli_cur_temp)296 static int predict_cur_temp(int milli_cur_temp)
297 {
298 	int cov_q = 18;
299 	int cov_r = 542;
300 
301 	int gain;
302 	int temp_mid;
303 	int temp_now;
304 	int prob_mid;
305 	int prob_now;
306 	static int cur_last = 50000;
307 	static int prob_last = 20;
308 	static int bounding_cnt;
309 
310 	if (bounding_cnt++ > START_DEBOUNCE_COUNT) {
311 		bounding_cnt = START_DEBOUNCE_COUNT;
312 		if (milli_cur_temp - cur_last > HIGHER_DEBOUNCE_TEMP)
313 			milli_cur_temp = cur_last + HIGHER_DEBOUNCE_TEMP / 3;
314 		if (cur_last - milli_cur_temp > LOWER_DEBOUNCE_TEMP)
315 			milli_cur_temp = cur_last - LOWER_DEBOUNCE_TEMP / 3;
316 	}
317 
318 	temp_mid = cur_last;
319 	prob_mid = prob_last + cov_q;
320 	gain = (prob_mid * BASE) / (prob_mid + cov_r);
321 
322 	temp_now =
323 	    temp_mid + (gain * (milli_cur_temp - temp_mid) >> BASE_SHIFT);
324 	prob_now = ((BASE - gain) * prob_mid) >> BASE_SHIFT;
325 
326 	prob_last = prob_now;
327 	cur_last = temp_now;
328 
329 	return cur_last;
330 }
331 
update_counting_time(void)332 static void update_counting_time(void)
333 {
334 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
335 	static ktime_t delta_last;
336 	ktime_t delta;
337 	unsigned long long duration;
338 	ktime_t timestamp = ktime_get();
339 
340 	delta = ktime_sub(timestamp, delta_last);
341 	duration = (unsigned long long)ktime_to_ns(delta) >> 20;
342 	delta_last = timestamp;
343 
344 	if (duration < TEMP_STABLE_TIME)
345 		ctx->sigma_time_20ms += div64_u64(duration, 20);
346 	else
347 		ctx->sigma_time_20ms = 0;
348 
349 	if (logout)
350 		dev_info(&platform_dev->dev, "sigma heating time %d\n",
351 			 ctx->sigma_time_20ms);
352 }
353 
update_working_time_for_gpu_vpu(void)354 static s64 update_working_time_for_gpu_vpu(void)
355 {
356 	static ktime_t last_timestamp;
357 	ktime_t delta;
358 	s64 duration;
359 	ktime_t timestamp = ktime_get();
360 
361 	delta = ktime_sub(timestamp, last_timestamp);
362 	duration = (long long)ktime_to_ns(delta) >> 20;
363 	last_timestamp = timestamp;
364 	duration = div64_s64(duration, 20);
365 	return duration;
366 }
367 
clk_get_by_name(const char * clk_name)368 static struct clk *clk_get_by_name(const char *clk_name)
369 {
370 	const char *name;
371 	struct clk *clk;
372 	struct device_node *np;
373 	struct of_phandle_args clkspec;
374 	int i;
375 
376 	np = of_find_node_by_name(NULL, "clock-controller");
377 	if (!np)
378 		return ERR_PTR(-ENODEV);
379 
380 	clkspec.np = np;
381 	clkspec.args_count = 1;
382 	for (i = 1; i < CLK_NR_CLKS; i++) {
383 		clkspec.args[0] = i;
384 		clk = of_clk_get_from_provider(&clkspec);
385 		if (IS_ERR_OR_NULL(clk))
386 			continue;
387 		name = __clk_get_name(clk);
388 
389 		if (strlen(name) != strlen(clk_name)) {
390 			clk_put(clk);
391 			continue;
392 		}
393 
394 		if (!strncmp(name, clk_name, strlen(clk_name)))
395 			break;
396 
397 		clk_put(clk);
398 	}
399 
400 	of_node_put(np);
401 
402 	if (i == CLK_NR_CLKS)
403 		clk = NULL;
404 
405 	return clk;
406 }
407 
get_actual_brightness(void)408 static int get_actual_brightness(void)
409 {
410 	struct backlight_device *bd;
411 
412 	struct device_node *np;
413 	int brightness = 0;
414 
415 	np = of_find_node_by_name(NULL, "backlight");
416 	if (!np)
417 		return 0;
418 	bd = of_find_backlight_by_node(np);
419 	if (!bd)
420 		goto exit;
421 
422 	mutex_lock(&bd->ops_lock);
423 	if (bd->ops && bd->ops->get_brightness)
424 		brightness = bd->ops->get_brightness(bd);
425 	else
426 		brightness = bd->props.brightness;
427 
428 	mutex_unlock(&bd->ops_lock);
429 
430 exit:
431 	of_node_put(np);
432 	return brightness;
433 }
434 
compensate_brightness(int cur)435 static int compensate_brightness(int cur)
436 {
437 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
438 
439 	int slope = ctx->tuning_info->bn_slope;
440 	int intercept = ctx->tuning_info->bn_slope;
441 	int offsite = ctx->tuning_info->bn_offsite;
442 
443 	int brightness;
444 	int cur_ajust = 0;
445 
446 	brightness = get_actual_brightness();
447 
448 	if (brightness == 0)
449 		cur_ajust = cur - offsite;
450 	else if (brightness > 0)
451 		cur_ajust = cur - intercept + brightness * slope;
452 
453 	if (logout)
454 		dev_info(&platform_dev->dev, "brightness %d cur %d cur_ajust %d\n",
455 			 brightness, cur, cur_ajust);
456 
457 	return cur_ajust;
458 }
459 
rockchip_get_efuse_value(struct device_node * np,char * porp_name,int * value)460 static int rockchip_get_efuse_value(struct device_node *np, char *porp_name,
461 				    int *value)
462 {
463 	struct nvmem_cell *cell;
464 	unsigned char *buf;
465 	size_t len;
466 
467 	cell = of_nvmem_cell_get(np, porp_name);
468 	if (IS_ERR(cell))
469 		return PTR_ERR(cell);
470 
471 	buf = (unsigned char *)nvmem_cell_read(cell, &len);
472 
473 	nvmem_cell_put(cell);
474 
475 	if (IS_ERR(buf))
476 		return PTR_ERR(buf);
477 
478 	if (buf[0] == LEAKAGE_INVALID) {
479 		kfree(buf);
480 		return -EINVAL;
481 	}
482 
483 	*value = buf[0];
484 
485 	kfree(buf);
486 
487 	return 0;
488 }
489 
ajust_temp_on_gpu_vpu(int temp)490 static int ajust_temp_on_gpu_vpu(int temp)
491 {
492 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
493 
494 	int vpu_slope = ctx->tuning_info->vpu_slope;
495 	int gpu_slope = ctx->tuning_info->gpu_slope;
496 	int vpu_ajust = ctx->tuning_info->vpu_ajust;
497 	int gpu_ajust = ctx->tuning_info->gpu_ajust;
498 
499 	int delta_gpu_temp = 0;
500 	int delta_vpu_temp = 0;
501 	int gpu_enabled = 0;
502 	int vpu_enabled = 0;
503 	int delta;
504 	static int sigma_vpu_20ms;
505 	static int sigma_gpu_20ms;
506 
507 	delta = (int)update_working_time_for_gpu_vpu();
508 
509 	if (__clk_is_enabled(ctx->gpu_clk)) {
510 		gpu_enabled = 1;
511 		sigma_gpu_20ms -= delta;
512 		sigma_gpu_20ms = max(sigma_gpu_20ms, 0);
513 	} else {
514 		sigma_gpu_20ms += delta;
515 	}
516 
517 	if (__clk_is_enabled(ctx->vpu_clk)) {
518 		vpu_enabled = 1;
519 		sigma_vpu_20ms -= delta;
520 		sigma_vpu_20ms = max(sigma_vpu_20ms, 0);
521 
522 	} else {
523 		sigma_vpu_20ms += delta;
524 	}
525 
526 	delta_gpu_temp = sigma_gpu_20ms * gpu_slope;
527 	delta_vpu_temp = sigma_vpu_20ms * vpu_slope;
528 
529 	if (delta_gpu_temp > gpu_ajust) {
530 		delta_gpu_temp = gpu_ajust;
531 		sigma_gpu_20ms = gpu_ajust / gpu_slope;
532 	}
533 
534 	if (delta_vpu_temp > vpu_ajust) {
535 		delta_vpu_temp = vpu_ajust;
536 		sigma_vpu_20ms = vpu_ajust / vpu_slope;
537 	}
538 
539 	if (logout)
540 		dev_info(&platform_dev->dev, "temp %d delta_vpu_temp %d delta_vpu_temp %d\n",
541 			 temp, delta_vpu_temp, delta_vpu_temp);
542 
543 	temp = temp - delta_gpu_temp - delta_vpu_temp;
544 
545 	return temp;
546 }
547 
ps_get_cur_current(struct power_supply * psy,int * power_cur)548 static int ps_get_cur_current(struct power_supply *psy, int *power_cur)
549 {
550 	union power_supply_propval val;
551 	int ret;
552 
553 	ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &val);
554 	if (!ret)
555 		*power_cur = val.intval;
556 
557 	return ret;
558 }
559 
map_temp_from_current(int cur)560 static int map_temp_from_current(int cur)
561 {
562 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
563 
564 	int slope = ctx->tuning_info->cur_slope;
565 	int intercept = ctx->tuning_info->cur_intercept;
566 
567 	int milli_degree = cur * slope + intercept;
568 
569 	milli_degree = predict_cur_temp(milli_degree);
570 	return milli_degree;
571 }
572 
get_temp_by_current(void)573 static int get_temp_by_current(void)
574 {
575 	int cur = 0;
576 	int temp = LOWEST_TEMP;
577 	int ret = -1;
578 
579 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
580 
581 	if (ctx->psy_bat)
582 		ret = ps_get_cur_current(ctx->psy_bat, &cur);
583 
584 	if (ret)
585 		return temp;
586 
587 	cur = compensate_brightness(cur);
588 
589 	if (cur < MINIMAL_DISCHARGE_CURRENT) {
590 		cur = -cur;
591 		temp = map_temp_from_current(cur / 1000);
592 	}
593 
594 	return temp;
595 }
596 
ajudt_temp_by_load(int temp_delta)597 static int ajudt_temp_by_load(int temp_delta)
598 {
599 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
600 
601 	int slope = ctx->tuning_info->load_slope;
602 	int intercept = ctx->tuning_info->load_intercept;
603 
604 	int load_rate;
605 	int total_load = 0;
606 	int temp_delta_ajust;
607 
608 	total_load = get_all_load();
609 
610 	load_rate = (total_load * slope + intercept) / 1000;
611 
612 	load_rate = min(load_rate, 100);
613 
614 	if (temp_delta > 0)
615 		temp_delta_ajust = temp_delta * load_rate / 100;
616 	else
617 		temp_delta_ajust = temp_delta * 100 / load_rate;
618 
619 	if (logout)
620 		dev_info(&platform_dev->dev, "temp_delta %d load_rate %d temp_delta_ajust %d\n",
621 			 temp_delta, load_rate, temp_delta_ajust);
622 
623 	return temp_delta_ajust;
624 }
625 
is_charger_pluged_in(void)626 static int is_charger_pluged_in(void)
627 {
628 	union power_supply_propval val;
629 	int ret = 0;
630 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
631 
632 	struct power_supply *psy_usb = ctx->psy_usb;
633 	struct power_supply *psy_ac = ctx->psy_ac;
634 
635 	if (psy_usb && psy_usb->desc && psy_usb->desc->get_property) {
636 		ret = psy_usb->desc->get_property(psy_usb,
637 						  POWER_SUPPLY_PROP_ONLINE,
638 						  &val);
639 		if (!ret && val.intval)
640 			return 1;
641 	}
642 	if (psy_ac && psy_ac->desc && psy_ac->desc->get_property) {
643 		ret = psy_ac->desc->get_property(psy_ac,
644 						 POWER_SUPPLY_PROP_ONLINE,
645 						 &val);
646 		if (!ret && val.intval)
647 			return 1;
648 	}
649 	return 0;
650 }
651 
estimate_temp_internal(void)652 static int estimate_temp_internal(void)
653 {
654 	int temp = 0;
655 	static int last_temp = LOWEST_TEMP;
656 	int temp_delta;
657 
658 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
659 
660 	struct cpufreq_freqs *current_freq = &ctx->current_freq;
661 
662 	update_counting_time();
663 
664 	temp = get_temp_by_freq_time(current_freq->new, ctx->sigma_time_20ms);
665 
666 	temp = ajust_temp_on_gpu_vpu(temp);
667 
668 	if (last_temp == LOWEST_TEMP)
669 		temp_delta = 0;
670 	else
671 		temp_delta = temp - last_temp;
672 
673 	temp_delta = ajudt_temp_by_load(temp_delta);
674 
675 	if (last_temp != LOWEST_TEMP)
676 		temp = last_temp + temp_delta;
677 
678 	last_temp = temp;
679 
680 	temp = clamp(temp, ctx->temp_freq->min_temp, ctx->temp_freq->stable_temp);
681 
682 	temp += ctx->cmp_lkg_temp;
683 
684 	temp = predict_normal_temp(temp);
685 
686 	ctx->sigma_time_20ms = get_time_by_temp(temp);
687 
688 	if (logout)
689 		dev_info(&platform_dev->dev, "Temp1 %d cmp_lkg_temp %d sigma %d\n",
690 			 temp, ctx->cmp_lkg_temp, ctx->sigma_time_20ms);
691 
692 	if (!is_charger_pluged_in()) {
693 		int temp_from_current = 0;
694 		int fusion_diff = 0;
695 		int fusing_step = ctx->tuning_info->fusing_step;
696 
697 		temp_from_current = get_temp_by_current();
698 		if (temp_from_current > LOWEST_WORKING_TEMP) {
699 			fusion_diff = temp_from_current - temp;
700 			temp = temp + fusion_diff / fusing_step;
701 			ctx->sigma_time_20ms = get_time_by_temp(temp);
702 			if (logout)
703 				dev_info(&platform_dev->dev, "Temp2 %d temp_from_current %d sigma %d\n",
704 					 temp, temp_from_current,
705 					 ctx->sigma_time_20ms);
706 		}
707 	}
708 	return temp;
709 }
710 
virtual_thermal_set_trips(void * _sensor,int low,int high)711 static int virtual_thermal_set_trips(void *_sensor, int low, int high)
712 {
713 	return 0;
714 }
715 
virtual_thermal_get_temp(void * _sensor,int * out_temp)716 static int virtual_thermal_get_temp(void *_sensor, int *out_temp)
717 {
718 	*out_temp = estimate_temp_internal();
719 	return 0;
720 }
721 
722 static const struct thermal_zone_of_device_ops virtual_of_thermal_ops = {
723 	.get_temp = virtual_thermal_get_temp,
724 	.set_trips = virtual_thermal_set_trips,
725 };
726 
727 static const struct of_device_id of_virtual_thermal_match[] = {
728 	{
729 	 .compatible = "rockchip,rk3126-tsadc-virtual",
730 	 .data = (void *)&rk3126_tuning_info,
731 	 },
732 
733 	{ /* end */ },
734 };
735 
736 MODULE_DEVICE_TABLE(of, of_virtual_thermal_match);
737 
temp_interactive_notifier(struct notifier_block * nb,unsigned long val,void * data)738 static int temp_interactive_notifier(struct notifier_block *nb,
739 				     unsigned long val, void *data)
740 {
741 	struct cpufreq_freqs *freq = data;
742 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
743 
744 	if (!ctx)
745 		return 0;
746 	if (val == CPUFREQ_POSTCHANGE) {
747 		ctx->current_freq.new = freq->new;
748 		ctx->current_freq.old = freq->old;
749 	}
750 	return 0;
751 }
752 
753 static struct notifier_block temp_notifier_block = {
754 	.notifier_call = temp_interactive_notifier,
755 };
756 
compensate_leakage(int lkg)757 static int compensate_leakage(int lkg)
758 {
759 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
760 
761 	int slope = ctx->tuning_info->lkg_slope;
762 	int intercept = ctx->tuning_info->lkg_slope;
763 
764 	int milli_degree = 0;
765 
766 	if (lkg == 0)
767 		milli_degree = 0;
768 	else
769 		milli_degree = slope * lkg - intercept;
770 
771 	return milli_degree;
772 }
773 
dump_virtual_temperature(void)774 void dump_virtual_temperature(void)
775 {
776 	struct virtual_thermal_data *ctx = platform_get_drvdata(platform_dev);
777 
778 	struct thermal_zone_device *tz = ctx->tzd;
779 
780 	if (tz->temperature != THERMAL_TEMP_INVALID)
781 		dev_warn(&platform_dev->dev, "virtual temperature(%d C)\n",
782 			 tz->temperature / 1000);
783 }
784 EXPORT_SYMBOL_GPL(dump_virtual_temperature);
785 
virtual_thermal_panic(struct notifier_block * this,unsigned long ev,void * ptr)786 static int virtual_thermal_panic(struct notifier_block *this,
787 				 unsigned long ev, void *ptr)
788 {
789 	dump_virtual_temperature();
790 	return NOTIFY_DONE;
791 }
792 
793 static struct notifier_block virtual_thermal_panic_block = {
794 	.notifier_call = virtual_thermal_panic,
795 };
796 
virtual_thermal_probe(struct platform_device * pdev)797 static int virtual_thermal_probe(struct platform_device *pdev)
798 {
799 	struct device_node *np = pdev->dev.of_node;
800 	int ret;
801 	int leakage = 0;
802 	struct virtual_thermal_data *ctx;
803 
804 	const struct of_device_id *match;
805 
806 	match = of_match_node(of_virtual_thermal_match, np);
807 	if (!match)
808 		return -ENXIO;
809 
810 	ctx = devm_kzalloc(&pdev->dev, sizeof(struct virtual_thermal_data),
811 			   GFP_KERNEL);
812 
813 	ctx->pdev = pdev;
814 	ctx->dev = &pdev->dev;
815 	platform_set_drvdata(pdev, ctx);
816 
817 	platform_dev = pdev;
818 
819 	ctx->tuning_info = (struct thermal_tuning_info *)match->data;
820 	if (!ctx->tuning_info) {
821 		dev_err(&pdev->dev,
822 			"failed to allocate memory for tuning info.\n");
823 		return -EINVAL;
824 	}
825 
826 	ret = rockchip_get_efuse_value(np, "cpu_leakage", &leakage);
827 	if (!ret)
828 		dev_info(&pdev->dev, "leakage=%d\n", leakage);
829 
830 	ctx->cmp_lkg_temp = compensate_leakage(leakage);
831 
832 	ctx->psy_bat = power_supply_get_by_name("battery");
833 	ctx->psy_usb = power_supply_get_by_name("usb");
834 	ctx->psy_ac = power_supply_get_by_name("ac");
835 
836 	ret = cpufreq_register_notifier(&temp_notifier_block,
837 					CPUFREQ_TRANSITION_NOTIFIER);
838 	if (ret) {
839 		dev_err(&pdev->dev, "failed to register cpufreq notifier: %d\n",
840 			ret);
841 		return ret;
842 	}
843 
844 	ctx->gpu_clk = clk_get_by_name("aclk_gpu");
845 	if (IS_ERR_OR_NULL(ctx->gpu_clk)) {
846 		ret = PTR_ERR(ctx->gpu_clk);
847 		ctx->gpu_clk = NULL;
848 		dev_warn(&pdev->dev, "failed to get gpu's clock: %d\n", ret);
849 	}
850 
851 	ctx->vpu_clk = clk_get_by_name("aclk_vdpu");
852 	if (IS_ERR_OR_NULL(ctx->vpu_clk)) {
853 		ret = PTR_ERR(ctx->vpu_clk);
854 		ctx->vpu_clk = NULL;
855 		dev_warn(&pdev->dev, "failed to get vpu's clock: %d\n", ret);
856 	}
857 
858 	ctx->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
859 						NULL,
860 						&virtual_of_thermal_ops);
861 	if (IS_ERR(ctx->tzd)) {
862 		ret = PTR_ERR(ctx->tzd);
863 		dev_err(&pdev->dev, "failed to register sensor 0: %d\n", ret);
864 		goto err_unreg_cpufreq_notifier;
865 	}
866 
867 	ret = atomic_notifier_chain_register(&panic_notifier_list,
868 					     &virtual_thermal_panic_block);
869 	if (ret) {
870 		dev_err(&pdev->dev, "failed to register panic notifier: %d\n",
871 			ret);
872 		goto err_unreg_cpufreq_notifier;
873 	}
874 
875 	dev_info(&pdev->dev, "virtual tsadc probed successfully\n");
876 
877 	return 0;
878 
879 err_unreg_cpufreq_notifier:
880 	cpufreq_unregister_notifier(&temp_notifier_block,
881 				    CPUFREQ_TRANSITION_NOTIFIER);
882 	if (ctx->gpu_clk)
883 		clk_put(ctx->gpu_clk);
884 	if (ctx->vpu_clk)
885 		clk_put(ctx->vpu_clk);
886 
887 	return ret;
888 }
889 
virtual_thermal_remove(struct platform_device * pdev)890 static int virtual_thermal_remove(struct platform_device *pdev)
891 {
892 	struct virtual_thermal_data *ctx = platform_get_drvdata(pdev);
893 	atomic_notifier_chain_unregister(&panic_notifier_list,
894 					 &virtual_thermal_panic_block);
895 	cpufreq_unregister_notifier(&temp_notifier_block,
896 				    CPUFREQ_TRANSITION_NOTIFIER);
897 	if (ctx->gpu_clk)
898 		clk_put(ctx->gpu_clk);
899 	if (ctx->vpu_clk)
900 		clk_put(ctx->vpu_clk);
901 
902 	return 0;
903 }
904 
905 static struct platform_driver virtual_thermal_driver = {
906 	.driver = {
907 		   .name = "virtual-thermal",
908 		   .of_match_table = of_virtual_thermal_match,
909 		   },
910 	.probe = virtual_thermal_probe,
911 	.remove = virtual_thermal_remove,
912 };
913 
virtual_thermal_init_driver(void)914 static int __init virtual_thermal_init_driver(void)
915 {
916 	return platform_driver_register(&virtual_thermal_driver);
917 }
918 
919 late_initcall(virtual_thermal_init_driver);
920 
921 MODULE_DESCRIPTION("ROCKCHIP THERMAL Driver");
922 MODULE_AUTHOR("Rockchip, Inc.");
923 MODULE_LICENSE("GPL v2");
924 MODULE_ALIAS("platform:virtual-thermal");
925