blob: db1c2c1e01c4b91734f3b9ed8d2aa9435d57a688 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Adrian Alonso69535742015-09-02 13:54:16 -05002/*
3 * Copyright (C) 2015 Freescale Semiconductor, Inc.
4 *
Adrian Alonso69535742015-09-02 13:54:16 -05005 * The file use ls102xa/timer.c as a reference.
6 */
7
8#include <common.h>
Simon Glass691d7192020-05-10 11:40:02 -06009#include <init.h>
Simon Glass6887c5b2019-11-14 12:57:26 -070010#include <time.h>
Adrian Alonso69535742015-09-02 13:54:16 -050011#include <asm/io.h>
12#include <div64.h>
13#include <asm/arch/imx-regs.h>
14#include <asm/arch/sys_proto.h>
Stefano Babic552a8482017-06-29 10:16:06 +020015#include <asm/mach-imx/syscounter.h>
Adrian Alonso69535742015-09-02 13:54:16 -050016
17DECLARE_GLOBAL_DATA_PTR;
18
19/*
20 * This function is intended for SHORT delays only.
21 * It will overflow at around 10 seconds @ 400MHz,
22 * or 20 seconds @ 200MHz.
23 */
24unsigned long usec2ticks(unsigned long usec)
25{
26 ulong ticks;
27
28 if (usec < 1000)
29 ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
30 else
31 ticks = ((usec / 10) * (get_tbclk() / 100000));
32
33 return ticks;
34}
35
36static inline unsigned long long tick_to_time(unsigned long long tick)
37{
38 unsigned long freq;
39
40 asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
41
42 tick *= CONFIG_SYS_HZ;
43 do_div(tick, freq);
44
45 return tick;
46}
47
48static inline unsigned long long us_to_tick(unsigned long long usec)
49{
50 unsigned long freq;
51
52 asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
53
54 usec = usec * freq + 999999;
55 do_div(usec, 1000000);
56
57 return usec;
58}
59
Rui Miguel Silvabe277c32018-09-05 11:56:05 +010060#ifndef CONFIG_SKIP_LOWLEVEL_INIT
Adrian Alonso69535742015-09-02 13:54:16 -050061int timer_init(void)
62{
63 struct sctr_regs *sctr = (struct sctr_regs *)SCTR_BASE_ADDR;
64 unsigned long val, freq;
65
66 freq = CONFIG_SC_TIMER_CLK;
Yasushi SHOJI314d9f72018-03-08 13:21:10 +090067 asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
Adrian Alonso69535742015-09-02 13:54:16 -050068
69 writel(freq, &sctr->cntfid0);
70
71 /* Enable system counter */
72 val = readl(&sctr->cntcr);
73 val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1);
74 val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG;
75 writel(val, &sctr->cntcr);
76
77 gd->arch.tbl = 0;
78 gd->arch.tbu = 0;
79
80 return 0;
81}
Rui Miguel Silvabe277c32018-09-05 11:56:05 +010082#endif
Adrian Alonso69535742015-09-02 13:54:16 -050083
84unsigned long long get_ticks(void)
85{
86 unsigned long long now;
87
Yasushi SHOJI314d9f72018-03-08 13:21:10 +090088 asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (now));
Adrian Alonso69535742015-09-02 13:54:16 -050089
90 gd->arch.tbl = (unsigned long)(now & 0xffffffff);
91 gd->arch.tbu = (unsigned long)(now >> 32);
92
93 return now;
94}
95
Adrian Alonso69535742015-09-02 13:54:16 -050096ulong get_timer(ulong base)
97{
Patrick Delaunay6180ea72018-10-05 11:33:52 +020098 return tick_to_time(get_ticks()) - base;
Adrian Alonso69535742015-09-02 13:54:16 -050099}
100
101void __udelay(unsigned long usec)
102{
103 unsigned long long tmp;
104 ulong tmo;
105
106 tmo = us_to_tick(usec);
107 tmp = get_ticks() + tmo; /* get current timestamp */
108
109 while (get_ticks() < tmp) /* loop till event */
110 /*NOP*/;
111}
112
113/*
114 * This function is derived from PowerPC code (timebase clock frequency).
115 * On ARM it returns the number of timer ticks per second.
116 */
117ulong get_tbclk(void)
118{
119 unsigned long freq;
120
121 asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
122
123 return freq;
124}