blob: a51822a53059e49ab82127d740e8a6c85de0415d [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek38b343d2012-09-13 20:23:35 +00002/*
Stefan Herbrechtsmeierc7abb822017-01-17 16:27:26 +01003 * Copyright (C) 2017 Weidmüller Interface GmbH & Co. KG
4 * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
5 *
Michal Simek38b343d2012-09-13 20:23:35 +00006 * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
Michal Simek3e1b61d2018-01-17 07:37:47 +01007 * Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved.
Michal Simek38b343d2012-09-13 20:23:35 +00008 *
9 * (C) Copyright 2008
10 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
11 *
12 * (C) Copyright 2004
13 * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
14 *
15 * (C) Copyright 2002-2004
16 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
17 *
18 * (C) Copyright 2003
19 * Texas Instruments <www.ti.com>
20 *
21 * (C) Copyright 2002
22 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
23 * Marius Groeger <mgroeger@sysgo.de>
24 *
25 * (C) Copyright 2002
26 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
27 * Alex Zuepke <azu@sysgo.de>
Michal Simek38b343d2012-09-13 20:23:35 +000028 */
29
Stefan Herbrechtsmeierc7abb822017-01-17 16:27:26 +010030#include <clk.h>
Michal Simek38b343d2012-09-13 20:23:35 +000031#include <common.h>
32#include <div64.h>
Stefan Herbrechtsmeierc7abb822017-01-17 16:27:26 +010033#include <dm.h>
Simon Glass691d7192020-05-10 11:40:02 -060034#include <init.h>
Simon Glass049f8d62019-12-28 10:44:59 -070035#include <time.h>
Simon Glass336d4612020-02-03 07:36:16 -070036#include <malloc.h>
Simon Glass401d1c42020-10-30 21:38:53 -060037#include <asm/global_data.h>
Michal Simek38b343d2012-09-13 20:23:35 +000038#include <asm/io.h>
Michal Simek4b212842013-04-12 16:21:26 +020039#include <asm/arch/hardware.h>
Soren Brinkmann614c2722013-11-21 13:38:57 -080040#include <asm/arch/clk.h>
Michal Simek38b343d2012-09-13 20:23:35 +000041
42DECLARE_GLOBAL_DATA_PTR;
43
44struct scu_timer {
45 u32 load; /* Timer Load Register */
46 u32 counter; /* Timer Counter Register */
47 u32 control; /* Timer Control Register */
48};
49
50static struct scu_timer *timer_base =
Michal Simek4b212842013-04-12 16:21:26 +020051 (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR;
Michal Simek38b343d2012-09-13 20:23:35 +000052
53#define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */
54#define SCUTIMER_CONTROL_PRESCALER_SHIFT 8
55#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /* Auto-reload */
56#define SCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /* Timer enable */
57
58#define TIMER_LOAD_VAL 0xFFFFFFFF
59#define TIMER_PRESCALE 255
Michal Simek38b343d2012-09-13 20:23:35 +000060
61int timer_init(void)
62{
63 const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK |
64 (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
65 SCUTIMER_CONTROL_ENABLE_MASK;
66
Stefan Herbrechtsmeierc7abb822017-01-17 16:27:26 +010067 struct udevice *dev;
68 struct clk clk;
69 int ret;
70
71 ret = uclass_get_device_by_driver(UCLASS_CLK,
Simon Glass65e25be2020-12-28 20:34:56 -070072 DM_DRIVER_GET(zynq_clk), &dev);
Stefan Herbrechtsmeierc7abb822017-01-17 16:27:26 +010073 if (ret)
74 return ret;
75
76 clk.id = cpu_6or4x_clk;
77 ret = clk_request(dev, &clk);
78 if (ret < 0)
79 return ret;
80
81 gd->cpu_clk = clk_get_rate(&clk);
82
83 clk_free(&clk);
Stefan Herbrechtsmeierc7abb822017-01-17 16:27:26 +010084
Michal Simek2826fd32013-11-22 15:29:38 +010085 gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
Soren Brinkmann614c2722013-11-21 13:38:57 -080086
Michal Simek38b343d2012-09-13 20:23:35 +000087 /* Load the timer counter register */
Michal Simek7ba69b72013-08-28 07:36:31 +020088 writel(0xFFFFFFFF, &timer_base->load);
Michal Simek38b343d2012-09-13 20:23:35 +000089
90 /*
91 * Start the A9Timer device
92 * Enable Auto reload mode, Clear prescaler control bits
93 * Set prescaler value, Enable the decrementer
94 */
95 clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK,
96 emask);
97
98 /* Reset time */
Simon Glass582601d2012-12-13 20:48:35 +000099 gd->arch.lastinc = readl(&timer_base->counter) /
Soren Brinkmann614c2722013-11-21 13:38:57 -0800100 (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
Simon Glass66ee6922012-12-13 20:48:34 +0000101 gd->arch.tbl = 0;
Michal Simek38b343d2012-09-13 20:23:35 +0000102
103 return 0;
104}
105
106/*
Michal Simek38b343d2012-09-13 20:23:35 +0000107 * This function is derived from PowerPC code (timebase clock frequency).
108 * On ARM it returns the number of timer ticks per second.
109 */
110ulong get_tbclk(void)
111{
Michal Simeka2ec7fb2015-04-20 12:56:24 +0200112 return gd->arch.timer_rate_hz;
Michal Simek38b343d2012-09-13 20:23:35 +0000113}