Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*  linux/include/linux/clockchips.h
0003  *
0004  *  This file contains the structure definitions for clockchips.
0005  *
0006  *  If you are not a clockchip, or the time of day code, you should
0007  *  not be including this file!
0008  */
0009 #ifndef _LINUX_CLOCKCHIPS_H
0010 #define _LINUX_CLOCKCHIPS_H
0011 
0012 #ifdef CONFIG_GENERIC_CLOCKEVENTS
0013 
0014 # include <linux/clocksource.h>
0015 # include <linux/cpumask.h>
0016 # include <linux/ktime.h>
0017 # include <linux/notifier.h>
0018 
0019 struct clock_event_device;
0020 struct module;
0021 
0022 /*
0023  * Possible states of a clock event device.
0024  *
0025  * DETACHED:    Device is not used by clockevents core. Initial state or can be
0026  *      reached from SHUTDOWN.
0027  * SHUTDOWN:    Device is powered-off. Can be reached from PERIODIC or ONESHOT.
0028  * PERIODIC:    Device is programmed to generate events periodically. Can be
0029  *      reached from DETACHED or SHUTDOWN.
0030  * ONESHOT: Device is programmed to generate event only once. Can be reached
0031  *      from DETACHED or SHUTDOWN.
0032  * ONESHOT_STOPPED: Device was programmed in ONESHOT mode and is temporarily
0033  *          stopped.
0034  */
0035 enum clock_event_state {
0036     CLOCK_EVT_STATE_DETACHED,
0037     CLOCK_EVT_STATE_SHUTDOWN,
0038     CLOCK_EVT_STATE_PERIODIC,
0039     CLOCK_EVT_STATE_ONESHOT,
0040     CLOCK_EVT_STATE_ONESHOT_STOPPED,
0041 };
0042 
0043 /*
0044  * Clock event features
0045  */
0046 # define CLOCK_EVT_FEAT_PERIODIC    0x000001
0047 # define CLOCK_EVT_FEAT_ONESHOT     0x000002
0048 # define CLOCK_EVT_FEAT_KTIME       0x000004
0049 
0050 /*
0051  * x86(64) specific (mis)features:
0052  *
0053  * - Clockevent source stops in C3 State and needs broadcast support.
0054  * - Local APIC timer is used as a dummy device.
0055  */
0056 # define CLOCK_EVT_FEAT_C3STOP      0x000008
0057 # define CLOCK_EVT_FEAT_DUMMY       0x000010
0058 
0059 /*
0060  * Core shall set the interrupt affinity dynamically in broadcast mode
0061  */
0062 # define CLOCK_EVT_FEAT_DYNIRQ      0x000020
0063 # define CLOCK_EVT_FEAT_PERCPU      0x000040
0064 
0065 /*
0066  * Clockevent device is based on a hrtimer for broadcast
0067  */
0068 # define CLOCK_EVT_FEAT_HRTIMER     0x000080
0069 
0070 /**
0071  * struct clock_event_device - clock event device descriptor
0072  * @event_handler:  Assigned by the framework to be called by the low
0073  *          level handler of the event source
0074  * @set_next_event: set next event function using a clocksource delta
0075  * @set_next_ktime: set next event function using a direct ktime value
0076  * @next_event:     local storage for the next event in oneshot mode
0077  * @max_delta_ns:   maximum delta value in ns
0078  * @min_delta_ns:   minimum delta value in ns
0079  * @mult:       nanosecond to cycles multiplier
0080  * @shift:      nanoseconds to cycles divisor (power of two)
0081  * @state_use_accessors:current state of the device, assigned by the core code
0082  * @features:       features
0083  * @retries:        number of forced programming retries
0084  * @set_state_periodic: switch state to periodic
0085  * @set_state_oneshot:  switch state to oneshot
0086  * @set_state_oneshot_stopped: switch state to oneshot_stopped
0087  * @set_state_shutdown: switch state to shutdown
0088  * @tick_resume:    resume clkevt device
0089  * @broadcast:      function to broadcast events
0090  * @min_delta_ticks:    minimum delta value in ticks stored for reconfiguration
0091  * @max_delta_ticks:    maximum delta value in ticks stored for reconfiguration
0092  * @name:       ptr to clock event name
0093  * @rating:     variable to rate clock event devices
0094  * @irq:        IRQ number (only for non CPU local devices)
0095  * @bound_on:       Bound on CPU
0096  * @cpumask:        cpumask to indicate for which CPUs this device works
0097  * @list:       list head for the management code
0098  * @owner:      module reference
0099  */
0100 struct clock_event_device {
0101     void            (*event_handler)(struct clock_event_device *);
0102     int         (*set_next_event)(unsigned long evt, struct clock_event_device *);
0103     int         (*set_next_ktime)(ktime_t expires, struct clock_event_device *);
0104     ktime_t         next_event;
0105     u64         max_delta_ns;
0106     u64         min_delta_ns;
0107     u32         mult;
0108     u32         shift;
0109     enum clock_event_state  state_use_accessors;
0110     unsigned int        features;
0111     unsigned long       retries;
0112 
0113     int         (*set_state_periodic)(struct clock_event_device *);
0114     int         (*set_state_oneshot)(struct clock_event_device *);
0115     int         (*set_state_oneshot_stopped)(struct clock_event_device *);
0116     int         (*set_state_shutdown)(struct clock_event_device *);
0117     int         (*tick_resume)(struct clock_event_device *);
0118 
0119     void            (*broadcast)(const struct cpumask *mask);
0120     void            (*suspend)(struct clock_event_device *);
0121     void            (*resume)(struct clock_event_device *);
0122     unsigned long       min_delta_ticks;
0123     unsigned long       max_delta_ticks;
0124 
0125     const char      *name;
0126     int         rating;
0127     int         irq;
0128     int         bound_on;
0129     const struct cpumask    *cpumask;
0130     struct list_head    list;
0131     struct module       *owner;
0132 } ____cacheline_aligned;
0133 
0134 /* Helpers to verify state of a clockevent device */
0135 static inline bool clockevent_state_detached(struct clock_event_device *dev)
0136 {
0137     return dev->state_use_accessors == CLOCK_EVT_STATE_DETACHED;
0138 }
0139 
0140 static inline bool clockevent_state_shutdown(struct clock_event_device *dev)
0141 {
0142     return dev->state_use_accessors == CLOCK_EVT_STATE_SHUTDOWN;
0143 }
0144 
0145 static inline bool clockevent_state_periodic(struct clock_event_device *dev)
0146 {
0147     return dev->state_use_accessors == CLOCK_EVT_STATE_PERIODIC;
0148 }
0149 
0150 static inline bool clockevent_state_oneshot(struct clock_event_device *dev)
0151 {
0152     return dev->state_use_accessors == CLOCK_EVT_STATE_ONESHOT;
0153 }
0154 
0155 static inline bool clockevent_state_oneshot_stopped(struct clock_event_device *dev)
0156 {
0157     return dev->state_use_accessors == CLOCK_EVT_STATE_ONESHOT_STOPPED;
0158 }
0159 
0160 /*
0161  * Calculate a multiplication factor for scaled math, which is used to convert
0162  * nanoseconds based values to clock ticks:
0163  *
0164  * clock_ticks = (nanoseconds * factor) >> shift.
0165  *
0166  * div_sc is the rearranged equation to calculate a factor from a given clock
0167  * ticks / nanoseconds ratio:
0168  *
0169  * factor = (clock_ticks << shift) / nanoseconds
0170  */
0171 static inline unsigned long
0172 div_sc(unsigned long ticks, unsigned long nsec, int shift)
0173 {
0174     u64 tmp = ((u64)ticks) << shift;
0175 
0176     do_div(tmp, nsec);
0177 
0178     return (unsigned long) tmp;
0179 }
0180 
0181 /* Clock event layer functions */
0182 extern u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt);
0183 extern void clockevents_register_device(struct clock_event_device *dev);
0184 extern int clockevents_unbind_device(struct clock_event_device *ced, int cpu);
0185 
0186 extern void clockevents_config_and_register(struct clock_event_device *dev,
0187                         u32 freq, unsigned long min_delta,
0188                         unsigned long max_delta);
0189 
0190 extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
0191 
0192 static inline void
0193 clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 maxsec)
0194 {
0195     return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, maxsec);
0196 }
0197 
0198 extern void clockevents_suspend(void);
0199 extern void clockevents_resume(void);
0200 
0201 # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
0202 #  ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
0203 extern void tick_broadcast(const struct cpumask *mask);
0204 #  else
0205 #   define tick_broadcast   NULL
0206 #  endif
0207 extern int tick_receive_broadcast(void);
0208 # endif
0209 
0210 # if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
0211 extern void tick_setup_hrtimer_broadcast(void);
0212 extern int tick_check_broadcast_expired(void);
0213 # else
0214 static inline int tick_check_broadcast_expired(void) { return 0; }
0215 static inline void tick_setup_hrtimer_broadcast(void) { }
0216 # endif
0217 
0218 #else /* !CONFIG_GENERIC_CLOCKEVENTS: */
0219 
0220 static inline void clockevents_suspend(void) { }
0221 static inline void clockevents_resume(void) { }
0222 static inline int tick_check_broadcast_expired(void) { return 0; }
0223 static inline void tick_setup_hrtimer_broadcast(void) { }
0224 
0225 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
0226 
0227 #endif /* _LINUX_CLOCKCHIPS_H */