175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt/*
275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * Windfarm PowerMac thermal control. Generic PID helpers
375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt *
475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt *                    <benh@kernel.crashing.org>
675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt *
775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * Released under the term of the GNU GPL v2.
875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt *
975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * This is a pair of generic PID helpers that can be used by
1075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * control loops. One is the basic PID implementation, the
1175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * other one is more specifically tailored to the loops used
1275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * for CPU control with 2 input sample types (temp and power)
1375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt */
1475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
1575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt/*
1675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * *** Simple PID ***
1775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt */
1875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
1975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt#define WF_PID_MAX_HISTORY	32
2075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
2175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt/* This parameter array is passed to the PID algorithm. Currently,
2275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * we don't support changing parameters on the fly as it's not needed
2375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * but could be implemented (with necessary adjustment of the history
2475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * buffer
2575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt */
2675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtstruct wf_pid_param {
2775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	interval;	/* Interval between samples in seconds */
2875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	history_len;	/* Size of history buffer */
2975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	additive;	/* 1: target relative to previous value */
3075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	gd, gp, gr;	/* PID gains */
3175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	itarget;	/* PID input target */
3275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	min,max;	/* min and max target values */
3375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt};
3475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
3575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtstruct wf_pid_state {
3675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	first;				/* first run of the loop */
3775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	index; 				/* index of current sample */
3875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	target;				/* current target value */
3975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	samples[WF_PID_MAX_HISTORY];	/* samples history buffer */
4075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	errors[WF_PID_MAX_HISTORY];	/* error history buffer */
4175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
4275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	struct wf_pid_param param;
4375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt};
4475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
4575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtextern void wf_pid_init(struct wf_pid_state *st, struct wf_pid_param *param);
4675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtextern s32 wf_pid_run(struct wf_pid_state *st, s32 sample);
4775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
4875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
4975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt/*
5075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * *** CPU PID ***
5175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt */
5275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
5375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt#define WF_CPU_PID_MAX_HISTORY	32
5475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
5575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt/* This parameter array is passed to the CPU PID algorithm. Currently,
5675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * we don't support changing parameters on the fly as it's not needed
5775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * but could be implemented (with necessary adjustment of the history
5875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt * buffer
5975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt */
6075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtstruct wf_cpu_pid_param {
6175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	interval;	/* Interval between samples in seconds */
6275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	history_len;	/* Size of history buffer */
6375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	gd, gp, gr;	/* PID gains */
6475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	pmaxadj;	/* PID max power adjust */
6575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	ttarget;	/* PID input target */
6675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	tmax;		/* PID input max */
6775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	min,max;	/* min and max target values */
6875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt};
6975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
7075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtstruct wf_cpu_pid_state {
7175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	first;				/* first run of the loop */
7275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	index; 				/* index of current power */
7375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	int	tindex; 			/* index of current temp */
7475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	target;				/* current target value */
75ac171c46667c1cb2ee9e22312291df6ed78e1b6eBenjamin Herrenschmidt	s32	last_delta;			/* last Tactual - Ttarget */
7675722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	powers[WF_PID_MAX_HISTORY];	/* power history buffer */
7775722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	errors[WF_PID_MAX_HISTORY];	/* error history buffer */
7875722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	s32	temps[2];			/* temp. history buffer */
7975722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
8075722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt	struct wf_cpu_pid_param param;
8175722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt};
8275722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt
8375722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtextern void wf_cpu_pid_init(struct wf_cpu_pid_state *st,
8475722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidt			    struct wf_cpu_pid_param *param);
8575722d3992f57375c0cc029dcceb2334a45ceff1Benjamin Herrenschmidtextern s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 power, s32 temp);
86