xref: /openbmc/u-boot/drivers/timer/sti-timer.c (revision 1d6edcbf)
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 
sti_timer_get_count(struct udevice * dev,u64 * count)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 
sti_timer_probe(struct udevice * dev)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 };
78