1 /* 2 * Common routines supporting board initialisation. 3 * 4 * Copyright (C) 2005-2006 Ingenic Semiconductor, <jlwei@ingenic.cn> 5 * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com> 6 * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "sdram.h" 23 #include "board.h" 24 25 unsigned long get_memory_size() 26 { 27 unsigned int dmcr; 28 unsigned int rows, cols, dw, banks; 29 unsigned long size; 30 31 dmcr = REG_EMC_DMCR; 32 rows = SDRAM_ROW0 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT); 33 cols = SDRAM_COL0 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT); 34 dw = (dmcr & EMC_DMCR_BW) ? 2 : 4; 35 banks = (dmcr & EMC_DMCR_BA) ? 4 : 2; 36 37 size = (1 << (rows + cols)) * dw * banks; 38 39 return size; 40 } 41 42 /* Timer routines. */ 43 44 extern unsigned long timestamp; 45 extern unsigned long lastdec; 46 47 unsigned long get_timer_masked() 48 { 49 unsigned long now = READ_TIMER; 50 51 if (lastdec <= now) { 52 /* normal mode */ 53 timestamp += (now - lastdec); 54 } else { 55 /* we have an overflow ... */ 56 timestamp += TIMER_FDATA + now - lastdec; 57 } 58 lastdec = now; 59 60 return timestamp; 61 } 62 63 void reset_timer_masked() 64 { 65 /* reset time */ 66 lastdec = READ_TIMER; 67 timestamp = 0; 68 } 69 70 void reset_timer() 71 { 72 reset_timer_masked (); 73 } 74 75 unsigned long get_timer(unsigned long base) 76 { 77 return get_timer_masked () - base; 78 } 79 80 void set_timer(unsigned long t) 81 { 82 timestamp = t; 83 } 84 85 void udelay(unsigned long usec) 86 { 87 unsigned long tmo,tmp; 88 89 /* normalize */ 90 if (usec >= 1000) { 91 tmo = usec / 1000; 92 tmo *= TIMER_HZ; 93 tmo /= 1000; 94 } 95 else { 96 if (usec >= 1) { 97 tmo = usec * TIMER_HZ; 98 tmo /= (1000*1000); 99 } 100 else 101 tmo = 1; 102 } 103 104 /* check for rollover during this delay */ 105 tmp = get_timer (0); 106 if ((tmp + tmo) < tmp ) 107 reset_timer_masked(); /* timer would roll over */ 108 else 109 tmo += tmp; 110 111 while (get_timer_masked () < tmo); 112 } 113 114 void udelay_masked(unsigned long usec) 115 { 116 unsigned long tmo; 117 unsigned long endtime; 118 signed long diff; 119 120 /* normalize */ 121 if (usec >= 1000) { 122 tmo = usec / 1000; 123 tmo *= TIMER_HZ; 124 tmo /= 1000; 125 } else { 126 if (usec > 1) { 127 tmo = usec * TIMER_HZ; 128 tmo /= (1000*1000); 129 } else { 130 tmo = 1; 131 } 132 } 133 134 endtime = get_timer_masked () + tmo; 135 136 do { 137 unsigned long now = get_timer_masked (); 138 diff = endtime - now; 139 } while (diff >= 0); 140 } 141 142 /* 143 * This function is derived from PowerPC code (read timebase as long long). 144 * On MIPS it just returns the timer value. 145 */ 146 unsigned long long get_ticks() 147 { 148 return get_timer(0); 149 } 150 151 /* 152 * This function is derived from PowerPC code (timebase clock frequency). 153 * On MIPS it returns the number of timer ticks per second. 154 */ 155 unsigned long get_tbclk() 156 { 157 return TIMER_HZ; 158 } 159 160 /* GPIO interrupt administration. */ 161 162 void gpio_clear(u8 gpio) 163 { 164 /* Clear interrupt status. */ 165 166 __gpio_ack_irq(gpio); 167 __intc_ack_irq(GPIO_IRQ); 168 } 169 170 /* Miscellaneous interrupt administration. */ 171 172 void irq_clear() 173 { 174 u8 i; 175 176 for (i = 0; i < 32; i++) { 177 if (REG_INTC_IPR & (1 << i)) 178 __intc_ack_irq(i); 179 } 180 }