Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Windfarm PowerMac thermal control.
0004  *
0005  * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
0006  *                    <benh@kernel.crashing.org>
0007  */
0008 
0009 #ifndef __WINDFARM_H__
0010 #define __WINDFARM_H__
0011 
0012 #include <linux/kref.h>
0013 #include <linux/list.h>
0014 #include <linux/module.h>
0015 #include <linux/notifier.h>
0016 #include <linux/device.h>
0017 
0018 /* Display a 16.16 fixed point value */
0019 #define FIX32TOPRINT(f) (((s32)(f)) >> 16),(((((s32)(f)) & 0xffff) * 1000) >> 16)
0020 
0021 /*
0022  * Control objects
0023  */
0024 
0025 struct wf_control;
0026 
0027 struct wf_control_ops {
0028     int         (*set_value)(struct wf_control *ct, s32 val);
0029     int         (*get_value)(struct wf_control *ct, s32 *val);
0030     s32         (*get_min)(struct wf_control *ct);
0031     s32         (*get_max)(struct wf_control *ct);
0032     void            (*release)(struct wf_control *ct);
0033     struct module       *owner;
0034 };
0035 
0036 struct wf_control {
0037     struct list_head        link;
0038     const struct wf_control_ops *ops;
0039     const char          *name;
0040     int             type;
0041     struct kref         ref;
0042     struct device_attribute     attr;
0043     void                *priv;
0044 };
0045 
0046 #define WF_CONTROL_TYPE_GENERIC     0
0047 #define WF_CONTROL_RPM_FAN      1
0048 #define WF_CONTROL_PWM_FAN      2
0049 
0050 
0051 /* Note about lifetime rules: wf_register_control() will initialize
0052  * the kref and wf_unregister_control will decrement it, thus the
0053  * object creating/disposing a given control shouldn't assume it
0054  * still exists after wf_unregister_control has been called.
0055  */
0056 extern int wf_register_control(struct wf_control *ct);
0057 extern void wf_unregister_control(struct wf_control *ct);
0058 extern int wf_get_control(struct wf_control *ct);
0059 extern void wf_put_control(struct wf_control *ct);
0060 
0061 static inline int wf_control_set_max(struct wf_control *ct)
0062 {
0063     s32 vmax = ct->ops->get_max(ct);
0064     return ct->ops->set_value(ct, vmax);
0065 }
0066 
0067 static inline int wf_control_set_min(struct wf_control *ct)
0068 {
0069     s32 vmin = ct->ops->get_min(ct);
0070     return ct->ops->set_value(ct, vmin);
0071 }
0072 
0073 static inline int wf_control_set(struct wf_control *ct, s32 val)
0074 {
0075     return ct->ops->set_value(ct, val);
0076 }
0077 
0078 static inline int wf_control_get(struct wf_control *ct, s32 *val)
0079 {
0080     return ct->ops->get_value(ct, val);
0081 }
0082 
0083 static inline s32 wf_control_get_min(struct wf_control *ct)
0084 {
0085     return ct->ops->get_min(ct);
0086 }
0087 
0088 static inline s32 wf_control_get_max(struct wf_control *ct)
0089 {
0090     return ct->ops->get_max(ct);
0091 }
0092 
0093 /*
0094  * Sensor objects
0095  */
0096 
0097 struct wf_sensor;
0098 
0099 struct wf_sensor_ops {
0100     int         (*get_value)(struct wf_sensor *sr, s32 *val);
0101     void            (*release)(struct wf_sensor *sr);
0102     struct module       *owner;
0103 };
0104 
0105 struct wf_sensor {
0106     struct list_head        link;
0107     const struct wf_sensor_ops  *ops;
0108     const char          *name;
0109     struct kref         ref;
0110     struct device_attribute     attr;
0111     void                *priv;
0112 };
0113 
0114 /* Same lifetime rules as controls */
0115 extern int wf_register_sensor(struct wf_sensor *sr);
0116 extern void wf_unregister_sensor(struct wf_sensor *sr);
0117 extern int wf_get_sensor(struct wf_sensor *sr);
0118 extern void wf_put_sensor(struct wf_sensor *sr);
0119 
0120 static inline int wf_sensor_get(struct wf_sensor *sr, s32 *val)
0121 {
0122     return sr->ops->get_value(sr, val);
0123 }
0124 
0125 /* For use by clients. Note that we are a bit racy here since
0126  * notifier_block doesn't have a module owner field. I may fix
0127  * it one day ...
0128  *
0129  * LOCKING NOTE !
0130  *
0131  * All "events" except WF_EVENT_TICK are called with an internal mutex
0132  * held which will deadlock if you call basically any core routine.
0133  * So don't ! Just take note of the event and do your actual operations
0134  * from the ticker.
0135  *
0136  */
0137 extern int wf_register_client(struct notifier_block *nb);
0138 extern int wf_unregister_client(struct notifier_block *nb);
0139 
0140 /* Overtemp conditions. Those are refcounted */
0141 extern void wf_set_overtemp(void);
0142 extern void wf_clear_overtemp(void);
0143 
0144 #define WF_EVENT_NEW_CONTROL    0 /* param is wf_control * */
0145 #define WF_EVENT_NEW_SENSOR 1 /* param is wf_sensor * */
0146 #define WF_EVENT_OVERTEMP   2 /* no param */
0147 #define WF_EVENT_NORMALTEMP 3 /* overtemp condition cleared */
0148 #define WF_EVENT_TICK       4 /* 1 second tick */
0149 
0150 /* Note: If that driver gets more broad use, we could replace the
0151  * simplistic overtemp bits with "environmental conditions". That
0152  * could then be used to also notify of things like fan failure,
0153  * case open, battery conditions, ...
0154  */
0155 
0156 #endif /* __WINDFARM_H__ */