Blame view
include/linux/clockchips.h
7.27 KB
b24413180
|
1 |
/* SPDX-License-Identifier: GPL-2.0 */ |
d316c57ff
|
2 3 4 5 6 7 8 9 10 |
/* linux/include/linux/clockchips.h * * This file contains the structure definitions for clockchips. * * If you are not a clockchip, or the time of day code, you should * not be including this file! */ #ifndef _LINUX_CLOCKCHIPS_H #define _LINUX_CLOCKCHIPS_H |
9f083b74d
|
11 |
#ifdef CONFIG_GENERIC_CLOCKEVENTS |
d316c57ff
|
12 |
|
9eed56e88
|
13 14 15 16 |
# include <linux/clocksource.h> # include <linux/cpumask.h> # include <linux/ktime.h> # include <linux/notifier.h> |
d316c57ff
|
17 18 |
struct clock_event_device; |
ccf33d688
|
19 |
struct module; |
d316c57ff
|
20 |
|
77e32c89a
|
21 22 23 24 25 26 27 28 29 30 |
/* * Possible states of a clock event device. * * DETACHED: Device is not used by clockevents core. Initial state or can be * reached from SHUTDOWN. * SHUTDOWN: Device is powered-off. Can be reached from PERIODIC or ONESHOT. * PERIODIC: Device is programmed to generate events periodically. Can be * reached from DETACHED or SHUTDOWN. * ONESHOT: Device is programmed to generate event only once. Can be reached * from DETACHED or SHUTDOWN. |
8fff52fd5
|
31 32 |
* ONESHOT_STOPPED: Device was programmed in ONESHOT mode and is temporarily * stopped. |
77e32c89a
|
33 34 |
*/ enum clock_event_state { |
9eed56e88
|
35 |
CLOCK_EVT_STATE_DETACHED, |
77e32c89a
|
36 37 38 |
CLOCK_EVT_STATE_SHUTDOWN, CLOCK_EVT_STATE_PERIODIC, CLOCK_EVT_STATE_ONESHOT, |
8fff52fd5
|
39 |
CLOCK_EVT_STATE_ONESHOT_STOPPED, |
d316c57ff
|
40 |
}; |
d316c57ff
|
41 42 43 |
/* * Clock event features */ |
9eed56e88
|
44 45 46 |
# define CLOCK_EVT_FEAT_PERIODIC 0x000001 # define CLOCK_EVT_FEAT_ONESHOT 0x000002 # define CLOCK_EVT_FEAT_KTIME 0x000004 |
d316c57ff
|
47 |
/* |
9eed56e88
|
48 |
* x86(64) specific (mis)features: |
d316c57ff
|
49 50 51 52 |
* * - Clockevent source stops in C3 State and needs broadcast support. * - Local APIC timer is used as a dummy device. */ |
9eed56e88
|
53 54 |
# define CLOCK_EVT_FEAT_C3STOP 0x000008 # define CLOCK_EVT_FEAT_DUMMY 0x000010 |
d316c57ff
|
55 |
|
d2348fb6f
|
56 57 58 |
/* * Core shall set the interrupt affinity dynamically in broadcast mode */ |
9eed56e88
|
59 60 |
# define CLOCK_EVT_FEAT_DYNIRQ 0x000020 # define CLOCK_EVT_FEAT_PERCPU 0x000040 |
d2348fb6f
|
61 |
|
5d1638acb
|
62 63 64 |
/* * Clockevent device is based on a hrtimer for broadcast */ |
9eed56e88
|
65 |
# define CLOCK_EVT_FEAT_HRTIMER 0x000080 |
5d1638acb
|
66 |
|
d316c57ff
|
67 68 |
/** * struct clock_event_device - clock event device descriptor |
847b2f42b
|
69 70 |
* @event_handler: Assigned by the framework to be called by the low * level handler of the event source |
65516f8a7
|
71 72 |
* @set_next_event: set next event function using a clocksource delta * @set_next_ktime: set next event function using a direct ktime value |
847b2f42b
|
73 |
* @next_event: local storage for the next event in oneshot mode |
d316c57ff
|
74 75 76 77 |
* @max_delta_ns: maximum delta value in ns * @min_delta_ns: minimum delta value in ns * @mult: nanosecond to cycles multiplier * @shift: nanoseconds to cycles divisor (power of two) |
be3ef76e9
|
78 |
* @state_use_accessors:current state of the device, assigned by the core code |
847b2f42b
|
79 80 |
* @features: features * @retries: number of forced programming retries |
eef7635a2
|
81 82 83 84 85 |
* @set_state_periodic: switch state to periodic * @set_state_oneshot: switch state to oneshot * @set_state_oneshot_stopped: switch state to oneshot_stopped * @set_state_shutdown: switch state to shutdown * @tick_resume: resume clkevt device |
847b2f42b
|
86 |
* @broadcast: function to broadcast events |
57f0fcbe1
|
87 88 |
* @min_delta_ticks: minimum delta value in ticks stored for reconfiguration * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration |
847b2f42b
|
89 |
* @name: ptr to clock event name |
d316c57ff
|
90 |
* @rating: variable to rate clock event devices |
ce0be1273
|
91 |
* @irq: IRQ number (only for non CPU local devices) |
5d1638acb
|
92 |
* @bound_on: Bound on CPU |
ce0be1273
|
93 |
* @cpumask: cpumask to indicate for which CPUs this device works |
d316c57ff
|
94 |
* @list: list head for the management code |
ccf33d688
|
95 |
* @owner: module reference |
d316c57ff
|
96 97 |
*/ struct clock_event_device { |
847b2f42b
|
98 |
void (*event_handler)(struct clock_event_device *); |
9eed56e88
|
99 100 |
int (*set_next_event)(unsigned long evt, struct clock_event_device *); int (*set_next_ktime)(ktime_t expires, struct clock_event_device *); |
847b2f42b
|
101 |
ktime_t next_event; |
97813f2fe
|
102 103 |
u64 max_delta_ns; u64 min_delta_ns; |
23af368e9
|
104 105 |
u32 mult; u32 shift; |
be3ef76e9
|
106 |
enum clock_event_state state_use_accessors; |
847b2f42b
|
107 108 |
unsigned int features; unsigned long retries; |
77e32c89a
|
109 110 |
int (*set_state_periodic)(struct clock_event_device *); int (*set_state_oneshot)(struct clock_event_device *); |
8fff52fd5
|
111 |
int (*set_state_oneshot_stopped)(struct clock_event_device *); |
77e32c89a
|
112 |
int (*set_state_shutdown)(struct clock_event_device *); |
554ef3876
|
113 |
int (*tick_resume)(struct clock_event_device *); |
bd624d75d
|
114 115 |
void (*broadcast)(const struct cpumask *mask); |
adc78e6b9
|
116 117 |
void (*suspend)(struct clock_event_device *); void (*resume)(struct clock_event_device *); |
57f0fcbe1
|
118 119 |
unsigned long min_delta_ticks; unsigned long max_delta_ticks; |
847b2f42b
|
120 |
const char *name; |
d316c57ff
|
121 122 |
int rating; int irq; |
5d1638acb
|
123 |
int bound_on; |
320ab2b0b
|
124 |
const struct cpumask *cpumask; |
d316c57ff
|
125 |
struct list_head list; |
ccf33d688
|
126 |
struct module *owner; |
847b2f42b
|
127 |
} ____cacheline_aligned; |
d316c57ff
|
128 |
|
3434d23b6
|
129 130 131 |
/* Helpers to verify state of a clockevent device */ static inline bool clockevent_state_detached(struct clock_event_device *dev) { |
be3ef76e9
|
132 |
return dev->state_use_accessors == CLOCK_EVT_STATE_DETACHED; |
3434d23b6
|
133 134 135 136 |
} static inline bool clockevent_state_shutdown(struct clock_event_device *dev) { |
be3ef76e9
|
137 |
return dev->state_use_accessors == CLOCK_EVT_STATE_SHUTDOWN; |
3434d23b6
|
138 139 140 141 |
} static inline bool clockevent_state_periodic(struct clock_event_device *dev) { |
be3ef76e9
|
142 |
return dev->state_use_accessors == CLOCK_EVT_STATE_PERIODIC; |
3434d23b6
|
143 144 145 146 |
} static inline bool clockevent_state_oneshot(struct clock_event_device *dev) { |
be3ef76e9
|
147 |
return dev->state_use_accessors == CLOCK_EVT_STATE_ONESHOT; |
3434d23b6
|
148 149 150 151 |
} static inline bool clockevent_state_oneshot_stopped(struct clock_event_device *dev) { |
be3ef76e9
|
152 |
return dev->state_use_accessors == CLOCK_EVT_STATE_ONESHOT_STOPPED; |
3434d23b6
|
153 |
} |
d316c57ff
|
154 155 156 157 158 159 160 161 162 163 164 |
/* * Calculate a multiplication factor for scaled math, which is used to convert * nanoseconds based values to clock ticks: * * clock_ticks = (nanoseconds * factor) >> shift. * * div_sc is the rearranged equation to calculate a factor from a given clock * ticks / nanoseconds ratio: * * factor = (clock_ticks << shift) / nanoseconds */ |
9eed56e88
|
165 166 |
static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec, int shift) |
d316c57ff
|
167 |
{ |
9eed56e88
|
168 |
u64 tmp = ((u64)ticks) << shift; |
d316c57ff
|
169 170 |
do_div(tmp, nsec); |
9eed56e88
|
171 |
|
d316c57ff
|
172 173 174 175 |
return (unsigned long) tmp; } /* Clock event layer functions */ |
9eed56e88
|
176 |
extern u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt); |
d316c57ff
|
177 |
extern void clockevents_register_device(struct clock_event_device *dev); |
03e13cf5e
|
178 |
extern int clockevents_unbind_device(struct clock_event_device *ced, int cpu); |
d316c57ff
|
179 |
|
57f0fcbe1
|
180 181 182 |
extern void clockevents_config_and_register(struct clock_event_device *dev, u32 freq, unsigned long min_delta, unsigned long max_delta); |
80b816b73
|
183 |
extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq); |
7d2f944a2
|
184 |
static inline void |
dd42ac8f0
|
185 |
clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 maxsec) |
7d2f944a2
|
186 |
{ |
dd42ac8f0
|
187 |
return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, maxsec); |
7d2f944a2
|
188 |
} |
adc78e6b9
|
189 190 |
extern void clockevents_suspend(void); extern void clockevents_resume(void); |
9eed56e88
|
191 192 |
# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST # ifdef CONFIG_ARCH_HAS_TICK_BROADCAST |
12ad10004
|
193 |
extern void tick_broadcast(const struct cpumask *mask); |
9eed56e88
|
194 195 196 |
# else # define tick_broadcast NULL # endif |
12572dbb5
|
197 |
extern int tick_receive_broadcast(void); |
9eed56e88
|
198 |
# endif |
12572dbb5
|
199 |
|
9eed56e88
|
200 |
# if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT) |
5d1638acb
|
201 |
extern void tick_setup_hrtimer_broadcast(void); |
eaa907c54
|
202 |
extern int tick_check_broadcast_expired(void); |
9eed56e88
|
203 |
# else |
eaa907c54
|
204 |
static inline int tick_check_broadcast_expired(void) { return 0; } |
9eed56e88
|
205 206 |
static inline void tick_setup_hrtimer_broadcast(void) { } # endif |
eaa907c54
|
207 |
|
9eed56e88
|
208 |
#else /* !CONFIG_GENERIC_CLOCKEVENTS: */ |
adc78e6b9
|
209 |
|
9eed56e88
|
210 211 |
static inline void clockevents_suspend(void) { } static inline void clockevents_resume(void) { } |
19919226c
|
212 |
static inline int tick_check_broadcast_expired(void) { return 0; } |
9eed56e88
|
213 |
static inline void tick_setup_hrtimer_broadcast(void) { } |
d316c57ff
|
214 |
|
9eed56e88
|
215 |
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ |
d316c57ff
|
216 |
|
9eed56e88
|
217 |
#endif /* _LINUX_CLOCKCHIPS_H */ |