clockevents.c revision c0e299b1a91cbdb21ae08e382a4176200398bc36
1d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/*
2d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * linux/kernel/time/clockevents.c
3d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
4d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * This file contains functions which manage clock event devices.
5d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
6d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
7d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
8d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
9d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
10d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * This code is licenced under the GPL version 2. For details see
11d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * kernel-base/COPYING.
12d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
13d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
14d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/clockchips.h>
15d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/hrtimer.h>
16d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/init.h>
17d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/module.h>
18d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/notifier.h>
19d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/smp.h>
20d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/sysdev.h>
21d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
228e1a928a2ed7e8d5cad97c8e985294b4caedd168H Hartley Sweeten#include "tick-internal.h"
238e1a928a2ed7e8d5cad97c8e985294b4caedd168H Hartley Sweeten
24d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* The registered clock event devices */
25d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic LIST_HEAD(clockevent_devices);
26d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic LIST_HEAD(clockevents_released);
27d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
28d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* Notification for clock events */
29d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic RAW_NOTIFIER_HEAD(clockevents_chain);
30d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
31d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* Protection for the above */
32b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixnerstatic DEFINE_RAW_SPINLOCK(clockevents_lock);
33d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
34d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
35d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
36d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @latch:	value to convert
37d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @evt:	pointer to clock event device descriptor
38d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
39d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Math helper, returns latch value converted to nanoseconds (bound checked)
40d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
4197813f2fe77804a4464564c75ba8d8826377feeaJon Hunteru64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
42d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
4397813f2fe77804a4464564c75ba8d8826377feeaJon Hunter	u64 clc = (u64) latch << evt->shift;
44d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
4545fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar	if (unlikely(!evt->mult)) {
4645fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar		evt->mult = 1;
4745fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar		WARN_ON(1);
4845fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar	}
4945fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar
50d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	do_div(clc, evt->mult);
51d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (clc < 1000)
52d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		clc = 1000;
5397813f2fe77804a4464564c75ba8d8826377feeaJon Hunter	if (clc > KTIME_MAX)
5497813f2fe77804a4464564c75ba8d8826377feeaJon Hunter		clc = KTIME_MAX;
55d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
5697813f2fe77804a4464564c75ba8d8826377feeaJon Hunter	return clc;
57d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
58c81fc2c331b8514ad112054cd2d87e6ec132286bMagnus DammEXPORT_SYMBOL_GPL(clockevent_delta2ns);
59d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
60d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
61d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_set_mode - set the operating mode of a clock event device
62d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @dev:	device to modify
63d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @mode:	new mode
64d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
65d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Must be called with interrupts disabled !
66d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
67d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_set_mode(struct clock_event_device *dev,
68d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner				 enum clock_event_mode mode)
69d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
70d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (dev->mode != mode) {
71d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		dev->set_mode(mode, dev);
72d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		dev->mode = mode;
732d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm
742d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm		/*
752d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm		 * A nsec2cyc multiplicator of 0 is invalid and we'd crash
762d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm		 * on it, so fix it up and emit a warning:
772d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm		 */
782d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm		if (mode == CLOCK_EVT_MODE_ONESHOT) {
792d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm			if (unlikely(!dev->mult)) {
802d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm				dev->mult = 1;
812d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm				WARN_ON(1);
822d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm			}
832d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm		}
84d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	}
85d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
86d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
87d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
882344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner * clockevents_shutdown - shutdown the device and clear next_event
892344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner * @dev:	device to shutdown
902344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner */
912344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixnervoid clockevents_shutdown(struct clock_event_device *dev)
922344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner{
932344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner	clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
942344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner	dev->next_event.tv64 = KTIME_MAX;
952344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner}
962344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner
972344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner/**
98d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_program_event - Reprogram the clock event device.
99d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @expires:	absolute expiry time (monotonic clock)
100d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
101d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Returns 0 on success, -ETIME when the event is in the past.
102d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
103d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerint clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
104d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner			      ktime_t now)
105d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
106d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	unsigned long long clc;
107d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	int64_t delta;
108d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
109167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner	if (unlikely(expires.tv64 < 0)) {
110167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner		WARN_ON_ONCE(1);
111167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner		return -ETIME;
112167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner	}
113167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner
114d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	delta = ktime_to_ns(ktime_sub(expires, now));
115d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
116d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (delta <= 0)
117d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		return -ETIME;
118d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
119d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	dev->next_event = expires;
120d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
121d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
122d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		return 0;
123d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
124d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (delta > dev->max_delta_ns)
125d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		delta = dev->max_delta_ns;
126d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (delta < dev->min_delta_ns)
127d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		delta = dev->min_delta_ns;
128d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
129d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	clc = delta * dev->mult;
130d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	clc >>= dev->shift;
131d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
132d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	return dev->set_next_event((unsigned long) clc, dev);
133d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
134d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
135d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
136d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_register_notifier - register a clock events change listener
137d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
138d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerint clockevents_register_notifier(struct notifier_block *nb)
139d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
140f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha	unsigned long flags;
141d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	int ret;
142d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
143b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner	raw_spin_lock_irqsave(&clockevents_lock, flags);
144d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	ret = raw_notifier_chain_register(&clockevents_chain, nb);
145b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
146d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
147d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	return ret;
148d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
149d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
150d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/*
151d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Notify about a clock event change. Called with clockevents_lock
152d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * held.
153d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
154d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic void clockevents_do_notify(unsigned long reason, void *dev)
155d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
156d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	raw_notifier_call_chain(&clockevents_chain, reason, dev);
157d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
158d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
159d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/*
1603eb056764dd806bbe84eb604e45e7470feeaafd8Li Zefan * Called after a notify add to make devices available which were
161d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released from the notifier call.
162d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
163d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic void clockevents_notify_released(void)
164d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
165d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	struct clock_event_device *dev;
166d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
167d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	while (!list_empty(&clockevents_released)) {
168d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		dev = list_entry(clockevents_released.next,
169d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner				 struct clock_event_device, list);
170d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		list_del(&dev->list);
171d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		list_add(&dev->list, &clockevent_devices);
172d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
173d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	}
174d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
175d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
176d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
177d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_register_device - register a clock event device
178d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @dev:	device to register
179d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
180d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_register_device(struct clock_event_device *dev)
181d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
182f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha	unsigned long flags;
183f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha
184d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
185320ab2b0b1e08e3805a3e1084a2f0eb1938d5d67Rusty Russell	BUG_ON(!dev->cpumask);
186320ab2b0b1e08e3805a3e1084a2f0eb1938d5d67Rusty Russell
187b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner	raw_spin_lock_irqsave(&clockevents_lock, flags);
188d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
189d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	list_add(&dev->list, &clockevent_devices);
190d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
191d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	clockevents_notify_released();
192d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
193b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
194d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
195c81fc2c331b8514ad112054cd2d87e6ec132286bMagnus DammEXPORT_SYMBOL_GPL(clockevents_register_device);
196d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
19757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixnerstatic void clockevents_config(struct clock_event_device *dev,
19857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner			       u32 freq)
19957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner{
200c0e299b1a91cbdb21ae08e382a4176200398bc36Thomas Gleixner	u64 sec;
20157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner
20257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
20357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner		return;
20457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner
20557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	/*
20657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	 * Calculate the maximum number of seconds we can sleep. Limit
20757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	 * to 10 minutes for hardware which can program more than
20857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	 * 32bit ticks so we still get reasonable conversion values.
20957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	 */
21057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	sec = dev->max_delta_ticks;
21157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	do_div(sec, freq);
21257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	if (!sec)
21357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner		sec = 1;
21457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	else if (sec > 600 && dev->max_delta_ticks > UINT_MAX)
21557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner		sec = 600;
21657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner
21757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	clockevents_calc_mult_shift(dev, freq, sec);
21857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev);
21957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev);
22057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner}
22157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner
22257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner/**
22357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * clockevents_config_and_register - Configure and register a clock event device
22457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @dev:	device to register
22557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @freq:	The clock frequency
22657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @min_delta:	The minimum clock ticks to program in oneshot mode
22757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @max_delta:	The maximum clock ticks to program in oneshot mode
22857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner *
22957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * min/max_delta can be 0 for devices which do not support oneshot mode.
23057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner */
23157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixnervoid clockevents_config_and_register(struct clock_event_device *dev,
23257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner				     u32 freq, unsigned long min_delta,
23357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner				     unsigned long max_delta)
23457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner{
23557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	dev->min_delta_ticks = min_delta;
23657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	dev->max_delta_ticks = max_delta;
23757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	clockevents_config(dev, freq);
23857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner	clockevents_register_device(dev);
23957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner}
24057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner
24180b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner/**
24280b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * clockevents_update_freq - Update frequency and reprogram a clock event device.
24380b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * @dev:	device to modify
24480b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * @freq:	new device frequency
24580b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner *
24680b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * Reconfigure and reprogram a clock event device in oneshot
24780b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * mode. Must be called on the cpu for which the device delivers per
24880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * cpu timer events with interrupts disabled!  Returns 0 on success,
24980b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * -ETIME when the event is in the past.
25080b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner */
25180b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixnerint clockevents_update_freq(struct clock_event_device *dev, u32 freq)
25280b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner{
25380b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner	clockevents_config(dev, freq);
25480b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner
25580b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner	if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
25680b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner		return 0;
25780b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner
25880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner	return clockevents_program_event(dev, dev->next_event, ktime_get());
25980b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner}
26080b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner
261d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/*
262d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Noop handler when we shut down an event device
263d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
2647c1e76897492d92b6a1c2d6892494d39ded9680cVenkatesh Pallipadivoid clockevents_handle_noop(struct clock_event_device *dev)
265d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
266d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
267d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
268d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
269d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_exchange_device - release and request clock devices
270d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @old:	device to release (can be NULL)
271d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @new:	device to request (can be NULL)
272d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner *
273d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Called from the notifier chain. clockevents_lock is held already
274d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
275d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_exchange_device(struct clock_event_device *old,
276d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner				 struct clock_event_device *new)
277d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
278d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	unsigned long flags;
279d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
280d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	local_irq_save(flags);
281d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	/*
282d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	 * Caller releases a clock event device. We queue it into the
283d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	 * released list and do a notify add later.
284d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	 */
285d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (old) {
286d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
287d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		list_del(&old->list);
288d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		list_add(&old->list, &clockevents_released);
289d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	}
290d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
291d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	if (new) {
292d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
2932344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner		clockevents_shutdown(new);
294d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	}
295d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	local_irq_restore(flags);
296d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
297d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
298de68d9b173ee657115dd0e584c2365b7954253a5Thomas Gleixner#ifdef CONFIG_GENERIC_CLOCKEVENTS
299d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/**
300d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_notify - notification about relevant events
301d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */
302d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_notify(unsigned long reason, void *arg)
303d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{
304bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner	struct clock_event_device *dev, *tmp;
305f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha	unsigned long flags;
306bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner	int cpu;
3070b858e6ff9a38b987a83d22e6f2a2f621c80608dLi Zefan
308b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner	raw_spin_lock_irqsave(&clockevents_lock, flags);
309d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	clockevents_do_notify(reason, arg);
310d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner
311d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	switch (reason) {
312d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	case CLOCK_EVT_NOTIFY_CPU_DEAD:
313d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		/*
314d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		 * Unregister the clock event devices which were
315d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		 * released from the users in the notify chain.
316d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		 */
317bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
318bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner			list_del(&dev->list);
319bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		/*
320bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		 * Now check whether the CPU has left unused per cpu devices
321bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		 */
322bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		cpu = *((int *)arg);
323bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
324bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner			if (cpumask_test_cpu(cpu, dev->cpumask) &&
325ea9d8e3f45404d411c00ae67b45cc35c58265bb7Xiaotian Feng			    cpumask_weight(dev->cpumask) == 1 &&
326ea9d8e3f45404d411c00ae67b45cc35c58265bb7Xiaotian Feng			    !tick_is_broadcast_device(dev)) {
327bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner				BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
328bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner				list_del(&dev->list);
329bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner			}
330bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner		}
331d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		break;
332d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	default:
333d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner		break;
334d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner	}
335b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
336d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner}
337d316c57ff6bfad9557462b9100f25c6260d2b774Thomas GleixnerEXPORT_SYMBOL_GPL(clockevents_notify);
338de68d9b173ee657115dd0e584c2365b7954253a5Thomas Gleixner#endif
339