2005-11-07 08:08:17 +03:00
/*
* Windfarm PowerMac thermal control . Generic PID helpers
*
* ( c ) Copyright 2005 Benjamin Herrenschmidt , IBM Corp .
* < benh @ kernel . crashing . org >
*
* Released under the term of the GNU GPL v2 .
*/
# 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 )
{
2006-02-08 08:42:51 +03:00
s64 integ , deriv , prop ;
s32 error , target , sval , adj ;
2005-11-07 08:08:17 +03:00
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 ;
2006-02-08 08:42:51 +03:00
sval = st - > param . tmax - ( s32 ) ( integ > > 20 ) ;
2005-11-07 08:08:17 +03:00
adj = min ( st - > param . ttarget , sval ) ;
DBG ( " integ: %lx, sval: %lx, adj: %lx \n " , 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 */
2006-02-08 08:42:51 +03:00
prop = st - > last_delta = ( new_temp - adj ) ;
2005-11-07 08:08:17 +03:00
prop * = st - > param . gp ;
DBG ( " deriv: %lx, prop: %lx \n " , 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 ) ;
2006-03-07 02:42:59 +03:00
MODULE_AUTHOR ( " Benjamin Herrenschmidt <benh@kernel.crashing.org> " ) ;
MODULE_DESCRIPTION ( " PID algorithm for PowerMacs thermal control " ) ;
MODULE_LICENSE ( " GPL " ) ;