From cdfed94f347a112638b914876de8069e10adf175 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 25 Jun 2018 11:12:24 +0200 Subject: bsp/riscv: Rework clock driver Use device tree provided timebase frequency. Do not write to read-only mtime register. Update #3433. --- bsps/include/bsp/fatal.h | 7 +- bsps/riscv/riscv/clock/clockdrv.c | 108 +++++++++++++++++++------------ bsps/riscv/riscv/include/bsp.h | 22 ------- bsps/riscv/riscv/include/dev/irq/clint.h | 53 +++++++++++++++ 4 files changed, 125 insertions(+), 65 deletions(-) create mode 100644 bsps/riscv/riscv/include/dev/irq/clint.h (limited to 'bsps') diff --git a/bsps/include/bsp/fatal.h b/bsps/include/bsp/fatal.h index ca2e39aba8..12d33a20e4 100644 --- a/bsps/include/bsp/fatal.h +++ b/bsps/include/bsp/fatal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016 embedded brains GmbH. All rights reserved. + * Copyright (c) 2012, 2018 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -137,7 +137,10 @@ typedef enum { ATSAM_FATAL_PIO_CONFIGURE_IT, /* i.MX fatal codes */ - IMX_FATAL_GENERIC_TIMER_FREQUENCY = BSP_FATAL_CODE_BLOCK(12) + IMX_FATAL_GENERIC_TIMER_FREQUENCY = BSP_FATAL_CODE_BLOCK(12), + + /* RISC-V fatal codes */ + RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE = BSP_FATAL_CODE_BLOCK(13) } bsp_fatal_code; RTEMS_NO_RETURN static inline void diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c index 340e158489..8be203757c 100644 --- a/bsps/riscv/riscv/clock/clockdrv.c +++ b/bsps/riscv/riscv/clock/clockdrv.c @@ -7,8 +7,7 @@ */ /* - * riscv_generic Clock driver - * + * Copyright (c) 2018 embedded brains GmbH * COPYRIGHT (c) 2015 Hesham Alatary * * Redistribution and use in source and binary forms, with or without @@ -33,75 +32,102 @@ * SUCH DAMAGE. */ -#include +#include + #include +#include +#include #include -#include -#include -#include -/* The number of clock cycles before generating a tick timer interrupt. */ -#define TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT 1000 -#define RISCV_CLOCK_CYCLE_TIME_NANOSECONDS 1 +#include -static struct timecounter riscv_generic_tc; +#include -/* CPU counter */ -static CPU_Counter_ticks cpu_counter_ticks; +#define CLINT ((volatile clint_regs *) 0x02000000) -/* This prototype is added here to Avoid warnings */ +/* This is defined in dev/clock/clockimpl.h */ void Clock_isr(void *arg); -static void riscv_generic_clock_at_tick(void) +static struct timecounter riscv_clock_tc; + +static uint32_t riscv_clock_interval; + +static void riscv_clock_at_tick(void) { - REG(MTIME_MM) = 0; - REG(MTIMECMP_MM) = TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT; + volatile clint_regs *clint; + uint64_t cmp; + + clint = CLINT; + + cmp = clint->mtimecmp[0].val_64; + cmp += riscv_clock_interval; - cpu_counter_ticks += TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT * 10000; +#if __riscv_xlen == 32 + clint->mtimecmp[0].val_32[0] = 0xffffffff; + clint->mtimecmp[0].val_32[1] = (uint32_t) (cmp >> 32); + clint->mtimecmp[0].val_32[0] = (uint32_t) cmp; +#elif __riscv_xlen == 64 + clint->mtimecmp[0].val_64 = cmp; +#endif } -static void riscv_generic_clock_handler_install(proc_ptr new_isr) +static void riscv_clock_handler_install(proc_ptr new_isr) { - rtems_status_code sc = RTEMS_SUCCESSFUL; _CPU_ISR_install_vector(RISCV_MACHINE_TIMER_INTERRUPT, new_isr, NULL); - - if (sc != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(0xdeadbeef); - } } -static uint32_t riscv_generic_get_timecount(struct timecounter *tc) +static uint32_t riscv_clock_get_timecount(struct timecounter *tc) { - uint32_t ticks_since_last_timer_interrupt = REG(MTIME_MM); + volatile clint_regs *clint; - return cpu_counter_ticks + ticks_since_last_timer_interrupt; + clint = CLINT; + return clint->mtime.val_32[0]; } CPU_Counter_ticks _CPU_Counter_read(void) { - return riscv_generic_get_timecount(NULL); + return riscv_clock_get_timecount(NULL); +} + +static uint32_t riscv_clock_get_timebase_frequency(const void *fdt) +{ + int node; + const uint32_t *val; + int len; + + node = fdt_path_offset(fdt, "/cpus"); + val = fdt_getprop(fdt, node, "timebase-frequency", &len); + if (val == NULL || len < 4) { + bsp_fatal(RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE); + } + + return fdt32_to_cpu(*val); } -static void riscv_generic_clock_initialize(void) +static void riscv_clock_initialize(void) { - uint32_t mtimecmp = TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT; - uint64_t frequency = (1000000000 / RISCV_CLOCK_CYCLE_TIME_NANOSECONDS); + const char *fdt; + uint32_t tb_freq; + uint64_t us_per_tick; + + fdt = bsp_fdt_get(); + tb_freq = riscv_clock_get_timebase_frequency(fdt); + us_per_tick = rtems_configuration_get_microseconds_per_tick(); + riscv_clock_interval = (uint32_t) ((tb_freq * us_per_tick) / 1000000); - REG(MTIME_MM) = 0; - REG(MTIMECMP_MM) = TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT; + riscv_clock_at_tick(); /* Enable mtimer interrupts */ set_csr(mie, MIP_MTIP); - set_csr(mip, MIP_MTIP); /* Initialize timecounter */ - riscv_generic_tc.tc_get_timecount = riscv_generic_get_timecount; - riscv_generic_tc.tc_counter_mask = 0xffffffff; - riscv_generic_tc.tc_frequency = frequency; - riscv_generic_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; - rtems_timecounter_install(&riscv_generic_tc); + riscv_clock_tc.tc_get_timecount = riscv_clock_get_timecount; + riscv_clock_tc.tc_counter_mask = 0xffffffff; + riscv_clock_tc.tc_frequency = tb_freq; + riscv_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&riscv_clock_tc); } CPU_Counter_ticks _CPU_Counter_difference( @@ -112,11 +138,11 @@ CPU_Counter_ticks _CPU_Counter_difference( return second - first; } -#define Clock_driver_support_at_tick() riscv_generic_clock_at_tick() +#define Clock_driver_support_at_tick() riscv_clock_at_tick() -#define Clock_driver_support_initialize_hardware() riscv_generic_clock_initialize() +#define Clock_driver_support_initialize_hardware() riscv_clock_initialize() #define Clock_driver_support_install_isr(isr) \ - riscv_generic_clock_handler_install(isr) + riscv_clock_handler_install(isr) #include "../../../shared/dev/clock/clockimpl.h" diff --git a/bsps/riscv/riscv/include/bsp.h b/bsps/riscv/riscv/include/bsp.h index 6298966a8c..5ec916e6b3 100644 --- a/bsps/riscv/riscv/include/bsp.h +++ b/bsps/riscv/riscv/include/bsp.h @@ -46,28 +46,6 @@ extern "C" { #define BSP_FDT_IS_SUPPORTED -/** - * @defgroup riscv_generic Register Definitions - * - * @ingroup riscv_generic - * - * @brief Shared register definitions for RISC-V systems. - * - * @{ - */ - -/** - * @name Register Macros - * - * @{ - */ - -#define REG(x) (*((volatile unsigned long *) (x))) -#define BIT(n) (1 << (n)) - -#define MTIME_MM 0x000000000200bff8 -#define MTIMECMP_MM 0x0000000002004000 - #ifdef __cplusplus } #endif diff --git a/bsps/riscv/riscv/include/dev/irq/clint.h b/bsps/riscv/riscv/include/dev/irq/clint.h new file mode 100644 index 0000000000..6be3145eb4 --- /dev/null +++ b/bsps/riscv/riscv/include/dev/irq/clint.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef DEV_IRQ_CLINT_H +#define DEV_IRQ_CLINT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct { + uint32_t msip[4096]; + union { + uint64_t val_64; + uint32_t val_32[2]; + } mtimecmp[2048]; + uint32_t reserved_8000[4094]; + union { + uint64_t val_64; + uint32_t val_32[2]; + } mtime; + uint32_t reserved_c000[4096]; +} clint_regs; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DEV_IRQ_CLINT_H */ -- cgit v1.2.3