162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci#ifndef _WINDFARM_PID_H
362306a36Sopenharmony_ci#define _WINDFARM_PID_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * Windfarm PowerMac thermal control. Generic PID helpers
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
962306a36Sopenharmony_ci *                    <benh@kernel.crashing.org>
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * This is a pair of generic PID helpers that can be used by
1262306a36Sopenharmony_ci * control loops. One is the basic PID implementation, the
1362306a36Sopenharmony_ci * other one is more specifically tailored to the loops used
1462306a36Sopenharmony_ci * for CPU control with 2 input sample types (temp and power)
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * *** Simple PID ***
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define WF_PID_MAX_HISTORY	32
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* This parameter array is passed to the PID algorithm. Currently,
2462306a36Sopenharmony_ci * we don't support changing parameters on the fly as it's not needed
2562306a36Sopenharmony_ci * but could be implemented (with necessary adjustment of the history
2662306a36Sopenharmony_ci * buffer
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_cistruct wf_pid_param {
2962306a36Sopenharmony_ci	int	interval;	/* Interval between samples in seconds */
3062306a36Sopenharmony_ci	int	history_len;	/* Size of history buffer */
3162306a36Sopenharmony_ci	int	additive;	/* 1: target relative to previous value */
3262306a36Sopenharmony_ci	s32	gd, gp, gr;	/* PID gains */
3362306a36Sopenharmony_ci	s32	itarget;	/* PID input target */
3462306a36Sopenharmony_ci	s32	min,max;	/* min and max target values */
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistruct wf_pid_state {
3862306a36Sopenharmony_ci	int	first;				/* first run of the loop */
3962306a36Sopenharmony_ci	int	index; 				/* index of current sample */
4062306a36Sopenharmony_ci	s32	target;				/* current target value */
4162306a36Sopenharmony_ci	s32	samples[WF_PID_MAX_HISTORY];	/* samples history buffer */
4262306a36Sopenharmony_ci	s32	errors[WF_PID_MAX_HISTORY];	/* error history buffer */
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	struct wf_pid_param param;
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciextern void wf_pid_init(struct wf_pid_state *st, struct wf_pid_param *param);
4862306a36Sopenharmony_ciextern s32 wf_pid_run(struct wf_pid_state *st, s32 sample);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * *** CPU PID ***
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define WF_CPU_PID_MAX_HISTORY	32
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* This parameter array is passed to the CPU PID algorithm. Currently,
5862306a36Sopenharmony_ci * we don't support changing parameters on the fly as it's not needed
5962306a36Sopenharmony_ci * but could be implemented (with necessary adjustment of the history
6062306a36Sopenharmony_ci * buffer
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_cistruct wf_cpu_pid_param {
6362306a36Sopenharmony_ci	int	interval;	/* Interval between samples in seconds */
6462306a36Sopenharmony_ci	int	history_len;	/* Size of history buffer */
6562306a36Sopenharmony_ci	s32	gd, gp, gr;	/* PID gains */
6662306a36Sopenharmony_ci	s32	pmaxadj;	/* PID max power adjust */
6762306a36Sopenharmony_ci	s32	ttarget;	/* PID input target */
6862306a36Sopenharmony_ci	s32	tmax;		/* PID input max */
6962306a36Sopenharmony_ci	s32	min,max;	/* min and max target values */
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct wf_cpu_pid_state {
7362306a36Sopenharmony_ci	int	first;				/* first run of the loop */
7462306a36Sopenharmony_ci	int	index; 				/* index of current power */
7562306a36Sopenharmony_ci	int	tindex; 			/* index of current temp */
7662306a36Sopenharmony_ci	s32	target;				/* current target value */
7762306a36Sopenharmony_ci	s32	last_delta;			/* last Tactual - Ttarget */
7862306a36Sopenharmony_ci	s32	powers[WF_PID_MAX_HISTORY];	/* power history buffer */
7962306a36Sopenharmony_ci	s32	errors[WF_PID_MAX_HISTORY];	/* error history buffer */
8062306a36Sopenharmony_ci	s32	temps[2];			/* temp. history buffer */
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	struct wf_cpu_pid_param param;
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciextern void wf_cpu_pid_init(struct wf_cpu_pid_state *st,
8662306a36Sopenharmony_ci			    struct wf_cpu_pid_param *param);
8762306a36Sopenharmony_ciextern s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 power, s32 temp);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#endif /* _WINDFARM_PID_H */
90