[COMMON] thermal: power_allocator: anti-windup for integral term
authorHyeonseong Gil <hs.gil@samsung.com>
Wed, 4 May 2016 07:43:48 +0000 (16:43 +0900)
committerChungwoo Park <cww.park@samsung.com>
Mon, 21 May 2018 08:09:34 +0000 (17:09 +0900)
Change-Id: Id62b77cc74dc69c9d54a43574d732c5bb16b1535
Signed-off-by: Hyeonseong Gil <hs.gil@samsung.com>
drivers/thermal/of-thermal.c
drivers/thermal/power_allocator.c
include/linux/thermal.h

index 548b325e7c48e6052e6afb4fd699368f074583bd..11617dc4e7692a34e3040591f63d65d24475b8c0 100644 (file)
@@ -1032,6 +1032,9 @@ int __init of_parse_thermal_zones(void)
                if (!of_property_read_u32(child, "k_i", &prop))
                        tzp->k_i = prop;
 
+               if (!of_property_read_u32(child, "i_max", &prop))
+                       tzp->integral_max = prop;
+
                for (i = 0; i < tz->ntrips; i++)
                        mask |= 1 << i;
 
index 9e0f02427b108e0efbae4cb8e357aaadcaf3208b..40debd67bf6848d88245a6c2d4b6f8f668f280a5 100644 (file)
@@ -158,13 +158,20 @@ static void estimate_pid_constants(struct thermal_zone_device *tz,
        if (!tz->tzp->k_po || force)
                tz->tzp->k_po = int_to_frac(sustainable_power) /
                        temperature_threshold;
+       else
+               tz->tzp->k_po = int_to_frac(tz->tzp->k_po);
 
        if (!tz->tzp->k_pu || force)
                tz->tzp->k_pu = int_to_frac(2 * sustainable_power) /
                        temperature_threshold;
+       else
+               tz->tzp->k_pu = int_to_frac(tz->tzp->k_pu);
 
        if (!tz->tzp->k_i || force)
                tz->tzp->k_i = int_to_frac(10) / 1000;
+       else
+               tz->tzp->k_i = int_to_frac(tz->tzp->k_i);
+
        /*
         * The default for k_d and integral_cutoff is 0, so we can
         * leave them as they are.
@@ -209,7 +216,7 @@ static u32 pid_controller(struct thermal_zone_device *tz,
                                       true);
        }
 
-       err = control_temp - tz->temperature;
+       err = (control_temp - tz->temperature) / 1000;
        err = int_to_frac(err);
 
        /* Calculate the proportional term */
@@ -225,8 +232,15 @@ static u32 pid_controller(struct thermal_zone_device *tz,
 
        if (err < int_to_frac(tz->tzp->integral_cutoff)) {
                s64 i_next = i + mul_frac(tz->tzp->k_i, err);
-
-               if (abs(i_next) < max_power_frac) {
+               s64 i_windup = int_to_frac(-1 * (s64)tz->tzp->sustainable_power);
+
+               if (i_next > int_to_frac(tz->tzp->integral_max)) {
+                       i = int_to_frac(tz->tzp->integral_max);
+                       params->err_integral = div_frac(i, tz->tzp->k_i);
+               } else if (i_next <= i_windup) {
+                       i = i_windup;
+                       params->err_integral = div_frac(i, tz->tzp->k_i);
+               } else {
                        i = i_next;
                        params->err_integral += err;
                }
index a85b78ed4b6c8d6dd26531e3fc5a8c94cc53e0f8..f969b5e790e1f360668bc0d068d3fd49b7e4575e 100644 (file)
@@ -333,6 +333,8 @@ struct thermal_zone_params {
        /* threshold below which the error is no longer accumulated */
        s32 integral_cutoff;
 
+       s32 integral_max;
+
        /*
         * @slope:      slope of a linear temperature adjustment curve.
         *              Used by thermal zone drivers.