aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/clockchips.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/clockchips.h')
-rw-r--r--include/linux/clockchips.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
new file mode 100644
index 00000000..acc14353
--- /dev/null
+++ b/include/linux/clockchips.h
@@ -0,0 +1,172 @@
+/* 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
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+
+#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,
+ CLOCK_EVT_MODE_RESUME,
+};
+
+/* Clock event notification values */
+enum clock_event_nofitiers {
+ CLOCK_EVT_NOTIFY_ADD,
+ CLOCK_EVT_NOTIFY_BROADCAST_ON,
+ CLOCK_EVT_NOTIFY_BROADCAST_OFF,
+ CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
+ CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
+ CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+ CLOCK_EVT_NOTIFY_SUSPEND,
+ CLOCK_EVT_NOTIFY_RESUME,
+ CLOCK_EVT_NOTIFY_CPU_DYING,
+ 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
+ * @event_handler: Assigned by the framework to be called by the low
+ * level handler of the event source
+ * @set_next_event: set next event function
+ * @next_event: local storage for the next event in oneshot mode
+ * @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)
+ * @mode: operating mode assigned by the management code
+ * @features: features
+ * @retries: number of forced programming retries
+ * @set_mode: set mode function
+ * @broadcast: function to broadcast events
+ * @min_delta_ticks: minimum delta value in ticks stored for reconfiguration
+ * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration
+ * @name: ptr to clock event name
+ * @rating: variable to rate clock event devices
+ * @irq: IRQ number (only for non CPU local devices)
+ * @cpumask: cpumask to indicate for which CPUs this device works
+ * @list: list head for the management code
+ */
+struct clock_event_device {
+ void (*event_handler)(struct clock_event_device *);
+ int (*set_next_event)(unsigned long evt,
+ struct clock_event_device *);
+ ktime_t next_event;
+ u64 max_delta_ns;
+ u64 min_delta_ns;
+ u32 mult;
+ u32 shift;
+ enum clock_event_mode mode;
+ unsigned int features;
+ unsigned long retries;
+
+ void (*broadcast)(const struct cpumask *mask);
+ void (*set_mode)(enum clock_event_mode mode,
+ struct clock_event_device *);
+ unsigned long min_delta_ticks;
+ unsigned long max_delta_ticks;
+
+ const char *name;
+ int rating;
+ int irq;
+ const struct cpumask *cpumask;
+ struct list_head list;
+} ____cacheline_aligned;
+
+/*
+ * 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 u64 clockevent_delta2ns(unsigned long latch,
+ struct clock_event_device *evt);
+extern void clockevents_register_device(struct clock_event_device *dev);
+
+extern void clockevents_config_and_register(struct clock_event_device *dev,
+ u32 freq, unsigned long min_delta,
+ unsigned long max_delta);
+
+extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
+
+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);
+
+extern void clockevents_handle_noop(struct clock_event_device *dev);
+
+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);
+}
+
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern int tick_check_broadcast_pending(void);
+#else
+static inline int tick_check_broadcast_pending(void) { return 0; }
+#endif
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+extern void clockevents_notify(unsigned long reason, void *arg);
+#else
+# define clockevents_notify(reason, arg) do { } while (0)
+#endif
+
+#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
+
+#define clockevents_notify(reason, arg) do { } while (0)
+
+#endif
+
+#endif