[U-Boot] [PATCH 1/2] drivers: timer: Introduce ARC timer driver

Simon Glass sjg at chromium.org
Wed Nov 2 21:14:07 CET 2016


Hi Vlad,

On 2 November 2016 at 09:44, Vlad Zakharov
<Vladislav.Zakharov at synopsys.com> wrote:
> This commit introduces timer driver for ARC.
>
> ARC timers are configured via ARC AUX registers so we use special
> functions to access timer control registers.
>
> This driver allows utilization of either timer0 or timer1
> depending on which one is available in real hardware. Essentially
> only existing timers should be mentioned in board's Device Tree
> description.
>
> Signed-off-by: Vlad Zakharov <vzakhar at synopsys.com>
> ---
>  arch/arc/include/asm/arcregs.h               |  4 ++
>  doc/device-tree-bindings/timer/arc_timer.txt | 24 +++++++
>  drivers/timer/Kconfig                        |  7 ++
>  drivers/timer/Makefile                       |  1 +
>  drivers/timer/arc_timer.c                    | 97 ++++++++++++++++++++++++++++
>  5 files changed, 133 insertions(+)
>  create mode 100644 doc/device-tree-bindings/timer/arc_timer.txt
>  create mode 100644 drivers/timer/arc_timer.c

Reviewed-by: Simon Glass <sjg at chromium.org>

Looks good. Nits below.

>
> diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
> index cf999b0..54a9b00 100644
> --- a/arch/arc/include/asm/arcregs.h
> +++ b/arch/arc/include/asm/arcregs.h
> @@ -33,6 +33,10 @@
>  #define ARC_AUX_TIMER0_CTRL    0x22    /* Timer 0 control */
>  #define ARC_AUX_TIMER0_LIMIT   0x23    /* Timer 0 limit */
>
> +#define ARC_AUX_TIMER1_CNT     0x100   /* Timer 1 count */
> +#define ARC_AUX_TIMER1_CTRL    0x101   /* Timer 1 control */
> +#define ARC_AUX_TIMER1_LIMIT   0x102   /* Timer 1 limit */
> +
>  #define ARC_AUX_INTR_VEC_BASE  0x25
>
>  /* Data cache related auxiliary registers */
> diff --git a/doc/device-tree-bindings/timer/arc_timer.txt b/doc/device-tree-bindings/timer/arc_timer.txt
> new file mode 100644
> index 0000000..e25c6ae
> --- /dev/null
> +++ b/doc/device-tree-bindings/timer/arc_timer.txt
> @@ -0,0 +1,24 @@
> +ARC Timer
> +
> +Required properties:
> +
> +- compatible : should be "snps,arc-timer"
> +- reg : Specifies timer ID, could be either 0 or 1.

You might consider adding a #define to a file in
include/dt-bindings/timer or similar for the 0 and 1. Then you can use
it in the source code. Up to you though.

> +- clock-frequency : The frequency of the clock that drives the counter, in Hz.
> +
> +Examples:
> +
> +timer at 0 {
> +       compatible = "snps,arc-timer";
> +       clock-frequency = <100000000>;
> +       reg = <0>;
> +};
> +
> +timer at 1 {
> +       compatible = "snps,arc-timer";
> +       clock-frequency = <100000000>;
> +       reg = <1>;
> +};
> +
> +NOTE: if you specify both timers, frequencies should always be the same as both timers
> +are driven by core clock.
> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
> index cb18f12..721007d 100644
> --- a/drivers/timer/Kconfig
> +++ b/drivers/timer/Kconfig
> @@ -46,4 +46,11 @@ config OMAP_TIMER
>         help
>           Select this to enable an timer for Omap devices.
>
> +config ARC_TIMER
> +       bool "ARC timer support"
> +       depends on TIMER
> +       depends on ARC
> +       help
> +         Select this to enable built-in ARC timers.

Good to include a bit more info like the capabilities of the timers

> +
>  endmenu
> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
> index f351fbb..e9624dd 100644
> --- a/drivers/timer/Makefile
> +++ b/drivers/timer/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_ALTERA_TIMER)      += altera_timer.o
>  obj-$(CONFIG_SANDBOX_TIMER)    += sandbox_timer.o
>  obj-$(CONFIG_X86_TSC_TIMER)    += tsc_timer.o
>  obj-$(CONFIG_OMAP_TIMER)       += omap-timer.o
> +obj-$(CONFIG_ARC_TIMER)        += arc_timer.o
> diff --git a/drivers/timer/arc_timer.c b/drivers/timer/arc_timer.c
> new file mode 100644
> index 0000000..727f2df
> --- /dev/null
> +++ b/drivers/timer/arc_timer.c
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (C) 2016 Synopsys, Inc. All rights reserved.
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
> +#include <asm/io.h>
> +#include <asm/arcregs.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * ARC timer control registers are mapped to auxiliary address space.
> + * There are special ARC asm command to access that addresses.
> + * Therefore we use built-in functions to read from and write to timer
> + * control register.
> + */
> +
> +/* Driver private data. Contains AUX register number. */
> +struct arc_timer_priv {
> +               uint32_t timer_id;

uint would do. It doesn't need to be 32 bits.

> +};
> +
> +static int arc_timer_get_count(struct udevice *dev, u64 *count)
> +{
> +       struct arc_timer_priv *priv = dev_get_priv(dev);

blank line here

> +       switch (priv->timer_id) {
> +       case 0:

Here is where you could use the defines.

> +               *count = read_aux_reg(ARC_AUX_TIMER0_CNT);
> +               break;
> +       case 1:
> +               *count = read_aux_reg(ARC_AUX_TIMER1_CNT);
> +               break;
> +       }

blank line before 'return'

> +       return 0;
> +}
> +
> +static int arc_timer_probe(struct udevice *dev)
> +{
> +       int id;
> +
> +       struct arc_timer_priv *priv = dev_get_priv(dev);
> +
> +       /* Get registers offset and size */
> +       id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
> +       if (id < 0)
> +               return -EINVAL;
> +       if (id > 1)

Could use the define here

> +               return -ENXIO;
> +
> +       priv->timer_id = (uint32_t)id;
> +
> +#define NH_MODE (1 << 1)

This should really go to the top of the file.

> +
> +       switch (priv->timer_id) {
> +       case 0:

Could use the define here

> +               /* Disable timer if CPU is halted */
> +               write_aux_reg(ARC_AUX_TIMER0_CTRL, NH_MODE);
> +               /* Set max value for counter/timer */
> +               write_aux_reg(ARC_AUX_TIMER0_LIMIT, 0xffffffff);
> +               /* Set initial count value and restart counter/timer */
> +               write_aux_reg(ARC_AUX_TIMER0_CNT, 0);
> +               break;
> +       case 1:
> +               /* Disable timer if CPU is halted */
> +               write_aux_reg(ARC_AUX_TIMER1_CTRL, NH_MODE);
> +               /* Set max value for counter/timer */
> +               write_aux_reg(ARC_AUX_TIMER1_LIMIT, 0xffffffff);
> +               /* Set initial count value and restart counter/timer */
> +               write_aux_reg(ARC_AUX_TIMER1_CNT, 0);
> +               break;
> +       }
> +       return 0;
> +}
> +
> +
> +static const struct timer_ops arc_timer_ops = {
> +       .get_count = arc_timer_get_count,
> +};
> +
> +static const struct udevice_id arc_timer_ids[] = {
> +       { .compatible = "snps,arc-timer" },
> +       {}
> +};
> +
> +U_BOOT_DRIVER(arc_timer) = {
> +       .name   = "arc_timer",
> +       .id     = UCLASS_TIMER,
> +       .of_match = arc_timer_ids,
> +       .probe = arc_timer_probe,
> +       .ops    = &arc_timer_ops,
> +       .flags = DM_FLAG_PRE_RELOC,
> +};
> --
> 2.7.4
>

Regards,
Simon


More information about the U-Boot mailing list