clockchips.h 4.4 KB
Newer Older
1 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

11
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <linux/clocksource.h>
#include <linux/cpumask.h>
#include <linux/ktime.h>
#include <linux/notifier.h>

struct clock_event_device;

/* Clock event mode commands */
enum clock_event_mode {
	CLOCK_EVT_MODE_UNUSED = 0,
	CLOCK_EVT_MODE_SHUTDOWN,
	CLOCK_EVT_MODE_PERIODIC,
	CLOCK_EVT_MODE_ONESHOT,
T
Thomas Gleixner 已提交
26
	CLOCK_EVT_MODE_RESUME,
27 28 29 30 31 32 33
};

/* Clock event notification values */
enum clock_event_nofitiers {
	CLOCK_EVT_NOTIFY_ADD,
	CLOCK_EVT_NOTIFY_BROADCAST_ON,
	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
34
	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
35 36 37 38
	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
	CLOCK_EVT_NOTIFY_SUSPEND,
	CLOCK_EVT_NOTIFY_RESUME,
39
	CLOCK_EVT_NOTIFY_CPU_DYING,
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
	CLOCK_EVT_NOTIFY_CPU_DEAD,
};

/*
 * Clock event features
 */
#define CLOCK_EVT_FEAT_PERIODIC		0x000001
#define CLOCK_EVT_FEAT_ONESHOT		0x000002
/*
 * x86(64) specific misfeatures:
 *
 * - Clockevent source stops in C3 State and needs broadcast support.
 * - Local APIC timer is used as a dummy device.
 */
#define CLOCK_EVT_FEAT_C3STOP		0x000004
#define CLOCK_EVT_FEAT_DUMMY		0x000008

/**
 * struct clock_event_device - clock event device descriptor
 * @name:		ptr to clock event name
S
Sergei Shtylyov 已提交
60
 * @features:		features
61 62 63 64 65
 * @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)
 * @rating:		variable to rate clock event devices
S
Sergei Shtylyov 已提交
66 67 68
 * @irq:		IRQ number (only for non CPU local devices)
 * @cpumask:		cpumask to indicate for which CPUs this device works
 * @set_next_event:	set next event function
69
 * @set_mode:		set mode function
S
Sergei Shtylyov 已提交
70
 * @event_handler:	Assigned by the framework to be called by the low
71 72 73 74 75 76 77 78 79 80 81
 *			level handler of the event source
 * @broadcast:		function to broadcast events
 * @list:		list head for the management code
 * @mode:		operating mode assigned by the management code
 * @next_event:		local storage for the next event in oneshot mode
 */
struct clock_event_device {
	const char		*name;
	unsigned int		features;
	unsigned long		max_delta_ns;
	unsigned long		min_delta_ns;
82 83
	u32			mult;
	u32			shift;
84 85
	int			rating;
	int			irq;
86
	const struct cpumask	*cpumask;
87 88 89 90 91
	int			(*set_next_event)(unsigned long evt,
						  struct clock_event_device *);
	void			(*set_mode)(enum clock_event_mode mode,
					    struct clock_event_device *);
	void			(*event_handler)(struct clock_event_device *);
92
	void			(*broadcast)(const struct cpumask *mask);
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
	struct list_head	list;
	enum clock_event_mode	mode;
	ktime_t			next_event;
};

/*
 * 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
 */
static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec,
				   int shift)
{
	uint64_t tmp = ((uint64_t)ticks) << shift;

	do_div(tmp, nsec);
	return (unsigned long) tmp;
}

/* Clock event layer functions */
extern unsigned long clockevent_delta2ns(unsigned long latch,
					 struct clock_event_device *evt);
extern void clockevents_register_device(struct clock_event_device *dev);

extern void clockevents_exchange_device(struct clock_event_device *old,
					struct clock_event_device *new);
extern void clockevents_set_mode(struct clock_event_device *dev,
				 enum clock_event_mode mode);
extern int clockevents_register_notifier(struct notifier_block *nb);
extern int clockevents_program_event(struct clock_event_device *dev,
				     ktime_t expires, ktime_t now);

131 132
extern void clockevents_handle_noop(struct clock_event_device *dev);

133 134 135 136 137 138 139
static inline void
clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
{
	return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC,
				      freq, minsec);
}

140
#ifdef CONFIG_GENERIC_CLOCKEVENTS
141 142
extern void clockevents_notify(unsigned long reason, void *arg);
#else
143 144 145 146
# define clockevents_notify(reason, arg) do { } while (0)
#endif

#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
147 148 149 150 151 152

#define clockevents_notify(reason, arg) do { } while (0)

#endif

#endif