^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Windfarm PowerMac thermal control. Generic PID helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * <benh@kernel.crashing.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This is a pair of generic PID helpers that can be used by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * control loops. One is the basic PID implementation, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * other one is more specifically tailored to the loops used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * for CPU control with 2 input sample types (temp and power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * *** Simple PID ***
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define WF_PID_MAX_HISTORY 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* This parameter array is passed to the PID algorithm. Currently,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * we don't support changing parameters on the fly as it's not needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * but could be implemented (with necessary adjustment of the history
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct wf_pid_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int interval; /* Interval between samples in seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int history_len; /* Size of history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int additive; /* 1: target relative to previous value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) s32 gd, gp, gr; /* PID gains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) s32 itarget; /* PID input target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) s32 min,max; /* min and max target values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct wf_pid_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int first; /* first run of the loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int index; /* index of current sample */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) s32 target; /* current target value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) s32 samples[WF_PID_MAX_HISTORY]; /* samples history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct wf_pid_param param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) extern void wf_pid_init(struct wf_pid_state *st, struct wf_pid_param *param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) extern s32 wf_pid_run(struct wf_pid_state *st, s32 sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * *** CPU PID ***
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define WF_CPU_PID_MAX_HISTORY 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* This parameter array is passed to the CPU PID algorithm. Currently,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * we don't support changing parameters on the fly as it's not needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * but could be implemented (with necessary adjustment of the history
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct wf_cpu_pid_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int interval; /* Interval between samples in seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int history_len; /* Size of history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) s32 gd, gp, gr; /* PID gains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) s32 pmaxadj; /* PID max power adjust */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) s32 ttarget; /* PID input target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) s32 tmax; /* PID input max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) s32 min,max; /* min and max target values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct wf_cpu_pid_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int first; /* first run of the loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int index; /* index of current power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int tindex; /* index of current temp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) s32 target; /* current target value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) s32 last_delta; /* last Tactual - Ttarget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) s32 temps[2]; /* temp. history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct wf_cpu_pid_param param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) extern void wf_cpu_pid_init(struct wf_cpu_pid_state *st,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct wf_cpu_pid_param *param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) extern s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 power, s32 temp);