Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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__ */