~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/drivers/macintosh/windfarm_pid.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  1 /*
  2  * Windfarm PowerMac thermal control. Generic PID helpers
  3  *
  4  * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
  5  *                    <benh@kernel.crashing.org>
  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 <benh@kernel.crashing.org>");
148 MODULE_DESCRIPTION("PID algorithm for PowerMacs thermal control");
149 MODULE_LICENSE("GPL");
150 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.