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