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