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