Blame view

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