You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user