1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
23dcc4436SWang Nan #ifndef __TRIGGER_H_
33dcc4436SWang Nan #define __TRIGGER_H_ 1
43dcc4436SWang Nan
53dcc4436SWang Nan #include "asm/bug.h"
63dcc4436SWang Nan
73dcc4436SWang Nan /*
83dcc4436SWang Nan * Use trigger to model operations which need to be executed when
93dcc4436SWang Nan * an event (a signal, for example) is observed.
103dcc4436SWang Nan *
113dcc4436SWang Nan * States and transits:
123dcc4436SWang Nan *
133dcc4436SWang Nan *
14*de19e5c3SAdrian Hunter * OFF--> ON --> READY --(hit)--> HIT
153dcc4436SWang Nan * ^ |
163dcc4436SWang Nan * | (ready)
173dcc4436SWang Nan * | |
183dcc4436SWang Nan * \_____________/
193dcc4436SWang Nan *
203dcc4436SWang Nan * is_hit and is_ready are two key functions to query the state of
213dcc4436SWang Nan * a trigger. is_hit means the event already happen; is_ready means the
223dcc4436SWang Nan * trigger is waiting for the event.
233dcc4436SWang Nan */
243dcc4436SWang Nan
253dcc4436SWang Nan struct trigger {
263dcc4436SWang Nan volatile enum {
273dcc4436SWang Nan TRIGGER_ERROR = -2,
283dcc4436SWang Nan TRIGGER_OFF = -1,
29*de19e5c3SAdrian Hunter TRIGGER_ON = 0,
30*de19e5c3SAdrian Hunter TRIGGER_READY = 1,
31*de19e5c3SAdrian Hunter TRIGGER_HIT = 2,
323dcc4436SWang Nan } state;
333dcc4436SWang Nan const char *name;
343dcc4436SWang Nan };
353dcc4436SWang Nan
363dcc4436SWang Nan #define TRIGGER_WARN_ONCE(t, exp) \
373dcc4436SWang Nan WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \
383dcc4436SWang Nan t->name, t->state, __func__)
393dcc4436SWang Nan
trigger_is_available(struct trigger * t)403dcc4436SWang Nan static inline bool trigger_is_available(struct trigger *t)
413dcc4436SWang Nan {
423dcc4436SWang Nan return t->state >= 0;
433dcc4436SWang Nan }
443dcc4436SWang Nan
trigger_is_error(struct trigger * t)453dcc4436SWang Nan static inline bool trigger_is_error(struct trigger *t)
463dcc4436SWang Nan {
473dcc4436SWang Nan return t->state <= TRIGGER_ERROR;
483dcc4436SWang Nan }
493dcc4436SWang Nan
trigger_on(struct trigger * t)503dcc4436SWang Nan static inline void trigger_on(struct trigger *t)
513dcc4436SWang Nan {
523dcc4436SWang Nan TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
53*de19e5c3SAdrian Hunter t->state = TRIGGER_ON;
543dcc4436SWang Nan }
553dcc4436SWang Nan
trigger_ready(struct trigger * t)563dcc4436SWang Nan static inline void trigger_ready(struct trigger *t)
573dcc4436SWang Nan {
583dcc4436SWang Nan if (!trigger_is_available(t))
593dcc4436SWang Nan return;
603dcc4436SWang Nan t->state = TRIGGER_READY;
613dcc4436SWang Nan }
623dcc4436SWang Nan
trigger_hit(struct trigger * t)633dcc4436SWang Nan static inline void trigger_hit(struct trigger *t)
643dcc4436SWang Nan {
653dcc4436SWang Nan if (!trigger_is_available(t))
663dcc4436SWang Nan return;
673dcc4436SWang Nan TRIGGER_WARN_ONCE(t, TRIGGER_READY);
683dcc4436SWang Nan t->state = TRIGGER_HIT;
693dcc4436SWang Nan }
703dcc4436SWang Nan
trigger_off(struct trigger * t)713dcc4436SWang Nan static inline void trigger_off(struct trigger *t)
723dcc4436SWang Nan {
733dcc4436SWang Nan if (!trigger_is_available(t))
743dcc4436SWang Nan return;
753dcc4436SWang Nan t->state = TRIGGER_OFF;
763dcc4436SWang Nan }
773dcc4436SWang Nan
trigger_error(struct trigger * t)783dcc4436SWang Nan static inline void trigger_error(struct trigger *t)
793dcc4436SWang Nan {
803dcc4436SWang Nan t->state = TRIGGER_ERROR;
813dcc4436SWang Nan }
823dcc4436SWang Nan
trigger_is_ready(struct trigger * t)833dcc4436SWang Nan static inline bool trigger_is_ready(struct trigger *t)
843dcc4436SWang Nan {
853dcc4436SWang Nan return t->state == TRIGGER_READY;
863dcc4436SWang Nan }
873dcc4436SWang Nan
trigger_is_hit(struct trigger * t)883dcc4436SWang Nan static inline bool trigger_is_hit(struct trigger *t)
893dcc4436SWang Nan {
903dcc4436SWang Nan return t->state == TRIGGER_HIT;
913dcc4436SWang Nan }
923dcc4436SWang Nan
933dcc4436SWang Nan #define DEFINE_TRIGGER(n) \
943dcc4436SWang Nan struct trigger n = {.state = TRIGGER_OFF, .name = #n}
953dcc4436SWang Nan #endif
96