diff options
author | Patrice Chotard <patrice.chotard@st.com> | 2017-02-21 13:37:05 +0100 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-03-14 20:40:18 -0400 |
commit | 347cb2edf96d1fcb10b0b98167533ee9e62c0c8e (patch) | |
tree | 6f76b5bba04cbd7edd1f57f63609e0845ea0f2f4 | |
parent | 94e9a4ef91817c43b8e5af99d8846491f51b0749 (diff) |
STiH410: Add STi timer driver
Add ARM global timer based timer
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | drivers/timer/Kconfig | 7 | ||||
-rw-r--r-- | drivers/timer/Makefile | 1 | ||||
-rw-r--r-- | drivers/timer/sti-timer.c | 78 |
3 files changed, 86 insertions, 0 deletions
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index cd38a6d4bd9..72c14168d6f 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -58,4 +58,11 @@ config AST_TIMER This is mostly because they all share several registers which makes it difficult to completely separate them. +config STI_TIMER + bool "STi timer support" + depends on TIMER + default y if ARCH_STI + help + Select this to enable a timer for STi devices. + endmenu diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index a4b1a486b0f..ae94be86c06 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o obj-$(CONFIG_OMAP_TIMER) += omap-timer.o obj-$(CONFIG_AST_TIMER) += ast_timer.o +obj-$(CONFIG_STI_TIMER) += sti-timer.o diff --git a/drivers/timer/sti-timer.c b/drivers/timer/sti-timer.c new file mode 100644 index 00000000000..e1419c49763 --- /dev/null +++ b/drivers/timer/sti-timer.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2017 Patrice Chotard <patrice.chotard@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <timer.h> + +#include <asm/io.h> +#include <asm/arch-armv7/globaltimer.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct sti_timer_priv { + struct globaltimer *global_timer; +}; + +static int sti_timer_get_count(struct udevice *dev, u64 *count) +{ + struct sti_timer_priv *priv = dev_get_priv(dev); + struct globaltimer *global_timer = priv->global_timer; + u32 low, high; + u64 timer; + u32 old = readl(&global_timer->cnt_h); + + while (1) { + low = readl(&global_timer->cnt_l); + high = readl(&global_timer->cnt_h); + if (old == high) + break; + else + old = high; + } + timer = high; + *count = (u64)((timer << 32) | low); + + return 0; +} + +static int sti_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct sti_timer_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK; + + /* get arm global timer base address */ + addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg"); + priv->global_timer = (struct globaltimer *)addr; + + /* init timer */ + writel(0x01, &priv->global_timer->ctl); + + return 0; +} + +static const struct timer_ops sti_timer_ops = { + .get_count = sti_timer_get_count, +}; + +static const struct udevice_id sti_timer_ids[] = { + { .compatible = "arm,cortex-a9-global-timer" }, + {} +}; + +U_BOOT_DRIVER(sti_timer) = { + .name = "sti_timer", + .id = UCLASS_TIMER, + .of_match = sti_timer_ids, + .priv_auto_alloc_size = sizeof(struct sti_timer_priv), + .probe = sti_timer_probe, + .ops = &sti_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; |