1/* @title: Clocks */
2#pragma once
3#include <errno.h>
4#include <math/fixed.h>
5#include <stddef.h>
6#include <stdint.h>
7#include <structures/list.h>
8#include <time/time.h>
9#include <types/types.h>
10
11struct clock_base {
12 freq_khz_t freq_khz;
13 uint64_t clock_mult;
14};
15
16enum clock_rating {
17 CLOCK_RATING_UNSUITABLE,
18 CLOCK_RATING_BASE,
19 CLOCK_RATING_GOOD,
20 CLOCK_RATING_BETTER,
21 CLOCK_RATING_BEST,
22 CLOCK_RATING_MAX,
23};
24
25enum clock_flags {
26 CLOCK_FLAG_NONE = 0,
27 CLOCK_FLAG_WATCHDOG = 1,
28 CLOCK_FLAG_HRES = 1 << 1,
29 CLOCK_FLAG_UNSTABLE = 1 << 2,
30 CLOCK_FLAG_TIMESTAMP_SOURCE = 1 << 3, /* This clock is where all of the
31 * timestamp_t's around the kernel
32 * are coming from */
33};
34
35enum clock_state {
36 CLOCK_STATE_OFF,
37 CLOCK_STATE_ON,
38};
39
40struct clock {
41 /* gives cycles */
42 uint64_t (*read)(struct clock *);
43 char *name;
44 uint64_t mult; /* cycle to ns */
45 fx32_32_t uncertainty_margin; /* ns per s */
46 freq_khz_t frequency_khz;
47 struct list_head list_internal;
48
49 enum clock_state state;
50 enum clock_flags flags;
51 enum clock_rating rating;
52 struct clock_base *base;
53
54 /* these expect state changes from OFF/ON */
55 enum errno (*enable)(struct clock *);
56 void (*disable)(struct clock *);
57 void (*suspend)(struct clock *);
58 void (*resume)(struct clock *);
59
60 void *private;
61};
62
63struct clock *clock_create(const char *fmt, ...);
64void clock_register(struct clock *c);
65void clock_unregister(struct clock *c);
66void clock_suspend_all(void);
67void clock_resume_all(void);
68void clocks_init(void);
69
70static inline uint64_t clock_frequency_to_mult(struct clock *clock) {
71 if (unlikely(clock->frequency_khz == 0))
72 return 0;
73 return ((1000000ULL << 32) + (clock->frequency_khz / 2)) /
74 clock->frequency_khz;
75}
76
77static inline time_ns_t clock_cycles_to_ns(struct clock *clock,
78 uint64_t cycles) {
79 return (time_ns_t) (((uint128_t) cycles * clock->mult) >> 32);
80}
81