VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
2c162f9b41722 (Thomas Gleixner        2019-06-03 07:45:02 +0200   1) // SPDX-License-Identifier: GPL-2.0-only
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   2) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   3)  * Windfarm PowerMac thermal control. Generic PID helpers
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   4)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   5)  * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   6)  *                    <benh@kernel.crashing.org>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   7)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   8) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   9) #include <linux/types.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  10) #include <linux/errno.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  11) #include <linux/kernel.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  12) #include <linux/string.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  13) #include <linux/module.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  14) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  15) #include "windfarm_pid.h"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  16) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  17) #undef DEBUG
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  18) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  19) #ifdef DEBUG
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  20) #define DBG(args...)	printk(args)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  21) #else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  22) #define DBG(args...)	do { } while(0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  23) #endif
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  24) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  25) void wf_pid_init(struct wf_pid_state *st, struct wf_pid_param *param)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  26) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  27) 	memset(st, 0, sizeof(struct wf_pid_state));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  28) 	st->param = *param;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  29) 	st->first = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  30) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  31) EXPORT_SYMBOL_GPL(wf_pid_init);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  32) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  33) s32 wf_pid_run(struct wf_pid_state *st, s32 new_sample)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  34) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  35) 	s64	error, integ, deriv;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  36) 	s32	target;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  37) 	int	i, hlen = st->param.history_len;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  38) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  39) 	/* Calculate error term */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  40) 	error = new_sample - st->param.itarget;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  41) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  42) 	/* Get samples into our history buffer */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  43) 	if (st->first) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  44) 		for (i = 0; i < hlen; i++) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  45) 			st->samples[i] = new_sample;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  46) 			st->errors[i] = error;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  47) 		}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  48) 		st->first = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  49) 		st->index = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  50) 	} else {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  51) 		st->index = (st->index + 1) % hlen;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  52) 		st->samples[st->index] = new_sample;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  53) 		st->errors[st->index] = error;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  54) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  55) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  56) 	/* Calculate integral term */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  57) 	for (i = 0, integ = 0; i < hlen; i++)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  58) 		integ += st->errors[(st->index + hlen - i) % hlen];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  59) 	integ *= st->param.interval;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  60) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  61) 	/* Calculate derivative term */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  62) 	deriv = st->errors[st->index] -
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  63) 		st->errors[(st->index + hlen - 1) % hlen];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  64) 	deriv /= st->param.interval;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  65) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  66) 	/* Calculate target */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  67) 	target = (s32)((integ * (s64)st->param.gr + deriv * (s64)st->param.gd +
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  68) 		  error * (s64)st->param.gp) >> 36);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  69) 	if (st->param.additive)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  70) 		target += st->target;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  71) 	target = max(target, st->param.min);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  72) 	target = min(target, st->param.max);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  73) 	st->target = target;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  74) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  75) 	return st->target;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  76) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  77) EXPORT_SYMBOL_GPL(wf_pid_run);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  78) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  79) void wf_cpu_pid_init(struct wf_cpu_pid_state *st,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  80) 		     struct wf_cpu_pid_param *param)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  81) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  82) 	memset(st, 0, sizeof(struct wf_cpu_pid_state));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  83) 	st->param = *param;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  84) 	st->first = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  85) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  86) EXPORT_SYMBOL_GPL(wf_cpu_pid_init);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  87) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  88) s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  89) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100  90) 	s64	integ, deriv, prop;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100  91) 	s32	error, target, sval, adj;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  92) 	int	i, hlen = st->param.history_len;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  93) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  94) 	/* Calculate error term */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  95) 	error = st->param.pmaxadj - new_power;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  96) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  97) 	/* Get samples into our history buffer */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  98) 	if (st->first) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  99) 		for (i = 0; i < hlen; i++) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 100) 			st->powers[i] = new_power;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 101) 			st->errors[i] = error;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 102) 		}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 103) 		st->temps[0] = st->temps[1] = new_temp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 104) 		st->first = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 105) 		st->index = st->tindex = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 106) 	} else {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 107) 		st->index = (st->index + 1) % hlen;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 108) 		st->powers[st->index] = new_power;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 109) 		st->errors[st->index] = error;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 110) 		st->tindex = (st->tindex + 1) % 2;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 111) 		st->temps[st->tindex] = new_temp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 112) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 113) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 114) 	/* Calculate integral term */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 115) 	for (i = 0, integ = 0; i < hlen; i++)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 116) 		integ += st->errors[(st->index + hlen - i) % hlen];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 117) 	integ *= st->param.interval;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 118) 	integ *= st->param.gr;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 119) 	sval = st->param.tmax - (s32)(integ >> 20);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 120) 	adj = min(st->param.ttarget, sval);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 121) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 122) 	DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 123) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 124) 	/* Calculate derivative term */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 125) 	deriv = st->temps[st->tindex] -
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 126) 		st->temps[(st->tindex + 2 - 1) % 2];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 127) 	deriv /= st->param.interval;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 128) 	deriv *= st->param.gd;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 129) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 130) 	/* Calculate proportional term */
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 131) 	prop = st->last_delta = (new_temp - adj);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 132) 	prop *= st->param.gp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 133) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 134) 	DBG("deriv: %lx, prop: %lx\n", deriv, prop);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 135) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 136) 	/* Calculate target */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 137) 	target = st->target + (s32)((deriv + prop) >> 36);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 138) 	target = max(target, st->param.min);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 139) 	target = min(target, st->param.max);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 140) 	st->target = target;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 141) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 142) 	return st->target;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 143) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 144) EXPORT_SYMBOL_GPL(wf_cpu_pid_run);
cdd440fe9f2e8 (Benjamin Herrenschmidt 2006-03-06 15:42:59 -0800 145) 
cdd440fe9f2e8 (Benjamin Herrenschmidt 2006-03-06 15:42:59 -0800 146) MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
cdd440fe9f2e8 (Benjamin Herrenschmidt 2006-03-06 15:42:59 -0800 147) MODULE_DESCRIPTION("PID algorithm for PowerMacs thermal control");
cdd440fe9f2e8 (Benjamin Herrenschmidt 2006-03-06 15:42:59 -0800 148) MODULE_LICENSE("GPL");