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