Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer and time updates from Thomas Gleixner:
 "A rather large update of timers, timekeeping & co

   - Core timekeeping code is year-2038 safe now for 32bit machines.
     Now we just need to fix all in kernel users and the gazillion of
     user space interfaces which rely on timespec/timeval :)

   - Better cache layout for the timekeeping internal data structures.

   - Proper nanosecond based interfaces for in kernel users.

   - Tree wide cleanup of code which wants nanoseconds but does hoops
     and loops to convert back and forth from timespecs.  Some of it
     definitely belongs into the ugly code museum.

   - Consolidation of the timekeeping interface zoo.

   - A fast NMI safe accessor to clock monotonic for tracing.  This is a
     long standing request to support correlated user/kernel space
     traces.  With proper NTP frequency correction it's also suitable
     for correlation of traces accross separate machines.

   - Checkpoint/restart support for timerfd.

   - A few NOHZ[_FULL] improvements in the [hr]timer code.

   - Code move from kernel to kernel/time of all time* related code.

   - New clocksource/event drivers from the ARM universe.  I'm really
     impressed that despite an architected timer in the newer chips SoC
     manufacturers insist on inventing new and differently broken SoC
     specific timers.

[ Ed. "Impressed"? I don't think that word means what you think it means ]

   - Another round of code move from arch to drivers.  Looks like most
     of the legacy mess in ARM regarding timers is sorted out except for
     a few obnoxious strongholds.

   - The usual updates and fixlets all over the place"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (114 commits)
  timekeeping: Fixup typo in update_vsyscall_old definition
  clocksource: document some basic timekeeping concepts
  timekeeping: Use cached ntp_tick_length when accumulating error
  timekeeping: Rework frequency adjustments to work better w/ nohz
  timekeeping: Minor fixup for timespec64->timespec assignment
  ftrace: Provide trace clocks monotonic
  timekeeping: Provide fast and NMI safe access to CLOCK_MONOTONIC
  seqcount: Add raw_write_seqcount_latch()
  seqcount: Provide raw_read_seqcount()
  timekeeping: Use tk_read_base as argument for timekeeping_get_ns()
  timekeeping: Create struct tk_read_base and use it in struct timekeeper
  timekeeping: Restructure the timekeeper some more
  clocksource: Get rid of cycle_last
  clocksource: Move cycle_last validation to core code
  clocksource: Make delta calculation a function
  wireless: ath9k: Get rid of timespec conversions
  drm: vmwgfx: Use nsec based interfaces
  drm: i915: Use nsec based interfaces
  timekeeping: Provide ktime_get_raw()
  hangcheck-timer: Use ktime_get_ns()
  ...
This commit is contained in:
Linus Torvalds
2014-08-05 17:46:42 -07:00
108 changed files with 3236 additions and 1938 deletions
+2 -2
View File
@@ -54,7 +54,7 @@
!Ikernel/sched/cpupri.c
!Ikernel/sched/fair.c
!Iinclude/linux/completion.h
!Ekernel/timer.c
!Ekernel/time/timer.c
</sect1>
<sect1><title>Wait queues and Wake events</title>
!Iinclude/linux/wait.h
@@ -63,7 +63,7 @@
<sect1><title>High-resolution timers</title>
!Iinclude/linux/ktime.h
!Iinclude/linux/hrtimer.h
!Ekernel/hrtimer.c
!Ekernel/time/hrtimer.c
</sect1>
<sect1><title>Workqueues and Kevents</title>
!Ekernel/workqueue.c
@@ -0,0 +1,29 @@
* Cirrus Logic CLPS711X Timer Counter
Required properties:
- compatible: Shall contain "cirrus,clps711x-timer".
- reg : Address and length of the register set.
- interrupts: The interrupt number of the timer.
- clocks : phandle of timer reference clock.
Note: Each timer should have an alias correctly numbered in "aliases" node.
Example:
aliases {
timer0 = &timer1;
timer1 = &timer2;
};
timer1: timer@80000300 {
compatible = "cirrus,ep7312-timer", "cirrus,clps711x-timer";
reg = <0x80000300 0x4>;
interrupts = <8>;
clocks = <&clks 5>;
};
timer2: timer@80000340 {
compatible = "cirrus,ep7312-timer", "cirrus,clps711x-timer";
reg = <0x80000340 0x4>;
interrupts = <9>;
clocks = <&clks 6>;
};
@@ -0,0 +1,17 @@
Mediatek MT6577, MT6572 and MT6589 Timers
---------------------------------------
Required properties:
- compatible: Should be "mediatek,mt6577-timer"
- reg: Should contain location and length for timers register.
- clocks: Clocks driving the timer hardware. This list should include two
clocks. The order is system clock and as second clock the RTC clock.
Examples:
timer@10008000 {
compatible = "mediatek,mt6577-timer";
reg = <0x10008000 0x80>;
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>;
clocks = <&system_clk>, <&rtc_clk>;
};
@@ -0,0 +1,47 @@
* Renesas R-Car Compare Match Timer (CMT)
The CMT is a multi-channel 16/32/48-bit timer/counter with configurable clock
inputs and programmable compare match.
Channels share hardware resources but their counter and compare match value
are independent. A particular CMT instance can implement only a subset of the
channels supported by the CMT model. Channel indices represent the hardware
position of the channel in the CMT and don't match the channel numbers in the
datasheets.
Required Properties:
- compatible: must contain one of the following.
- "renesas,cmt-32" for the 32-bit CMT
(CMT0 on sh7372, sh73a0 and r8a7740)
- "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
(CMT[234] on sh7372, sh73a0 and r8a7740)
- "renesas,cmt-48" for the 48-bit CMT
(CMT1 on sh7372, sh73a0 and r8a7740)
- "renesas,cmt-48-gen2" for the second generation 48-bit CMT
(CMT[01] on r8a73a4, r8a7790 and r8a7791)
- reg: base address and length of the registers block for the timer module.
- interrupts: interrupt-specifier for the timer, one per channel.
- clocks: a list of phandle + clock-specifier pairs, one for each entry
in clock-names.
- clock-names: must contain "fck" for the functional clock.
- renesas,channels-mask: bitmask of the available channels.
Example: R8A7790 (R-Car H2) CMT0 node
CMT0 on R8A7790 implements hardware channels 5 and 6 only and names
them channels 0 and 1 in the documentation.
cmt0: timer@ffca0000 {
compatible = "renesas,cmt-48-gen2";
reg = <0 0xffca0000 0 0x1004>;
interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
<0 142 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
clock-names = "fck";
renesas,channels-mask = <0x60>;
};
@@ -0,0 +1,39 @@
* Renesas R-Car Multi-Function Timer Pulse Unit 2 (MTU2)
The MTU2 is a multi-purpose, multi-channel timer/counter with configurable
clock inputs and programmable compare match.
Channels share hardware resources but their counter and compare match value
are independent. The MTU2 hardware supports five channels indexed from 0 to 4.
Required Properties:
- compatible: must contain "renesas,mtu2"
- reg: base address and length of the registers block for the timer module.
- interrupts: interrupt specifiers for the timer, one for each entry in
interrupt-names.
- interrupt-names: must contain one entry named "tgi?a" for each enabled
channel, where "?" is the channel index expressed as one digit from "0" to
"4".
- clocks: a list of phandle + clock-specifier pairs, one for each entry
in clock-names.
- clock-names: must contain "fck" for the functional clock.
Example: R7S72100 (RZ/A1H) MTU2 node
mtu2: timer@fcff0000 {
compatible = "renesas,mtu2";
reg = <0xfcff0000 0x400>;
interrupts = <0 139 IRQ_TYPE_LEVEL_HIGH>,
<0 146 IRQ_TYPE_LEVEL_HIGH>,
<0 150 IRQ_TYPE_LEVEL_HIGH>,
<0 154 IRQ_TYPE_LEVEL_HIGH>,
<0 159 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tgi0a", "tgi1a", "tgi2a", "tgi3a", "tgi4a";
clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
clock-names = "fck";
};
@@ -0,0 +1,39 @@
* Renesas R-Car Timer Unit (TMU)
The TMU is a 32-bit timer/counter with configurable clock inputs and
programmable compare match.
Channels share hardware resources but their counter and compare match value
are independent. The TMU hardware supports up to three channels.
Required Properties:
- compatible: must contain "renesas,tmu"
- reg: base address and length of the registers block for the timer module.
- interrupts: interrupt-specifier for the timer, one per channel.
- clocks: a list of phandle + clock-specifier pairs, one for each entry
in clock-names.
- clock-names: must contain "fck" for the functional clock.
Optional Properties:
- #renesas,channels: number of channels implemented by the timer, must be 2
or 3 (if not specified the value defaults to 3).
Example: R8A7779 (R-Car H1) TMU0 node
tmu0: timer@ffd80000 {
compatible = "renesas,tmu";
reg = <0xffd80000 0x30>;
interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
<0 33 IRQ_TYPE_LEVEL_HIGH>,
<0 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp0_clks R8A7779_CLK_TMU0>;
clock-names = "fck";
#renesas,channels = <3>;
};
@@ -78,6 +78,7 @@ lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products
mediatek MediaTek Inc.
micrel Micrel Inc.
microchip Microchip Technology Inc.
mosaixtech Mosaix Technologies, Inc.
+19
View File
@@ -1743,6 +1743,25 @@ pair provide additional information particular to the objects they represent.
While the first three lines are mandatory and always printed, the rest is
optional and may be omitted if no marks created yet.
Timerfd files
~~~~~~~~~~~~~
pos: 0
flags: 02
mnt_id: 9
clockid: 0
ticks: 0
settime flags: 01
it_value: (0, 49406829)
it_interval: (1, 0)
where 'clockid' is the clock type and 'ticks' is the number of the timer expirations
that have occurred [see timerfd_create(2) for details]. 'settime flags' are
flags in octal form been used to setup the timer [see timerfd_settime(2) for
details]. 'it_value' is remaining time until the timer exiration.
'it_interval' is the interval for the timer. Note the timer might be set up
with TIMER_ABSTIME option which will be shown in 'settime flags', but 'it_value'
still exhibits timer's remaining time.
------------------------------------------------------------------------------
Configuring procfs
+2
View File
@@ -12,6 +12,8 @@ Makefile
- Build and link hpet_example
NO_HZ.txt
- Summary of the different methods for the scheduler clock-interrupts management.
timekeeping.txt
- Clock sources, clock events, sched_clock() and delay timer notes
timers-howto.txt
- how to insert delays in the kernel the right (tm) way.
timer_stats.txt
+179
View File
@@ -0,0 +1,179 @@
Clock sources, Clock events, sched_clock() and delay timers
-----------------------------------------------------------
This document tries to briefly explain some basic kernel timekeeping
abstractions. It partly pertains to the drivers usually found in
drivers/clocksource in the kernel tree, but the code may be spread out
across the kernel.
If you grep through the kernel source you will find a number of architecture-
specific implementations of clock sources, clockevents and several likewise
architecture-specific overrides of the sched_clock() function and some
delay timers.
To provide timekeeping for your platform, the clock source provides
the basic timeline, whereas clock events shoot interrupts on certain points
on this timeline, providing facilities such as high-resolution timers.
sched_clock() is used for scheduling and timestamping, and delay timers
provide an accurate delay source using hardware counters.
Clock sources
-------------
The purpose of the clock source is to provide a timeline for the system that
tells you where you are in time. For example issuing the command 'date' on
a Linux system will eventually read the clock source to determine exactly
what time it is.
Typically the clock source is a monotonic, atomic counter which will provide
n bits which count from 0 to 2^(n-1) and then wraps around to 0 and start over.
It will ideally NEVER stop ticking as long as the system is running. It
may stop during system suspend.
The clock source shall have as high resolution as possible, and the frequency
shall be as stable and correct as possible as compared to a real-world wall
clock. It should not move unpredictably back and forth in time or miss a few
cycles here and there.
It must be immune to the kind of effects that occur in hardware where e.g.
the counter register is read in two phases on the bus lowest 16 bits first
and the higher 16 bits in a second bus cycle with the counter bits
potentially being updated in between leading to the risk of very strange
values from the counter.
When the wall-clock accuracy of the clock source isn't satisfactory, there
are various quirks and layers in the timekeeping code for e.g. synchronizing
the user-visible time to RTC clocks in the system or against networked time
servers using NTP, but all they do basically is update an offset against
the clock source, which provides the fundamental timeline for the system.
These measures does not affect the clock source per se, they only adapt the
system to the shortcomings of it.
The clock source struct shall provide means to translate the provided counter
into a nanosecond value as an unsigned long long (unsigned 64 bit) number.
Since this operation may be invoked very often, doing this in a strict
mathematical sense is not desirable: instead the number is taken as close as
possible to a nanosecond value using only the arithmetic operations
multiply and shift, so in clocksource_cyc2ns() you find:
ns ~= (clocksource * mult) >> shift
You will find a number of helper functions in the clock source code intended
to aid in providing these mult and shift values, such as
clocksource_khz2mult(), clocksource_hz2mult() that help determine the
mult factor from a fixed shift, and clocksource_register_hz() and
clocksource_register_khz() which will help out assigning both shift and mult
factors using the frequency of the clock source as the only input.
For real simple clock sources accessed from a single I/O memory location
there is nowadays even clocksource_mmio_init() which will take a memory
location, bit width, a parameter telling whether the counter in the
register counts up or down, and the timer clock rate, and then conjure all
necessary parameters.
Since a 32-bit counter at say 100 MHz will wrap around to zero after some 43
seconds, the code handling the clock source will have to compensate for this.
That is the reason why the clock source struct also contains a 'mask'
member telling how many bits of the source are valid. This way the timekeeping
code knows when the counter will wrap around and can insert the necessary
compensation code on both sides of the wrap point so that the system timeline
remains monotonic.
Clock events
------------
Clock events are the conceptual reverse of clock sources: they take a
desired time specification value and calculate the values to poke into
hardware timer registers.
Clock events are orthogonal to clock sources. The same hardware
and register range may be used for the clock event, but it is essentially
a different thing. The hardware driving clock events has to be able to
fire interrupts, so as to trigger events on the system timeline. On an SMP
system, it is ideal (and customary) to have one such event driving timer per
CPU core, so that each core can trigger events independently of any other
core.
You will notice that the clock event device code is based on the same basic
idea about translating counters to nanoseconds using mult and shift
arithmetic, and you find the same family of helper functions again for
assigning these values. The clock event driver does not need a 'mask'
attribute however: the system will not try to plan events beyond the time
horizon of the clock event.
sched_clock()
-------------
In addition to the clock sources and clock events there is a special weak
function in the kernel called sched_clock(). This function shall return the
number of nanoseconds since the system was started. An architecture may or
may not provide an implementation of sched_clock() on its own. If a local
implementation is not provided, the system jiffy counter will be used as
sched_clock().
As the name suggests, sched_clock() is used for scheduling the system,
determining the absolute timeslice for a certain process in the CFS scheduler
for example. It is also used for printk timestamps when you have selected to
include time information in printk for things like bootcharts.
Compared to clock sources, sched_clock() has to be very fast: it is called
much more often, especially by the scheduler. If you have to do trade-offs
between accuracy compared to the clock source, you may sacrifice accuracy
for speed in sched_clock(). It however requires some of the same basic
characteristics as the clock source, i.e. it should be monotonic.
The sched_clock() function may wrap only on unsigned long long boundaries,
i.e. after 64 bits. Since this is a nanosecond value this will mean it wraps
after circa 585 years. (For most practical systems this means "never".)
If an architecture does not provide its own implementation of this function,
it will fall back to using jiffies, making its maximum resolution 1/HZ of the
jiffy frequency for the architecture. This will affect scheduling accuracy
and will likely show up in system benchmarks.
The clock driving sched_clock() may stop or reset to zero during system
suspend/sleep. This does not matter to the function it serves of scheduling
events on the system. However it may result in interesting timestamps in
printk().
The sched_clock() function should be callable in any context, IRQ- and
NMI-safe and return a sane value in any context.
Some architectures may have a limited set of time sources and lack a nice
counter to derive a 64-bit nanosecond value, so for example on the ARM
architecture, special helper functions have been created to provide a
sched_clock() nanosecond base from a 16- or 32-bit counter. Sometimes the
same counter that is also used as clock source is used for this purpose.
On SMP systems, it is crucial for performance that sched_clock() can be called
independently on each CPU without any synchronization performance hits.
Some hardware (such as the x86 TSC) will cause the sched_clock() function to
drift between the CPUs on the system. The kernel can work around this by
enabling the CONFIG_HAVE_UNSTABLE_SCHED_CLOCK option. This is another aspect
that makes sched_clock() different from the ordinary clock source.
Delay timers (some architectures only)
--------------------------------------
On systems with variable CPU frequency, the various kernel delay() functions
will sometimes behave strangely. Basically these delays usually use a hard
loop to delay a certain number of jiffy fractions using a "lpj" (loops per
jiffy) value, calibrated on boot.
Let's hope that your system is running on maximum frequency when this value
is calibrated: as an effect when the frequency is geared down to half the
full frequency, any delay() will be twice as long. Usually this does not
hurt, as you're commonly requesting that amount of delay *or more*. But
basically the semantics are quite unpredictable on such systems.
Enter timer-based delays. Using these, a timer read may be used instead of
a hard-coded loop for providing the desired delay.
This is done by declaring a struct delay_timer and assigning the appropriate
function pointers and rate settings for this delay timer.
This is available on some architectures like OpenRISC or ARM.
+3 -3
View File
@@ -4237,7 +4237,7 @@ L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
S: Maintained
F: Documentation/timers/
F: kernel/hrtimer.c
F: kernel/time/hrtimer.c
F: kernel/time/clockevents.c
F: kernel/time/tick*.*
F: kernel/time/timer_*.c
@@ -7053,10 +7053,10 @@ POSIX CLOCKS and TIMERS
M: Thomas Gleixner <tglx@linutronix.de>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
S: Supported
S: Maintained
F: fs/timerfd.c
F: include/linux/timer*
F: kernel/*timer*
F: kernel/time/*timer*
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+1 -1
View File
@@ -65,7 +65,6 @@ config ARM
select HAVE_UID16
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select IRQ_FORCED_THREADING
select KTIME_SCALAR
select MODULES_USE_ELF_REL
select NO_BOOTMEM
select OLD_SIGACTION
@@ -648,6 +647,7 @@ config ARCH_PXA
select AUTO_ZRELADDR
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select CLKSRC_OF
select GENERIC_CLOCKEVENTS
select GPIO_PXA
select HAVE_IDE
+3 -13
View File
@@ -57,16 +57,6 @@ static int read_mpidr(void)
return id & MPIDR_HWID_BITMASK;
}
/*
* Get a global nanosecond time stamp for tracing.
*/
static s64 get_ns(void)
{
struct timespec ts;
getnstimeofday(&ts);
return timespec_to_ns(&ts);
}
/*
* bL switcher core code.
*/
@@ -224,7 +214,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
*/
local_irq_disable();
local_fiq_disable();
trace_cpu_migrate_begin(get_ns(), ob_mpidr);
trace_cpu_migrate_begin(ktime_get_real_ns(), ob_mpidr);
/* redirect GIC's SGIs to our counterpart */
gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
@@ -267,7 +257,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
tdev->evtdev->next_event, 1);
}
trace_cpu_migrate_finish(get_ns(), ib_mpidr);
trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
local_fiq_enable();
local_irq_enable();
@@ -558,7 +548,7 @@ int bL_switcher_get_logical_index(u32 mpidr)
static void bL_switcher_trace_trigger_cpu(void *__always_unused info)
{
trace_cpu_migrate_current(get_ns(), read_mpidr());
trace_cpu_migrate_current(ktime_get_real_ns(), read_mpidr());
}
int bL_switcher_trace_trigger(void)
+1 -1
View File
@@ -4,7 +4,7 @@
# Common support (must be linked before board specific support)
obj-y += clock.o devices.o generic.o irq.o \
time.o reset.o
reset.o
obj-$(CONFIG_PM) += pm.o sleep.o standby.o
# Generic drivers that other drivers may depend upon
+11
View File
@@ -25,11 +25,13 @@
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <mach/irqs.h>
#include <mach/reset.h>
#include <mach/smemc.h>
#include <mach/pxa3xx-regs.h>
#include "generic.h"
#include <clocksource/pxa.h>
void clear_reset_status(unsigned int mask)
{
@@ -56,6 +58,15 @@ unsigned long get_clock_tick_rate(void)
}
EXPORT_SYMBOL(get_clock_tick_rate);
/*
* For non device-tree builds, keep legacy timer init
*/
void pxa_timer_init(void)
{
pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
get_clock_tick_rate());
}
/*
* Get the clock frequency as reflected by CCCR and the turbo flag.
* We assume these values have been applied via a fcs.
-162
View File
@@ -1,162 +0,0 @@
/*
* arch/arm/mach-pxa/time.c
*
* PXA clocksource, clockevents, and OST interrupt handlers.
* Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
*
* Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
* by MontaVista Software, Inc. (Nico, your code rocks!)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
#include <linux/sched_clock.h>
#include <asm/div64.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <mach/regs-ost.h>
#include <mach/irqs.h>
/*
* This is PXA's sched_clock implementation. This has a resolution
* of at least 308 ns and a maximum value of 208 days.
*
* The return value is guaranteed to be monotonic in that range as
* long as there is always less than 582 seconds between successive
* calls to sched_clock() which should always be the case in practice.
*/
static u64 notrace pxa_read_sched_clock(void)
{
return readl_relaxed(OSCR);
}
#define MIN_OSCR_DELTA 16
static irqreturn_t
pxa_ost0_interrupt(int irq, void *dev_id)
{
struct clock_event_device *c = dev_id;
/* Disarm the compare/match, signal the event. */
writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
writel_relaxed(OSSR_M0, OSSR);
c->event_handler(c);
return IRQ_HANDLED;
}
static int
pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
{
unsigned long next, oscr;
writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER);
next = readl_relaxed(OSCR) + delta;
writel_relaxed(next, OSMR0);
oscr = readl_relaxed(OSCR);
return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
}
static void
pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{
switch (mode) {
case CLOCK_EVT_MODE_ONESHOT:
writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
writel_relaxed(OSSR_M0, OSSR);
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
/* initializing, released, or preparing for suspend */
writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
writel_relaxed(OSSR_M0, OSSR);
break;
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_PERIODIC:
break;
}
}
#ifdef CONFIG_PM
static unsigned long osmr[4], oier, oscr;
static void pxa_timer_suspend(struct clock_event_device *cedev)
{
osmr[0] = readl_relaxed(OSMR0);
osmr[1] = readl_relaxed(OSMR1);
osmr[2] = readl_relaxed(OSMR2);
osmr[3] = readl_relaxed(OSMR3);
oier = readl_relaxed(OIER);
oscr = readl_relaxed(OSCR);
}
static void pxa_timer_resume(struct clock_event_device *cedev)
{
/*
* Ensure that we have at least MIN_OSCR_DELTA between match
* register 0 and the OSCR, to guarantee that we will receive
* the one-shot timer interrupt. We adjust OSMR0 in preference
* to OSCR to guarantee that OSCR is monotonically incrementing.
*/
if (osmr[0] - oscr < MIN_OSCR_DELTA)
osmr[0] += MIN_OSCR_DELTA;
writel_relaxed(osmr[0], OSMR0);
writel_relaxed(osmr[1], OSMR1);
writel_relaxed(osmr[2], OSMR2);
writel_relaxed(osmr[3], OSMR3);
writel_relaxed(oier, OIER);
writel_relaxed(oscr, OSCR);
}
#else
#define pxa_timer_suspend NULL
#define pxa_timer_resume NULL
#endif
static struct clock_event_device ckevt_pxa_osmr0 = {
.name = "osmr0",
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.set_next_event = pxa_osmr0_set_next_event,
.set_mode = pxa_osmr0_set_mode,
.suspend = pxa_timer_suspend,
.resume = pxa_timer_resume,
};
static struct irqaction pxa_ost0_irq = {
.name = "ost0",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = pxa_ost0_interrupt,
.dev_id = &ckevt_pxa_osmr0,
};
void __init pxa_timer_init(void)
{
unsigned long clock_tick_rate = get_clock_tick_rate();
writel_relaxed(0, OIER);
writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate);
ckevt_pxa_osmr0.cpumask = cpumask_of(0);
setup_irq(IRQ_OST0, &pxa_ost0_irq);
clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
clocksource_mmio_readl_up);
clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
MIN_OSCR_DELTA * 2, 0x7fffffff);
}
+5 -5
View File
@@ -219,7 +219,7 @@ struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
void update_vsyscall(struct timekeeper *tk)
{
struct timespec xtime_coarse;
u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter");
u32 use_syscall = strcmp(tk->tkr.clock->name, "arch_sys_counter");
++vdso_data->tb_seq_count;
smp_wmb();
@@ -232,11 +232,11 @@ void update_vsyscall(struct timekeeper *tk)
vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
if (!use_syscall) {
vdso_data->cs_cycle_last = tk->clock->cycle_last;
vdso_data->cs_cycle_last = tk->tkr.cycle_last;
vdso_data->xtime_clock_sec = tk->xtime_sec;
vdso_data->xtime_clock_nsec = tk->xtime_nsec;
vdso_data->cs_mult = tk->mult;
vdso_data->cs_shift = tk->shift;
vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
vdso_data->cs_mult = tk->tkr.mult;
vdso_data->cs_shift = tk->tkr.shift;
}
smp_wmb();
-1
View File
@@ -23,7 +23,6 @@ config HEXAGON
select GENERIC_IOMAP
select GENERIC_SMP_IDLE_THREAD
select STACKTRACE_SUPPORT
select KTIME_SCALAR
select GENERIC_CLOCKEVENTS
select GENERIC_CLOCKEVENTS_BROADCAST
select MODULES_USE_ELF_RELA
+2 -2
View File
@@ -441,7 +441,7 @@ void update_vsyscall_tz(void)
}
void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
struct clocksource *c, u32 mult)
struct clocksource *c, u32 mult, cycle_t cycle_last)
{
write_seqcount_begin(&fsyscall_gtod_data.seq);
@@ -450,7 +450,7 @@ void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
fsyscall_gtod_data.clk_mult = mult;
fsyscall_gtod_data.clk_shift = c->shift;
fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
fsyscall_gtod_data.clk_cycle_last = cycle_last;
/* copy kernel time structures */
fsyscall_gtod_data.wall_time.tv_sec = wall->tv_sec;
+2 -2
View File
@@ -741,7 +741,7 @@ static cycle_t timebase_read(struct clocksource *cs)
}
void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
struct clocksource *clock, u32 mult)
struct clocksource *clock, u32 mult, cycle_t cycle_last)
{
u64 new_tb_to_xs, new_stamp_xsec;
u32 frac_sec;
@@ -774,7 +774,7 @@ void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
* We expect the caller to have done the first increment of
* vdso_data->tb_update_count already.
*/
vdso_data->tb_orig_stamp = clock->cycle_last;
vdso_data->tb_orig_stamp = cycle_last;
vdso_data->stamp_xsec = new_stamp_xsec;
vdso_data->tb_to_xs = new_tb_to_xs;
vdso_data->wtom_clock_sec = wtm->tv_sec;

Some files were not shown because too many files have changed in this diff Show More