Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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