1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2347cb2edSPatrice Chotard /* 3fb48bc44SPatrice Chotard * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 4fb48bc44SPatrice Chotard * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics. 5347cb2edSPatrice Chotard */ 6347cb2edSPatrice Chotard 7347cb2edSPatrice Chotard #include <common.h> 8347cb2edSPatrice Chotard #include <dm.h> 9347cb2edSPatrice Chotard #include <fdtdec.h> 10347cb2edSPatrice Chotard #include <timer.h> 11347cb2edSPatrice Chotard 12347cb2edSPatrice Chotard #include <asm/io.h> 13347cb2edSPatrice Chotard #include <asm/arch-armv7/globaltimer.h> 14347cb2edSPatrice Chotard 15347cb2edSPatrice Chotard DECLARE_GLOBAL_DATA_PTR; 16347cb2edSPatrice Chotard 17347cb2edSPatrice Chotard struct sti_timer_priv { 18347cb2edSPatrice Chotard struct globaltimer *global_timer; 19347cb2edSPatrice Chotard }; 20347cb2edSPatrice Chotard 21347cb2edSPatrice Chotard static int sti_timer_get_count(struct udevice *dev, u64 *count) 22347cb2edSPatrice Chotard { 23347cb2edSPatrice Chotard struct sti_timer_priv *priv = dev_get_priv(dev); 24347cb2edSPatrice Chotard struct globaltimer *global_timer = priv->global_timer; 25347cb2edSPatrice Chotard u32 low, high; 26347cb2edSPatrice Chotard u64 timer; 27347cb2edSPatrice Chotard u32 old = readl(&global_timer->cnt_h); 28347cb2edSPatrice Chotard 29347cb2edSPatrice Chotard while (1) { 30347cb2edSPatrice Chotard low = readl(&global_timer->cnt_l); 31347cb2edSPatrice Chotard high = readl(&global_timer->cnt_h); 32347cb2edSPatrice Chotard if (old == high) 33347cb2edSPatrice Chotard break; 34347cb2edSPatrice Chotard else 35347cb2edSPatrice Chotard old = high; 36347cb2edSPatrice Chotard } 37347cb2edSPatrice Chotard timer = high; 38347cb2edSPatrice Chotard *count = (u64)((timer << 32) | low); 39347cb2edSPatrice Chotard 40347cb2edSPatrice Chotard return 0; 41347cb2edSPatrice Chotard } 42347cb2edSPatrice Chotard 43347cb2edSPatrice Chotard static int sti_timer_probe(struct udevice *dev) 44347cb2edSPatrice Chotard { 45347cb2edSPatrice Chotard struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 46347cb2edSPatrice Chotard struct sti_timer_priv *priv = dev_get_priv(dev); 47347cb2edSPatrice Chotard fdt_addr_t addr; 48347cb2edSPatrice Chotard 49347cb2edSPatrice Chotard uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK; 50347cb2edSPatrice Chotard 51347cb2edSPatrice Chotard /* get arm global timer base address */ 52347cb2edSPatrice Chotard addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg"); 53347cb2edSPatrice Chotard priv->global_timer = (struct globaltimer *)addr; 54347cb2edSPatrice Chotard 55347cb2edSPatrice Chotard /* init timer */ 56347cb2edSPatrice Chotard writel(0x01, &priv->global_timer->ctl); 57347cb2edSPatrice Chotard 58347cb2edSPatrice Chotard return 0; 59347cb2edSPatrice Chotard } 60347cb2edSPatrice Chotard 61347cb2edSPatrice Chotard static const struct timer_ops sti_timer_ops = { 62347cb2edSPatrice Chotard .get_count = sti_timer_get_count, 63347cb2edSPatrice Chotard }; 64347cb2edSPatrice Chotard 65347cb2edSPatrice Chotard static const struct udevice_id sti_timer_ids[] = { 66347cb2edSPatrice Chotard { .compatible = "arm,cortex-a9-global-timer" }, 67347cb2edSPatrice Chotard {} 68347cb2edSPatrice Chotard }; 69347cb2edSPatrice Chotard 70347cb2edSPatrice Chotard U_BOOT_DRIVER(sti_timer) = { 71347cb2edSPatrice Chotard .name = "sti_timer", 72347cb2edSPatrice Chotard .id = UCLASS_TIMER, 73347cb2edSPatrice Chotard .of_match = sti_timer_ids, 74347cb2edSPatrice Chotard .priv_auto_alloc_size = sizeof(struct sti_timer_priv), 75347cb2edSPatrice Chotard .probe = sti_timer_probe, 76347cb2edSPatrice Chotard .ops = &sti_timer_ops, 77347cb2edSPatrice Chotard .flags = DM_FLAG_PRE_RELOC, 78347cb2edSPatrice Chotard }; 79