46b7b46659c3243aff573db9ec2da4b9eabb8b81
[oweals/u-boot.git] / arch / arm / mach-lpc32xx / timer.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com>
4  */
5
6 #include <common.h>
7 #include <init.h>
8 #include <time.h>
9 #include <asm/arch/cpu.h>
10 #include <asm/arch/clk.h>
11 #include <asm/arch/timer.h>
12 #include <asm/io.h>
13
14 static struct timer_regs  *timer0 = (struct timer_regs *)TIMER0_BASE;
15 static struct timer_regs  *timer1 = (struct timer_regs *)TIMER1_BASE;
16 static struct clk_pm_regs *clk    = (struct clk_pm_regs *)CLK_PM_BASE;
17
18 static void lpc32xx_timer_clock(u32 bit, int enable)
19 {
20         if (enable)
21                 setbits_le32(&clk->timclk_ctrl1, bit);
22         else
23                 clrbits_le32(&clk->timclk_ctrl1, bit);
24 }
25
26 static void lpc32xx_timer_reset(struct timer_regs *timer, u32 freq)
27 {
28         writel(TIMER_TCR_COUNTER_RESET,   &timer->tcr);
29         writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr);
30         writel(0, &timer->tc);
31         writel(0, &timer->pr);
32
33         /* Count mode is every rising PCLK edge */
34         writel(TIMER_CTCR_MODE_TIMER, &timer->ctcr);
35
36         /* Set prescale counter value */
37         writel((get_periph_clk_rate() / freq) - 1, &timer->pr);
38
39         /* Ensure that the counter is not reset when matching TC */
40         writel(0,  &timer->mcr);
41 }
42
43 static void lpc32xx_timer_count(struct timer_regs *timer, int enable)
44 {
45         if (enable)
46                 writel(TIMER_TCR_COUNTER_ENABLE,  &timer->tcr);
47         else
48                 writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr);
49 }
50
51 int timer_init(void)
52 {
53         lpc32xx_timer_clock(CLK_TIMCLK_TIMER0, 1);
54         lpc32xx_timer_reset(timer0, CONFIG_SYS_HZ);
55         lpc32xx_timer_count(timer0, 1);
56
57         return 0;
58 }
59
60 ulong get_timer(ulong base)
61 {
62         return readl(&timer0->tc) - base;
63 }
64
65 void __udelay(unsigned long usec)
66 {
67         lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 1);
68         lpc32xx_timer_reset(timer1, CONFIG_SYS_HZ * 1000);
69         lpc32xx_timer_count(timer1, 1);
70
71         while (readl(&timer1->tc) < usec)
72                 /* NOP */;
73
74         lpc32xx_timer_count(timer1, 0);
75         lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 0);
76 }
77
78 unsigned long long get_ticks(void)
79 {
80         return get_timer(0);
81 }
82
83 ulong get_tbclk(void)
84 {
85         return CONFIG_SYS_HZ;
86 }