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