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) */ 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 78 static unsigned int get_timer_value(void) 79 { 80 return mmio_read_32(TIMER00_VALUE); 81 } 82 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 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