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