162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Windfarm PowerMac thermal control. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. 662306a36Sopenharmony_ci * <benh@kernel.crashing.org> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef __WINDFARM_H__ 1062306a36Sopenharmony_ci#define __WINDFARM_H__ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kref.h> 1362306a36Sopenharmony_ci#include <linux/list.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/notifier.h> 1662306a36Sopenharmony_ci#include <linux/device.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Display a 16.16 fixed point value */ 1962306a36Sopenharmony_ci#define FIX32TOPRINT(f) (((s32)(f)) >> 16),(((((s32)(f)) & 0xffff) * 1000) >> 16) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Control objects 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct wf_control; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistruct wf_control_ops { 2862306a36Sopenharmony_ci int (*set_value)(struct wf_control *ct, s32 val); 2962306a36Sopenharmony_ci int (*get_value)(struct wf_control *ct, s32 *val); 3062306a36Sopenharmony_ci s32 (*get_min)(struct wf_control *ct); 3162306a36Sopenharmony_ci s32 (*get_max)(struct wf_control *ct); 3262306a36Sopenharmony_ci void (*release)(struct wf_control *ct); 3362306a36Sopenharmony_ci struct module *owner; 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistruct wf_control { 3762306a36Sopenharmony_ci struct list_head link; 3862306a36Sopenharmony_ci const struct wf_control_ops *ops; 3962306a36Sopenharmony_ci const char *name; 4062306a36Sopenharmony_ci int type; 4162306a36Sopenharmony_ci struct kref ref; 4262306a36Sopenharmony_ci struct device_attribute attr; 4362306a36Sopenharmony_ci void *priv; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define WF_CONTROL_TYPE_GENERIC 0 4762306a36Sopenharmony_ci#define WF_CONTROL_RPM_FAN 1 4862306a36Sopenharmony_ci#define WF_CONTROL_PWM_FAN 2 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Note about lifetime rules: wf_register_control() will initialize 5262306a36Sopenharmony_ci * the kref and wf_unregister_control will decrement it, thus the 5362306a36Sopenharmony_ci * object creating/disposing a given control shouldn't assume it 5462306a36Sopenharmony_ci * still exists after wf_unregister_control has been called. 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_ciextern int wf_register_control(struct wf_control *ct); 5762306a36Sopenharmony_ciextern void wf_unregister_control(struct wf_control *ct); 5862306a36Sopenharmony_ciextern int wf_get_control(struct wf_control *ct); 5962306a36Sopenharmony_ciextern void wf_put_control(struct wf_control *ct); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic inline int wf_control_set_max(struct wf_control *ct) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci s32 vmax = ct->ops->get_max(ct); 6462306a36Sopenharmony_ci return ct->ops->set_value(ct, vmax); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic inline int wf_control_set_min(struct wf_control *ct) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci s32 vmin = ct->ops->get_min(ct); 7062306a36Sopenharmony_ci return ct->ops->set_value(ct, vmin); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic inline int wf_control_set(struct wf_control *ct, s32 val) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci return ct->ops->set_value(ct, val); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic inline int wf_control_get(struct wf_control *ct, s32 *val) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci return ct->ops->get_value(ct, val); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic inline s32 wf_control_get_min(struct wf_control *ct) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci return ct->ops->get_min(ct); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic inline s32 wf_control_get_max(struct wf_control *ct) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci return ct->ops->get_max(ct); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 9462306a36Sopenharmony_ci * Sensor objects 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistruct wf_sensor; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct wf_sensor_ops { 10062306a36Sopenharmony_ci int (*get_value)(struct wf_sensor *sr, s32 *val); 10162306a36Sopenharmony_ci void (*release)(struct wf_sensor *sr); 10262306a36Sopenharmony_ci struct module *owner; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct wf_sensor { 10662306a36Sopenharmony_ci struct list_head link; 10762306a36Sopenharmony_ci const struct wf_sensor_ops *ops; 10862306a36Sopenharmony_ci const char *name; 10962306a36Sopenharmony_ci struct kref ref; 11062306a36Sopenharmony_ci struct device_attribute attr; 11162306a36Sopenharmony_ci void *priv; 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* Same lifetime rules as controls */ 11562306a36Sopenharmony_ciextern int wf_register_sensor(struct wf_sensor *sr); 11662306a36Sopenharmony_ciextern void wf_unregister_sensor(struct wf_sensor *sr); 11762306a36Sopenharmony_ciextern int wf_get_sensor(struct wf_sensor *sr); 11862306a36Sopenharmony_ciextern void wf_put_sensor(struct wf_sensor *sr); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic inline int wf_sensor_get(struct wf_sensor *sr, s32 *val) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return sr->ops->get_value(sr, val); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* For use by clients. Note that we are a bit racy here since 12662306a36Sopenharmony_ci * notifier_block doesn't have a module owner field. I may fix 12762306a36Sopenharmony_ci * it one day ... 12862306a36Sopenharmony_ci * 12962306a36Sopenharmony_ci * LOCKING NOTE ! 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * All "events" except WF_EVENT_TICK are called with an internal mutex 13262306a36Sopenharmony_ci * held which will deadlock if you call basically any core routine. 13362306a36Sopenharmony_ci * So don't ! Just take note of the event and do your actual operations 13462306a36Sopenharmony_ci * from the ticker. 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ciextern int wf_register_client(struct notifier_block *nb); 13862306a36Sopenharmony_ciextern int wf_unregister_client(struct notifier_block *nb); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* Overtemp conditions. Those are refcounted */ 14162306a36Sopenharmony_ciextern void wf_set_overtemp(void); 14262306a36Sopenharmony_ciextern void wf_clear_overtemp(void); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#define WF_EVENT_NEW_CONTROL 0 /* param is wf_control * */ 14562306a36Sopenharmony_ci#define WF_EVENT_NEW_SENSOR 1 /* param is wf_sensor * */ 14662306a36Sopenharmony_ci#define WF_EVENT_OVERTEMP 2 /* no param */ 14762306a36Sopenharmony_ci#define WF_EVENT_NORMALTEMP 3 /* overtemp condition cleared */ 14862306a36Sopenharmony_ci#define WF_EVENT_TICK 4 /* 1 second tick */ 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* Note: If that driver gets more broad use, we could replace the 15162306a36Sopenharmony_ci * simplistic overtemp bits with "environmental conditions". That 15262306a36Sopenharmony_ci * could then be used to also notify of things like fan failure, 15362306a36Sopenharmony_ci * case open, battery conditions, ... 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#endif /* __WINDFARM_H__ */ 157