mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
rk_timer: v1.2, update sched clock support, only use 32bits
This commit is contained in:
@@ -862,7 +862,6 @@ config ARCH_OMAP
|
||||
config ARCH_RK29
|
||||
bool "Rockchip RK29xx"
|
||||
select PLAT_RK
|
||||
select HAVE_SCHED_CLOCK
|
||||
select CPU_V7
|
||||
select ARM_GIC
|
||||
select PL330
|
||||
@@ -875,7 +874,6 @@ config ARCH_RK29
|
||||
config ARCH_RK2928
|
||||
bool "Rockchip RK2928"
|
||||
select PLAT_RK
|
||||
select HAVE_SCHED_CLOCK
|
||||
select CPU_V7
|
||||
select ARM_GIC
|
||||
select RK_PL330_DMA
|
||||
@@ -888,7 +886,6 @@ config ARCH_RK2928
|
||||
config ARCH_RK30
|
||||
bool "Rockchip RK30xx/RK3108/RK3168"
|
||||
select PLAT_RK
|
||||
select HAVE_SCHED_CLOCK
|
||||
select CPU_V7
|
||||
select ARM_GIC
|
||||
select RK_PL330_DMA
|
||||
@@ -1090,6 +1087,7 @@ config PLAT_PXA
|
||||
config PLAT_RK
|
||||
bool
|
||||
select CLKDEV_LOOKUP
|
||||
select HAVE_SCHED_CLOCK
|
||||
select ARCH_HAS_CPUFREQ
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/sched_clock.h>
|
||||
|
||||
#define TIMER_NAME "rk_timer"
|
||||
|
||||
@@ -51,23 +52,9 @@ static inline void rk_timer_enable(void __iomem *base, u32 flags)
|
||||
dsb();
|
||||
}
|
||||
|
||||
static inline u64 rk_timer_read_current_value(void __iomem *base)
|
||||
static inline u32 rk_timer_read_current_value(void __iomem *base)
|
||||
{
|
||||
/*
|
||||
* 1. Read the upper 32-bit timer counter register
|
||||
* 2. Read the lower 32-bit timer counter register
|
||||
* 3. Read the upper 32-bit timer counter register again. If the value is different to the 32-bit
|
||||
* upper value read previously, go back to step 2. Otherwise the 64-bit timer counter value
|
||||
* is correct.
|
||||
*/
|
||||
u32 upper, lower;
|
||||
|
||||
do {
|
||||
upper = readl_relaxed(base + TIMER_CURRENT_VALUE1);
|
||||
lower = readl_relaxed(base + TIMER_CURRENT_VALUE0);
|
||||
} while (upper != readl_relaxed(base + TIMER_CURRENT_VALUE1));
|
||||
|
||||
return ((u64) upper << 32) + lower;
|
||||
return readl_relaxed(base + TIMER_CURRENT_VALUE0);
|
||||
}
|
||||
|
||||
struct rk_timer {
|
||||
@@ -181,11 +168,19 @@ static cycle_t rk_timer_read(struct clocksource *cs)
|
||||
return ~rk_timer_read_current_value(timer.cs_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constants generated by clocksource_hz2mult(24000000, 26).
|
||||
* This gives a resolution of about 41ns and a wrap period of about 178s.
|
||||
*/
|
||||
#define MULT 2796202667u
|
||||
#define SHIFT 26
|
||||
#define MASK (u32)~0
|
||||
|
||||
static struct clocksource rk_timer_clocksource = {
|
||||
.name = TIMER_NAME,
|
||||
.rating = 200,
|
||||
.read = rk_timer_read,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
@@ -208,6 +203,30 @@ static void __init rk_timer_init_clocksource(void)
|
||||
printk(err, cs->name);
|
||||
}
|
||||
|
||||
static DEFINE_CLOCK_DATA(cd);
|
||||
|
||||
unsigned long long notrace sched_clock(void)
|
||||
{
|
||||
cycle_t cyc;
|
||||
|
||||
if (!timer.cs_base)
|
||||
return 0;
|
||||
|
||||
cyc = ~rk_timer_read_current_value(timer.cs_base);
|
||||
return cyc_to_fixed_sched_clock(&cd, cyc, MASK, MULT, SHIFT);
|
||||
}
|
||||
|
||||
static void notrace rk_timer_update_sched_clock(void)
|
||||
{
|
||||
u32 cyc = ~rk_timer_read_current_value(timer.cs_base);
|
||||
update_sched_clock(&cd, cyc, MASK);
|
||||
}
|
||||
|
||||
static void __init rk_timer_init_sched_clock(void)
|
||||
{
|
||||
init_fixed_sched_clock(&cd, rk_timer_update_sched_clock, 32, 24000000, MULT, SHIFT);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_LOCAL_TIMERS
|
||||
static struct clock_event_device rk_timer_clockevent;
|
||||
#endif
|
||||
@@ -253,8 +272,9 @@ static int __init rk_timer_probe(struct platform_device *pdev)
|
||||
rk_timer_clockevent.rating = 200;
|
||||
rk_timer_init_clockevent(&rk_timer_clockevent, 0);
|
||||
#endif
|
||||
rk_timer_init_sched_clock();
|
||||
|
||||
printk("rk_timer: version 1.1\n");
|
||||
printk("rk_timer: version 1.2\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -296,18 +316,3 @@ int local_timer_ack(void)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*/
|
||||
unsigned long long notrace sched_clock(void)
|
||||
{
|
||||
const struct clocksource *cs = &rk_timer_clocksource;
|
||||
cycle_t cyc;
|
||||
|
||||
if (!timer.cs_base)
|
||||
return 0;
|
||||
|
||||
cyc = ~rk_timer_read_current_value(timer.cs_base);
|
||||
return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user