Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932913AbdGLBdM (ORCPT ); Tue, 11 Jul 2017 21:33:12 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:33755 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756388AbdGLBce (ORCPT ); Tue, 11 Jul 2017 21:32:34 -0400 Subject: [PATCH 05/17] clocksource: New RISC-V SBI timer driver Date: Tue, 11 Jul 2017 18:31:18 -0700 Message-Id: <20170712013130.14792-6-palmer@dabbelt.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170712013130.14792-1-palmer@dabbelt.com> References: <20170712013130.14792-1-palmer@dabbelt.com> Cc: albert@sifive.com, yamada.masahiro@socionext.com, mmarek@suse.com, will.deacon@arm.com, peterz@infradead.org, boqun.feng@gmail.com, mingo@redhat.com, daniel.lezcano@linaro.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, gregkh@linuxfoundation.org, jslaby@suse.com, davem@davemloft.net, mchehab@kernel.org, sfr@canb.auug.org.au, fweisbec@gmail.com, viro@zeniv.linux.org.uk, mcgrof@kernel.org, dledford@redhat.com, bart.vanassche@sandisk.com, sstabellini@kernel.org, daniel.vetter@ffwll.ch, mpe@ellerman.id.au, msalter@redhat.com, nicolas.dichtel@6wind.com, james.hogan@imgtec.com, paul.gortmaker@windriver.com, linux@roeck-us.net, heiko.carstens@de.ibm.com, schwidefsky@de.ibm.com, linux-kernel@vger.kernel.org, patches@groups.riscv.org, Palmer Dabbelt From: Palmer Dabbelt To: Olof Johansson , Arnd Bergmann , akpm@linux-foundation.org Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6039 Lines: 164 The RISC-V ISA defines a per-hart real-time clock and timer, which is present on all systems. The clock is accessed via the 'rdtime' pseudo-instruction (which reads a CSR), and the timer is set via an SBI call. This driver attempts to split out the RISC-V ISA specific mechanisms of accessing the hardware from the clocksource driver by taking a pair of function pointers to issue the actual RISC-V specific instructions. Signed-off-by: Palmer Dabbelt --- drivers/clocksource/Kconfig | 8 +++++ drivers/clocksource/Makefile | 1 + drivers/clocksource/riscv_timer.c | 64 +++++++++++++++++++++++++++++++++++++++ include/linux/timer_riscv.h | 41 +++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 drivers/clocksource/riscv_timer.c create mode 100644 include/linux/timer_riscv.h diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index fcae5ca6ac92..a5829c0b3ae4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -607,4 +607,12 @@ config CLKSRC_ST_LPC Enable this option to use the Low Power controller timer as clocksource. +config RISCV_TIMER + bool "Timer for the RISC-V platform" if COMPILE_TEST + depends on RISCV + help + This enables the per-hart timer built into all RISC-V systems, which + is accessed via both the SBI and the rdcycle instruction. This is + required for all RISC-V systems. + endmenu diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 6df949402dfc..20d75b3f22e4 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -73,3 +73,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o +obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o diff --git a/drivers/clocksource/riscv_timer.c b/drivers/clocksource/riscv_timer.c new file mode 100644 index 000000000000..6063c7abe21c --- /dev/null +++ b/drivers/clocksource/riscv_timer.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 Regents of the University of California + * Copyright (C) 2017 SiFive + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +/* + * See for the rationale behind pre-allocating per-cpu + * timers on RISC-V systems. + */ +static DEFINE_PER_CPU(struct clocksource, clock_source); +static DEFINE_PER_CPU(struct clock_event_device, clock_event); + +struct clock_event_device *timer_riscv_device(int cpu) +{ + return &per_cpu(clock_event, cpu); +} + +struct clocksource *timer_riscv_source(int cpu) +{ + return &per_cpu(clock_source, cpu); +} + +void timer_riscv_init(int cpu_id, + unsigned long riscv_timebase, + unsigned long long (*rdtime)(struct clocksource *), + int (*next)(unsigned long, struct clock_event_device*)) +{ + struct clocksource *cs = &per_cpu(clock_source, cpu_id); + struct clock_event_device *ce = &per_cpu(clock_event, cpu_id); + + *cs = (struct clocksource) { + .name = "riscv_clocksource", + .rating = 300, + .read = rdtime, + .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }; + clocksource_register_hz(cs, riscv_timebase); + + *ce = (struct clock_event_device){ + .name = "riscv_timer_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .cpumask = cpumask_of(cpu_id), + .set_next_event = next, + .set_state_oneshot = NULL, + .set_state_shutdown = NULL, + }; + clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff); +} diff --git a/include/linux/timer_riscv.h b/include/linux/timer_riscv.h new file mode 100644 index 000000000000..f2f91fe46979 --- /dev/null +++ b/include/linux/timer_riscv.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 SiFive + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _LINUX_TIMER_RISCV_H +#define _LINUX_TIMER_RISCV_H + +/* + * All RISC-V systems have a timer attached to every hart. These timers can be + * read by the 'rdcycle' pseudo instruction, and can use the SBI to setup + * events. In order to abstract the architecture-specific timer reading and + * setting functions away from the clock event insertion code, we provide + * function pointers to the clockevent subsystem that perform two basic operations: + * rdtime() reads the timer on the current CPU, and next_event(delta) sets the + * next timer event to 'delta' cycles in the future. As the timers are + * inherently a per-cpu resource, these callbacks perform operations on the + * current hart. There is guaranteed to be exactly one timer per hart on all + * RISC-V systems. + */ +void timer_riscv_init(int cpu_id, + unsigned long riscv_timebase, + unsigned long long (*rdtime)(struct clocksource *), + int (*next_event)(unsigned long, struct clock_event_device *)); + +/* + * Looks up the clocksource or clock_even_device that cooresponds the given + * hart. + */ +struct clocksource *timer_riscv_source(int cpuid); +struct clock_event_device *timer_riscv_device(int cpu_id); + +#endif -- 2.13.0