blob: 5af441efb37754fb7c76483c37e8aa50eb1d0848 [file] [log] [blame]
Gennady Sharapovcff65c42006-01-18 17:42:42 -08001/*
Jeff Dikeba180fd2007-10-16 01:27:00 -07002 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Licensed under the GPL
4 */
5
Jeff Dikec5d4bb12008-02-04 22:31:14 -08006#include <linux/clockchips.h>
Adrian Bunk7d195a52008-04-29 00:59:18 -07007#include <linux/init.h>
Jeff Dikec5d4bb12008-02-04 22:31:14 -08008#include <linux/interrupt.h>
9#include <linux/jiffies.h>
10#include <linux/threads.h>
11#include <asm/irq.h>
12#include <asm/param.h>
Al Viro37185b32012-10-08 03:27:32 +010013#include <kern_util.h>
14#include <os.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
Martin Pärteld3c1cfc2012-08-02 00:49:17 +020016void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017{
Jeff Dike31ccc1f2007-10-16 01:27:24 -070018 unsigned long flags;
Jeff Dike31ccc1f2007-10-16 01:27:24 -070019
20 local_irq_save(flags);
Jeff Diked2753a6d2007-10-16 01:27:25 -070021 do_IRQ(TIMER_IRQ, regs);
Jeff Dike31ccc1f2007-10-16 01:27:24 -070022 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070023}
24
Viresh Kumar71b52802015-07-16 16:56:31 +053025static int itimer_shutdown(struct clock_event_device *evt)
Gennady Sharapovcff65c42006-01-18 17:42:42 -080026{
Viresh Kumar71b52802015-07-16 16:56:31 +053027 disable_timer();
28 return 0;
29}
Gennady Sharapovcff65c42006-01-18 17:42:42 -080030
Viresh Kumar71b52802015-07-16 16:56:31 +053031static int itimer_set_periodic(struct clock_event_device *evt)
32{
33 set_interval();
34 return 0;
Gennady Sharapovcff65c42006-01-18 17:42:42 -080035}
36
Jeff Diked2753a6d2007-10-16 01:27:25 -070037static int itimer_next_event(unsigned long delta,
38 struct clock_event_device *evt)
39{
40 return timer_one_shot(delta + 1);
41}
42
Jeff Dike31ccc1f2007-10-16 01:27:24 -070043static struct clock_event_device itimer_clockevent = {
Viresh Kumar71b52802015-07-16 16:56:31 +053044 .name = "itimer",
45 .rating = 250,
46 .cpumask = cpu_all_mask,
47 .features = CLOCK_EVT_FEAT_PERIODIC |
48 CLOCK_EVT_FEAT_ONESHOT,
49 .set_state_shutdown = itimer_shutdown,
50 .set_state_periodic = itimer_set_periodic,
51 .set_state_oneshot = itimer_shutdown,
52 .set_next_event = itimer_next_event,
53 .shift = 32,
54 .irq = 0,
Jeff Dike31ccc1f2007-10-16 01:27:24 -070055};
56
57static irqreturn_t um_timer(int irq, void *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058{
Jeff Dike31ccc1f2007-10-16 01:27:24 -070059 (*itimer_clockevent.event_handler)(&itimer_clockevent);
Gennady Sharapovcff65c42006-01-18 17:42:42 -080060
Jeff Dike572e6142006-06-30 01:55:56 -070061 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062}
63
Magnus Damm8e196082009-04-21 12:24:00 -070064static cycle_t itimer_read(struct clocksource *cs)
Jeff Dike791a6442007-10-16 01:27:25 -070065{
Jeff Dikecfd28f62008-05-12 14:01:53 -070066 return os_nsecs() / 1000;
Jeff Dike791a6442007-10-16 01:27:25 -070067}
68
69static struct clocksource itimer_clocksource = {
70 .name = "itimer",
71 .rating = 300,
72 .read = itimer_read,
73 .mask = CLOCKSOURCE_MASK(64),
Jeff Dike791a6442007-10-16 01:27:25 -070074 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
75};
76
Jeff Dike31ccc1f2007-10-16 01:27:24 -070077static void __init setup_itimer(void)
Jeff Dikeaceb34342006-07-10 04:45:05 -070078{
79 int err;
80
Yong Zhangc0b79a92011-09-22 16:58:46 +080081 err = request_irq(TIMER_IRQ, um_timer, 0, "timer", NULL);
Jeff Dikeba180fd2007-10-16 01:27:00 -070082 if (err != 0)
Jeff Dike537ae942006-09-25 23:33:05 -070083 printk(KERN_ERR "register_timer : request_irq failed - "
Jeff Dikeaceb34342006-07-10 04:45:05 -070084 "errno = %d\n", -err);
85
Jeff Dike31ccc1f2007-10-16 01:27:24 -070086 itimer_clockevent.mult = div_sc(HZ, NSEC_PER_SEC, 32);
87 itimer_clockevent.max_delta_ns =
88 clockevent_delta2ns(60 * HZ, &itimer_clockevent);
89 itimer_clockevent.min_delta_ns =
90 clockevent_delta2ns(1, &itimer_clockevent);
John Stultz60d687e2010-04-26 20:25:16 -070091 err = clocksource_register_hz(&itimer_clocksource, USEC_PER_SEC);
Jeff Dike791a6442007-10-16 01:27:25 -070092 if (err) {
John Stultz60d687e2010-04-26 20:25:16 -070093 printk(KERN_ERR "clocksource_register_hz returned %d\n", err);
Jeff Dike791a6442007-10-16 01:27:25 -070094 return;
95 }
Jeff Dike31ccc1f2007-10-16 01:27:24 -070096 clockevents_register_device(&itimer_clockevent);
Jeff Dikeaceb34342006-07-10 04:45:05 -070097}
98
John Stultz9f31f572010-07-13 17:56:24 -070099void read_persistent_clock(struct timespec *ts)
100{
Thomas Gleixnerb2923072010-08-03 20:34:48 +0200101 long long nsecs = os_nsecs();
102
John Stultz9f31f572010-07-13 17:56:24 -0700103 set_normalized_timespec(ts, nsecs / NSEC_PER_SEC,
104 nsecs % NSEC_PER_SEC);
105}
106
Jeff Dike31ccc1f2007-10-16 01:27:24 -0700107void __init time_init(void)
Jeff Dikeaceb34342006-07-10 04:45:05 -0700108{
Jeff Dike31ccc1f2007-10-16 01:27:24 -0700109 timer_init();
Jeff Dike31ccc1f2007-10-16 01:27:24 -0700110 late_time_init = setup_itimer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}