"Das U-Boot" Source Tree
at master 87 lines 2.0 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 4 * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics. 5 * 6 * ARM Cortext A9 global timer driver 7 */ 8 9#include <config.h> 10#include <dm.h> 11#include <clk.h> 12#include <timer.h> 13#include <linux/err.h> 14 15#include <asm/io.h> 16#include <asm/arch-armv7/globaltimer.h> 17 18struct arm_global_timer_priv { 19 struct globaltimer *global_timer; 20}; 21 22static u64 arm_global_timer_get_count(struct udevice *dev) 23{ 24 struct arm_global_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 return (u64)((timer << 32) | low); 40} 41 42static int arm_global_timer_probe(struct udevice *dev) 43{ 44 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 45 struct arm_global_timer_priv *priv = dev_get_priv(dev); 46 struct clk clk; 47 int err; 48 ulong ret; 49 50 /* get arm global timer base address */ 51 priv->global_timer = (struct globaltimer *)dev_read_addr_ptr(dev); 52 if (!priv->global_timer) 53 return -ENOENT; 54 55 err = clk_get_by_index(dev, 0, &clk); 56 if (!err) { 57 ret = clk_get_rate(&clk); 58 if (IS_ERR_VALUE(ret)) 59 return ret; 60 uc_priv->clock_rate = ret; 61 } else { 62 uc_priv->clock_rate = CFG_SYS_HZ_CLOCK; 63 } 64 65 /* init timer */ 66 writel(0x01, &priv->global_timer->ctl); 67 68 return 0; 69} 70 71static const struct timer_ops arm_global_timer_ops = { 72 .get_count = arm_global_timer_get_count, 73}; 74 75static const struct udevice_id arm_global_timer_ids[] = { 76 { .compatible = "arm,cortex-a9-global-timer" }, 77 {} 78}; 79 80U_BOOT_DRIVER(arm_global_timer) = { 81 .name = "arm_global_timer", 82 .id = UCLASS_TIMER, 83 .of_match = arm_global_timer_ids, 84 .priv_auto = sizeof(struct arm_global_timer_priv), 85 .probe = arm_global_timer_probe, 86 .ops = &arm_global_timer_ops, 87};