1d316c57fSThomas Gleixner /* linux/include/linux/clockchips.h 2d316c57fSThomas Gleixner * 3d316c57fSThomas Gleixner * This file contains the structure definitions for clockchips. 4d316c57fSThomas Gleixner * 5d316c57fSThomas Gleixner * If you are not a clockchip, or the time of day code, you should 6d316c57fSThomas Gleixner * not be including this file! 7d316c57fSThomas Gleixner */ 8d316c57fSThomas Gleixner #ifndef _LINUX_CLOCKCHIPS_H 9d316c57fSThomas Gleixner #define _LINUX_CLOCKCHIPS_H 10d316c57fSThomas Gleixner 119f083b74SThomas Gleixner #ifdef CONFIG_GENERIC_CLOCKEVENTS 12d316c57fSThomas Gleixner 13d316c57fSThomas Gleixner # include <linux/clocksource.h> 14d316c57fSThomas Gleixner # include <linux/cpumask.h> 15d316c57fSThomas Gleixner # include <linux/ktime.h> 16d316c57fSThomas Gleixner # include <linux/notifier.h> 17d316c57fSThomas Gleixner 18d316c57fSThomas Gleixner struct clock_event_device; 19ccf33d68SThomas Gleixner struct module; 20d316c57fSThomas Gleixner 2177e32c89SViresh Kumar /* 2277e32c89SViresh Kumar * Possible states of a clock event device. 2377e32c89SViresh Kumar * 2477e32c89SViresh Kumar * DETACHED: Device is not used by clockevents core. Initial state or can be 2577e32c89SViresh Kumar * reached from SHUTDOWN. 2677e32c89SViresh Kumar * SHUTDOWN: Device is powered-off. Can be reached from PERIODIC or ONESHOT. 2777e32c89SViresh Kumar * PERIODIC: Device is programmed to generate events periodically. Can be 2877e32c89SViresh Kumar * reached from DETACHED or SHUTDOWN. 2977e32c89SViresh Kumar * ONESHOT: Device is programmed to generate event only once. Can be reached 3077e32c89SViresh Kumar * from DETACHED or SHUTDOWN. 318fff52fdSViresh Kumar * ONESHOT_STOPPED: Device was programmed in ONESHOT mode and is temporarily 328fff52fdSViresh Kumar * stopped. 3377e32c89SViresh Kumar */ 3477e32c89SViresh Kumar enum clock_event_state { 359eed56e8SIngo Molnar CLOCK_EVT_STATE_DETACHED, 3677e32c89SViresh Kumar CLOCK_EVT_STATE_SHUTDOWN, 3777e32c89SViresh Kumar CLOCK_EVT_STATE_PERIODIC, 3877e32c89SViresh Kumar CLOCK_EVT_STATE_ONESHOT, 398fff52fdSViresh Kumar CLOCK_EVT_STATE_ONESHOT_STOPPED, 40d316c57fSThomas Gleixner }; 41d316c57fSThomas Gleixner 42d316c57fSThomas Gleixner /* 43d316c57fSThomas Gleixner * Clock event features 44d316c57fSThomas Gleixner */ 45d316c57fSThomas Gleixner # define CLOCK_EVT_FEAT_PERIODIC 0x000001 46d316c57fSThomas Gleixner # define CLOCK_EVT_FEAT_ONESHOT 0x000002 4765516f8aSMartin Schwidefsky # define CLOCK_EVT_FEAT_KTIME 0x000004 489eed56e8SIngo Molnar 49d316c57fSThomas Gleixner /* 509eed56e8SIngo Molnar * x86(64) specific (mis)features: 51d316c57fSThomas Gleixner * 52d316c57fSThomas Gleixner * - Clockevent source stops in C3 State and needs broadcast support. 53d316c57fSThomas Gleixner * - Local APIC timer is used as a dummy device. 54d316c57fSThomas Gleixner */ 5565516f8aSMartin Schwidefsky # define CLOCK_EVT_FEAT_C3STOP 0x000008 5665516f8aSMartin Schwidefsky # define CLOCK_EVT_FEAT_DUMMY 0x000010 57d316c57fSThomas Gleixner 58d2348fb6SDaniel Lezcano /* 59d2348fb6SDaniel Lezcano * Core shall set the interrupt affinity dynamically in broadcast mode 60d2348fb6SDaniel Lezcano */ 61d2348fb6SDaniel Lezcano # define CLOCK_EVT_FEAT_DYNIRQ 0x000020 623713c0cfSSoren Brinkmann # define CLOCK_EVT_FEAT_PERCPU 0x000040 63d2348fb6SDaniel Lezcano 645d1638acSPreeti U Murthy /* 655d1638acSPreeti U Murthy * Clockevent device is based on a hrtimer for broadcast 665d1638acSPreeti U Murthy */ 675d1638acSPreeti U Murthy # define CLOCK_EVT_FEAT_HRTIMER 0x000080 685d1638acSPreeti U Murthy 69d316c57fSThomas Gleixner /** 70d316c57fSThomas Gleixner * struct clock_event_device - clock event device descriptor 71847b2f42SThomas Gleixner * @event_handler: Assigned by the framework to be called by the low 72847b2f42SThomas Gleixner * level handler of the event source 7365516f8aSMartin Schwidefsky * @set_next_event: set next event function using a clocksource delta 7465516f8aSMartin Schwidefsky * @set_next_ktime: set next event function using a direct ktime value 75847b2f42SThomas Gleixner * @next_event: local storage for the next event in oneshot mode 76d316c57fSThomas Gleixner * @max_delta_ns: maximum delta value in ns 77d316c57fSThomas Gleixner * @min_delta_ns: minimum delta value in ns 78d316c57fSThomas Gleixner * @mult: nanosecond to cycles multiplier 79d316c57fSThomas Gleixner * @shift: nanoseconds to cycles divisor (power of two) 80be3ef76eSThomas Gleixner * @state_use_accessors:current state of the device, assigned by the core code 81847b2f42SThomas Gleixner * @features: features 82847b2f42SThomas Gleixner * @retries: number of forced programming retries 83*eef7635aSViresh Kumar * @set_state_periodic: switch state to periodic 84*eef7635aSViresh Kumar * @set_state_oneshot: switch state to oneshot 85*eef7635aSViresh Kumar * @set_state_oneshot_stopped: switch state to oneshot_stopped 86*eef7635aSViresh Kumar * @set_state_shutdown: switch state to shutdown 87*eef7635aSViresh Kumar * @tick_resume: resume clkevt device 88847b2f42SThomas Gleixner * @broadcast: function to broadcast events 8957f0fcbeSThomas Gleixner * @min_delta_ticks: minimum delta value in ticks stored for reconfiguration 9057f0fcbeSThomas Gleixner * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration 91847b2f42SThomas Gleixner * @name: ptr to clock event name 92d316c57fSThomas Gleixner * @rating: variable to rate clock event devices 93ce0be127SSergei Shtylyov * @irq: IRQ number (only for non CPU local devices) 945d1638acSPreeti U Murthy * @bound_on: Bound on CPU 95ce0be127SSergei Shtylyov * @cpumask: cpumask to indicate for which CPUs this device works 96d316c57fSThomas Gleixner * @list: list head for the management code 97ccf33d68SThomas Gleixner * @owner: module reference 98d316c57fSThomas Gleixner */ 99d316c57fSThomas Gleixner struct clock_event_device { 100847b2f42SThomas Gleixner void (*event_handler)(struct clock_event_device *); 1019eed56e8SIngo Molnar int (*set_next_event)(unsigned long evt, struct clock_event_device *); 1029eed56e8SIngo Molnar int (*set_next_ktime)(ktime_t expires, struct clock_event_device *); 103847b2f42SThomas Gleixner ktime_t next_event; 10497813f2fSJon Hunter u64 max_delta_ns; 10597813f2fSJon Hunter u64 min_delta_ns; 10623af368eSThomas Gleixner u32 mult; 10723af368eSThomas Gleixner u32 shift; 108be3ef76eSThomas Gleixner enum clock_event_state state_use_accessors; 109847b2f42SThomas Gleixner unsigned int features; 110847b2f42SThomas Gleixner unsigned long retries; 111847b2f42SThomas Gleixner 11277e32c89SViresh Kumar int (*set_state_periodic)(struct clock_event_device *); 11377e32c89SViresh Kumar int (*set_state_oneshot)(struct clock_event_device *); 1148fff52fdSViresh Kumar int (*set_state_oneshot_stopped)(struct clock_event_device *); 11577e32c89SViresh Kumar int (*set_state_shutdown)(struct clock_event_device *); 116554ef387SViresh Kumar int (*tick_resume)(struct clock_event_device *); 117bd624d75SViresh Kumar 118bd624d75SViresh Kumar void (*broadcast)(const struct cpumask *mask); 119adc78e6bSRafael J. Wysocki void (*suspend)(struct clock_event_device *); 120adc78e6bSRafael J. Wysocki void (*resume)(struct clock_event_device *); 12157f0fcbeSThomas Gleixner unsigned long min_delta_ticks; 12257f0fcbeSThomas Gleixner unsigned long max_delta_ticks; 12357f0fcbeSThomas Gleixner 124847b2f42SThomas Gleixner const char *name; 125d316c57fSThomas Gleixner int rating; 126d316c57fSThomas Gleixner int irq; 1275d1638acSPreeti U Murthy int bound_on; 128320ab2b0SRusty Russell const struct cpumask *cpumask; 129d316c57fSThomas Gleixner struct list_head list; 130ccf33d68SThomas Gleixner struct module *owner; 131847b2f42SThomas Gleixner } ____cacheline_aligned; 132d316c57fSThomas Gleixner 1333434d23bSViresh Kumar /* Helpers to verify state of a clockevent device */ 1343434d23bSViresh Kumar static inline bool clockevent_state_detached(struct clock_event_device *dev) 1353434d23bSViresh Kumar { 136be3ef76eSThomas Gleixner return dev->state_use_accessors == CLOCK_EVT_STATE_DETACHED; 1373434d23bSViresh Kumar } 1383434d23bSViresh Kumar 1393434d23bSViresh Kumar static inline bool clockevent_state_shutdown(struct clock_event_device *dev) 1403434d23bSViresh Kumar { 141be3ef76eSThomas Gleixner return dev->state_use_accessors == CLOCK_EVT_STATE_SHUTDOWN; 1423434d23bSViresh Kumar } 1433434d23bSViresh Kumar 1443434d23bSViresh Kumar static inline bool clockevent_state_periodic(struct clock_event_device *dev) 1453434d23bSViresh Kumar { 146be3ef76eSThomas Gleixner return dev->state_use_accessors == CLOCK_EVT_STATE_PERIODIC; 1473434d23bSViresh Kumar } 1483434d23bSViresh Kumar 1493434d23bSViresh Kumar static inline bool clockevent_state_oneshot(struct clock_event_device *dev) 1503434d23bSViresh Kumar { 151be3ef76eSThomas Gleixner return dev->state_use_accessors == CLOCK_EVT_STATE_ONESHOT; 1523434d23bSViresh Kumar } 1533434d23bSViresh Kumar 1543434d23bSViresh Kumar static inline bool clockevent_state_oneshot_stopped(struct clock_event_device *dev) 1553434d23bSViresh Kumar { 156be3ef76eSThomas Gleixner return dev->state_use_accessors == CLOCK_EVT_STATE_ONESHOT_STOPPED; 1573434d23bSViresh Kumar } 1583434d23bSViresh Kumar 159d316c57fSThomas Gleixner /* 160d316c57fSThomas Gleixner * Calculate a multiplication factor for scaled math, which is used to convert 161d316c57fSThomas Gleixner * nanoseconds based values to clock ticks: 162d316c57fSThomas Gleixner * 163d316c57fSThomas Gleixner * clock_ticks = (nanoseconds * factor) >> shift. 164d316c57fSThomas Gleixner * 165d316c57fSThomas Gleixner * div_sc is the rearranged equation to calculate a factor from a given clock 166d316c57fSThomas Gleixner * ticks / nanoseconds ratio: 167d316c57fSThomas Gleixner * 168d316c57fSThomas Gleixner * factor = (clock_ticks << shift) / nanoseconds 169d316c57fSThomas Gleixner */ 1709eed56e8SIngo Molnar static inline unsigned long 1719eed56e8SIngo Molnar div_sc(unsigned long ticks, unsigned long nsec, int shift) 172d316c57fSThomas Gleixner { 1739eed56e8SIngo Molnar u64 tmp = ((u64)ticks) << shift; 174d316c57fSThomas Gleixner 175d316c57fSThomas Gleixner do_div(tmp, nsec); 1769eed56e8SIngo Molnar 177d316c57fSThomas Gleixner return (unsigned long) tmp; 178d316c57fSThomas Gleixner } 179d316c57fSThomas Gleixner 180d316c57fSThomas Gleixner /* Clock event layer functions */ 1819eed56e8SIngo Molnar extern u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt); 182d316c57fSThomas Gleixner extern void clockevents_register_device(struct clock_event_device *dev); 18303e13cf5SThomas Gleixner extern int clockevents_unbind_device(struct clock_event_device *ced, int cpu); 184d316c57fSThomas Gleixner 185e5400321SMagnus Damm extern void clockevents_config(struct clock_event_device *dev, u32 freq); 18657f0fcbeSThomas Gleixner extern void clockevents_config_and_register(struct clock_event_device *dev, 18757f0fcbeSThomas Gleixner u32 freq, unsigned long min_delta, 18857f0fcbeSThomas Gleixner unsigned long max_delta); 18957f0fcbeSThomas Gleixner 19080b816b7SThomas Gleixner extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq); 19180b816b7SThomas Gleixner 1927d2f944aSThomas Gleixner static inline void 1937d2f944aSThomas Gleixner clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec) 1947d2f944aSThomas Gleixner { 1959eed56e8SIngo Molnar return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, minsec); 1967d2f944aSThomas Gleixner } 1977d2f944aSThomas Gleixner 198adc78e6bSRafael J. Wysocki extern void clockevents_suspend(void); 199adc78e6bSRafael J. Wysocki extern void clockevents_resume(void); 200adc78e6bSRafael J. Wysocki 20112572dbbSMark Rutland # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 20212ad1000SMark Rutland # ifdef CONFIG_ARCH_HAS_TICK_BROADCAST 20312ad1000SMark Rutland extern void tick_broadcast(const struct cpumask *mask); 20412ad1000SMark Rutland # else 20512ad1000SMark Rutland # define tick_broadcast NULL 20612ad1000SMark Rutland # endif 20712572dbbSMark Rutland extern int tick_receive_broadcast(void); 20812572dbbSMark Rutland # endif 20912572dbbSMark Rutland 210eaa907c5SThomas Gleixner # if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT) 2115d1638acSPreeti U Murthy extern void tick_setup_hrtimer_broadcast(void); 212eaa907c5SThomas Gleixner extern int tick_check_broadcast_expired(void); 213eaa907c5SThomas Gleixner # else 214eaa907c5SThomas Gleixner static inline int tick_check_broadcast_expired(void) { return 0; } 2159eed56e8SIngo Molnar static inline void tick_setup_hrtimer_broadcast(void) { } 216eaa907c5SThomas Gleixner # endif 217eaa907c5SThomas Gleixner 2189eed56e8SIngo Molnar #else /* !CONFIG_GENERIC_CLOCKEVENTS: */ 219d316c57fSThomas Gleixner 220adc78e6bSRafael J. Wysocki static inline void clockevents_suspend(void) { } 221adc78e6bSRafael J. Wysocki static inline void clockevents_resume(void) { } 22219919226SThomas Gleixner static inline int tick_check_broadcast_expired(void) { return 0; } 2239eed56e8SIngo Molnar static inline void tick_setup_hrtimer_broadcast(void) { } 224d316c57fSThomas Gleixner 2259eed56e8SIngo Molnar #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ 226d316c57fSThomas Gleixner 2279eed56e8SIngo Molnar #endif /* _LINUX_CLOCKCHIPS_H */ 228