drivers/macintosh/windfarm_pid.c

Source file repositories/reference/linux-study-clean/drivers/macintosh/windfarm_pid.c

File Facts

System
Linux kernel
Corpus path
drivers/macintosh/windfarm_pid.c
Extension
.c
Size
3743 bytes
Lines
149
Domain
Driver Families
Bucket
drivers/macintosh
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Windfarm PowerMac thermal control. Generic PID helpers
 *
 * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
 *                    <benh@kernel.crashing.org>
 */

#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)
{
	s64	integ, deriv, prop;

Annotation

Implementation Notes