[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