1 /*
2 * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
3 * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of ARM nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific
17 * prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <console.h>
33 #include <debug.h>
34 #include <errno.h>
35 #include <hi6220.h>
36 #include <mmio.h>
37 #include <sp804_timer.h>
38
39 /* Init dual timer0 (TIMER00 & TIMER01) */
hi6220_timer_init(void)40 void hi6220_timer_init(void)
41 {
42 unsigned int data;
43
44 /* select 32KHz as the clock of dual timer0 */
45 /* FIXME: But I find that it's 19.2MHz, not 32KHz. */
46 data = mmio_read_32(AO_SC_TIMER_EN0);
47 while (data & 3) {
48 data &= ~3;
49 data |= 3 << 16;
50 mmio_write_32(AO_SC_TIMER_EN0, data);
51 data = mmio_read_32(AO_SC_TIMER_EN0);
52 }
53 /* enable the pclk of dual timer0 */
54 data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
55 while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
56 mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
57 data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
58 }
59 /* reset dual timer0 */
60 data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
61 mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
62 do {
63 data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
64 } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
65 /* unreset dual timer0 */
66 mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
67 do {
68 data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
69 } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
70
71 /* disable timer00 */
72 mmio_write_32(TIMER00_CONTROL, 0);
73 mmio_write_32(TIMER00_LOAD, 0xffffffff);
74 /* free running */
75 mmio_write_32(TIMER00_CONTROL, 0x82);
76 }
77
get_timer_value(void)78 static unsigned int get_timer_value(void)
79 {
80 return mmio_read_32(TIMER00_VALUE);
81 }
82
udelay(int us)83 void udelay(int us)
84 {
85 unsigned int start, cnt, delta, delta_us;
86
87 if (us <= 0)
88 us = 1;
89 /* counter is decreasing */
90 start = get_timer_value();
91 do {
92 cnt = get_timer_value();
93 if (cnt > start) {
94 delta = 0xffffffff - cnt;
95 delta += start;
96 } else
97 delta = start - cnt;
98 delta_us = (delta * 10) / 192;
99 } while (delta_us < us);
100 }
101
mdelay(int ms)102 void mdelay(int ms)
103 {
104 unsigned int start, cnt, delta, delta_ms;
105
106 if (ms <= 0)
107 ms = 1;
108
109 /* counter is decreasing */
110 start = get_timer_value();
111 do {
112 cnt = get_timer_value();
113 if (cnt > start) {
114 delta = 0xffffffff - cnt;
115 delta += start;
116 } else
117 delta = start - cnt;
118 delta_ms = delta / 19200;
119 } while (delta_ms < ms);
120 }
121