[rtems commit] bsp/riscv: Rework clock driver
Hesham Almatary
heshamelmatary at gmail.com
Fri Jul 6 14:38:21 UTC 2018
On Fri, Jun 29, 2018 at 10:57 AM, Sebastian Huber <sebh at rtems.org> wrote:
> Module: rtems
> Branch: master
> Commit: cdfed94f347a112638b914876de8069e10adf175
> Changeset: http://git.rtems.org/rtems/commit/?id=cdfed94f347a112638b914876de8069e10adf175
>
> Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
> Date: Mon Jun 25 11:12:24 2018 +0200
>
> 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(-)
>
> diff --git a/bsps/include/bsp/fatal.h b/bsps/include/bsp/fatal.h
> index ca2e39a..12d33a2 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 340e158..8be2037 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 <hesham at alumni.york.ac.uk>
> *
> * Redistribution and use in source and binary forms, with or without
> @@ -33,75 +32,102 @@
> * SUCH DAMAGE.
> */
>
> -#include <rtems.h>
> +#include <rtems/timecounter.h>
> +
> #include <bsp.h>
> +#include <bsp/fatal.h>
> +#include <bsp/fdt.h>
> #include <bsp/irq.h>
> -#include <rtems/score/riscv-utility.h>
> -#include <rtems/score/cpu.h>
> -#include <rtems/timecounter.h>
>
> -/* 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 <dev/irq/clint.h>
>
> -static struct timecounter riscv_generic_tc;
> +#include <libfdt.h>
>
> -/* CPU counter */
> -static CPU_Counter_ticks cpu_counter_ticks;
> +#define CLINT ((volatile clint_regs *) 0x02000000)
>
Can we get CLINT address from DTB instead of hardcoding it?
> -/* 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 6298966..5ec916e 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 0000000..6be3145
> --- /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 <stdint.h>
> +
> +#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 */
>
> _______________________________________________
> vc mailing list
> vc at rtems.org
> http://lists.rtems.org/mailman/listinfo/vc
--
Hesham
More information about the vc
mailing list