From 34db37c63a08b8f06f8ff15c5c301a26635ddf25 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Nov 2015 13:07:31 -0800 Subject: MAINTAINERS: Add entry for kernel/time/alarmtimer.c I've been missing patches against alarmtimer.c due to a lack of a proper entry for it in the MAINTAINERS file. So update MAINTAINERS to fix this, adding it in with the timekeeping, ntp and core clocksource logic I share with Thomas. Signed-off-by: John Stultz --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index e9caa4b28828..e11c043d5d33 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9334,7 +9334,7 @@ M: Andreas Noever S: Maintained F: drivers/thunderbolt/ -TIMEKEEPING, CLOCKSOURCE CORE, NTP +TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER M: John Stultz M: Thomas Gleixner L: linux-kernel@vger.kernel.org @@ -9347,6 +9347,7 @@ F: include/uapi/linux/time.h F: include/uapi/linux/timex.h F: kernel/time/clocksource.c F: kernel/time/time*.c +F: kernel/time/alarmtimer.c F: kernel/time/ntp.c F: tools/testing/selftests/timers/ -- cgit v1.2.3 From 09a9982016499daeb3fbee5ac8d87797310a565a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 19 Nov 2015 11:43:09 +0100 Subject: timekeeping: Lift clocksource cacheline restriction We cache all hotpath members of a clocksource in the time keeper core. So there is no requirement in general to cache line align struct clocksource. Remove the enforces alignment. That allows users which need to wrap struct clocksource into their own struct to align the struct without getting extra padding. Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Russell King - ARM Linux Cc: Marc Gonzalez Cc: Daniel Lezcano Cc: Mans Rullgard Cc: Viresh Kumar Cc: Nicolas Pitre Cc: Tony Lindgren Cc: Sebastian Frias Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1511191209000.3898@nanos --- include/linux/clocksource.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7784b597e959..6013021a3b39 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -62,12 +62,18 @@ struct module; * @suspend: suspend function for the clocksource, if necessary * @resume: resume function for the clocksource, if necessary * @owner: module reference, must be set by clocksource in modules + * + * Note: This struct is not used in hotpathes of the timekeeping code + * because the timekeeper caches the hot path fields in its own data + * structure, so no line cache alignment is required, + * + * The pointer to the clocksource itself is handed to the read + * callback. If you need extra information there you can wrap struct + * clocksource into your own struct. Depending on the amount of + * information you need you should consider to cache line align that + * structure. */ struct clocksource { - /* - * Hotpath data, fits in a single cache line when the - * clocksource itself is cacheline aligned. - */ cycle_t (*read)(struct clocksource *cs); cycle_t mask; u32 mult; @@ -95,7 +101,7 @@ struct clocksource { cycle_t wd_last; #endif struct module *owner; -} ____cacheline_aligned; +}; /* * Clock source flags bits:: -- cgit v1.2.3 From 82bbe34b3d895fb026b2fc0e7da2e641797bfaed Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 19 Nov 2015 17:21:06 +0100 Subject: nohz: Clarify magic in tick_nohz_stop_sched_tick() While going through the nohz code I got stumped by some of it. This patch adds a few comments clarifying the code; based on discussion with Thomas. Signed-off-by: Peter Zijlstra (Intel) Cc: Frederic Weisbecker Link: http://lkml.kernel.org/r/20151119162106.GO3816@twins.programming.kicks-ass.net Signed-off-by: Thomas Gleixner --- kernel/time/tick-sched.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 7c7ec4515983..7ea28ed3109d 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -603,15 +603,31 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, /* * If the tick is due in the next period, keep it ticking or - * restart it proper. + * force prod the timer. */ delta = next_tick - basemono; if (delta <= (u64)TICK_NSEC) { tick.tv64 = 0; + /* + * We've not stopped the tick yet, and there's a timer in the + * next period, so no point in stopping it either, bail. + */ if (!ts->tick_stopped) goto out; + + /* + * If, OTOH, we did stop it, but there's a pending (expired) + * timer reprogram the timer hardware to fire now. + * + * We will not restart the tick proper, just prod the timer + * hardware into firing an interrupt to process the pending + * timers. Just like tick_irq_exit() will not restart the tick + * for 'normal' interrupts. + * + * Only once we exit the idle loop will we re-enable the tick, + * see tick_nohz_idle_exit(). + */ if (delta == 0) { - /* Tick is stopped, but required now. Enforce it */ tick_nohz_restart(ts, now); goto out; } -- cgit v1.2.3 From a0e3213f836640065e2a23ad55fa6f72e812a4f1 Mon Sep 17 00:00:00 2001 From: zhuo-hao Date: Tue, 17 Nov 2015 20:08:07 +0800 Subject: alarmtimer: Avoid unexpected rtc interrupt when system resume from S3 Before the system go to suspend (S3), if user create a timer with clockid CLOCK_REALTIME_ALARM/CLOCK_BOOTTIME_ALARM and set a "large" timeout value to this timer. The function alarmtimer_suspend will be called to setup a timeout value to RTC timer to avoid the system sleep over time. However, if the system wakeup early than RTC timeout, the RTC timer will not be cleared. And this will cause the hpet_rtc_interrupt come unexpectedly until the RTC timeout. To fix this problem, just adding alarmtimer_resume to cancel the RTC timer. This was noticed because the HPET RTC emulation fires an interrupt every 16ms(=1/2^DEFAULT_RTC_SHIFT) up to the point where the alarm time is reached. This program always hits this situation (https://lkml.org/lkml/2015/11/8/326), if system wake up earlier than alarm time. Cc: Thomas Gleixner Cc: John Stultz Signed-off-by: Zhuo-hao Lee [jstultz: Tweak commit subject & formatting slightly] Signed-off-by: John Stultz --- kernel/time/alarmtimer.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 7fbba635a549..e840ed867a5d 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -271,11 +271,27 @@ static int alarmtimer_suspend(struct device *dev) __pm_wakeup_event(ws, MSEC_PER_SEC); return ret; } + +static int alarmtimer_resume(struct device *dev) +{ + struct rtc_device *rtc; + + rtc = alarmtimer_get_rtcdev(); + if (rtc) + rtc_timer_cancel(rtc, &rtctimer); + return 0; +} + #else static int alarmtimer_suspend(struct device *dev) { return 0; } + +static int alarmtimer_resume(struct device *dev) +{ + return 0; +} #endif static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) @@ -800,6 +816,7 @@ out: /* Suspend hook structures */ static const struct dev_pm_ops alarmtimer_pm_ops = { .suspend = alarmtimer_suspend, + .resume = alarmtimer_resume, }; static struct platform_driver alarmtimer_driver = { -- cgit v1.2.3 From 35a4933a895927990772ae96fdcfd2f806929ee2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Nov 2015 12:30:30 +1100 Subject: time: Avoid signed overflow in timekeeping_get_ns() 1e75fa8 "time: Condense timekeeper.xtime into xtime_sec" replaced a call to clocksource_cyc2ns() from timekeeping_get_ns() with an open-coded version of the same logic to avoid keeping a semi-redundant struct timespec in struct timekeeper. However, the commit also introduced a subtle semantic change - where clocksource_cyc2ns() uses purely unsigned math, the new version introduces a signed temporary, meaning that if (delta * tk->mult) has a 63-bit overflow the following shift will still give a negative result. The choice of 'maxsec' in __clocksource_updatefreq_scale() means this will generally happen if there's a ~10 minute pause in examining the clocksource. This can be triggered on a powerpc KVM guest by stopping it from qemu for a bit over 10 minutes. After resuming time has jumped backwards several minutes causing numerous problems (jiffies does not advance, msleep()s can be extended by minutes..). It doesn't happen on x86 KVM guests, because the guest TSC is effectively frozen while the guest is stopped, which is not the case for the powerpc timebase. Obviously an unsigned (64 bit) overflow will only take twice as long as a signed, 63-bit overflow. I don't know the time code well enough to know if that will still cause incorrect calculations, or if a 64-bit overflow is avoided elsewhere. Still, an incorrect forwards clock adjustment will cause less trouble than time going backwards. So, this patch removes the potential for intermediate signed overflow. Cc: stable@vger.kernel.org (3.7+) Suggested-by: Laurent Vivier Tested-by: Laurent Vivier Signed-off-by: David Gibson Signed-off-by: John Stultz --- kernel/time/timekeeping.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d563c1960302..99188ee5d9d0 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -305,8 +305,7 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr) delta = timekeeping_get_delta(tkr); - nsec = delta * tkr->mult + tkr->xtime_nsec; - nsec >>= tkr->shift; + nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift; /* If arch requires, add in get_arch_timeoffset() */ return nsec + arch_gettimeoffset(); -- cgit v1.2.3 From 390dd67c471a43a8a0f36c7d5177de49e7749c59 Mon Sep 17 00:00:00 2001 From: Seiichi Ikarashi Date: Thu, 10 Sep 2015 18:01:56 +0900 Subject: clocksource: Add CPU info to clocksource watchdog reporting The clocksource watchdog reporting was improved by 0b046b217ad4c6. I want to add the info of CPU where the watchdog detects a deviation because it is necessary to identify the trouble spot if the clocksource is TSC. Signed-off-by: Seiichi Ikarashi [jstultz: Tweaked commit message] Signed-off-by: John Stultz --- kernel/time/clocksource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 1347882d131e..664de539299b 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -218,8 +218,8 @@ static void clocksource_watchdog(unsigned long data) /* Check the deviation from the watchdog clocksource. */ if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { - pr_warn("timekeeping watchdog: Marking clocksource '%s' as unstable because the skew is too large:\n", - cs->name); + pr_warn("timekeeping watchdog on CPU%d: Marking clocksource '%s' as unstable because the skew is too large:\n", + smp_processor_id(), cs->name); pr_warn(" '%s' wd_now: %llx wd_last: %llx mask: %llx\n", watchdog->name, wdnow, wdlast, watchdog->mask); pr_warn(" '%s' cs_now: %llx cs_last: %llx mask: %llx\n", -- cgit v1.2.3 From 3b44edaaa1fffccea7edc018dd807581c97a6aea Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:41 +0200 Subject: selftests/timers: fix write return value handlng The function can return negative value. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: John Stultz --- tools/testing/selftests/timers/clocksource-switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c index 627ec7425f78..fd88e3025bed 100644 --- a/tools/testing/selftests/timers/clocksource-switch.c +++ b/tools/testing/selftests/timers/clocksource-switch.c @@ -97,7 +97,7 @@ int get_cur_clocksource(char *buf, size_t size) int change_clocksource(char *clocksource) { int fd; - size_t size; + ssize_t size; fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY); -- cgit v1.2.3 From 52d189f1b38810b1b483d5bac2e4fa90b9afd372 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 3 Dec 2015 15:46:48 -0500 Subject: ntp: Verify offset doesn't overflow in ntp_update_offset We need to make sure that the offset is valid before manipulating it, otherwise it might overflow on the multiplication. Cc: Sasha Levin Cc: Richard Cochran Cc: Thomas Gleixner Signed-off-by: Sasha Levin [jstultz: Reworked one of the checks so it makes more sense] Signed-off-by: John Stultz --- kernel/time/ntp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 149cc8086aea..125fc0342355 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -297,15 +297,17 @@ static void ntp_update_offset(long offset) if (!(time_status & STA_PLL)) return; - if (!(time_status & STA_NANO)) + if (!(time_status & STA_NANO)) { + /* Make sure the multiplication below won't overflow */ + offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC); offset *= NSEC_PER_USEC; + } /* * Scale the phase adjustment and * clamp to the operating range. */ - offset = min(offset, MAXPHASE); - offset = max(offset, -MAXPHASE); + offset = clamp(offset, -MAXPHASE, MAXPHASE); /* * Select how the frequency is to be controlled -- cgit v1.2.3 From 37cf4dc3370fbca0344e23bb96446eb2c3548ba7 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 3 Dec 2015 22:09:31 -0500 Subject: time: Verify time values in adjtimex ADJ_SETOFFSET to avoid overflow For adjtimex()'s ADJ_SETOFFSET, make sure the tv_usec value is sane. We might multiply them later which can cause an overflow and undefined behavior. This patch introduces new helper functions to simplify the checking code and adds comments to clarify Orginally this patch was by Sasha Levin, but I've basically rewritten it, so he should get credit for finding the issue and I should get the blame for any mistakes made since. Also, credit to Richard Cochran for the phrasing used in the comment for what is considered valid here. Cc: Sasha Levin Cc: Richard Cochran Cc: Thomas Gleixner Reported-by: Sasha Levin Signed-off-by: John Stultz --- include/linux/time.h | 26 ++++++++++++++++++++++++++ kernel/time/ntp.c | 10 ++++++++-- kernel/time/timekeeping.c | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/linux/time.h b/include/linux/time.h index beebe3a02d43..297f09f23896 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -125,6 +125,32 @@ static inline bool timeval_valid(const struct timeval *tv) extern struct timespec timespec_trunc(struct timespec t, unsigned gran); +/* + * Validates if a timespec/timeval used to inject a time offset is valid. + * Offsets can be postive or negative. The value of the timeval/timespec + * is the sum of its fields, but *NOTE*: the field tv_usec/tv_nsec must + * always be non-negative. + */ +static inline bool timeval_inject_offset_valid(const struct timeval *tv) +{ + /* We don't check the tv_sec as it can be positive or negative */ + + /* Can't have more microseconds then a second */ + if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC) + return false; + return true; +} + +static inline bool timespec_inject_offset_valid(const struct timespec *ts) +{ + /* We don't check the tv_sec as it can be positive or negative */ + + /* Can't have more nanoseconds then a second */ + if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC) + return false; + return true; +} + #define CURRENT_TIME (current_kernel_time()) #define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 }) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 125fc0342355..4073c9550af9 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -676,8 +676,14 @@ int ntp_validate_timex(struct timex *txc) return -EINVAL; } - if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) - return -EPERM; + if (txc->modes & ADJ_SETOFFSET) { + /* In order to inject time, you gotta be super-user! */ + if (!capable(CAP_SYS_TIME)) + return -EPERM; + + if (!timeval_inject_offset_valid(&txc->time)) + return -EINVAL; + } /* * Check for potential multiplication overflows that can diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 99188ee5d9d0..d9249daf14ba 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -958,7 +958,7 @@ int timekeeping_inject_offset(struct timespec *ts) struct timespec64 ts64, tmp; int ret = 0; - if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) + if (!timespec_inject_offset_valid(ts)) return -EINVAL; ts64 = timespec_to_timespec64(*ts); -- cgit v1.2.3 From 9a78ec45bd6ac7650a995a9de0912fd75d6b6886 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Sun, 25 Oct 2015 23:21:22 +0000 Subject: clocksource/drivers/mtk_timer: Add pr_fmt define It's a bit unclear what subsystem/driver emits some messages to dmesg in the function mtk_init_timer(). Use pr_fmt to auto-prefix the messages appropriately. Acked-by: Matthias Brugger Signed-off-by: Alexey Klimov Signed-off-by: Daniel Lezcano --- drivers/clocksource/mtk_timer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index fbfc74685e6a..8f99cd73fced 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c @@ -16,6 +16,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -- cgit v1.2.3 From 6cd7ccaaa84f6d9ee9ed33c66d7492121e2b98fd Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Sun, 25 Oct 2015 23:21:23 +0000 Subject: clocksource/drivers/mtk_timer: Fix pr_warn() messages in mtk_timer_init 1) Change pr_warn()s to pr_err()s. These messages are actually errors and not warnings. 2) Add missing \n. 3) Error message for kzalloc() failure is removed per suggestion by Joe Perches. There is generic stack_dump() for allocation issues. Signed-off-by: Alexey Klimov Signed-off-by: Daniel Lezcano --- drivers/clocksource/mtk_timer.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index 8f99cd73fced..e1e06429734f 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c @@ -189,10 +189,8 @@ static void __init mtk_timer_init(struct device_node *node) struct clk *clk; evt = kzalloc(sizeof(*evt), GFP_KERNEL); - if (!evt) { - pr_warn("Can't allocate mtk clock event driver struct"); + if (!evt) return; - } evt->dev.name = "mtk_tick"; evt->dev.rating = 300; @@ -206,31 +204,31 @@ static void __init mtk_timer_init(struct device_node *node) evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer"); if (IS_ERR(evt->gpt_base)) { - pr_warn("Can't get resource\n"); + pr_err("Can't get resource\n"); return; } evt->dev.irq = irq_of_parse_and_map(node, 0); if (evt->dev.irq <= 0) { - pr_warn("Can't parse IRQ"); + pr_err("Can't parse IRQ\n"); goto err_mem; } clk = of_clk_get(node, 0); if (IS_ERR(clk)) { - pr_warn("Can't get timer clock"); + pr_err("Can't get timer clock\n"); goto err_irq; } if (clk_prepare_enable(clk)) { - pr_warn("Can't prepare clock"); + pr_err("Can't prepare clock\n"); goto err_clk_put; } rate = clk_get_rate(clk); if (request_irq(evt->dev.irq, mtk_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) { - pr_warn("failed to setup irq %d\n", evt->dev.irq); + pr_err("failed to setup irq %d\n", evt->dev.irq); goto err_clk_disable; } -- cgit v1.2.3 From 11faa20eb43997baae0c72916d8a959efcb6f8c4 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Sun, 25 Oct 2015 23:21:24 +0000 Subject: clocksource/drivers/mtk_timer: Fix memleak in mtk_timer_init() Add error path to clear evt struct allocated by kzalloc() in the beginning of function mtk_timer_init(). Acked-by: Matthias Brugger Signed-off-by: Alexey Klimov Signed-off-by: Daniel Lezcano --- drivers/clocksource/mtk_timer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index e1e06429734f..d67bc356488f 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c @@ -205,7 +205,7 @@ static void __init mtk_timer_init(struct device_node *node) evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer"); if (IS_ERR(evt->gpt_base)) { pr_err("Can't get resource\n"); - return; + goto err_kzalloc; } evt->dev.irq = irq_of_parse_and_map(node, 0); @@ -260,5 +260,7 @@ err_mem: iounmap(evt->gpt_base); of_address_to_resource(node, 0, &res); release_mem_region(res.start, resource_size(&res)); +err_kzalloc: + kfree(evt); } CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init); -- cgit v1.2.3 From a3a8908fb02bfa2514750734bfd3afc6c1daeb89 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sun, 25 Oct 2015 16:40:30 +0100 Subject: clocksource/drivers/tegra: Allow timer irq affinity change Allow the timer core to change the smp affinity of the broadcast timer irq by setting CLOCK_EVT_FEAT_DYNIRQ flag. This reduces interrupt pressure and wakeups on CPU0 as well as vastly reducing the number of timer broadcast IPIs. Signed-off-by: Lucas Stach Signed-off-by: Daniel Lezcano --- drivers/clocksource/tegra20_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 6ebda1177e79..38333aba3055 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -96,7 +96,8 @@ static struct clock_event_device tegra_clockevent = { .name = "timer0", .rating = 300, .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC, + CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_DYNIRQ, .set_next_event = tegra_timer_set_next_event, .set_state_shutdown = tegra_timer_shutdown, .set_state_periodic = tegra_timer_set_periodic, -- cgit v1.2.3 From a0d2216ec0d04ec6bf2a7282774338d5ffb3ff0b Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Fri, 25 Sep 2015 10:14:56 +0800 Subject: clocksource/drivers/rockchip: Make the driver more readable Let's checkstyle to clean up the macros with such trivial details. Signed-off-by: Caesar Wang Signed-off-by: Daniel Lezcano --- drivers/clocksource/rockchip_timer.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index d3c1742ded1a..b14716b62d63 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c @@ -17,16 +17,16 @@ #define TIMER_NAME "rk_timer" -#define TIMER_LOAD_COUNT0 0x00 -#define TIMER_LOAD_COUNT1 0x04 -#define TIMER_CONTROL_REG 0x10 -#define TIMER_INT_STATUS 0x18 +#define TIMER_LOAD_COUNT0 0x00 +#define TIMER_LOAD_COUNT1 0x04 +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INT_STATUS 0x18 -#define TIMER_DISABLE 0x0 -#define TIMER_ENABLE 0x1 -#define TIMER_MODE_FREE_RUNNING (0 << 1) -#define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) -#define TIMER_INT_UNMASK (1 << 2) +#define TIMER_DISABLE 0x0 +#define TIMER_ENABLE 0x1 +#define TIMER_MODE_FREE_RUNNING (0 << 1) +#define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) +#define TIMER_INT_UNMASK (1 << 2) struct bc_timer { struct clock_event_device ce; @@ -173,4 +173,5 @@ static void __init rk_timer_init(struct device_node *np) clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX); } + CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init); -- cgit v1.2.3 From 364eba4b3a58a3e9af5a1355f4131a58cd1f3b8d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 29 Oct 2015 18:33:47 +0100 Subject: time: Define dummy functions for the generic sched clock When we try to compile a clocksource driver with the COMPILE_TEST option, we can't select the GENERIC_SCHED_CLOCK because the sched_clock() symbol will be duplicated with the one defined for the x86. In order to fix that, we don't select the GENERIC_SCHED_CLOCK in the driver Kconfig's file but we define some empty functions for the different symbols in order to prevent the unresolved ones. This patch fixes the COMPILE_TEST option for the compile test coverage for the clocksource drivers. Without this patch, we can't add the COMPILE_TEST option for the clocksource drivers using the GENERIC_SCHED_CLOCK. Signed-off-by: Daniel Lezcano --- include/linux/sched_clock.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h index efa931c5cef1..411b52e424e1 100644 --- a/include/linux/sched_clock.h +++ b/include/linux/sched_clock.h @@ -10,11 +10,17 @@ #ifdef CONFIG_GENERIC_SCHED_CLOCK extern void sched_clock_postinit(void); -#else -static inline void sched_clock_postinit(void) { } -#endif extern void sched_clock_register(u64 (*read)(void), int bits, unsigned long rate); +#else +static inline void sched_clock_postinit(void) { } + +static inline void sched_clock_register(u64 (*read)(void), int bits, + unsigned long rate) +{ + ; +} +#endif #endif -- cgit v1.2.3 From 23b8f81f3890edd06bcabdaac33ff5c087114c59 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Fri, 25 Sep 2015 10:14:55 +0800 Subject: clocksource/drivers/rockchip: Remove dsb() usage The dsb() instruction is pointless in this code. Remove it. That also fixes the ARM64 compilation issue. Signed-off-by: Daniel Lezcano Tested-by: Caesar Wang --- drivers/clocksource/rockchip_timer.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index b14716b62d63..8c77a529d0d4 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c @@ -49,14 +49,12 @@ static inline void __iomem *rk_base(struct clock_event_device *ce) static inline void rk_timer_disable(struct clock_event_device *ce) { writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG); - dsb(); } static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags) { writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags, rk_base(ce) + TIMER_CONTROL_REG); - dsb(); } static void rk_timer_update_counter(unsigned long cycles, @@ -64,13 +62,11 @@ static void rk_timer_update_counter(unsigned long cycles, { writel_relaxed(cycles, rk_base(ce) + TIMER_LOAD_COUNT0); writel_relaxed(0, rk_base(ce) + TIMER_LOAD_COUNT1); - dsb(); } static void rk_timer_interrupt_clear(struct clock_event_device *ce) { writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS); - dsb(); } static inline int rk_timer_set_next_event(unsigned long cycles, -- cgit v1.2.3 From 3dc0e9f6fda39d1f9c893806bc971ec4ee4939fa Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 Oct 2015 11:10:43 +0200 Subject: clocksource/drivers/qcom: Make COMPILE_TEST enabled for ARM architecture In order to be consistent with the rest of the drivers compilation, let's introduce the COMPILE_TEST option. Unfortunately, the delay.h code is not portable, so the compilation test coverage will be restricted to the ARM architecture. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 2eb5f0efae90..b423785d6afc 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -279,7 +279,12 @@ config EM_TIMER_STI such as EMEV2 from former NEC Electronics. config CLKSRC_QCOM - bool + bool "Qualcomm MSM timer" if COMPILE_TEST + depends on ARM + select CLKSRC_OF + help + This enables the clocksource and the per CPU clockevent driver for the + Qualcomm SoCs. config CLKSRC_VERSATILE bool "ARM Versatile (Express) reference platforms clock source" -- cgit v1.2.3 From 2ffdf71b83bfe5df46f959029c3aad1fd5c298e6 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 Oct 2015 15:33:06 +0200 Subject: clocksource/drivers/st_lpc: Fix Kconfig dependency Change the Kconfig selection rule by letting the STI arch to select the timer. Signed-off-by: Daniel Lezcano Acked-by: Maxime Coquelin --- arch/arm/mach-sti/Kconfig | 1 + drivers/clocksource/Kconfig | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index 125865daaf17..12dd1dc0a041 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig @@ -3,6 +3,7 @@ menuconfig ARCH_STI select ARM_GIC select ST_IRQCHIP select ARM_GLOBAL_TIMER + select CLKSRC_ST_LPC select PINCTRL select PINCTRL_ST select MFD_SYSCON diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index b423785d6afc..3594a2b0b130 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -326,7 +326,6 @@ config CLKSRC_IMX_GPT config CLKSRC_ST_LPC bool - depends on ARCH_STI select CLKSRC_OF if OF help Enable this option to use the Low Power controller timer -- cgit v1.2.3 From baacaf8338516d107b568ae727a47855c7fe6b51 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 Oct 2015 15:36:28 +0200 Subject: clocksource/drivers/st_lpc: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 3594a2b0b130..4117386d8051 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -325,7 +325,7 @@ config CLKSRC_IMX_GPT select CLKSRC_MMIO config CLKSRC_ST_LPC - bool + bool "Low power clocksource found in the LPC" if COMPILE_TEST select CLKSRC_OF if OF help Enable this option to use the Low Power controller timer -- cgit v1.2.3 From 389d9b5841b031103208f1836bcb49a0710531ed Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 Oct 2015 15:48:38 +0200 Subject: clocksource/drivers/pxa_timer: Move the Kconfig rule Instead of having the clocksource's Kconfig depending on the arch, let the arch to select the timer it needs. The CLKSRC_OF dependency is removed because already selected by the ARCH_PXA, and it is added for SA1100. Signed-off-by: Daniel Lezcano --- arch/arm/Kconfig | 3 +++ drivers/clocksource/Kconfig | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0365cbbc9179..a5d416ec1d01 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -609,6 +609,7 @@ config ARCH_PXA select AUTO_ZRELADDR select COMMON_CLK select CLKDEV_LOOKUP + select CLKSRC_PXA select CLKSRC_MMIO select CLKSRC_OF select GENERIC_CLOCKEVENTS @@ -648,6 +649,8 @@ config ARCH_SA1100 select ARCH_SPARSEMEM_ENABLE select CLKDEV_LOOKUP select CLKSRC_MMIO + select CLKSRC_PXA + select CLKSRC_OF if OF select CPU_FREQ select CPU_SA1100 select GENERIC_CLOCKEVENTS diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 4117386d8051..d4221e04868d 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -307,8 +307,7 @@ config CLKSRC_TANGO_XTAL select CLKSRC_OF config CLKSRC_PXA - def_bool y if ARCH_PXA || ARCH_SA1100 - select CLKSRC_OF if OF + bool help This enables OST0 support available on PXA and SA-11x0 platforms. -- cgit v1.2.3 From 5ae996cbee445e899915d16903f140d064b53cc7 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 Oct 2015 17:47:32 +0200 Subject: clocksource/drivers/pxa_timer: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index d4221e04868d..e07ada91966b 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -307,7 +307,9 @@ config CLKSRC_TANGO_XTAL select CLKSRC_OF config CLKSRC_PXA - bool + bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS + select CLKSRC_MMIO help This enables OST0 support available on PXA and SA-11x0 platforms. -- cgit v1.2.3 From 5a7351f0e156d1b359b5662d4475bd295f0617d9 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 29 Oct 2015 20:54:19 +0100 Subject: clocksource/drivers/tango: Add COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e07ada91966b..8ea7140649e4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -303,8 +303,11 @@ config CLKSRC_MIPS_GIC select CLKSRC_OF config CLKSRC_TANGO_XTAL - bool + bool "Clocksource for Tango SoC" if COMPILE_TEST + depends on ARM select CLKSRC_OF + help + This enables the clocksource for Tango SoC config CLKSRC_PXA bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST -- cgit v1.2.3 From dfdb16525b1093328617c15d57593ef4c4759d7a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 17:28:13 +0100 Subject: clocksource/drivers/pistachio: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 8ea7140649e4..96a34dcf3262 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -121,8 +121,10 @@ config CLKSRC_LPC32XX select CLKSRC_OF config CLKSRC_PISTACHIO - bool + bool "Clocksource for Pistachio SoC" if COMPILE_TEST select CLKSRC_OF + help + Enables the clocksource for the Pistachio SoC. config CLKSRC_TI_32K bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST -- cgit v1.2.3 From fbca9eabe9b6c7602c13b0d671f58f62c1a15d4d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 17:53:27 +0100 Subject: clocksource/drivers/mediatek: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 96a34dcf3262..3ba43f63e1a2 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -228,9 +228,11 @@ config SYS_SUPPORTS_SH_CMT bool config MTK_TIMER + bool "Mediatek timer driver" if COMPILE_TEST select CLKSRC_OF select CLKSRC_MMIO - bool + help + Support for Mediatek timer driver. config SYS_SUPPORTS_SH_MTU2 bool -- cgit v1.2.3 From 40ada2aac5e3a3c38f295d4e37b182fc4feff723 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 17:58:47 +0100 Subject: clocksource/drivers/rockchip: Add COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Due to the dsb() usage in the driver, this driver is only compilable on ARM and ARM64. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 3ba43f63e1a2..0c06103769a6 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -39,8 +39,11 @@ config DW_APB_TIMER_OF select CLKSRC_OF config ROCKCHIP_TIMER - bool + bool "Rockchip timer driver" if COMPILE_TEST + depends on ARM || ARM64 select CLKSRC_OF + help + Enables the support for the rockchip timer driver. config ARMADA_370_XP_TIMER bool -- cgit v1.2.3 From 9519e80c755592b3527f435497521563d158649d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 20:30:34 +0100 Subject: clocksource/drivers/armada-370-xp: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Due to the non portable 'delay' code, the compilation is restricted to the ARM architecture only. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 0c06103769a6..b6bb0a613999 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -46,8 +46,11 @@ config ROCKCHIP_TIMER Enables the support for the rockchip timer driver. config ARMADA_370_XP_TIMER - bool + bool "Armada 370 and XP timer driver" if COMPILE_TEST + depends on ARM select CLKSRC_OF + help + Enables the support for the Armada 370 and XP timer driver. config MESON6_TIMER bool -- cgit v1.2.3 From 0b7a7bb70562960834f4c2b7ed703f06dbb0c7e8 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 22:07:39 +0100 Subject: clocksource/drivers/meson6: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index b6bb0a613999..f6e71b74405f 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -53,8 +53,10 @@ config ARMADA_370_XP_TIMER Enables the support for the Armada 370 and XP timer driver. config MESON6_TIMER - bool + bool "Meson6 timer driver" if COMPILE_TEST select CLKSRC_MMIO + help + Enables the support for the Meson6 timer driver. config ORION_TIMER select CLKSRC_OF -- cgit v1.2.3 From c916554971fdfda3d34259851684a76ece5f85d1 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 22:28:31 +0100 Subject: clocksource/drivers/orion: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. The driver is using the atomic_io API which is not portable, so the compilation is restricted to ARM only. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index f6e71b74405f..68a63b2447c5 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -59,9 +59,12 @@ config MESON6_TIMER Enables the support for the Meson6 timer driver. config ORION_TIMER + bool "Orion timer driver" if COMPILE_TEST + depends on ARM select CLKSRC_OF select CLKSRC_MMIO - bool + help + Enables the support for the Orion timer driver config SUN4I_TIMER select CLKSRC_MMIO -- cgit v1.2.3 From e6c1db13f955a7b2091d047dc8c294717e0d1a8f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 22:32:10 +0100 Subject: clocksource/drivers/digicolor: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 68a63b2447c5..63a8c6fb4172 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -28,7 +28,9 @@ config CLKSRC_MMIO bool config DIGICOLOR_TIMER - bool + bool "Digicolor timer driver" if COMPILE_TEST + help + Enables the support for the digicolor timer driver. config DW_APB_TIMER bool -- cgit v1.2.3 From 5b097f6ba57fb4a8e7da11147048f7e1c898bc29 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 22:35:00 +0100 Subject: clocksource/drivers/dw_apb: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 63a8c6fb4172..24a8d8d021dd 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -33,7 +33,9 @@ config DIGICOLOR_TIMER Enables the support for the digicolor timer driver. config DW_APB_TIMER - bool + bool "DW APB timer driver" if COMPILE_TEST + help + Enables the support for the dw_apb timer. config DW_APB_TIMER_OF bool -- cgit v1.2.3 From b4fcd48b887eb4bb4511b17ed65d2588602a938a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 30 Oct 2015 22:39:00 +0100 Subject: clocksource/drivers/sun4i: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 24a8d8d021dd..67be8f4057b4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -71,8 +71,10 @@ config ORION_TIMER Enables the support for the Orion timer driver config SUN4I_TIMER + bool "Sun4i timer driver" if COMPILE_TEST select CLKSRC_MMIO - bool + help + Enables support for the Sun4i timer. config SUN5I_HSTIMER select CLKSRC_MMIO -- cgit v1.2.3 From f0c5afb787cfc800f7678f614d746b9bd2f18d01 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 17:01:46 +0100 Subject: clocksource/drivers/sun5i: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. The driver depends on the common clock framework, thus the dependency added on COMMON_CLK. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 67be8f4057b4..625d45943ca1 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -77,8 +77,11 @@ config SUN4I_TIMER Enables support for the Sun4i timer. config SUN5I_HSTIMER + bool "Sun5i timer driver" if COMPILE_TEST select CLKSRC_MMIO - bool + depends on COMMON_CLK + help + Enables support the Sun5i timer. config TEGRA_TIMER bool -- cgit v1.2.3 From adce4bc8311f43dd0c2207eae841f925f3a6fcf2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 20:13:09 +0100 Subject: clocksource/drivers/tegra2: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Due to the non portable code for the delay timer, this option is only available for the ARM architecture. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 625d45943ca1..e33ed768992e 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -84,7 +84,10 @@ config SUN5I_HSTIMER Enables support the Sun5i timer. config TEGRA_TIMER - bool + bool "Tegra timer driver" if COMPILE_TEST + depends on ARM + help + Enables support for the Tegra driver. config VT8500_TIMER bool -- cgit v1.2.3 From 351bb99b71048529f6977389859a9f83fb2115ab Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 20:20:43 +0100 Subject: clocksource/drivers/vt8500: Remove unneeded header Remove the header inclusion which is pointless. Signed-off-by: Daniel Lezcano --- drivers/clocksource/vt8500_timer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index a92e94b40b5b..de49805fbb09 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From b4bdf7ef301655b85875c9cf04f93a54bd763f97 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 20:23:54 +0100 Subject: clocksource/drivers/vt8500: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e33ed768992e..c2b87b4d002d 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -90,7 +90,9 @@ config TEGRA_TIMER Enables support for the Tegra driver. config VT8500_TIMER - bool + bool "VT8500 timer driver" if COMPILE_TEST + help + Enables support for the VT8500 driver. config CADENCE_TTC_TIMER bool -- cgit v1.2.3 From 57f49318f9b1a083bcada14505c4c5397b9dd8f2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 21:39:03 +0100 Subject: clocksource/drivers/cadence_ttc: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. The driver depends on the common clock framework, thus the dependency added on COMMON_CLK. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index c2b87b4d002d..badef7286eb9 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -95,7 +95,10 @@ config VT8500_TIMER Enables support for the VT8500 driver. config CADENCE_TTC_TIMER - bool + bool "Cadence TTC timer driver" if COMPILE_TEST + depends on COMMON_CLK + help + Enables support for the cadence ttc driver. config ASM9260_TIMER bool -- cgit v1.2.3 From b9755841e7b2280b94d72a7f42a0d2062a43b201 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 21:41:23 +0100 Subject: clocksource/drivers/asm9260: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index badef7286eb9..a65819089210 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -101,9 +101,11 @@ config CADENCE_TTC_TIMER Enables support for the cadence ttc driver. config ASM9260_TIMER - bool + bool "ASM9260 timer driver" if COMPILE_TEST select CLKSRC_MMIO select CLKSRC_OF + help + Enables support for the ASM9260 timer. config CLKSRC_NOMADIK_MTU bool -- cgit v1.2.3 From ddcf48c776845b9b83e7ab514b54220358993a6f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 31 Oct 2015 21:44:52 +0100 Subject: clocksource/drivers/lpc32xx: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a65819089210..ed7a8249696a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -146,9 +146,11 @@ config CLKSRC_EFM32 event device. config CLKSRC_LPC32XX - bool + bool "Clocksource for LPC32XX" if COMPILE_TEST select CLKSRC_MMIO select CLKSRC_OF + help + Support for the LPC32XX clocksource. config CLKSRC_PISTACHIO bool "Clocksource for Pistachio SoC" if COMPILE_TEST -- cgit v1.2.3 From 703296530609ef37e22e715c9f5438d60a7ec11f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 1 Nov 2015 21:11:28 +0100 Subject: clocksource/drivers/nomadik_mtu: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Due to the non portable code for the delay timer, this option is only available for the ARM architecture. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index ed7a8249696a..847b3b1b70f4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -108,8 +108,8 @@ config ASM9260_TIMER Enables support for the ASM9260 timer. config CLKSRC_NOMADIK_MTU - bool - depends on (ARCH_NOMADIK || ARCH_U8500) + bool "Nomakdik clocksource driver" if COMPILE_TEST + depends on ARM select CLKSRC_MMIO help Support for Multi Timer Unit. MTU provides access -- cgit v1.2.3 From 1becd6edea0c2849bc1a585d8c549d611517dd76 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 1 Nov 2015 21:16:01 +0100 Subject: clocksource/drivers/prcmu: Fix Kconfig and add COMPILE_TEST option Let the platform's Kconfig to select the clock instead of having a reverse dependency from the driver to the platform options. Add the COMPILE_TEST option for the compilation test coverage. This change is debatable as the option itself in the Kconfig allows to select the driver for the platform or not. This change will make the prcmu timer always selected. Signed-off-by: Daniel Lezcano Acked-by: Linus Walleij --- arch/arm/mach-ux500/Kconfig | 1 + drivers/clocksource/Kconfig | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index c9ac19b24e5a..5eacdd61e61c 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -32,6 +32,7 @@ config UX500_SOC_DB8500 select PINCTRL_AB8540 select REGULATOR select REGULATOR_DB8500_PRCMU + select CLKSRC_DBX500_PRCMU select PM_GENERIC_DOMAINS if PM config MACH_MOP500 diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 847b3b1b70f4..e3ba5b45f357 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -123,9 +123,7 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK Use the Multi Timer Unit as the sched_clock. config CLKSRC_DBX500_PRCMU - bool "Clocksource PRCMU Timer" - depends on UX500_SOC_DB8500 - default y + bool "Clocksource PRCMU Timer" if COMPILE_TEST help Use the always on PRCMU Timer as clocksource -- cgit v1.2.3 From 39366ef42194b58519274afc35f4a9282fb05931 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 1 Nov 2015 21:51:30 +0100 Subject: clocksource/drivers/exynos_mct: Fix Kconfig and add COMPILE_TEST option Let the platform's Kconfig to select the clock instead of having a reverse dependency from the driver to the platform options. Add the COMPILE_TEST option for the compilation test coverage. Due to the non portable 'delay' code, this driver is only compilable on ARM. Signed-off-by: Daniel Lezcano Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi --- arch/arm/mach-exynos/Kconfig | 1 + drivers/clocksource/Kconfig | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 3a10f1a8317a..ff105399aae4 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -27,6 +27,7 @@ menuconfig ARCH_EXYNOS select SRAM select THERMAL select MFD_SYSCON + select CLKSRC_EXYNOS_MCT help Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e3ba5b45f357..2062783fe1a8 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -231,8 +231,8 @@ config CLKSRC_METAG_GENERIC This option enables support for the Meta per-thread timers. config CLKSRC_EXYNOS_MCT - def_bool y if ARCH_EXYNOS - depends on !ARM64 + bool "Exynos multi core timer driver" if COMPILE_TEST + depends on ARM help Support for Multi Core Timer controller on Exynos SoCs. -- cgit v1.2.3 From 778c5696b93f45c3d11442150e2634f454bb5213 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 1 Nov 2015 21:57:05 +0100 Subject: clocksource/drivers/samsung-pwm: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 2062783fe1a8..3457a8607bf0 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -237,7 +237,7 @@ config CLKSRC_EXYNOS_MCT Support for Multi Core Timer controller on Exynos SoCs. config CLKSRC_SAMSUNG_PWM - bool + bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST help This is a new clocksource driver for the PWM timer found in Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver -- cgit v1.2.3 From ef49336bbd15bd4ffbdcf81501d25abcd87f16ab Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 2 Nov 2015 09:51:02 +0100 Subject: clocksource/drivers/fsl-ftm: Add the COMPILE_TEST option Increase the compilation test coverage by adding the COMPILE_TEST option. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 3457a8607bf0..7085eb7dded2 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -245,7 +245,7 @@ config CLKSRC_SAMSUNG_PWM needed only on systems that do not have the Exynos MCT available. config FSL_FTM_TIMER - bool + bool "Freescale FlexTimer Module driver" if COMPILE_TEST help Support for Freescale FlexTimer Module (FTM) timer. -- cgit v1.2.3 From 0901f18432db704b7622c969a09fba9846e4cfcd Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 4 Nov 2015 14:21:42 +0100 Subject: clocksource/drivers/Kconfig: Add missing GENERIC_CLOCKEVENTS dependency In order to compile on all arch without error with 'allyesconfig' make sure the platform selected the GENERIC_CLOCKEVENTS. Without this patch the new added drivers will prevent the kernel to compile on PARISC. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 7085eb7dded2..de331b8346d8 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -29,11 +29,13 @@ config CLKSRC_MMIO config DIGICOLOR_TIMER bool "Digicolor timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS help Enables the support for the digicolor timer driver. config DW_APB_TIMER bool "DW APB timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS help Enables the support for the dw_apb timer. @@ -58,6 +60,7 @@ config ARMADA_370_XP_TIMER config MESON6_TIMER bool "Meson6 timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS select CLKSRC_MMIO help Enables the support for the Meson6 timer driver. @@ -72,6 +75,7 @@ config ORION_TIMER config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS select CLKSRC_MMIO help Enables support for the Sun4i timer. @@ -91,6 +95,7 @@ config TEGRA_TIMER config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS help Enables support for the VT8500 driver. @@ -102,6 +107,7 @@ config CADENCE_TTC_TIMER config ASM9260_TIMER bool "ASM9260 timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS select CLKSRC_MMIO select CLKSRC_OF help @@ -124,6 +130,7 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK config CLKSRC_DBX500_PRCMU bool "Clocksource PRCMU Timer" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS help Use the always on PRCMU Timer as clocksource @@ -145,6 +152,7 @@ config CLKSRC_EFM32 config CLKSRC_LPC32XX bool "Clocksource for LPC32XX" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS select CLKSRC_MMIO select CLKSRC_OF help @@ -238,6 +246,7 @@ config CLKSRC_EXYNOS_MCT config CLKSRC_SAMSUNG_PWM bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS help This is a new clocksource driver for the PWM timer found in Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver @@ -246,6 +255,7 @@ config CLKSRC_SAMSUNG_PWM config FSL_FTM_TIMER bool "Freescale FlexTimer Module driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS help Support for Freescale FlexTimer Module (FTM) timer. @@ -259,6 +269,7 @@ config SYS_SUPPORTS_SH_CMT config MTK_TIMER bool "Mediatek timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS select CLKSRC_OF select CLKSRC_MMIO help -- cgit v1.2.3 From 9115df89d12c2cf6db080a7ee57cd076f8416e4a Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 5 Nov 2015 10:32:06 +0800 Subject: clocksource/drivers/dw_apb_timer_of: Implement ARM delay timer Implement an ARM delay timer to be used for udelay(). This allows us to skip the delay loop calibration at boot on Marvell BG2, BG2Q, BG2CD platforms. And after this patch, udelay() will be unaffected by CPU frequency changes. Note: Although in case there are several possible delay timers, we may not select the "best" delay timer. Take one Marvell Berlin platform for example: we have arch timer and dw-apb timer. The arch timer freq is 25MHZ while the dw-apb timer freq is 100MHZ, current selection would choose the dw-apb timer. But the dw apb timer is on the APB bus while arch timer sits in CPU, the cost of accessing the apb timer is higher than the arch timer. We could introduce "rating" concept to delay timer, but this approach "brings a lot of complexity and workarounds in the code for a small benefit" as pointed out by Daniel. Later, Arnd pointed out "However, we could argue that this actually doesn't matter at all, because the entire point of the ndelay()/ udelay()/mdelay() functions is to waste CPU cycles doing not much at all, so we can just as well waste them reading the timer register than spinning on the CPU reading the arch timer more often.", so we just simply register the dw apb base delay timer. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer_of.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index a19a3f619cc7..860843cef572 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include #include #include @@ -130,6 +131,17 @@ static void __init init_sched_clock(void) sched_clock_register(read_sched_clock, 32, sched_rate); } +#ifdef CONFIG_ARM +static unsigned long dw_apb_delay_timer_read(void) +{ + return ~readl_relaxed(sched_io_base); +} + +static struct delay_timer dw_apb_delay_timer = { + .read_current_timer = dw_apb_delay_timer_read, +}; +#endif + static int num_called; static void __init dw_apb_timer_init(struct device_node *timer) { @@ -142,6 +154,10 @@ static void __init dw_apb_timer_init(struct device_node *timer) pr_debug("%s: found clocksource timer\n", __func__); add_clocksource(timer); init_sched_clock(); +#ifdef CONFIG_ARM + dw_apb_delay_timer.freq = sched_rate; + register_current_timer_delay(&dw_apb_delay_timer); +#endif break; default: break; -- cgit v1.2.3 From 4633f4cac85ad19f586fdd4f832ebd145190a68c Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 7 Nov 2015 01:31:44 +0900 Subject: clocksource/drivers/h8300: Cleanup startup and remove module code. Remove some legacy code and replace it by the clksrc-of code. Do some cleanup and code consolidation. Signed-off-by: Yoshinori Sato Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 141 +++++++++++++-------------------- drivers/clocksource/h8300_timer8.c | 150 ++++++++++++------------------------ drivers/clocksource/h8300_tpu.c | 117 ++++++++++------------------ 3 files changed, 144 insertions(+), 264 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 0e076c6fc006..cdf0d83a91be 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -47,9 +49,7 @@ #define ABSOLUTE 1 struct timer16_priv { - struct platform_device *pdev; struct clocksource cs; - struct irqaction irqaction; unsigned long total_cycles; unsigned long mapbase; unsigned long mapcommon; @@ -144,110 +144,77 @@ static void timer16_disable(struct clocksource *cs) p->cs_enabled = false; } +static struct timer16_priv timer16_priv = { + .cs = { + .name = "h8300_16timer", + .rating = 200, + .read = timer16_clocksource_read, + .enable = timer16_enable, + .disable = timer16_disable, + .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }, +}; + #define REG_CH 0 #define REG_COMM 1 -static int timer16_setup(struct timer16_priv *p, struct platform_device *pdev) +static void __init h8300_16timer_init(struct device_node *node) { - struct resource *res[2]; + void __iomem *base[2]; int ret, irq; unsigned int ch; + struct clk *clk; - p->pdev = pdev; - - res[REG_CH] = platform_get_resource(p->pdev, - IORESOURCE_MEM, REG_CH); - res[REG_COMM] = platform_get_resource(p->pdev, - IORESOURCE_MEM, REG_COMM); - if (!res[REG_CH] || !res[REG_COMM]) { - dev_err(&p->pdev->dev, "failed to get I/O memory\n"); - return -ENXIO; - } - irq = platform_get_irq(p->pdev, 0); - if (irq < 0) { - dev_err(&p->pdev->dev, "failed to get irq\n"); - return irq; + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) { + pr_err("failed to get clock for clocksource\n"); + return; } - p->clk = clk_get(&p->pdev->dev, "fck"); - if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "can't get clk\n"); - return PTR_ERR(p->clk); + base[REG_CH] = of_iomap(node, 0); + if (!base[REG_CH]) { + pr_err("failed to map registers for clocksource\n"); + goto free_clk; } - of_property_read_u32(p->pdev->dev.of_node, "renesas,channel", &ch); - - p->pdev = pdev; - p->mapbase = res[REG_CH]->start; - p->mapcommon = res[REG_COMM]->start; - p->enb = 1 << ch; - p->imfa = 1 << ch; - p->imiea = 1 << (4 + ch); - p->cs.name = pdev->name; - p->cs.rating = 200; - p->cs.read = timer16_clocksource_read; - p->cs.enable = timer16_enable; - p->cs.disable = timer16_disable; - p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); - p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; - ret = request_irq(irq, timer16_interrupt, - IRQF_TIMER, pdev->name, p); - if (ret < 0) { - dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); - return ret; + base[REG_COMM] = of_iomap(node, 1); + if (!base[REG_COMM]) { + pr_err("failed to map registers for clocksource\n"); + goto unmap_ch; } - clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 8); - - return 0; -} - -static int timer16_probe(struct platform_device *pdev) -{ - struct timer16_priv *p = platform_get_drvdata(pdev); - - if (p) { - dev_info(&pdev->dev, "kept as earlytimer\n"); - return 0; + irq = irq_of_parse_and_map(node, 0); + if (irq < 0) { + pr_err("failed to get irq for clockevent\n"); + goto unmap_comm; } - p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; + of_property_read_u32(node, "renesas,channel", &ch); - return timer16_setup(p, pdev); -} + timer16_priv.mapbase = (unsigned long)base[REG_CH]; + timer16_priv.mapcommon = (unsigned long)base[REG_COMM]; + timer16_priv.enb = 1 << ch; + timer16_priv.imfa = 1 << ch; + timer16_priv.imiea = 1 << (4 + ch); -static int timer16_remove(struct platform_device *pdev) -{ - return -EBUSY; -} - -static const struct of_device_id timer16_of_table[] = { - { .compatible = "renesas,16bit-timer" }, - { } -}; -static struct platform_driver timer16_driver = { - .probe = timer16_probe, - .remove = timer16_remove, - .driver = { - .name = "h8300h-16timer", - .of_match_table = of_match_ptr(timer16_of_table), + ret = request_irq(irq, timer16_interrupt, + IRQF_TIMER, timer16_priv.cs.name, &timer16_priv); + if (ret < 0) { + pr_err("failed to request irq %d of clocksource\n", irq); + goto unmap_comm; } -}; -static int __init timer16_init(void) -{ - return platform_driver_register(&timer16_driver); -} + clocksource_register_hz(&timer16_priv.cs, + clk_get_rate(timer16_priv.clk) / 8); + return; -static void __exit timer16_exit(void) -{ - platform_driver_unregister(&timer16_driver); +unmap_comm: + iounmap(base[REG_COMM]); +unmap_ch: + iounmap(base[REG_CH]); +free_clk: + clk_put(clk); } -subsys_initcall(timer16_init); -module_exit(timer16_exit); -MODULE_AUTHOR("Yoshinori Sato"); -MODULE_DESCRIPTION("H8/300H 16bit Timer Driver"); -MODULE_LICENSE("GPL v2"); +CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer", h8300_16timer_init); diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 44375d8b9bc4..f0680eb4f93d 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -12,13 +12,14 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include #include @@ -39,10 +40,10 @@ #define RELATIVE 0 #define ABSOLUTE 1 +#define SCALE 64 + struct timer8_priv { - struct platform_device *pdev; struct clock_event_device ced; - struct irqaction irqaction; unsigned long mapbase; raw_spinlock_t lock; unsigned long flags; @@ -111,7 +112,7 @@ static void timer8_set_next(struct timer8_priv *p, unsigned long delta) static int timer8_enable(struct timer8_priv *p) { - p->rate = clk_get_rate(p->pclk) / 64; + p->rate = clk_get_rate(p->pclk) / SCALE; ctrl_outw(0xffff, p->mapbase + TCORA); ctrl_outw(0x0000, p->mapbase + _8TCNT); ctrl_outw(0x0c02, p->mapbase + _8TCR); @@ -179,7 +180,7 @@ static int timer8_clock_event_periodic(struct clock_event_device *ced) { struct timer8_priv *p = ced_to_priv(ced); - dev_info(&p->pdev->dev, "used for periodic clock events\n"); + pr_info("%s: used for periodic clock events\n", ced->name); timer8_stop(p); timer8_clock_event_start(p, PERIODIC); @@ -190,7 +191,7 @@ static int timer8_clock_event_oneshot(struct clock_event_device *ced) { struct timer8_priv *p = ced_to_priv(ced); - dev_info(&p->pdev->dev, "used for oneshot clock events\n"); + pr_info("%s: used for oneshot clock events\n", ced->name); timer8_stop(p); timer8_clock_event_start(p, ONESHOT); @@ -208,110 +209,61 @@ static int timer8_clock_event_next(unsigned long delta, return 0; } -static int timer8_setup(struct timer8_priv *p, - struct platform_device *pdev) +static struct timer8_priv timer8_priv = { + .ced = { + .name = "h8300_8timer", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = timer8_clock_event_next, + .set_state_shutdown = timer8_clock_event_shutdown, + .set_state_periodic = timer8_clock_event_periodic, + .set_state_oneshot = timer8_clock_event_oneshot, + }, +}; + +static void __init h8300_8timer_init(struct device_node *node) { - struct resource *res; + void __iomem *base; int irq; - int ret; + int ret = 0; + int rate; + struct clk *clk; - p->pdev = pdev; + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) { + pr_err("failed to get clock for clockevent\n"); + return; + } - res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&p->pdev->dev, "failed to get I/O memory\n"); - return -ENXIO; + base = of_iomap(node, 0); + if (!base) { + pr_err("failed to map registers for clockevent\n"); + goto free_clk; } - irq = platform_get_irq(p->pdev, 0); + irq = irq_of_parse_and_map(node, 0); if (irq < 0) { - dev_err(&p->pdev->dev, "failed to get irq\n"); - return -ENXIO; + pr_err("failed to get irq for clockevent\n"); + goto unmap_reg; } - p->mapbase = res->start; - - p->irqaction.name = dev_name(&p->pdev->dev); - p->irqaction.handler = timer8_interrupt; - p->irqaction.dev_id = p; - p->irqaction.flags = IRQF_TIMER; - - p->pclk = clk_get(&p->pdev->dev, "fck"); - if (IS_ERR(p->pclk)) { - dev_err(&p->pdev->dev, "can't get clk\n"); - return PTR_ERR(p->pclk); - } + timer8_priv.mapbase = (unsigned long)base; + timer8_priv.pclk = clk; - p->ced.name = pdev->name; - p->ced.features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT; - p->ced.rating = 200; - p->ced.cpumask = cpumask_of(0); - p->ced.set_next_event = timer8_clock_event_next; - p->ced.set_state_shutdown = timer8_clock_event_shutdown; - p->ced.set_state_periodic = timer8_clock_event_periodic; - p->ced.set_state_oneshot = timer8_clock_event_oneshot; - - ret = setup_irq(irq, &p->irqaction); + ret = request_irq(irq, timer8_interrupt, + IRQF_TIMER, timer8_priv.ced.name, &timer8_priv); if (ret < 0) { - dev_err(&p->pdev->dev, - "failed to request irq %d\n", irq); - return ret; + pr_err("failed to request irq %d for clockevent\n", irq); + goto unmap_reg; } - clockevents_register_device(&p->ced); - platform_set_drvdata(pdev, p); - - return 0; -} - -static int timer8_probe(struct platform_device *pdev) -{ - struct timer8_priv *p = platform_get_drvdata(pdev); - - if (p) { - dev_info(&pdev->dev, "kept as earlytimer\n"); - return 0; - } - - p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - return timer8_setup(p, pdev); -} - -static int timer8_remove(struct platform_device *pdev) -{ - return -EBUSY; -} - -static const struct of_device_id timer8_of_table[] __maybe_unused = { - { .compatible = "renesas,8bit-timer" }, - { } -}; - -MODULE_DEVICE_TABLE(of, timer8_of_table); -static struct platform_driver timer8_driver = { - .probe = timer8_probe, - .remove = timer8_remove, - .driver = { - .name = "h8300-8timer", - .of_match_table = of_match_ptr(timer8_of_table), - } -}; - -static int __init timer8_init(void) -{ - return platform_driver_register(&timer8_driver); -} - -static void __exit timer8_exit(void) -{ - platform_driver_unregister(&timer8_driver); + rate = clk_get_rate(clk) / SCALE; + clockevents_config_and_register(&timer8_priv.ced, rate, 1, 0x0000ffff); + return; + +unmap_reg: + iounmap(base); +free_clk: + clk_put(clk); } -subsys_initcall(timer8_init); -module_exit(timer8_exit); -MODULE_AUTHOR("Yoshinori Sato"); -MODULE_DESCRIPTION("H8/300 8bit Timer Driver"); -MODULE_LICENSE("GPL v2"); +CLOCKSOURCE_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init); diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index 5487410bfabb..ed0b49344577 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -1,5 +1,5 @@ /* - * H8/300 TPU Driver + * H8S TPU Driver * * Copyright 2015 Yoshinori Sato * @@ -17,8 +17,8 @@ #include #include #include - -#include +#include +#include #define TCR 0 #define TMDR 1 @@ -32,9 +32,7 @@ #define TGRD 14 struct tpu_priv { - struct platform_device *pdev; struct clocksource cs; - struct clk *clk; unsigned long mapbase1; unsigned long mapbase2; raw_spinlock_t lock; @@ -116,91 +114,54 @@ static void tpu_clocksource_disable(struct clocksource *cs) p->cs_enabled = false; } +static struct tpu_priv tpu_priv = { + .cs = { + .name = "H8S_TPU", + .rating = 200, + .read = tpu_clocksource_read, + .enable = tpu_clocksource_enable, + .disable = tpu_clocksource_disable, + .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }, +}; + #define CH_L 0 #define CH_H 1 -static int __init tpu_setup(struct tpu_priv *p, struct platform_device *pdev) +static void __init h8300_tpu_init(struct device_node *node) { - struct resource *res[2]; - - p->pdev = pdev; + void __iomem *base[2]; + struct clk *clk; - res[CH_L] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_L); - res[CH_H] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_H); - if (!res[CH_L] || !res[CH_H]) { - dev_err(&p->pdev->dev, "failed to get I/O memory\n"); - return -ENXIO; + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) { + pr_err("failed to get clock for clocksource\n"); + return; } - p->clk = clk_get(&p->pdev->dev, "fck"); - if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "can't get clk\n"); - return PTR_ERR(p->clk); + base[CH_L] = of_iomap(node, CH_L); + if (!base[CH_L]) { + pr_err("failed to map registers for clocksource\n"); + goto free_clk; } - - p->mapbase1 = res[CH_L]->start; - p->mapbase2 = res[CH_H]->start; - - p->cs.name = pdev->name; - p->cs.rating = 200; - p->cs.read = tpu_clocksource_read; - p->cs.enable = tpu_clocksource_enable; - p->cs.disable = tpu_clocksource_disable; - p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); - p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; - clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 64); - platform_set_drvdata(pdev, p); - - return 0; -} - -static int tpu_probe(struct platform_device *pdev) -{ - struct tpu_priv *p = platform_get_drvdata(pdev); - - if (p) { - dev_info(&pdev->dev, "kept as earlytimer\n"); - return 0; + base[CH_H] = of_iomap(node, CH_H); + if (!base[CH_H]) { + pr_err("failed to map registers for clocksource\n"); + goto unmap_L; } - p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; + tpu_priv.mapbase1 = (unsigned long)base[CH_L]; + tpu_priv.mapbase2 = (unsigned long)base[CH_H]; - return tpu_setup(p, pdev); -} + clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64); -static int tpu_remove(struct platform_device *pdev) -{ - return -EBUSY; -} + return; -static const struct of_device_id tpu_of_table[] = { - { .compatible = "renesas,tpu" }, - { } -}; - -static struct platform_driver tpu_driver = { - .probe = tpu_probe, - .remove = tpu_remove, - .driver = { - .name = "h8s-tpu", - .of_match_table = of_match_ptr(tpu_of_table), - } -}; - -static int __init tpu_init(void) -{ - return platform_driver_register(&tpu_driver); -} - -static void __exit tpu_exit(void) -{ - platform_driver_unregister(&tpu_driver); +unmap_L: + iounmap(base[CH_H]); +free_clk: + clk_put(clk); } -subsys_initcall(tpu_init); -module_exit(tpu_exit); -MODULE_AUTHOR("Yoshinori Sato"); -MODULE_DESCRIPTION("H8S Timer Pulse Unit Driver"); -MODULE_LICENSE("GPL v2"); +CLOCKSOURCE_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init); -- cgit v1.2.3 From 8c09b7d6ba91ece6d10c7703f5cb201ff3265771 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 09:02:38 +0100 Subject: clocksource/drivers/h8300_timer8: Fix compilation error with dev_warn The dev_warn is using the platform driver which was removed in the previous patch. Let's replace dev_warn by pr_warn. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index f0680eb4f93d..35b0e8f98caf 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -98,7 +98,7 @@ static void timer8_set_next(struct timer8_priv *p, unsigned long delta) raw_spin_lock_irqsave(&p->lock, flags); if (delta >= 0x10000) - dev_warn(&p->pdev->dev, "delta out of range\n"); + pr_warn("delta out of range\n"); now = timer8_get_counter(p); p->tcora = delta; ctrl_outb(ctrl_inb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR); -- cgit v1.2.3 From 9471f1d95442e35c04d429378fb01a962ebfba55 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 7 Nov 2015 14:18:51 +0100 Subject: clocksource/drivers/h8300_tpu: Remove unused macros Some macros are unused, delete them. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_tpu.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index ed0b49344577..576dae6f2a91 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -20,16 +20,9 @@ #include #include -#define TCR 0 -#define TMDR 1 -#define TIOR 2 -#define TER 4 -#define TSR 5 -#define TCNT 6 -#define TGRA 8 -#define TGRB 10 -#define TGRC 12 -#define TGRD 14 +#define TCR 0x0 +#define TSR 0x5 +#define TCNT 0x6 struct tpu_priv { struct clocksource cs; -- cgit v1.2.3 From 31221a4bfbf2717c9d8f7a8a1f490ac890fe867f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 7 Nov 2015 14:26:46 +0100 Subject: clocksource/drivers/h8300_tpu: Remove pointless headers for TPU Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_tpu.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index 576dae6f2a91..c1eef423b2a1 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -6,14 +6,9 @@ */ #include -#include #include -#include #include -#include -#include #include -#include #include #include #include -- cgit v1.2.3 From d1f9db13e36de0d66bbc41e65da0dec08907d23a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 17:39:05 +0100 Subject: clocksource/drivers/h8300_timer8: Remove unused headers Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 35b0e8f98caf..62a7f8c97091 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -8,21 +8,16 @@ */ #include -#include #include #include #include -#include #include -#include #include #include #include #include #include -#include - #define _8TCR 0 #define _8TCSR 2 #define TCORA 4 -- cgit v1.2.3 From 7116ae437fc7380ffc0b9429438bba9de9681024 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 17:40:35 +0100 Subject: clocksource/drivers/h8300_timer8: Remove unused macros Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 62a7f8c97091..88b9b0630fbe 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -24,7 +24,6 @@ #define TCORB 6 #define _8TCNT 8 -#define FLAG_REPROGRAM (1 << 0) #define FLAG_SKIPEVENT (1 << 1) #define FLAG_IRQCONTEXT (1 << 2) #define FLAG_STARTED (1 << 3) @@ -32,9 +31,6 @@ #define ONESHOT 0 #define PERIODIC 1 -#define RELATIVE 0 -#define ABSOLUTE 1 - #define SCALE 64 struct timer8_priv { -- cgit v1.2.3 From 1f058d52b3e32b919742d451c673b3ab71c487dc Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 17:46:54 +0100 Subject: clocksource/drivers/h8300_timer8: Remove PERIODIC and ONESHOT macro Specify the delta as parameter for the timer8_clock_event_start function instead of using a macro to tell PERIODIC or ONESHOT. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 88b9b0630fbe..2433325bd38f 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -28,9 +28,6 @@ #define FLAG_IRQCONTEXT (1 << 2) #define FLAG_STARTED (1 << 3) -#define ONESHOT 0 -#define PERIODIC 1 - #define SCALE 64 struct timer8_priv { @@ -147,7 +144,7 @@ static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) return container_of(ced, struct timer8_priv, ced); } -static void timer8_clock_event_start(struct timer8_priv *p, int periodic) +static void timer8_clock_event_start(struct timer8_priv *p, unsigned long delta) { struct clock_event_device *ced = &p->ced; @@ -158,7 +155,7 @@ static void timer8_clock_event_start(struct timer8_priv *p, int periodic) ced->max_delta_ns = clockevent_delta2ns(0xffff, ced); ced->min_delta_ns = clockevent_delta2ns(0x0001, ced); - timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000); + timer8_set_next(p, delta); } static int timer8_clock_event_shutdown(struct clock_event_device *ced) @@ -173,7 +170,7 @@ static int timer8_clock_event_periodic(struct clock_event_device *ced) pr_info("%s: used for periodic clock events\n", ced->name); timer8_stop(p); - timer8_clock_event_start(p, PERIODIC); + timer8_clock_event_start(p, (p->rate + HZ/2) / HZ); return 0; } @@ -184,7 +181,7 @@ static int timer8_clock_event_oneshot(struct clock_event_device *ced) pr_info("%s: used for oneshot clock events\n", ced->name); timer8_stop(p); - timer8_clock_event_start(p, ONESHOT); + timer8_clock_event_start(p, 0x10000); return 0; } -- cgit v1.2.3 From 54a0cd5a7e107ba0cf15a4fb876595d0c8a7faab Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 17:56:18 +0100 Subject: clocksource/drivers/h8300_timer8: Fix irq return value check The value returned in case of error for the 'irq_of_parse_and_map' function is zero in case of error. Fix the check in the init code. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 2433325bd38f..3eedeffccc26 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -230,7 +230,7 @@ static void __init h8300_8timer_init(struct device_node *node) } irq = irq_of_parse_and_map(node, 0); - if (irq < 0) { + if (!irq) { pr_err("failed to get irq for clockevent\n"); goto unmap_reg; } -- cgit v1.2.3 From 7053fdac76451efe5f16c9e0974dc17fcf29f6d6 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 18:07:38 +0100 Subject: clocksource/drivers/h8300_timer8: Remove pointless irq re-entrant safe code The current code assumes the interrupt function is re-entrant. That is not correct. An interrupt handler is never invoked concurrently. The interrupt line is masked on all processors. Remove the chewing flags in the code. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 3eedeffccc26..7111b99be6d5 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -24,8 +24,6 @@ #define TCORB 6 #define _8TCNT 8 -#define FLAG_SKIPEVENT (1 << 1) -#define FLAG_IRQCONTEXT (1 << 2) #define FLAG_STARTED (1 << 3) #define SCALE 64 @@ -67,14 +65,13 @@ static irqreturn_t timer8_interrupt(int irq, void *dev_id) ctrl_outb(ctrl_inb(p->mapbase + _8TCSR) & ~0x40, p->mapbase + _8TCSR); - p->flags |= FLAG_IRQCONTEXT; + ctrl_outw(p->tcora, p->mapbase + TCORA); - if (!(p->flags & FLAG_SKIPEVENT)) { - if (clockevent_state_oneshot(&p->ced)) - ctrl_outw(0x0000, p->mapbase + _8TCR); - p->ced.event_handler(&p->ced); - } - p->flags &= ~(FLAG_SKIPEVENT | FLAG_IRQCONTEXT); + + if (clockevent_state_oneshot(&p->ced)) + ctrl_outw(0x0000, p->mapbase + _8TCR); + + p->ced.event_handler(&p->ced); return IRQ_HANDLED; } -- cgit v1.2.3 From 254d8b5d59516d670111e0ac14d53fed4d61118d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 22:39:12 +0100 Subject: clocksource/drivers/h8300_timer8: Remove irq and lock legacy code The time framawork takes care of disabling the interrupts and takes a lock to prevent races. Remove the legacy code in the driver taking care of the races. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 7111b99be6d5..24d91b1a5d5c 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -31,7 +31,6 @@ struct timer8_priv { struct clock_event_device ced; unsigned long mapbase; - raw_spinlock_t lock; unsigned long flags; unsigned int rate; unsigned int tcora; @@ -78,10 +77,8 @@ static irqreturn_t timer8_interrupt(int irq, void *dev_id) static void timer8_set_next(struct timer8_priv *p, unsigned long delta) { - unsigned long flags; unsigned long now; - raw_spin_lock_irqsave(&p->lock, flags); if (delta >= 0x10000) pr_warn("delta out of range\n"); now = timer8_get_counter(p); @@ -91,8 +88,6 @@ static void timer8_set_next(struct timer8_priv *p, unsigned long delta) ctrl_outw(delta, p->mapbase + TCORA); else ctrl_outw(now + 1, p->mapbase + TCORA); - - raw_spin_unlock_irqrestore(&p->lock, flags); } static int timer8_enable(struct timer8_priv *p) @@ -108,9 +103,6 @@ static int timer8_enable(struct timer8_priv *p) static int timer8_start(struct timer8_priv *p) { int ret = 0; - unsigned long flags; - - raw_spin_lock_irqsave(&p->lock, flags); if (!(p->flags & FLAG_STARTED)) ret = timer8_enable(p); @@ -120,20 +112,12 @@ static int timer8_start(struct timer8_priv *p) p->flags |= FLAG_STARTED; out: - raw_spin_unlock_irqrestore(&p->lock, flags); - return ret; } static void timer8_stop(struct timer8_priv *p) { - unsigned long flags; - - raw_spin_lock_irqsave(&p->lock, flags); - ctrl_outw(0x0000, p->mapbase + _8TCR); - - raw_spin_unlock_irqrestore(&p->lock, flags); } static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) -- cgit v1.2.3 From cce483e0ee70c2c9c6ff08e502b6f0bba3e15f62 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 23:24:28 +0100 Subject: clocksource/drivers/h8300_timer8: Retrieve the clock rate at init time The current code retrieves the rate value when the timer is enabled which occurs each time a timer is re-armed. Except if the clock frequency has changed magically I don't see why this should be done each time. Retrieve the clock rate value at init time only. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 24d91b1a5d5c..187c41619b13 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -34,7 +34,6 @@ struct timer8_priv { unsigned long flags; unsigned int rate; unsigned int tcora; - struct clk *pclk; }; static unsigned long timer8_get_counter(struct timer8_priv *p) @@ -92,7 +91,6 @@ static void timer8_set_next(struct timer8_priv *p, unsigned long delta) static int timer8_enable(struct timer8_priv *p) { - p->rate = clk_get_rate(p->pclk) / SCALE; ctrl_outw(0xffff, p->mapbase + TCORA); ctrl_outw(0x0000, p->mapbase + _8TCNT); ctrl_outw(0x0c02, p->mapbase + _8TCR); @@ -102,16 +100,15 @@ static int timer8_enable(struct timer8_priv *p) static int timer8_start(struct timer8_priv *p) { - int ret = 0; + int ret; - if (!(p->flags & FLAG_STARTED)) - ret = timer8_enable(p); + if ((p->flags & FLAG_STARTED)) + return 0; - if (ret) - goto out; - p->flags |= FLAG_STARTED; + ret = timer8_enable(p); + if (!ret) + p->flags |= FLAG_STARTED; - out: return ret; } @@ -217,7 +214,12 @@ static void __init h8300_8timer_init(struct device_node *node) } timer8_priv.mapbase = (unsigned long)base; - timer8_priv.pclk = clk; + + rate = clk_get_rate(clk) / SCALE; + if (!rate) { + pr_err("Failed to get rate for the clocksource\n"); + goto unmap_reg; + } ret = request_irq(irq, timer8_interrupt, IRQF_TIMER, timer8_priv.ced.name, &timer8_priv); @@ -225,10 +227,10 @@ static void __init h8300_8timer_init(struct device_node *node) pr_err("failed to request irq %d for clockevent\n", irq); goto unmap_reg; } - rate = clk_get_rate(clk) / SCALE; + clockevents_config_and_register(&timer8_priv.ced, rate, 1, 0x0000ffff); - return; + return; unmap_reg: iounmap(base); free_clk: -- cgit v1.2.3 From 8cbade52715634481cf4fd8ab9d4f091860724e2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 10:46:13 +0100 Subject: clocksource/drivers/h8300_timer16: Remove pointless headers The headers are not needed, remove them. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index cdf0d83a91be..1c9dd02efb0d 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -4,25 +4,15 @@ * Copyright 2015 Yoshinori Sato */ -#include -#include -#include -#include -#include #include #include -#include #include -#include #include #include #include #include #include -#include -#include - #define TSTR 0 #define TSNC 1 #define TMDR 2 -- cgit v1.2.3 From 8b24e8d7177257279f842c8169672c1180e6c831 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 10:49:14 +0100 Subject: clocksource/drivers/h8300_timer16: Remove unused macros The macros are no longer used in the code, remove them. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 1c9dd02efb0d..bc9289b2b00d 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -14,29 +14,11 @@ #include #define TSTR 0 -#define TSNC 1 -#define TMDR 2 -#define TOLR 3 #define TISRA 4 -#define TISRB 5 #define TISRC 6 #define TCR 0 -#define TIOR 1 #define TCNT 2 -#define GRA 4 -#define GRB 6 - -#define FLAG_REPROGRAM (1 << 0) -#define FLAG_SKIPEVENT (1 << 1) -#define FLAG_IRQCONTEXT (1 << 2) -#define FLAG_STARTED (1 << 3) - -#define ONESHOT 0 -#define PERIODIC 1 - -#define RELATIVE 0 -#define ABSOLUTE 1 struct timer16_priv { struct clocksource cs; -- cgit v1.2.3 From 903e5fd3f857c978ff8a75ae4bc5c51e6161031c Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 10:51:09 +0100 Subject: clocksource/drivers/h8300_timer16: Remove unused fields in timer16_priv The fields are not used in the code, remove them. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index bc9289b2b00d..6705bf784d84 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -25,8 +25,6 @@ struct timer16_priv { unsigned long total_cycles; unsigned long mapbase; unsigned long mapcommon; - unsigned long flags; - unsigned short gra; unsigned short cs_enabled; unsigned char enb; unsigned char imfa; -- cgit v1.2.3 From 5019c9023251efd3bfa22b1090d8ad1901914c93 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 10:52:35 +0100 Subject: clocksource/drivers/h8300_timer16: Fix irq return value check The function irq_of_parse_and_map returns zero in case of failure. Fix the return code test to check against zero. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 6705bf784d84..129dca02b3ee 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -155,7 +155,7 @@ static void __init h8300_16timer_init(struct device_node *node) } irq = irq_of_parse_and_map(node, 0); - if (irq < 0) { + if (!irq) { pr_err("failed to get irq for clockevent\n"); goto unmap_comm; } -- cgit v1.2.3 From 05de7ed6795a1826e67fac56051f0ec23a643d38 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 10:55:30 +0100 Subject: clocksource/drivers/h8300_timer16: Remove pointless lock The lock in the timer16_clocksource_read is not needed, remove it. Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 129dca02b3ee..f39660586b1a 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -30,7 +30,6 @@ struct timer16_priv { unsigned char imfa; unsigned char imiea; unsigned char ovf; - raw_spinlock_t lock; struct clk *clk; }; @@ -75,13 +74,10 @@ static inline struct timer16_priv *cs_to_priv(struct clocksource *cs) static cycle_t timer16_clocksource_read(struct clocksource *cs) { struct timer16_priv *p = cs_to_priv(cs); - unsigned long flags, raw; - unsigned long value; + unsigned long raw, value; - raw_spin_lock_irqsave(&p->lock, flags); value = p->total_cycles; raw = timer16_get_counter(p); - raw_spin_unlock_irqrestore(&p->lock, flags); return value + raw; } -- cgit v1.2.3 From 157dfadef8323046df32caa4b39b46bf7737ca23 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 12 Nov 2015 18:05:11 +0100 Subject: clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init The current code to initialize, register and read the clocksource is already factored out in mmio.c via the clocksource_mmio_init function. The only difference is the readl vs readl_relaxed. Factor out the code with the clocksource_mmio_init function. Signed-off-by: Daniel Lezcano Acked-by: Maxime Ripard --- drivers/clocksource/timer-sun5i.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index bca9573e036a..24c83f9efd87 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -152,13 +152,6 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static cycle_t sun5i_clksrc_read(struct clocksource *clksrc) -{ - struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc); - - return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1)); -} - static int sun5i_rate_cb_clksrc(struct notifier_block *nb, unsigned long event, void *data) { @@ -217,13 +210,8 @@ static int __init sun5i_setup_clocksource(struct device_node *node, writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, base + TIMER_CTL_REG(1)); - cs->clksrc.name = node->name; - cs->clksrc.rating = 340; - cs->clksrc.read = sun5i_clksrc_read; - cs->clksrc.mask = CLOCKSOURCE_MASK(32); - cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; - - ret = clocksource_register_hz(&cs->clksrc, rate); + ret = clocksource_mmio_init(base + TIMER_CNTVAL_LO_REG(1), node->name, + rate, 340, 32, clocksource_mmio_readl_down); if (ret) { pr_err("Couldn't register clock source.\n"); goto err_remove_notifier; -- cgit v1.2.3 From 97a23beb8db9766ed8f673479af4dcc883311504 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 14:43:52 +0100 Subject: clocksource/drivers/h8300_timer8: Separate the Kconfig option from the arch The current Kconfig option is the H8300 arch option. In order to comply to the current rule, let's create a specific option for the timer8 and select it from the arch's Kconfig. Signed-off-by: Daniel Lezcano --- arch/h8300/Kconfig | 1 + drivers/clocksource/Kconfig | 3 +++ drivers/clocksource/Makefile | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index dd3ac75776ad..2e20333cbce9 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -17,6 +17,7 @@ config H8300 select HAVE_MEMBLOCK select HAVE_DMA_ATTRS select CLKSRC_OF + select H8300_TMR8 config RWSEM_GENERIC_SPINLOCK def_bool y diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index de331b8346d8..73477b5e094b 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -362,6 +362,9 @@ config CLKSRC_PXA This enables OST0 support available on PXA and SA-11x0 platforms. +config H8300_TMR8 + bool + config H8300_TMR16 bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 56bd16e77ae3..dc2b8997f6e6 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -60,7 +60,7 @@ obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o -obj-$(CONFIG_H8300) += h8300_timer8.o +obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o -- cgit v1.2.3 From 751605152b4dbcdf3da2643c965ec1c3b734e11d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 8 Nov 2015 22:55:12 +0100 Subject: h8300: Rename ctlr_out/in[bwl] to raw_read/write[bwl] For the sake of consistency, let rename all ctrl_out/in calls to the write/read calls so we have the same API consistent with the other architectures hence open the door for the increasing of the test compilation coverage. The unsigned long coercive cast is removed because all variables are set to the right type "void __iomem *". Signed-off-by: Daniel Lezcano --- arch/h8300/include/asm/io.h | 39 +++++++++++++++++++++--------------- arch/h8300/kernel/setup.c | 8 ++++---- drivers/clocksource/h8300_timer16.c | 28 +++++++++++++------------- drivers/clocksource/h8300_timer8.c | 34 +++++++++++++++---------------- drivers/clocksource/h8300_tpu.c | 28 +++++++++++++------------- drivers/irqchip/irq-renesas-h8300h.c | 8 ++++---- 6 files changed, 76 insertions(+), 69 deletions(-) diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h index bb837cded268..f0e14f3a800d 100644 --- a/arch/h8300/include/asm/io.h +++ b/arch/h8300/include/asm/io.h @@ -3,40 +3,45 @@ #ifdef __KERNEL__ -#include - /* H8/300 internal I/O functions */ -static inline unsigned char ctrl_inb(unsigned long addr) + +#define __raw_readb __raw_readb +static inline u8 __raw_readb(const volatile void __iomem *addr) { - return *(volatile unsigned char *)addr; + return *(volatile u8 *)addr; } -static inline unsigned short ctrl_inw(unsigned long addr) +#define __raw_readw __raw_readw +static inline u16 __raw_readw(const volatile void __iomem *addr) { - return *(volatile unsigned short *)addr; + return *(volatile u16 *)addr; } -static inline unsigned long ctrl_inl(unsigned long addr) +#define __raw_readl __raw_readl +static inline u32 __raw_readl(const volatile void __iomem *addr) { - return *(volatile unsigned long *)addr; + return *(volatile u32 *)addr; } -static inline void ctrl_outb(unsigned char b, unsigned long addr) +#define __raw_writeb __raw_writeb +static inline void __raw_writeb(u8 b, const volatile void __iomem *addr) { - *(volatile unsigned char *)addr = b; + *(volatile u8 *)addr = b; } -static inline void ctrl_outw(unsigned short b, unsigned long addr) +#define __raw_writew __raw_writew +static inline void __raw_writew(u16 b, const volatile void __iomem *addr) { - *(volatile unsigned short *)addr = b; + *(volatile u16 *)addr = b; } -static inline void ctrl_outl(unsigned long b, unsigned long addr) +#define __raw_writel __raw_writel +static inline void __raw_writel(u32 b, const volatile void __iomem *addr) { - *(volatile unsigned long *)addr = b; + *(volatile u32 *)addr = b; } -static inline void ctrl_bclr(int b, unsigned char *addr) +static inline void ctrl_bclr(int b, void __iomem *addr) { if (__builtin_constant_p(b)) __asm__("bclr %1,%0" : "+WU"(*addr): "i"(b)); @@ -44,7 +49,7 @@ static inline void ctrl_bclr(int b, unsigned char *addr) __asm__("bclr %w1,%0" : "+WU"(*addr): "r"(b)); } -static inline void ctrl_bset(int b, unsigned char *addr) +static inline void ctrl_bset(int b, void __iomem *addr) { if (__builtin_constant_p(b)) __asm__("bset %1,%0" : "+WU"(*addr): "i"(b)); @@ -52,6 +57,8 @@ static inline void ctrl_bset(int b, unsigned char *addr) __asm__("bset %w1,%0" : "+WU"(*addr): "r"(b)); } +#include + #endif /* __KERNEL__ */ #endif /* _H8300_IO_H */ diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c index c772abe6d19c..e4985dfa91dc 100644 --- a/arch/h8300/kernel/setup.c +++ b/arch/h8300/kernel/setup.c @@ -207,14 +207,14 @@ device_initcall(device_probe); #define get_wait(base, addr) ({ \ int baddr; \ baddr = ((addr) / 0x200000 * 2); \ - w *= (ctrl_inw((unsigned long)(base) + 2) & (3 << baddr)) + 1; \ + w *= (readw((base) + 2) & (3 << baddr)) + 1; \ }) #endif #if defined(CONFIG_CPU_H8S) #define get_wait(base, addr) ({ \ int baddr; \ baddr = ((addr) / 0x200000 * 16); \ - w *= (ctrl_inl((unsigned long)(base) + 2) & (7 << baddr)) + 1; \ + w *= (readl((base) + 2) & (7 << baddr)) + 1; \ }) #endif @@ -228,8 +228,8 @@ static __init int access_timing(void) bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc"); base = of_iomap(bsc, 0); - w = (ctrl_inb((unsigned long)base + 0) & bit)?2:1; - if (ctrl_inb((unsigned long)base + 1) & bit) + w = (readb(base + 0) & bit)?2:1; + if (readb(base + 1) & bit) w *= get_wait(base, addr); else w *= 2; diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index f39660586b1a..fc14a3f741bf 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -23,8 +23,8 @@ struct timer16_priv { struct clocksource cs; unsigned long total_cycles; - unsigned long mapbase; - unsigned long mapcommon; + void __iomem *mapbase; + void __iomem *mapcommon; unsigned short cs_enabled; unsigned char enb; unsigned char imfa; @@ -38,15 +38,15 @@ static unsigned long timer16_get_counter(struct timer16_priv *p) unsigned long v1, v2, v3; int o1, o2; - o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf; + o1 = readb(p->mapcommon + TISRC) & p->ovf; /* Make sure the timer value is stable. Stolen from acpi_pm.c */ do { o2 = o1; - v1 = ctrl_inw(p->mapbase + TCNT); - v2 = ctrl_inw(p->mapbase + TCNT); - v3 = ctrl_inw(p->mapbase + TCNT); - o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf; + v1 = readw(p->mapbase + TCNT); + v2 = readw(p->mapbase + TCNT); + v3 = readw(p->mapbase + TCNT); + o1 = readb(p->mapcommon + TISRC) & p->ovf; } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); @@ -59,7 +59,7 @@ static irqreturn_t timer16_interrupt(int irq, void *dev_id) { struct timer16_priv *p = (struct timer16_priv *)dev_id; - ctrl_outb(ctrl_inb(p->mapcommon + TISRA) & ~p->imfa, + writeb(readb(p->mapcommon + TISRA) & ~p->imfa, p->mapcommon + TISRA); p->total_cycles += 0x10000; @@ -89,9 +89,9 @@ static int timer16_enable(struct clocksource *cs) WARN_ON(p->cs_enabled); p->total_cycles = 0; - ctrl_outw(0x0000, p->mapbase + TCNT); - ctrl_outb(0x83, p->mapbase + TCR); - ctrl_outb(ctrl_inb(p->mapcommon + TSTR) | p->enb, + writew(0x0000, p->mapbase + TCNT); + writeb(0x83, p->mapbase + TCR); + writeb(readb(p->mapcommon + TSTR) | p->enb, p->mapcommon + TSTR); p->cs_enabled = true; @@ -104,7 +104,7 @@ static void timer16_disable(struct clocksource *cs) WARN_ON(!p->cs_enabled); - ctrl_outb(ctrl_inb(p->mapcommon + TSTR) & ~p->enb, + writeb(readb(p->mapcommon + TSTR) & ~p->enb, p->mapcommon + TSTR); p->cs_enabled = false; @@ -158,8 +158,8 @@ static void __init h8300_16timer_init(struct device_node *node) of_property_read_u32(node, "renesas,channel", &ch); - timer16_priv.mapbase = (unsigned long)base[REG_CH]; - timer16_priv.mapcommon = (unsigned long)base[REG_COMM]; + timer16_priv.mapbase = base[REG_CH]; + timer16_priv.mapcommon = base[REG_COMM]; timer16_priv.enb = 1 << ch; timer16_priv.imfa = 1 << ch; timer16_priv.imiea = 1 << (4 + ch); diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 187c41619b13..aa4b2a989747 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -30,7 +30,7 @@ struct timer8_priv { struct clock_event_device ced; - unsigned long mapbase; + void __iomem *mapbase; unsigned long flags; unsigned int rate; unsigned int tcora; @@ -41,15 +41,15 @@ static unsigned long timer8_get_counter(struct timer8_priv *p) unsigned long v1, v2, v3; int o1, o2; - o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20; + o1 = readb(p->mapbase + _8TCSR) & 0x20; /* Make sure the timer value is stable. Stolen from acpi_pm.c */ do { o2 = o1; - v1 = ctrl_inw(p->mapbase + _8TCNT); - v2 = ctrl_inw(p->mapbase + _8TCNT); - v3 = ctrl_inw(p->mapbase + _8TCNT); - o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20; + v1 = readw(p->mapbase + _8TCNT); + v2 = readw(p->mapbase + _8TCNT); + v3 = readw(p->mapbase + _8TCNT); + o1 = readb(p->mapbase + _8TCSR) & 0x20; } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); @@ -61,13 +61,13 @@ static irqreturn_t timer8_interrupt(int irq, void *dev_id) { struct timer8_priv *p = dev_id; - ctrl_outb(ctrl_inb(p->mapbase + _8TCSR) & ~0x40, + writeb(readb(p->mapbase + _8TCSR) & ~0x40, p->mapbase + _8TCSR); - ctrl_outw(p->tcora, p->mapbase + TCORA); + writew(p->tcora, p->mapbase + TCORA); if (clockevent_state_oneshot(&p->ced)) - ctrl_outw(0x0000, p->mapbase + _8TCR); + writew(0x0000, p->mapbase + _8TCR); p->ced.event_handler(&p->ced); @@ -82,18 +82,18 @@ static void timer8_set_next(struct timer8_priv *p, unsigned long delta) pr_warn("delta out of range\n"); now = timer8_get_counter(p); p->tcora = delta; - ctrl_outb(ctrl_inb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR); + writeb(readb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR); if (delta > now) - ctrl_outw(delta, p->mapbase + TCORA); + writew(delta, p->mapbase + TCORA); else - ctrl_outw(now + 1, p->mapbase + TCORA); + writew(now + 1, p->mapbase + TCORA); } static int timer8_enable(struct timer8_priv *p) { - ctrl_outw(0xffff, p->mapbase + TCORA); - ctrl_outw(0x0000, p->mapbase + _8TCNT); - ctrl_outw(0x0c02, p->mapbase + _8TCR); + writew(0xffff, p->mapbase + TCORA); + writew(0x0000, p->mapbase + _8TCNT); + writew(0x0c02, p->mapbase + _8TCR); return 0; } @@ -114,7 +114,7 @@ static int timer8_start(struct timer8_priv *p) static void timer8_stop(struct timer8_priv *p) { - ctrl_outw(0x0000, p->mapbase + _8TCR); + writew(0x0000, p->mapbase + _8TCR); } static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) @@ -213,7 +213,7 @@ static void __init h8300_8timer_init(struct device_node *node) goto unmap_reg; } - timer8_priv.mapbase = (unsigned long)base; + timer8_priv.mapbase = base; rate = clk_get_rate(clk) / SCALE; if (!rate) { diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index c1eef423b2a1..91bf1992320e 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -21,8 +21,8 @@ struct tpu_priv { struct clocksource cs; - unsigned long mapbase1; - unsigned long mapbase2; + void __iomem *mapbase1; + void __iomem *mapbase2; raw_spinlock_t lock; unsigned int cs_enabled; }; @@ -31,8 +31,8 @@ static inline unsigned long read_tcnt32(struct tpu_priv *p) { unsigned long tcnt; - tcnt = ctrl_inw(p->mapbase1 + TCNT) << 16; - tcnt |= ctrl_inw(p->mapbase2 + TCNT); + tcnt = readw(p->mapbase1 + TCNT) << 16; + tcnt |= readw(p->mapbase2 + TCNT); return tcnt; } @@ -41,7 +41,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) unsigned long v1, v2, v3; int o1, o2; - o1 = ctrl_inb(p->mapbase1 + TSR) & 0x10; + o1 = readb(p->mapbase1 + TSR) & 0x10; /* Make sure the timer value is stable. Stolen from acpi_pm.c */ do { @@ -49,7 +49,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) v1 = read_tcnt32(p); v2 = read_tcnt32(p); v3 = read_tcnt32(p); - o1 = ctrl_inb(p->mapbase1 + TSR) & 0x10; + o1 = readb(p->mapbase1 + TSR) & 0x10; } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); @@ -82,10 +82,10 @@ static int tpu_clocksource_enable(struct clocksource *cs) WARN_ON(p->cs_enabled); - ctrl_outw(0, p->mapbase1 + TCNT); - ctrl_outw(0, p->mapbase2 + TCNT); - ctrl_outb(0x0f, p->mapbase1 + TCR); - ctrl_outb(0x03, p->mapbase2 + TCR); + writew(0, p->mapbase1 + TCNT); + writew(0, p->mapbase2 + TCNT); + writeb(0x0f, p->mapbase1 + TCR); + writeb(0x03, p->mapbase2 + TCR); p->cs_enabled = true; return 0; @@ -97,8 +97,8 @@ static void tpu_clocksource_disable(struct clocksource *cs) WARN_ON(!p->cs_enabled); - ctrl_outb(0, p->mapbase1 + TCR); - ctrl_outb(0, p->mapbase2 + TCR); + writeb(0, p->mapbase1 + TCR); + writeb(0, p->mapbase2 + TCR); p->cs_enabled = false; } @@ -139,8 +139,8 @@ static void __init h8300_tpu_init(struct device_node *node) goto unmap_L; } - tpu_priv.mapbase1 = (unsigned long)base[CH_L]; - tpu_priv.mapbase2 = (unsigned long)base[CH_H]; + tpu_priv.mapbase1 = base[CH_L]; + tpu_priv.mapbase2 = base[CH_H]; clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64); diff --git a/drivers/irqchip/irq-renesas-h8300h.c b/drivers/irqchip/irq-renesas-h8300h.c index 6fd30d5ee14d..c378768d75b3 100644 --- a/drivers/irqchip/irq-renesas-h8300h.c +++ b/drivers/irqchip/irq-renesas-h8300h.c @@ -21,9 +21,9 @@ static const char ipr_bit[] = { 10, 10, 10, 10, 9, 9, 9, 9, }; -static void *intc_baseaddr; +static void __iomem *intc_baseaddr; -#define IPR ((unsigned long)intc_baseaddr + 6) +#define IPR (intc_baseaddr + 6) static void h8300h_disable_irq(struct irq_data *data) { @@ -81,8 +81,8 @@ static int __init h8300h_intc_of_init(struct device_node *intc, BUG_ON(!intc_baseaddr); /* All interrupt priority low */ - ctrl_outb(0x00, IPR + 0); - ctrl_outb(0x00, IPR + 1); + writeb(0x00, IPR + 0); + writeb(0x00, IPR + 1); domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL); BUG_ON(!domain); -- cgit v1.2.3 From 46e7c3c6e5c56aadac391f92771e37dc03bec9b8 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 9 Nov 2015 15:18:08 +0100 Subject: clocksource/drivers/h8300: Increase the compilation test coverage Add the COMPILE_TEST option so the drivers can be compiled on different architecture with the 'allyesconfig' kernel configuration. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 73477b5e094b..db240cb56da7 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -363,13 +363,24 @@ config CLKSRC_PXA platforms. config H8300_TMR8 - bool + bool "Clockevent timer for the H8300 platform" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS + help + This enables the 8 bits timer for the H8300 platform. config H8300_TMR16 - bool + bool "Clockevent timer for the H83069 platform" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS + help + This enables the 16 bits timer for the H8300 platform with the + H83069 cpu. config H8300_TPU - bool + bool "Clocksource for the H8300 platform" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS + help + This enables the clocksource for the H8300 platform with the + H8S2678 cpu. config CLKSRC_IMX_GPT bool "Clocksource using i.MX GPT" if COMPILE_TEST -- cgit v1.2.3 From 0881841f7e7863ba0d33d4c34ee284cde85e18c4 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 13 Nov 2015 10:44:38 +0100 Subject: clocksource/drivers/tango-xtal: Replace code by clocksource_mmio_init The current code to initialize, register and read the clocksource is already factored out in mmio.c via the clocksource_mmio_init function. Factor out the code with the clocksource_mmio_init function. Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 1 + drivers/clocksource/tango_xtal.c | 18 +++--------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index db240cb56da7..b251013eef0a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -351,6 +351,7 @@ config CLKSRC_TANGO_XTAL bool "Clocksource for Tango SoC" if COMPILE_TEST depends on ARM select CLKSRC_OF + select CLKSRC_MMIO help This enables the clocksource for Tango SoC diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c index d297b30d2bc0..2bcecafdeaea 100644 --- a/drivers/clocksource/tango_xtal.c +++ b/drivers/clocksource/tango_xtal.c @@ -19,19 +19,6 @@ static u64 notrace read_sched_clock(void) return read_xtal_counter(); } -static cycle_t read_clocksource(struct clocksource *cs) -{ - return read_xtal_counter(); -} - -static struct clocksource tango_xtal = { - .name = "tango-xtal", - .rating = 350, - .read = read_clocksource, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static void __init tango_clocksource_init(struct device_node *np) { struct clk *clk; @@ -53,8 +40,9 @@ static void __init tango_clocksource_init(struct device_node *np) delay_timer.freq = xtal_freq; delay_timer.read_current_timer = read_xtal_counter; - ret = clocksource_register_hz(&tango_xtal, xtal_freq); - if (ret != 0) { + ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350, + 32, clocksource_mmio_readl_up); + if (!ret) { pr_err("%s: registration failed\n", np->full_name); return; } -- cgit v1.2.3 From 9f4165dc4e9e6dd10627b7b4d4e09c09fc01410c Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 25 Nov 2015 23:41:23 +0800 Subject: clocksource/drivers/dw_apb_timer: Fix apbt_readl return types On Marvell BG4CT platform, we observed the __apbt_read_clocksource() return wrong value: Let's assume the APBTMR_N_CURRENT_VALUE value is 0xf0000000, we got 0xffffffff0fffffff, but it should be 0xfffffff. This issue should be common on all 64bit platforms. We fix the issue by letting aptb_readl() return u32. apbt_writel() is also updated to write u32 val rather than unsigned long. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index c76c75006ea6..3a6d9dbe315d 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -49,12 +49,12 @@ clocksource_to_dw_apb_clocksource(struct clocksource *cs) return container_of(cs, struct dw_apb_clocksource, cs); } -static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs) +static u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs) { return readl(timer->base + offs); } -static void apbt_writel(struct dw_apb_timer *timer, unsigned long val, +static void apbt_writel(struct dw_apb_timer *timer, u32 val, unsigned long offs) { writel(val, timer->base + offs); @@ -62,7 +62,7 @@ static void apbt_writel(struct dw_apb_timer *timer, unsigned long val, static void apbt_disable_int(struct dw_apb_timer *timer) { - unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL); + u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); ctrl |= APBTMR_CONTROL_INT; apbt_writel(timer, ctrl, APBTMR_N_CONTROL); @@ -103,7 +103,7 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) static void apbt_enable_int(struct dw_apb_timer *timer) { - unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL); + u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); /* clear pending intr */ apbt_readl(timer, APBTMR_N_EOI); ctrl &= ~APBTMR_CONTROL_INT; @@ -113,7 +113,7 @@ static void apbt_enable_int(struct dw_apb_timer *timer) static int apbt_shutdown(struct clock_event_device *evt) { struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); - unsigned long ctrl; + u32 ctrl; pr_debug("%s CPU %d state=shutdown\n", __func__, cpumask_first(evt->cpumask)); @@ -127,7 +127,7 @@ static int apbt_shutdown(struct clock_event_device *evt) static int apbt_set_oneshot(struct clock_event_device *evt) { struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); - unsigned long ctrl; + u32 ctrl; pr_debug("%s CPU %d state=oneshot\n", __func__, cpumask_first(evt->cpumask)); @@ -160,7 +160,7 @@ static int apbt_set_periodic(struct clock_event_device *evt) { struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); - unsigned long ctrl; + u32 ctrl; pr_debug("%s CPU %d state=periodic\n", __func__, cpumask_first(evt->cpumask)); @@ -196,7 +196,7 @@ static int apbt_resume(struct clock_event_device *evt) static int apbt_next_event(unsigned long delta, struct clock_event_device *evt) { - unsigned long ctrl; + u32 ctrl; struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); /* Disable timer */ @@ -323,7 +323,7 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) * start count down from 0xffff_ffff. this is done by toggling the * enable bit then load initial load count to ~0. */ - unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); + u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); ctrl &= ~APBTMR_CONTROL_ENABLE; apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); @@ -338,7 +338,7 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) static cycle_t __apbt_read_clocksource(struct clocksource *cs) { - unsigned long current_count; + u32 current_count; struct dw_apb_clocksource *dw_cs = clocksource_to_dw_apb_clocksource(cs); -- cgit v1.2.3 From 39d3611f2d8ff5dcba523c9081e6f5e51f066c86 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 26 Nov 2015 00:01:53 +0800 Subject: clocksource/drivers/dw_apb_timer: Use {readl|writel}_relaxed in critical path It's safe to use the relaxed version. From another side, the relaxed io accessor macros are available on all architectures now, so we can use the relaxed versions to get a trivial system performance improvement, we measured time the following functions spent on Marvell BG4CT: 4096 rounds of __apbt_read_clocksource() call: before the patch: 1263240ns on average after the patch: 1250080ns on average improved by 1% 4096 rounds of apbt_eoi() call: before the patch: 1290960ns on average after the patch: 1248240ns on average 4096 rounds of apbt_next_event() call: before the patch: 3333660ns on average after the patch: 1322040ns on average improved by 60%! Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 3a6d9dbe315d..7f95b5347a9a 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -60,6 +60,17 @@ static void apbt_writel(struct dw_apb_timer *timer, u32 val, writel(val, timer->base + offs); } +static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs) +{ + return readl_relaxed(timer->base + offs); +} + +static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val, + unsigned long offs) +{ + writel_relaxed(val, timer->base + offs); +} + static void apbt_disable_int(struct dw_apb_timer *timer) { u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); @@ -81,7 +92,7 @@ void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced) static void apbt_eoi(struct dw_apb_timer *timer) { - apbt_readl(timer, APBTMR_N_EOI); + apbt_readl_relaxed(timer, APBTMR_N_EOI); } static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) @@ -200,13 +211,13 @@ static int apbt_next_event(unsigned long delta, struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); /* Disable timer */ - ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); + ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL); ctrl &= ~APBTMR_CONTROL_ENABLE; - apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); /* write new count */ - apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); + apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); ctrl |= APBTMR_CONTROL_ENABLE; - apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); return 0; } @@ -342,7 +353,8 @@ static cycle_t __apbt_read_clocksource(struct clocksource *cs) struct dw_apb_clocksource *dw_cs = clocksource_to_dw_apb_clocksource(cs); - current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); + current_count = apbt_readl_relaxed(&dw_cs->timer, + APBTMR_N_CURRENT_VALUE); return (cycle_t)~current_count; } -- cgit v1.2.3 From 520ddad4e560423a320bc1861792da19b0b879f9 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 26 Nov 2015 00:01:52 +0800 Subject: clocksource/drivers/dw_apb_timer: Inline apbt_readl and apbt_writel It seems gcc can automatically inline apbt_writel() for us, but apbt_real isn't inlined. This patch makes them inline to get a trivial performance improvement: 4096 rounds of __apbt_read_clocksource() call spend time on Marvell BG4CT platform: before the patch 1275240ns on average after the patch 1263240ns on average so we get 1% performance improvement. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 7f95b5347a9a..63345260244d 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -49,13 +49,13 @@ clocksource_to_dw_apb_clocksource(struct clocksource *cs) return container_of(cs, struct dw_apb_clocksource, cs); } -static u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs) +static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs) { return readl(timer->base + offs); } -static void apbt_writel(struct dw_apb_timer *timer, u32 val, - unsigned long offs) +static inline void apbt_writel(struct dw_apb_timer *timer, u32 val, + unsigned long offs) { writel(val, timer->base + offs); } -- cgit v1.2.3 From 08e4b44852626f3549c8bd45308431d9c9e0ee6d Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 26 Nov 2015 20:20:38 +0800 Subject: clockevents/drivers/arm_global_timer: Use writel_relaxed in gt_compare_set Use the relaxed version to improve performance. we measured time of 4096 rounds of gt_compare_set() spent on Marvell BG2Q: before the patch: 3690648ns on average after the patch: 1083023ns on average improved by 70%! Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/clocksource/arm_global_timer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index a2cb6fae9295..f99be6bafad1 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -99,17 +99,17 @@ static void gt_compare_set(unsigned long delta, int periodic) counter += delta; ctrl = GT_CONTROL_TIMER_ENABLE; - writel(ctrl, gt_base + GT_CONTROL); - writel(lower_32_bits(counter), gt_base + GT_COMP0); - writel(upper_32_bits(counter), gt_base + GT_COMP1); + writel_relaxed(ctrl, gt_base + GT_CONTROL); + writel_relaxed(lower_32_bits(counter), gt_base + GT_COMP0); + writel_relaxed(upper_32_bits(counter), gt_base + GT_COMP1); if (periodic) { - writel(delta, gt_base + GT_AUTO_INC); + writel_relaxed(delta, gt_base + GT_AUTO_INC); ctrl |= GT_CONTROL_AUTO_INC; } ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE; - writel(ctrl, gt_base + GT_CONTROL); + writel_relaxed(ctrl, gt_base + GT_CONTROL); } static int gt_clockevent_shutdown(struct clock_event_device *evt) -- cgit v1.2.3 From 272a25a247ce6d31315856721014635469500e96 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 25 Nov 2015 23:42:49 +0800 Subject: clocksource/drivers/pistachio: Fix wrong calculated clocksource read value Let's assume the counter value is 0xf0000000, the pistachio clocksource read cycles function should return ~0x0fffffff but actually it returns 0xffffffff0fffffff. That occurs because: ~(cycle_t)value is different from (cycle_t)~value. unsigned long val = ~(unsigned long)0xf0000000; 40049a: 48 b8 ff ff ff 0f ff movabs $0xffffffff0fffffff,%rax unsigned long val = (unsigned long)~0xf0000000; 40049a: 48 c7 45 f8 ff ff ff movq $0xfffffff,-0x8(%rbp) We fix this issue by calculating bitwise-not counter, then cast to cycle_t. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/clocksource/time-pistachio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c index bba679900054..3269d9ef7a18 100644 --- a/drivers/clocksource/time-pistachio.c +++ b/drivers/clocksource/time-pistachio.c @@ -84,7 +84,7 @@ pistachio_clocksource_read_cycles(struct clocksource *cs) counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); raw_spin_unlock_irqrestore(&pcs->lock, flags); - return ~(cycle_t)counter; + return (cycle_t)~counter; } static u64 notrace pistachio_read_sched_clock(void) -- cgit v1.2.3 From 9c9ae5ffee2831c0b8c0b002443b093e141d08f1 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 30 Nov 2015 20:25:12 +0200 Subject: clocksource/drivers/arm_global_timer: Fix suspend resume Now the System stall is observed on TI AM437x based board (am437x-gp-evm) during resuming from System suspend when ARM Global timer is selected as clocksource device (CPUIdle not enabled) - SysRq are working, but nothing else. The reason of stall is that ARM Global timer loses its contexts during System suspend: GT_CONTROL.TIMER_ENABLE = 0 (unbanked) GT_COUNTERx = 0 Hence, update ARM Global timer driver to reflect above behaviour - re-enable ARM Global timer on resume (GT_CONTROL.TIMER_ENABLE = 1) if not enabled. CC: Arnd Bergmann Cc: John Stultz Cc: Felipe Balbi Cc: Tony Lindgren Cc: Marc Zyngier Reviewed-by: Santosh Shilimkar Signed-off-by: Grygorii Strashko Signed-off-by: Daniel Lezcano --- drivers/clocksource/arm_global_timer.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index f99be6bafad1..d189d8cb69f7 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -195,12 +195,23 @@ static cycle_t gt_clocksource_read(struct clocksource *cs) return gt_counter_read(); } +static void gt_resume(struct clocksource *cs) +{ + unsigned long ctrl; + + ctrl = readl(gt_base + GT_CONTROL); + if (!(ctrl & GT_CONTROL_TIMER_ENABLE)) + /* re-enable timer on resume */ + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); +} + static struct clocksource gt_clocksource = { .name = "arm_global_timer", .rating = 300, .read = gt_clocksource_read, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .resume = gt_resume, }; #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK -- cgit v1.2.3 From d662ed204357cfcf3b069ba705446f7395b80fc5 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 2 Dec 2015 08:02:08 +0200 Subject: clocksource/drivers/lpc32: Correct pr_err() output format If by some reason timerclk is not available, both clockevent and clocksource initializations correctly exit, but output of errno to kernel log buffer may be confusing: lpc32xx_clk_init: failed to map system control block registers lpc32xx_clocksource_init: clock get failed (4294966779) lpc32xx_clockevent_init: clock get failed (4294966779) Use signed integer output in the correspondent pr_err() string formats: lpc32xx_clocksource_init: clock get failed (-517) lpc32xx_clockevent_init: clock get failed (-517) Signed-off-by: Vladimir Zapolskiy Signed-off-by: Daniel Lezcano --- drivers/clocksource/time-lpc32xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c index a1c06a2bc77c..1316876b487a 100644 --- a/drivers/clocksource/time-lpc32xx.c +++ b/drivers/clocksource/time-lpc32xx.c @@ -125,7 +125,7 @@ static int __init lpc32xx_clocksource_init(struct device_node *np) clk = of_clk_get_by_name(np, "timerclk"); if (IS_ERR(clk)) { - pr_err("clock get failed (%lu)\n", PTR_ERR(clk)); + pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); return PTR_ERR(clk); } @@ -184,7 +184,7 @@ static int __init lpc32xx_clockevent_init(struct device_node *np) clk = of_clk_get_by_name(np, "timerclk"); if (IS_ERR(clk)) { - pr_err("clock get failed (%lu)\n", PTR_ERR(clk)); + pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); return PTR_ERR(clk); } -- cgit v1.2.3 From 2a0ff87774e468e4b146fe5af9ffadf5169424f9 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 5 Dec 2015 02:48:14 +0900 Subject: clocksource/drivers/h8300: Change to overflow interrupt Counter overflow detection use for overflow interrupt Signed-off-by: Yoshinori Sato Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index fc14a3f741bf..b14a8da90ecc 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -14,7 +14,6 @@ #include #define TSTR 0 -#define TISRA 4 #define TISRC 6 #define TCR 0 @@ -27,9 +26,8 @@ struct timer16_priv { void __iomem *mapcommon; unsigned short cs_enabled; unsigned char enb; - unsigned char imfa; - unsigned char imiea; unsigned char ovf; + unsigned char ovie; struct clk *clk; }; @@ -59,8 +57,8 @@ static irqreturn_t timer16_interrupt(int irq, void *dev_id) { struct timer16_priv *p = (struct timer16_priv *)dev_id; - writeb(readb(p->mapcommon + TISRA) & ~p->imfa, - p->mapcommon + TISRA); + writeb(readb(p->mapcommon + TISRC) & ~p->ovf, + p->mapcommon + TISRC); p->total_cycles += 0x10000; return IRQ_HANDLED; @@ -93,6 +91,8 @@ static int timer16_enable(struct clocksource *cs) writeb(0x83, p->mapbase + TCR); writeb(readb(p->mapcommon + TSTR) | p->enb, p->mapcommon + TSTR); + writeb(readb(p->mapcommon + TISRC) | p->ovie, + p->mapcommon + TSTR); p->cs_enabled = true; return 0; @@ -161,8 +161,8 @@ static void __init h8300_16timer_init(struct device_node *node) timer16_priv.mapbase = base[REG_CH]; timer16_priv.mapcommon = base[REG_COMM]; timer16_priv.enb = 1 << ch; - timer16_priv.imfa = 1 << ch; - timer16_priv.imiea = 1 << (4 + ch); + timer16_priv.ovf = 1 << ch; + timer16_priv.ovie = 1 << (4 + ch); ret = request_irq(irq, timer16_interrupt, IRQF_TIMER, timer16_priv.cs.name, &timer16_priv); -- cgit v1.2.3 From 2f445e0aa00e3bdbcf6e99b88a6aab54b6b02f2a Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 5 Dec 2015 02:48:15 +0900 Subject: clocksource/drivers/h8300: Fix timer not overflow case Signed-off-by: Yoshinori Sato Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index b14a8da90ecc..934ed0bceec5 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -48,8 +48,10 @@ static unsigned long timer16_get_counter(struct timer16_priv *p) } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); - v2 |= 0x10000; - return v2; + if (likely(!o1)) + return v2; + else + return v2 + 0x10000; } -- cgit v1.2.3 From f37632d1e9ff8445e0d1ea761f4ce7b98e059d75 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 5 Dec 2015 02:48:16 +0900 Subject: clocksource/drivers/h8300: Simplify delta handling Signed-off-by: Yoshinori Sato Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 40 ++++++-------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index aa4b2a989747..1ba453b47478 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -36,57 +36,29 @@ struct timer8_priv { unsigned int tcora; }; -static unsigned long timer8_get_counter(struct timer8_priv *p) -{ - unsigned long v1, v2, v3; - int o1, o2; - - o1 = readb(p->mapbase + _8TCSR) & 0x20; - - /* Make sure the timer value is stable. Stolen from acpi_pm.c */ - do { - o2 = o1; - v1 = readw(p->mapbase + _8TCNT); - v2 = readw(p->mapbase + _8TCNT); - v3 = readw(p->mapbase + _8TCNT); - o1 = readb(p->mapbase + _8TCSR) & 0x20; - } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) - || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); - - v2 |= o1 << 10; - return v2; -} - static irqreturn_t timer8_interrupt(int irq, void *dev_id) { struct timer8_priv *p = dev_id; - writeb(readb(p->mapbase + _8TCSR) & ~0x40, - p->mapbase + _8TCSR); - - writew(p->tcora, p->mapbase + TCORA); - if (clockevent_state_oneshot(&p->ced)) writew(0x0000, p->mapbase + _8TCR); p->ced.event_handler(&p->ced); + writeb(readb(p->mapbase + _8TCSR) & ~0x40, + p->mapbase + _8TCSR); + return IRQ_HANDLED; } static void timer8_set_next(struct timer8_priv *p, unsigned long delta) { - unsigned long now; - if (delta >= 0x10000) pr_warn("delta out of range\n"); - now = timer8_get_counter(p); - p->tcora = delta; + writeb(readb(p->mapbase + _8TCR) & ~0x40, p->mapbase + _8TCR); + writew(0, p->mapbase + _8TCNT); + writew(delta, p->mapbase + TCORA); writeb(readb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR); - if (delta > now) - writew(delta, p->mapbase + TCORA); - else - writew(now + 1, p->mapbase + TCORA); } static int timer8_enable(struct timer8_priv *p) -- cgit v1.2.3 From 6f2b611db23404426a2b21b343392dc1d9584f92 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 5 Dec 2015 02:48:17 +0900 Subject: clocksource/drivers/h8300: Initializer cleanup. Signed-off-by: Yoshinori Sato Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer8.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 1ba453b47478..9087dd27ec69 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -33,7 +33,6 @@ struct timer8_priv { void __iomem *mapbase; unsigned long flags; unsigned int rate; - unsigned int tcora; }; static irqreturn_t timer8_interrupt(int irq, void *dev_id) @@ -163,8 +162,6 @@ static void __init h8300_8timer_init(struct device_node *node) { void __iomem *base; int irq; - int ret = 0; - int rate; struct clk *clk; clk = of_clk_get(node, 0); @@ -187,20 +184,20 @@ static void __init h8300_8timer_init(struct device_node *node) timer8_priv.mapbase = base; - rate = clk_get_rate(clk) / SCALE; - if (!rate) { + timer8_priv.rate = clk_get_rate(clk) / SCALE; + if (!timer8_priv.rate) { pr_err("Failed to get rate for the clocksource\n"); goto unmap_reg; } - ret = request_irq(irq, timer8_interrupt, - IRQF_TIMER, timer8_priv.ced.name, &timer8_priv); - if (ret < 0) { + if (request_irq(irq, timer8_interrupt, IRQF_TIMER, + timer8_priv.ced.name, &timer8_priv) < 0) { pr_err("failed to request irq %d for clockevent\n", irq); goto unmap_reg; } - clockevents_config_and_register(&timer8_priv.ced, rate, 1, 0x0000ffff); + clockevents_config_and_register(&timer8_priv.ced, + timer8_priv.rate, 1, 0x0000ffff); return; unmap_reg: -- cgit v1.2.3 From d33f250af4e67d449f2c748b861ba99d50955469 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 5 Dec 2015 02:48:18 +0900 Subject: clocksource/drivers/h8300: Use ioread / iowrite Signed-off-by: Yoshinori Sato Signed-off-by: Daniel Lezcano --- drivers/clocksource/h8300_timer16.c | 43 ++++++++++++++++++------------------- drivers/clocksource/h8300_timer8.c | 28 ++++++++++++++---------- drivers/clocksource/h8300_tpu.c | 22 ++++++++++--------- 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 934ed0bceec5..75c44079b345 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -19,6 +19,9 @@ #define TCR 0 #define TCNT 2 +#define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a)) +#define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a)) + struct timer16_priv { struct clocksource cs; unsigned long total_cycles; @@ -28,23 +31,22 @@ struct timer16_priv { unsigned char enb; unsigned char ovf; unsigned char ovie; - struct clk *clk; }; static unsigned long timer16_get_counter(struct timer16_priv *p) { - unsigned long v1, v2, v3; - int o1, o2; + unsigned short v1, v2, v3; + unsigned char o1, o2; - o1 = readb(p->mapcommon + TISRC) & p->ovf; + o1 = ioread8(p->mapcommon + TISRC) & p->ovf; /* Make sure the timer value is stable. Stolen from acpi_pm.c */ do { o2 = o1; - v1 = readw(p->mapbase + TCNT); - v2 = readw(p->mapbase + TCNT); - v3 = readw(p->mapbase + TCNT); - o1 = readb(p->mapcommon + TISRC) & p->ovf; + v1 = ioread16be(p->mapbase + TCNT); + v2 = ioread16be(p->mapbase + TCNT); + v3 = ioread16be(p->mapbase + TCNT); + o1 = ioread8(p->mapcommon + TISRC) & p->ovf; } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); @@ -59,8 +61,7 @@ static irqreturn_t timer16_interrupt(int irq, void *dev_id) { struct timer16_priv *p = (struct timer16_priv *)dev_id; - writeb(readb(p->mapcommon + TISRC) & ~p->ovf, - p->mapcommon + TISRC); + bclr(p->ovf, p->mapcommon + TISRC); p->total_cycles += 0x10000; return IRQ_HANDLED; @@ -89,12 +90,10 @@ static int timer16_enable(struct clocksource *cs) WARN_ON(p->cs_enabled); p->total_cycles = 0; - writew(0x0000, p->mapbase + TCNT); - writeb(0x83, p->mapbase + TCR); - writeb(readb(p->mapcommon + TSTR) | p->enb, - p->mapcommon + TSTR); - writeb(readb(p->mapcommon + TISRC) | p->ovie, - p->mapcommon + TSTR); + iowrite16be(0x0000, p->mapbase + TCNT); + iowrite8(0x83, p->mapbase + TCR); + bset(p->ovie, p->mapcommon + TISRC); + bset(p->enb, p->mapcommon + TSTR); p->cs_enabled = true; return 0; @@ -106,8 +105,8 @@ static void timer16_disable(struct clocksource *cs) WARN_ON(!p->cs_enabled); - writeb(readb(p->mapcommon + TSTR) & ~p->enb, - p->mapcommon + TSTR); + bclr(p->ovie, p->mapcommon + TISRC); + bclr(p->enb, p->mapcommon + TSTR); p->cs_enabled = false; } @@ -162,9 +161,9 @@ static void __init h8300_16timer_init(struct device_node *node) timer16_priv.mapbase = base[REG_CH]; timer16_priv.mapcommon = base[REG_COMM]; - timer16_priv.enb = 1 << ch; - timer16_priv.ovf = 1 << ch; - timer16_priv.ovie = 1 << (4 + ch); + timer16_priv.enb = ch; + timer16_priv.ovf = ch; + timer16_priv.ovie = 4 + ch; ret = request_irq(irq, timer16_interrupt, IRQF_TIMER, timer16_priv.cs.name, &timer16_priv); @@ -174,7 +173,7 @@ static void __init h8300_16timer_init(struct device_node *node) } clocksource_register_hz(&timer16_priv.cs, - clk_get_rate(timer16_priv.clk) / 8); + clk_get_rate(clk) / 8); return; unmap_comm: diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 9087dd27ec69..c151941e1956 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -24,10 +24,16 @@ #define TCORB 6 #define _8TCNT 8 +#define CMIEA 6 +#define CMFA 6 + #define FLAG_STARTED (1 << 3) #define SCALE 64 +#define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a)) +#define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a)) + struct timer8_priv { struct clock_event_device ced; void __iomem *mapbase; @@ -40,12 +46,11 @@ static irqreturn_t timer8_interrupt(int irq, void *dev_id) struct timer8_priv *p = dev_id; if (clockevent_state_oneshot(&p->ced)) - writew(0x0000, p->mapbase + _8TCR); + iowrite16be(0x0000, p->mapbase + _8TCR); p->ced.event_handler(&p->ced); - writeb(readb(p->mapbase + _8TCSR) & ~0x40, - p->mapbase + _8TCSR); + bclr(CMFA, p->mapbase + _8TCSR); return IRQ_HANDLED; } @@ -54,17 +59,18 @@ static void timer8_set_next(struct timer8_priv *p, unsigned long delta) { if (delta >= 0x10000) pr_warn("delta out of range\n"); - writeb(readb(p->mapbase + _8TCR) & ~0x40, p->mapbase + _8TCR); - writew(0, p->mapbase + _8TCNT); - writew(delta, p->mapbase + TCORA); - writeb(readb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR); + bclr(CMIEA, p->mapbase + _8TCR); + iowrite16be(delta, p->mapbase + TCORA); + iowrite16be(0x0000, p->mapbase + _8TCNT); + bclr(CMFA, p->mapbase + _8TCSR); + bset(CMIEA, p->mapbase + _8TCR); } static int timer8_enable(struct timer8_priv *p) { - writew(0xffff, p->mapbase + TCORA); - writew(0x0000, p->mapbase + _8TCNT); - writew(0x0c02, p->mapbase + _8TCR); + iowrite16be(0xffff, p->mapbase + TCORA); + iowrite16be(0x0000, p->mapbase + _8TCNT); + iowrite16be(0x0c02, p->mapbase + _8TCR); return 0; } @@ -85,7 +91,7 @@ static int timer8_start(struct timer8_priv *p) static void timer8_stop(struct timer8_priv *p) { - writew(0x0000, p->mapbase + _8TCR); + iowrite16be(0x0000, p->mapbase + _8TCR); } static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index 91bf1992320e..d4c1a287c262 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -19,6 +19,8 @@ #define TSR 0x5 #define TCNT 0x6 +#define TCFV 0x10 + struct tpu_priv { struct clocksource cs; void __iomem *mapbase1; @@ -31,8 +33,8 @@ static inline unsigned long read_tcnt32(struct tpu_priv *p) { unsigned long tcnt; - tcnt = readw(p->mapbase1 + TCNT) << 16; - tcnt |= readw(p->mapbase2 + TCNT); + tcnt = ioread16be(p->mapbase1 + TCNT) << 16; + tcnt |= ioread16be(p->mapbase2 + TCNT); return tcnt; } @@ -41,7 +43,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) unsigned long v1, v2, v3; int o1, o2; - o1 = readb(p->mapbase1 + TSR) & 0x10; + o1 = ioread8(p->mapbase1 + TSR) & TCFV; /* Make sure the timer value is stable. Stolen from acpi_pm.c */ do { @@ -49,7 +51,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) v1 = read_tcnt32(p); v2 = read_tcnt32(p); v3 = read_tcnt32(p); - o1 = readb(p->mapbase1 + TSR) & 0x10; + o1 = ioread8(p->mapbase1 + TSR) & TCFV; } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); @@ -82,10 +84,10 @@ static int tpu_clocksource_enable(struct clocksource *cs) WARN_ON(p->cs_enabled); - writew(0, p->mapbase1 + TCNT); - writew(0, p->mapbase2 + TCNT); - writeb(0x0f, p->mapbase1 + TCR); - writeb(0x03, p->mapbase2 + TCR); + iowrite16be(0, p->mapbase1 + TCNT); + iowrite16be(0, p->mapbase2 + TCNT); + iowrite8(0x0f, p->mapbase1 + TCR); + iowrite8(0x03, p->mapbase2 + TCR); p->cs_enabled = true; return 0; @@ -97,8 +99,8 @@ static void tpu_clocksource_disable(struct clocksource *cs) WARN_ON(!p->cs_enabled); - writeb(0, p->mapbase1 + TCR); - writeb(0, p->mapbase2 + TCR); + iowrite8(0, p->mapbase1 + TCR); + iowrite8(0, p->mapbase2 + TCR); p->cs_enabled = false; } -- cgit v1.2.3 From dee3665416a8553279d10b62b5e62685cbe5daa8 Mon Sep 17 00:00:00 2001 From: DengChao Date: Sun, 13 Dec 2015 12:24:18 +0800 Subject: timekeeping: Provide internal function __ktime_get_real_seconds In order to fix Y2038 issues in the ntp code we will need replace get_seconds() with ktime_get_real_seconds() but as the ntp code uses the timekeeping lock which is also used by ktime_get_real_seconds(), we need a version without locking. Add a new function __ktime_get_real_seconds() in timekeeping to do this. Reviewed-by: John Stultz Signed-off-by: DengChao Signed-off-by: John Stultz --- kernel/time/timekeeping.c | 13 +++++++++++++ kernel/time/timekeeping_internal.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d9249daf14ba..21cc23918cbd 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -845,6 +845,19 @@ time64_t ktime_get_real_seconds(void) } EXPORT_SYMBOL_GPL(ktime_get_real_seconds); +/** + * __ktime_get_real_seconds - The same as ktime_get_real_seconds + * but without the sequence counter protect. This internal function + * is called just when timekeeping lock is already held. + */ +time64_t __ktime_get_real_seconds(void) +{ + struct timekeeper *tk = &tk_core.timekeeper; + + return tk->xtime_sec; +} + + #ifdef CONFIG_NTP_PPS /** diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h index 4ea005a7f9da..e20466ffc208 100644 --- a/kernel/time/timekeeping_internal.h +++ b/kernel/time/timekeeping_internal.h @@ -26,4 +26,6 @@ static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) } #endif +extern time64_t __ktime_get_real_seconds(void); + #endif /* _TIMEKEEPING_INTERNAL_H */ -- cgit v1.2.3 From 0af864651b459afb0435ee8786a19cbe5a044cdb Mon Sep 17 00:00:00 2001 From: DengChao Date: Sun, 13 Dec 2015 12:24:19 +0800 Subject: ntp: Change time_reftime to time64_t and utilize 64bit __ktime_get_real_seconds The type of static variant "time_reftime" and the call of get_seconds in ntp are both not y2038 safe. So change the type of time_reftime to time64_t and replace get_seconds with __ktime_get_real_seconds. The local variant "secs" in ntp_update_offset represents seconds between now and last ntp adjustment, it seems impossible that this time will last more than 68 years, so keep its type as "long". Reviewed-by: John Stultz Signed-off-by: DengChao [jstultz: Tweaked commit message] Signed-off-by: John Stultz --- kernel/time/ntp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 4073c9550af9..e947bfddd2c2 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -18,6 +18,8 @@ #include #include "ntp_internal.h" +#include "timekeeping_internal.h" + /* * NTP timekeeping variables: @@ -70,7 +72,7 @@ static long time_esterror = NTP_PHASE_LIMIT; static s64 time_freq; /* time at last adjustment (secs): */ -static long time_reftime; +static time64_t time_reftime; static long time_adjust; @@ -313,11 +315,11 @@ static void ntp_update_offset(long offset) * Select how the frequency is to be controlled * and in which mode (PLL or FLL). */ - secs = get_seconds() - time_reftime; + secs = (long)(__ktime_get_real_seconds() - time_reftime); if (unlikely(time_status & STA_FREQHOLD)) secs = 0; - time_reftime = get_seconds(); + time_reftime = __ktime_get_real_seconds(); offset64 = offset; freq_adj = ntp_update_offset_fll(offset64, secs); @@ -592,7 +594,7 @@ static inline void process_adj_status(struct timex *txc, struct timespec64 *ts) * reference time to current time. */ if (!(time_status & STA_PLL) && (txc->status & STA_PLL)) - time_reftime = get_seconds(); + time_reftime = __ktime_get_real_seconds(); /* only set allowed bits */ time_status &= STA_RONLY; -- cgit v1.2.3 From c796348774f15c6e682834ed288bcae0f2c95707 Mon Sep 17 00:00:00 2001 From: DengChao Date: Sun, 13 Dec 2015 12:26:42 +0800 Subject: ntp: Fix second_overflow's input parameter type to be 64bits The function "second_overflow" uses "unsign long" as its input parameter type which will overflow after year 2106 on 32bit systems. Thus this patch replaces it with time64_t type. While the 64-bit division is expensive, "next_ntp_leap_sec" has been calculated already, so we can just re-use it in the TIME_INS/DEL cases, allowing one expensive division per leapsecond instead of re-doing the divsion once a second after the leap flag has been set. Signed-off-by: DengChao [jstultz: Tweaked commit message] Signed-off-by: John Stultz --- kernel/time/ntp.c | 16 +++++++++------- kernel/time/ntp_internal.h | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index e947bfddd2c2..36f2ca09aa5e 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "ntp_internal.h" #include "timekeeping_internal.h" @@ -394,10 +395,11 @@ ktime_t ntp_get_next_leap(void) * * Also handles leap second processing, and returns leap offset */ -int second_overflow(unsigned long secs) +int second_overflow(time64_t secs) { s64 delta; int leap = 0; + s32 rem; /* * Leap second processing. If in leap-insert state at the end of the @@ -408,19 +410,19 @@ int second_overflow(unsigned long secs) case TIME_OK: if (time_status & STA_INS) { time_state = TIME_INS; - ntp_next_leap_sec = secs + SECS_PER_DAY - - (secs % SECS_PER_DAY); + div_s64_rem(secs, SECS_PER_DAY, &rem); + ntp_next_leap_sec = secs + SECS_PER_DAY - rem; } else if (time_status & STA_DEL) { time_state = TIME_DEL; - ntp_next_leap_sec = secs + SECS_PER_DAY - - ((secs+1) % SECS_PER_DAY); + div_s64_rem(secs + 1, SECS_PER_DAY, &rem); + ntp_next_leap_sec = secs + SECS_PER_DAY - rem; } break; case TIME_INS: if (!(time_status & STA_INS)) { ntp_next_leap_sec = TIME64_MAX; time_state = TIME_OK; - } else if (secs % SECS_PER_DAY == 0) { + } else if (secs == ntp_next_leap_sec) { leap = -1; time_state = TIME_OOP; printk(KERN_NOTICE @@ -431,7 +433,7 @@ int second_overflow(unsigned long secs) if (!(time_status & STA_DEL)) { ntp_next_leap_sec = TIME64_MAX; time_state = TIME_OK; - } else if ((secs + 1) % SECS_PER_DAY == 0) { + } else if (secs == ntp_next_leap_sec) { leap = 1; ntp_next_leap_sec = TIME64_MAX; time_state = TIME_WAIT; diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h index af924470eac0..d8a7c11fa71a 100644 --- a/kernel/time/ntp_internal.h +++ b/kernel/time/ntp_internal.h @@ -6,7 +6,7 @@ extern void ntp_clear(void); /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */ extern u64 ntp_tick_length(void); extern ktime_t ntp_get_next_leap(void); -extern int second_overflow(unsigned long secs); +extern int second_overflow(time64_t secs); extern int ntp_validate_timex(struct timex *); extern int __do_adjtimex(struct timex *, struct timespec64 *, s32 *); extern void __hardpps(const struct timespec64 *, const struct timespec64 *); -- cgit v1.2.3 From ec02b076ceab63f99e5b3d80fd223d777266c236 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 3 Dec 2015 10:23:30 -0800 Subject: timekeeping: Cap adjustments so they don't exceed the maxadj value Thus its been occasionally noted that users have seen confusing warnings like: Adjusting tsc more than 11% (5941981 vs 7759439) We try to limit the maximum total adjustment to 11% (10% tick adjustment + 0.5% frequency adjustment). But this is done by bounding the requested adjustment values, and the internal steering that is done by tracking the error from what was requested and what was applied, does not have any such limits. This is usually not problematic, but in some cases has a risk that an adjustment could cause the clocksource mult value to overflow, so its an indication things are outside of what is expected. It ends up most of the reports of this 11% warning are on systems using chrony, which utilizes the adjtimex() ADJ_TICK interface (which allows a +-10% adjustment). The original rational for ADJ_TICK unclear to me but my assumption it was originally added to allow broken systems to get a big constant correction at boot (see adjtimex userspace package for an example) which would allow the system to work w/ ntpd's 0.5% adjustment limit. Chrony uses ADJ_TICK to make very aggressive short term corrections (usually right at startup). Which push us close enough to the max bound that a few late ticks can cause the internal steering to push past the max adjust value (tripping the warning). Thus this patch adds some extra logic to enforce the max adjustment cap in the internal steering. Note: This has the potential to slow corrections when the ADJ_TICK value is furthest away from the default value. So it would be good to get some testing from folks using chrony, to make sure we don't cause any troubles there. Cc: Miroslav Lichvar Cc: Thomas Gleixner Cc: Richard Cochran Cc: Prarit Bhargava Cc: Andy Lutomirski Tested-by: Miroslav Lichvar Reported-by: Andy Lutomirski Signed-off-by: John Stultz --- kernel/time/timekeeping.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 21cc23918cbd..34b4cedfa80d 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1604,9 +1604,12 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk, { s64 interval = tk->cycle_interval; s64 xinterval = tk->xtime_interval; + u32 base = tk->tkr_mono.clock->mult; + u32 max = tk->tkr_mono.clock->maxadj; + u32 cur_adj = tk->tkr_mono.mult; s64 tick_error; bool negative; - u32 adj; + u32 adj_scale; /* Remove any current error adj from freq calculation */ if (tk->ntp_err_mult) @@ -1625,13 +1628,33 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk, /* preserve the direction of correction */ negative = (tick_error < 0); - /* Sort out the magnitude of the correction */ + /* If any adjustment would pass the max, just return */ + if (negative && (cur_adj - 1) <= (base - max)) + return; + if (!negative && (cur_adj + 1) >= (base + max)) + return; + /* + * Sort out the magnitude of the correction, but + * avoid making so large a correction that we go + * over the max adjustment. + */ + adj_scale = 0; tick_error = abs(tick_error); - for (adj = 0; tick_error > interval; adj++) + while (tick_error > interval) { + u32 adj = 1 << (adj_scale + 1); + + /* Check if adjustment gets us within 1 unit from the max */ + if (negative && (cur_adj - adj) <= (base - max)) + break; + if (!negative && (cur_adj + adj) >= (base + max)) + break; + + adj_scale++; tick_error >>= 1; + } /* scale the corrections */ - timekeeping_apply_adjustment(tk, offset, negative, adj); + timekeeping_apply_adjustment(tk, offset, negative, adj_scale); } /* -- cgit v1.2.3 From 1f45f1f33c8c8b96722dbc5e6b7acf74eaa721f7 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 31 Oct 2015 18:20:55 +0800 Subject: clocksource: Make clocksource validation work for all clocksources The clocksource validation which makes sure that the newly read value is not smaller than the last value only works if the clocksource mask is 64bit, i.e. the counter is 64bit wide. But we want to use that mechanism also for clocksources which are less than 64bit wide. So instead of checking whether bit 63 is set, we check whether the most significant bit of the clocksource mask is set in the delta result. If it is set, we return 0. [ tglx: Simplified the implementation, added a comment and massaged the commit message ] Suggested-by: Thomas Gleixner Signed-off-by: Yang Yingliang Cc: Link: http://lkml.kernel.org/r/56349607.6070708@huawei.com Signed-off-by: Thomas Gleixner --- kernel/time/timekeeping_internal.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h index e20466ffc208..5be76270ec4a 100644 --- a/kernel/time/timekeeping_internal.h +++ b/kernel/time/timekeeping_internal.h @@ -17,7 +17,11 @@ static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) { cycle_t ret = (now - last) & mask; - return (s64) ret > 0 ? ret : 0; + /* + * Prevent time going backwards by checking the MSB of mask in + * the result. If set, return 0. + */ + return ret & ~(mask >> 1) ? 0 : ret; } #else static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) -- cgit v1.2.3 From 1b9f23727abb92c5e58f139e7d180befcaa06fe0 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Tue, 22 Dec 2015 22:19:58 +0100 Subject: posix-clock: Fix return code on the poll method's error path The posix_clock_poll function is supposed to return a bit mask of POLLxxx values. However, in case the hardware has disappeared (due to hot plugging for example) this code returns -ENODEV in a futile attempt to throw an error at the file descriptor level. The kernel's file_operations interface does not accept such error codes from the poll method. Instead, this function aught to return POLLERR. The value -ENODEV does, in fact, contain the POLLERR bit (and almost all the other POLLxxx bits as well), but only by chance. This patch fixes code to return a proper bit mask. Credit goes to Markus Elfring for pointing out the suspicious signed/unsigned mismatch. Reported-by: Markus Elfring igned-off-by: Richard Cochran Cc: John Stultz Cc: Julia Lawall Link: http://lkml.kernel.org/r/1450819198-17420-1-git-send-email-richardcochran@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner --- kernel/time/posix-clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index ce033c7aa2e8..9cff0ab82b63 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -69,10 +69,10 @@ static ssize_t posix_clock_read(struct file *fp, char __user *buf, static unsigned int posix_clock_poll(struct file *fp, poll_table *wait) { struct posix_clock *clk = get_posix_clock(fp); - int result = 0; + unsigned int result = 0; if (!clk) - return -ENODEV; + return POLLERR; if (clk->ops.poll) result = clk->ops.poll(clk, fp, wait); -- cgit v1.2.3 From 01414888eaf725a677171605cb051b1c6311e6ab Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 28 Dec 2015 15:41:25 +0200 Subject: clocksource/drivers/acpi_pm: Convert to pr_* macros Like it's already done in one place in the driver, convert the rest to use pr_* macros instead of printk(KERN_LEVEL) calls. While here, join strings to be one string for one line to make grep on them easier. There is no functional change. Signed-off-by: Andy Shevchenko Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1451310085-113182-1-git-send-email-andriy.shevchenko@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/acpi_pm.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 6eab88985670..28037d0b8dcd 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -109,10 +109,8 @@ static void acpi_pm_check_blacklist(struct pci_dev *dev) /* the bug has been fixed in PIIX4M */ if (dev->revision < 3) { - printk(KERN_WARNING "* Found PM-Timer Bug on the chipset." - " Due to workarounds for a bug,\n" - "* this clock source is slow. Consider trying" - " other clock sources\n"); + pr_warn("* Found PM-Timer Bug on the chipset. Due to workarounds for a bug,\n" + "* this clock source is slow. Consider trying other clock sources\n"); acpi_pm_need_workaround(); } @@ -125,12 +123,9 @@ static void acpi_pm_check_graylist(struct pci_dev *dev) if (acpi_pm_good) return; - printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to" - " workarounds for a bug,\n" - "* this clock source is slow. If you are sure your timer" - " does not have\n" - "* this bug, please use \"acpi_pm_good\" to disable the" - " workaround\n"); + pr_warn("* The chipset may have PM-Timer Bug. Due to workarounds for a bug,\n" + "* this clock source is slow. If you are sure your timer does not have\n" + "* this bug, please use \"acpi_pm_good\" to disable the workaround\n"); acpi_pm_need_workaround(); } @@ -162,8 +157,7 @@ static int verify_pmtmr_rate(void) /* Check that the PMTMR delta is within 5% of what we expect */ if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || delta > (PMTMR_EXPECTED_RATE * 21) / 20) { - printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% " - "of normal - aborting.\n", + pr_info("PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", 100UL * delta / PMTMR_EXPECTED_RATE); return -1; } @@ -199,15 +193,14 @@ static int __init init_acpi_pm_clocksource(void) break; if ((value2 < value1) && ((value2) < 0xFFF)) break; - printk(KERN_INFO "PM-Timer had inconsistent results:" - " %#llx, %#llx - aborting.\n", - value1, value2); + pr_info("PM-Timer had inconsistent results: %#llx, %#llx - aborting.\n", + value1, value2); pmtmr_ioport = 0; return -EINVAL; } if (i == ACPI_PM_READ_CHECKS) { - printk(KERN_INFO "PM-Timer failed consistency check " - " (%#llx) - aborting.\n", value1); + pr_info("PM-Timer failed consistency check (%#llx) - aborting.\n", + value1); pmtmr_ioport = 0; return -ENODEV; } -- cgit v1.2.3