• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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