]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-zynq/timer.c
sunxi: Add SUN6I_P2WI kconfig entry
[u-boot] / arch / arm / mach-zynq / timer.c
1 /*
2  * Copyright (C) 2017 Weidmüller Interface GmbH & Co. KG
3  * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
4  *
5  * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
6  * Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved.
7  *
8  * (C) Copyright 2008
9  * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
10  *
11  * (C) Copyright 2004
12  * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
13  *
14  * (C) Copyright 2002-2004
15  * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
16  *
17  * (C) Copyright 2003
18  * Texas Instruments <www.ti.com>
19  *
20  * (C) Copyright 2002
21  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
22  * Marius Groeger <mgroeger@sysgo.de>
23  *
24  * (C) Copyright 2002
25  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
26  * Alex Zuepke <azu@sysgo.de>
27  *
28  * SPDX-License-Identifier:     GPL-2.0+
29  */
30
31 #include <clk.h>
32 #include <common.h>
33 #include <div64.h>
34 #include <dm.h>
35 #include <asm/io.h>
36 #include <asm/arch/hardware.h>
37 #include <asm/arch/clk.h>
38
39 DECLARE_GLOBAL_DATA_PTR;
40
41 struct scu_timer {
42         u32 load; /* Timer Load Register */
43         u32 counter; /* Timer Counter Register */
44         u32 control; /* Timer Control Register */
45 };
46
47 static struct scu_timer *timer_base =
48                               (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR;
49
50 #define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */
51 #define SCUTIMER_CONTROL_PRESCALER_SHIFT        8
52 #define SCUTIMER_CONTROL_AUTO_RELOAD_MASK       0x00000002 /* Auto-reload */
53 #define SCUTIMER_CONTROL_ENABLE_MASK            0x00000001 /* Timer enable */
54
55 #define TIMER_LOAD_VAL 0xFFFFFFFF
56 #define TIMER_PRESCALE 255
57
58 int timer_init(void)
59 {
60         const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK |
61                         (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
62                         SCUTIMER_CONTROL_ENABLE_MASK;
63
64         struct udevice *dev;
65         struct clk clk;
66         int ret;
67
68         ret = uclass_get_device_by_driver(UCLASS_CLK,
69                 DM_GET_DRIVER(zynq_clk), &dev);
70         if (ret)
71                 return ret;
72
73         clk.id = cpu_6or4x_clk;
74         ret = clk_request(dev, &clk);
75         if (ret < 0)
76                 return ret;
77
78         gd->cpu_clk = clk_get_rate(&clk);
79
80         clk_free(&clk);
81
82         gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
83
84         /* Load the timer counter register */
85         writel(0xFFFFFFFF, &timer_base->load);
86
87         /*
88          * Start the A9Timer device
89          * Enable Auto reload mode, Clear prescaler control bits
90          * Set prescaler value, Enable the decrementer
91          */
92         clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK,
93                                                                 emask);
94
95         /* Reset time */
96         gd->arch.lastinc = readl(&timer_base->counter) /
97                                 (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
98         gd->arch.tbl = 0;
99
100         return 0;
101 }
102
103 /*
104  * This function is derived from PowerPC code (timebase clock frequency).
105  * On ARM it returns the number of timer ticks per second.
106  */
107 ulong get_tbclk(void)
108 {
109         return gd->arch.timer_rate_hz;
110 }