^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.
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #ifndef __WINDFARM_H__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define __WINDFARM_H__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kref.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* Display a 16.16 fixed point value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define FIX32TOPRINT(f) (((s32)(f)) >> 16),(((((s32)(f)) & 0xffff) * 1000) >> 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Control objects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct wf_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct wf_control_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int (*set_value)(struct wf_control *ct, s32 val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int (*get_value)(struct wf_control *ct, s32 *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) s32 (*get_min)(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) s32 (*get_max)(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) void (*release)(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct module *owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct wf_control {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct list_head link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) const struct wf_control_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct kref ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct device_attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define WF_CONTROL_TYPE_GENERIC 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define WF_CONTROL_RPM_FAN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define WF_CONTROL_PWM_FAN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Note about lifetime rules: wf_register_control() will initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * the kref and wf_unregister_control will decrement it, thus the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * object creating/disposing a given control shouldn't assume it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * still exists after wf_unregister_control has been called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) extern int wf_register_control(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) extern void wf_unregister_control(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) extern int wf_get_control(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) extern void wf_put_control(struct wf_control *ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline int wf_control_set_max(struct wf_control *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) s32 vmax = ct->ops->get_max(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return ct->ops->set_value(ct, vmax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static inline int wf_control_set_min(struct wf_control *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) s32 vmin = ct->ops->get_min(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return ct->ops->set_value(ct, vmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static inline int wf_control_set(struct wf_control *ct, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return ct->ops->set_value(ct, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static inline int wf_control_get(struct wf_control *ct, s32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return ct->ops->get_value(ct, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static inline s32 wf_control_get_min(struct wf_control *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return ct->ops->get_min(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static inline s32 wf_control_get_max(struct wf_control *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ct->ops->get_max(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Sensor objects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct wf_sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct wf_sensor_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int (*get_value)(struct wf_sensor *sr, s32 *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void (*release)(struct wf_sensor *sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct module *owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct wf_sensor {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct list_head link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) const struct wf_sensor_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct kref ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct device_attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Same lifetime rules as controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) extern int wf_register_sensor(struct wf_sensor *sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) extern void wf_unregister_sensor(struct wf_sensor *sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) extern int wf_get_sensor(struct wf_sensor *sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) extern void wf_put_sensor(struct wf_sensor *sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline int wf_sensor_get(struct wf_sensor *sr, s32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return sr->ops->get_value(sr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* For use by clients. Note that we are a bit racy here since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * notifier_block doesn't have a module owner field. I may fix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * it one day ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * LOCKING NOTE !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * All "events" except WF_EVENT_TICK are called with an internal mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * held which will deadlock if you call basically any core routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * So don't ! Just take note of the event and do your actual operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * from the ticker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) extern int wf_register_client(struct notifier_block *nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) extern int wf_unregister_client(struct notifier_block *nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* Overtemp conditions. Those are refcounted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) extern void wf_set_overtemp(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) extern void wf_clear_overtemp(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define WF_EVENT_NEW_CONTROL 0 /* param is wf_control * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define WF_EVENT_NEW_SENSOR 1 /* param is wf_sensor * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define WF_EVENT_OVERTEMP 2 /* no param */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define WF_EVENT_NORMALTEMP 3 /* overtemp condition cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define WF_EVENT_TICK 4 /* 1 second tick */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* Note: If that driver gets more broad use, we could replace the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * simplistic overtemp bits with "environmental conditions". That
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * could then be used to also notify of things like fan failure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * case open, battery conditions, ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #endif /* __WINDFARM_H__ */