1/* @title: Clock Event Device */
2#pragma once
3#include <errno.h>
4#include <smp/domain.h>
5#include <structures/list.h>
6#include <time/clock.h>
7#include <types/types.h>
8
9enum clock_evdev_state {
10 CLOCK_EVDEV_STATE_OFF,
11 CLOCK_EVDEV_STATE_PERIODIC,
12 CLOCK_EVDEV_STATE_ONESHOT,
13 CLOCK_EVDEV_STATE_ONESHOT_STOPPED,
14};
15
16enum clock_evdev_flags {
17 CLOCK_EVDEV_PERIODIC = 1,
18 CLOCK_EVDEV_ONESHOT = 1 << 1,
19 CLOCK_EVDEV_DYNIRQ = 1 << 2,
20 CLOCK_EVDEV_PERCPU = 1 << 3,
21 CLOCK_EVDEV_TICK_SUITABLE = 1 << 4,
22};
23
24enum clock_evdev_group_flags {
25 CLOCK_EVDEV_GROUP_PERCPU = 1, /* Each CPU has one */
26};
27
28struct clock_evdev {
29 char *name;
30 enum errno (*set_next_event)(struct clock_evdev *, time_t delta_ns);
31 timestamp_t next_event;
32
33 time_t min_delta_ns;
34 time_t max_delta_ns;
35
36 enum clock_evdev_state state;
37 enum clock_evdev_flags flags;
38 enum clock_rating rating;
39
40 enum errno (*change_state)(struct clock_evdev *,
41 enum clock_evdev_state state);
42 enum errno (*resume_tick)(struct clock_evdev *);
43
44 size_t min_delta_ticks;
45 size_t max_delta_ticks;
46
47 fx32_32_t mult; /* Tick -> NS */
48
49 struct list_head list_internal; /* Used in global list */
50 struct list_head group_list; /* struct clock_evdev_group */
51 cpu_id_t bound_to_cpu; /* If CPU_ID_NONE, no binding */
52 struct cpu_mask cpu_mask;
53
54 irq_t irq;
55 struct clock *clock; /* Optional pointer */
56 void *private;
57};
58
59/* The clock evdevs are meant to be sequentially added to this */
60struct clock_evdev_group {
61 char *name;
62 struct list_head clock_evdevs;
63 enum clock_evdev_group_flags flags;
64 struct list_head list_internal; /* Global list as well */
65};
66
67struct clock_evdev_group *clock_evdev_group_create(const char *fmt, ...);
68struct clock_evdev *clock_evdev_create(const char *fmt, ...);
69void clock_evdev_register(struct clock_evdev *ced);
70void clock_evdev_group_register(struct clock_evdev_group *cedg);
71
72static inline void clock_evdev_group_add(struct clock_evdev_group *cedg,
73 struct clock_evdev *ced) {
74 list_add(new: &ced->group_list, head: &cedg->clock_evdevs);
75}
76