@@ -381,6 +381,44 @@ static ssize_t status_store(struct kobject *kobj, struct kobj_attribute *attr,
381381static struct system_monitor_attr status =
382382 __ATTR (system_status , 0644 , status_show , status_store );
383383
384+ static int rockchip_get_temp_freq_table (struct device_node * np ,
385+ char * porp_name ,
386+ struct temp_freq_table * * freq_table )
387+ {
388+ struct temp_freq_table * table ;
389+ const struct property * prop ;
390+ int count , i ;
391+
392+ prop = of_find_property (np , porp_name , NULL );
393+ if (!prop )
394+ return - EINVAL ;
395+
396+ if (!prop -> value )
397+ return - ENODATA ;
398+
399+ count = of_property_count_u32_elems (np , porp_name );
400+ if (count < 0 )
401+ return - EINVAL ;
402+
403+ if (count % 2 )
404+ return - EINVAL ;
405+
406+ table = kzalloc (sizeof (* table ) * (count / 2 + 1 ), GFP_KERNEL );
407+ if (!table )
408+ return - ENOMEM ;
409+
410+ for (i = 0 ; i < count / 2 ; i ++ ) {
411+ of_property_read_u32_index (np , porp_name , 2 * i ,
412+ & table [i ].temp );
413+ of_property_read_u32_index (np , porp_name , 2 * i + 1 ,
414+ & table [i ].freq );
415+ }
416+ table [i ].freq = UINT_MAX ;
417+ * freq_table = table ;
418+
419+ return 0 ;
420+ }
421+
384422static int rockchip_get_adjust_volt_table (struct device_node * np ,
385423 char * porp_name ,
386424 struct volt_adjust_table * * table )
@@ -553,17 +591,25 @@ static int monitor_device_parse_wide_temp_config(struct device_node *np,
553591 else
554592 info -> high_temp_max_volt = value ;
555593 rockchip_init_temp_opp_table (info );
556- if (!of_property_read_u32 (np , "rockchip,high-temp-max-freq" , & value )) {
557- high_temp_max_freq = value * 1000 ;
558- if (info -> high_limit )
559- info -> high_limit = min (high_temp_max_freq ,
560- info -> high_limit );
561- else
562- info -> high_limit = high_temp_max_freq ;
594+ if (rockchip_get_temp_freq_table (np , "rockchip,high-temp-limit-table" ,
595+ & info -> high_limit_table )) {
596+ info -> high_limit_table = NULL ;
597+ if (!of_property_read_u32 (np , "rockchip,high-temp-max-freq" ,
598+ & value )) {
599+ high_temp_max_freq = value * 1000 ;
600+ if (info -> high_limit )
601+ info -> high_limit = min (high_temp_max_freq ,
602+ info -> high_limit );
603+ else
604+ info -> high_limit = high_temp_max_freq ;
605+ }
606+ } else {
607+ info -> high_limit = 0 ;
563608 }
564- dev_info (dev , "l=%d h=%d hyst=%d l_limit=%lu h_limit=%lu\n" ,
609+ dev_info (dev , "l=%d h=%d hyst=%d l_limit=%lu h_limit=%lu h_table=%d \n" ,
565610 info -> low_temp , info -> high_temp , info -> temp_hysteresis ,
566- info -> low_limit , info -> high_limit );
611+ info -> low_limit , info -> high_limit ,
612+ info -> high_limit_table ? true : false);
567613
568614 if ((info -> low_temp + info -> temp_hysteresis ) > info -> high_temp ) {
569615 dev_err (dev , "Invalid temperature, low=%d high=%d hyst=%d\n" ,
@@ -573,7 +619,7 @@ static int monitor_device_parse_wide_temp_config(struct device_node *np,
573619 goto err ;
574620 }
575621 if (!info -> low_temp_adjust_table && !info -> low_temp_min_volt &&
576- !info -> low_limit && !info -> high_limit ) {
622+ !info -> low_limit && !info -> high_limit && ! info -> high_limit_table ) {
577623 ret = - EINVAL ;
578624 goto err ;
579625 }
@@ -609,44 +655,6 @@ static int monitor_device_parse_status_config(struct device_node *np,
609655 return ret ;
610656}
611657
612- static int rockchip_get_temp_freq_table (struct device_node * np ,
613- char * porp_name ,
614- struct temp_freq_table * * freq_table )
615- {
616- struct temp_freq_table * table ;
617- const struct property * prop ;
618- int count , i ;
619-
620- prop = of_find_property (np , porp_name , NULL );
621- if (!prop )
622- return - EINVAL ;
623-
624- if (!prop -> value )
625- return - ENODATA ;
626-
627- count = of_property_count_u32_elems (np , porp_name );
628- if (count < 0 )
629- return - EINVAL ;
630-
631- if (count % 2 )
632- return - EINVAL ;
633-
634- table = kzalloc (sizeof (* table ) * (count / 2 + 1 ), GFP_KERNEL );
635- if (!table )
636- return - ENOMEM ;
637-
638- for (i = 0 ; i < count / 2 ; i ++ ) {
639- of_property_read_u32_index (np , porp_name , 2 * i ,
640- & table [i ].temp );
641- of_property_read_u32_index (np , porp_name , 2 * i + 1 ,
642- & table [i ].freq );
643- }
644- table [i ].freq = UINT_MAX ;
645- * freq_table = table ;
646-
647- return 0 ;
648- }
649-
650658static int monitor_device_parse_dt (struct device * dev ,
651659 struct monitor_dev_info * info )
652660{
@@ -717,12 +725,17 @@ int rockchip_monitor_cpu_high_temp_adjust(struct monitor_dev_info *info,
717725{
718726 unsigned int cpu = cpumask_any (& info -> devp -> allowed_cpus );
719727
720- if (info -> high_limit ) {
721- if (is_high )
722- info -> wide_temp_limit = info -> high_limit ;
723- else
724- info -> wide_temp_limit = 0 ;
728+ if (info -> high_limit_table ) {
729+ info -> wide_temp_limit = info -> high_limit ;
725730 cpufreq_update_policy (cpu );
731+ } else {
732+ if (info -> high_limit ) {
733+ if (is_high )
734+ info -> wide_temp_limit = info -> high_limit ;
735+ else
736+ info -> wide_temp_limit = 0 ;
737+ cpufreq_update_policy (cpu );
738+ }
726739 }
727740
728741 return 0 ;
@@ -767,16 +780,23 @@ int rockchip_monitor_dev_high_temp_adjust(struct monitor_dev_info *info,
767780{
768781 struct devfreq * df ;
769782
770- if (info -> high_limit ) {
771- if (is_high )
772- info -> wide_temp_limit = info -> high_limit ;
773- else
774- info -> wide_temp_limit = 0 ;
775- }
776-
777- if (info -> devp && info -> devp -> data ) {
778- df = (struct devfreq * )info -> devp -> data ;
779- rockchip_monitor_update_devfreq (df );
783+ if (info -> high_limit_table ) {
784+ info -> wide_temp_limit = info -> high_limit ;
785+ if (info -> devp && info -> devp -> data ) {
786+ df = (struct devfreq * )info -> devp -> data ;
787+ rockchip_monitor_update_devfreq (df );
788+ }
789+ } else {
790+ if (info -> high_limit ) {
791+ if (is_high )
792+ info -> wide_temp_limit = info -> high_limit ;
793+ else
794+ info -> wide_temp_limit = 0 ;
795+ if (info -> devp && info -> devp -> data ) {
796+ df = (struct devfreq * )info -> devp -> data ;
797+ rockchip_monitor_update_devfreq (df );
798+ }
799+ }
780800 }
781801
782802 return 0 ;
@@ -850,20 +870,28 @@ static void rockchip_high_temp_adjust(struct monitor_dev_info *info,
850870 struct monitor_dev_profile * devp = info -> devp ;
851871 int ret = 0 ;
852872
853- dev_dbg (info -> dev , "high_temp %d\n" , is_high );
854- if (devp -> high_temp_adjust )
855- ret = devp -> high_temp_adjust (info , is_high );
856- if (!ret )
857- info -> is_high_temp = is_high ;
873+ if (info -> high_limit_table ) {
874+ devp -> high_temp_adjust (info , is_high );
875+ } else {
876+ dev_dbg (info -> dev , "high_temp %d\n" , is_high );
877+ if (devp -> high_temp_adjust )
878+ ret = devp -> high_temp_adjust (info , is_high );
879+ if (!ret )
880+ info -> is_high_temp = is_high ;
881+ }
858882}
859883
860884int rockchip_monitor_suspend_low_temp_adjust (struct monitor_dev_info * info )
861885{
862886 if (!info || !info -> is_low_temp_enabled )
863887 return 0 ;
864888
865- if (info -> is_high_temp )
889+ if (info -> high_limit_table ) {
890+ info -> high_limit = 0 ;
891+ rockchip_high_temp_adjust (info , true);
892+ } else if (info -> is_high_temp ) {
866893 rockchip_high_temp_adjust (info , false);
894+ }
867895 if (!info -> is_low_temp )
868896 rockchip_low_temp_adjust (info , true);
869897
@@ -875,24 +903,35 @@ static int
875903rockchip_system_monitor_wide_temp_adjust (struct monitor_dev_info * info ,
876904 int temp )
877905{
906+ unsigned long target_freq = 0 ;
907+ int i ;
908+
878909 if (temp < info -> low_temp ) {
879- if (info -> is_high_temp )
880- rockchip_high_temp_adjust (info , false);
881910 if (!info -> is_low_temp )
882911 rockchip_low_temp_adjust (info , true);
883912 } else if (temp > (info -> low_temp + info -> temp_hysteresis )) {
884913 if (info -> is_low_temp )
885914 rockchip_low_temp_adjust (info , false);
886915 }
887916
888- if (temp > info -> high_temp ) {
889- if (info -> is_low_temp )
890- rockchip_low_temp_adjust (info , false);
891- if (!info -> is_high_temp )
917+ if (info -> high_limit_table ) {
918+ for (i = 0 ; info -> high_limit_table [i ].freq != UINT_MAX ; i ++ ) {
919+ if (temp > info -> high_limit_table [i ].temp )
920+ target_freq =
921+ info -> high_limit_table [i ].freq * 1000 ;
922+ }
923+ if (target_freq != info -> high_limit ) {
924+ info -> high_limit = target_freq ;
892925 rockchip_high_temp_adjust (info , true);
893- } else if (temp < (info -> high_temp - info -> temp_hysteresis )) {
894- if (info -> is_high_temp )
895- rockchip_high_temp_adjust (info , false);
926+ }
927+ } else {
928+ if (temp > info -> high_temp ) {
929+ if (!info -> is_high_temp )
930+ rockchip_high_temp_adjust (info , true);
931+ } else if (temp < (info -> high_temp - info -> temp_hysteresis )) {
932+ if (info -> is_high_temp )
933+ rockchip_high_temp_adjust (info , false);
934+ }
896935 }
897936
898937 return 0 ;
@@ -1225,13 +1264,18 @@ static void rockchip_system_monitor_thermal_update(void)
12251264{
12261265 int temp , ret ;
12271266 struct monitor_dev_info * info ;
1267+ static int last_temp = INT_MAX ;
12281268
12291269 ret = thermal_zone_get_temp (system_monitor -> tz , & temp );
12301270 if (ret || temp == THERMAL_TEMP_INVALID )
12311271 goto out ;
12321272
12331273 dev_dbg (system_monitor -> dev , "temperature=%d\n" , temp );
12341274
1275+ if (temp < last_temp && last_temp - temp <= 2000 )
1276+ goto out ;
1277+ last_temp = temp ;
1278+
12351279 down_read (& mdev_list_sem );
12361280 list_for_each_entry (info , & monitor_dev_list , node )
12371281 rockchip_system_monitor_wide_temp_adjust (info , temp );
0 commit comments