1*347cb2edSPatrice Chotard /* 2*347cb2edSPatrice Chotard * (C) Copyright 2017 Patrice Chotard <patrice.chotard@st.com> 3*347cb2edSPatrice Chotard * 4*347cb2edSPatrice Chotard * SPDX-License-Identifier: GPL-2.0+ 5*347cb2edSPatrice Chotard */ 6*347cb2edSPatrice Chotard 7*347cb2edSPatrice Chotard #include <common.h> 8*347cb2edSPatrice Chotard #include <dm.h> 9*347cb2edSPatrice Chotard #include <fdtdec.h> 10*347cb2edSPatrice Chotard #include <timer.h> 11*347cb2edSPatrice Chotard 12*347cb2edSPatrice Chotard #include <asm/io.h> 13*347cb2edSPatrice Chotard #include <asm/arch-armv7/globaltimer.h> 14*347cb2edSPatrice Chotard 15*347cb2edSPatrice Chotard DECLARE_GLOBAL_DATA_PTR; 16*347cb2edSPatrice Chotard 17*347cb2edSPatrice Chotard struct sti_timer_priv { 18*347cb2edSPatrice Chotard struct globaltimer *global_timer; 19*347cb2edSPatrice Chotard }; 20*347cb2edSPatrice Chotard 21*347cb2edSPatrice Chotard static int sti_timer_get_count(struct udevice *dev, u64 *count) 22*347cb2edSPatrice Chotard { 23*347cb2edSPatrice Chotard struct sti_timer_priv *priv = dev_get_priv(dev); 24*347cb2edSPatrice Chotard struct globaltimer *global_timer = priv->global_timer; 25*347cb2edSPatrice Chotard u32 low, high; 26*347cb2edSPatrice Chotard u64 timer; 27*347cb2edSPatrice Chotard u32 old = readl(&global_timer->cnt_h); 28*347cb2edSPatrice Chotard 29*347cb2edSPatrice Chotard while (1) { 30*347cb2edSPatrice Chotard low = readl(&global_timer->cnt_l); 31*347cb2edSPatrice Chotard high = readl(&global_timer->cnt_h); 32*347cb2edSPatrice Chotard if (old == high) 33*347cb2edSPatrice Chotard break; 34*347cb2edSPatrice Chotard else 35*347cb2edSPatrice Chotard old = high; 36*347cb2edSPatrice Chotard } 37*347cb2edSPatrice Chotard timer = high; 38*347cb2edSPatrice Chotard *count = (u64)((timer << 32) | low); 39*347cb2edSPatrice Chotard 40*347cb2edSPatrice Chotard return 0; 41*347cb2edSPatrice Chotard } 42*347cb2edSPatrice Chotard 43*347cb2edSPatrice Chotard static int sti_timer_probe(struct udevice *dev) 44*347cb2edSPatrice Chotard { 45*347cb2edSPatrice Chotard struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 46*347cb2edSPatrice Chotard struct sti_timer_priv *priv = dev_get_priv(dev); 47*347cb2edSPatrice Chotard fdt_addr_t addr; 48*347cb2edSPatrice Chotard 49*347cb2edSPatrice Chotard uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK; 50*347cb2edSPatrice Chotard 51*347cb2edSPatrice Chotard /* get arm global timer base address */ 52*347cb2edSPatrice Chotard addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg"); 53*347cb2edSPatrice Chotard priv->global_timer = (struct globaltimer *)addr; 54*347cb2edSPatrice Chotard 55*347cb2edSPatrice Chotard /* init timer */ 56*347cb2edSPatrice Chotard writel(0x01, &priv->global_timer->ctl); 57*347cb2edSPatrice Chotard 58*347cb2edSPatrice Chotard return 0; 59*347cb2edSPatrice Chotard } 60*347cb2edSPatrice Chotard 61*347cb2edSPatrice Chotard static const struct timer_ops sti_timer_ops = { 62*347cb2edSPatrice Chotard .get_count = sti_timer_get_count, 63*347cb2edSPatrice Chotard }; 64*347cb2edSPatrice Chotard 65*347cb2edSPatrice Chotard static const struct udevice_id sti_timer_ids[] = { 66*347cb2edSPatrice Chotard { .compatible = "arm,cortex-a9-global-timer" }, 67*347cb2edSPatrice Chotard {} 68*347cb2edSPatrice Chotard }; 69*347cb2edSPatrice Chotard 70*347cb2edSPatrice Chotard U_BOOT_DRIVER(sti_timer) = { 71*347cb2edSPatrice Chotard .name = "sti_timer", 72*347cb2edSPatrice Chotard .id = UCLASS_TIMER, 73*347cb2edSPatrice Chotard .of_match = sti_timer_ids, 74*347cb2edSPatrice Chotard .priv_auto_alloc_size = sizeof(struct sti_timer_priv), 75*347cb2edSPatrice Chotard .probe = sti_timer_probe, 76*347cb2edSPatrice Chotard .ops = &sti_timer_ops, 77*347cb2edSPatrice Chotard .flags = DM_FLAG_PRE_RELOC, 78*347cb2edSPatrice Chotard }; 79