diff options
author | Patrice Chotard <patrice.chotard@st.com> | 2018-02-07 10:44:45 +0100 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-03-13 21:45:37 -0400 |
commit | 5120a083e797aec3180fbda9ab845486da990909 (patch) | |
tree | 4875bbabe8d1b7c2c0fc7fe7dd0955117a73dcb3 /drivers/timer | |
parent | cc66dcdd16a88a56791d1951bca54b3048e3f96c (diff) | |
download | u-boot-5120a083e797aec3180fbda9ab845486da990909.tar.gz |
timer: stm32: Add timer support for STM32 SoCs family
This timer driver is using GPT Timer (General Purpose Timer)
available on all STM32 SOCs family.
This driver can be used on STM32F4/F7 and H7 SoCs family
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Diffstat (limited to 'drivers/timer')
-rw-r--r-- | drivers/timer/Kconfig | 7 | ||||
-rw-r--r-- | drivers/timer/Makefile | 1 | ||||
-rw-r--r-- | drivers/timer/stm32_timer.c | 138 |
3 files changed, 146 insertions, 0 deletions
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 3a1f8311c1..2c96896726 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -119,4 +119,11 @@ config ROCKCHIP_TIMER Select this to enable support for the timer found on Rockchip devices. +config STM32_TIMER + bool "STM32 timer support" + depends on TIMER + help + Select this to enable support for the timer found on + STM32 devices. + endmenu diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 15e515407e..a6e7832154 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o +obj-$(CONFIG_STM32_TIMER) += stm32_timer.o diff --git a/drivers/timer/stm32_timer.c b/drivers/timer/stm32_timer.c new file mode 100644 index 0000000000..344e6fba1e --- /dev/null +++ b/drivers/timer/stm32_timer.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> +#include <timer.h> + +#include <asm/io.h> + +/* Timer control1 register */ +#define CR1_CEN BIT(0) +#define CR1_ARPE BIT(7) + +/* Event Generation Register register */ +#define EGR_UG BIT(0) + +/* Auto reload register for free running config */ +#define GPT_FREE_RUNNING 0xFFFFFFFF + +struct stm32_timer_regs { + u32 cr1; + u32 cr2; + u32 smcr; + u32 dier; + u32 sr; + u32 egr; + u32 ccmr1; + u32 ccmr2; + u32 ccer; + u32 cnt; + u32 psc; + u32 arr; + u32 reserved; + u32 ccr1; + u32 ccr2; + u32 ccr3; + u32 ccr4; + u32 reserved1; + u32 dcr; + u32 dmar; + u32 tim2_5_or; +}; + +struct stm32_timer_priv { + struct stm32_timer_regs *base; +}; + +static int stm32_timer_get_count(struct udevice *dev, u64 *count) +{ + struct stm32_timer_priv *priv = dev_get_priv(dev); + struct stm32_timer_regs *regs = priv->base; + + *count = readl(®s->cnt); + + return 0; +} + +static int stm32_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct stm32_timer_priv *priv = dev_get_priv(dev); + struct stm32_timer_regs *regs; + struct clk clk; + fdt_addr_t addr; + int ret; + u32 rate, psc; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = (struct stm32_timer_regs *)addr; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + + regs = priv->base; + + /* Stop the timer */ + clrbits_le32(®s->cr1, CR1_CEN); + + /* get timer clock */ + rate = clk_get_rate(&clk); + + /* we set timer prescaler to obtain a 1MHz timer counter frequency */ + psc = (rate / CONFIG_SYS_HZ_CLOCK) - 1; + writel(psc, ®s->psc); + + /* Set timer frequency to 1MHz */ + uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK; + + /* Configure timer for auto-reload */ + setbits_le32(®s->cr1, CR1_ARPE); + + /* load value for auto reload */ + writel(GPT_FREE_RUNNING, ®s->arr); + + /* start timer */ + setbits_le32(®s->cr1, CR1_CEN); + + /* Update generation */ + setbits_le32(®s->egr, EGR_UG); + + return 0; +} + +static const struct timer_ops stm32_timer_ops = { + .get_count = stm32_timer_get_count, +}; + +static const struct udevice_id stm32_timer_ids[] = { + { .compatible = "st,stm32-timer" }, + {} +}; + +U_BOOT_DRIVER(stm32_timer) = { + .name = "stm32_timer", + .id = UCLASS_TIMER, + .of_match = stm32_timer_ids, + .priv_auto_alloc_size = sizeof(struct stm32_timer_priv), + .probe = stm32_timer_probe, + .ops = &stm32_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + |