Hi Vlad, On 2 November 2016 at 09:44, Vlad Zakharov <vladislav.zakha...@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 <vzak...@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 <s...@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@0 { > + compatible = "snps,arc-timer"; > + clock-frequency = <100000000>; > + reg = <0>; > +}; > + > +timer@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot