1 /* 2 * Common routines supporting board initialisation. 3 * 4 * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, <wd@denx.de> 5 * Copyright (C) 2005-2006 Ingenic Semiconductor, <jlwei@ingenic.cn> 6 * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com> 7 * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify it under 10 * the terms of the GNU General Public License as published by the Free Software 11 * Foundation; either version 3 of the License, or (at your option) any later 12 * version. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "sdram.h" 24 #include "board.h" 25 26 unsigned long get_memory_size(void) 27 { 28 unsigned int dmcr; 29 unsigned int rows, cols, dw, banks; 30 unsigned long size; 31 32 dmcr = REG_EMC_DMCR; 33 rows = SDRAM_ROW0 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT); 34 cols = SDRAM_COL0 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT); 35 dw = (dmcr & EMC_DMCR_BW) ? 2 : 4; 36 banks = (dmcr & EMC_DMCR_BA) ? 4 : 2; 37 38 size = (1 << (rows + cols)) * dw * banks; 39 40 return size; 41 } 42 43 /* Timer routines. */ 44 45 extern unsigned long timestamp; 46 extern unsigned long lastdec; 47 48 unsigned long get_timer_masked (void) 49 { 50 unsigned long now = READ_TIMER; 51 52 if (lastdec <= now) { 53 /* normal mode */ 54 timestamp += (now - lastdec); 55 } else { 56 /* we have an overflow ... */ 57 timestamp += TIMER_FDATA + now - lastdec; 58 } 59 lastdec = now; 60 61 return timestamp; 62 } 63 64 void reset_timer_masked (void) 65 { 66 /* reset time */ 67 lastdec = READ_TIMER; 68 timestamp = 0; 69 } 70 71 void reset_timer(void) 72 { 73 reset_timer_masked (); 74 } 75 76 unsigned long get_timer(unsigned long base) 77 { 78 return get_timer_masked () - base; 79 } 80 81 void set_timer(unsigned long t) 82 { 83 timestamp = t; 84 } 85 86 void udelay (unsigned long usec) 87 { 88 unsigned long tmo,tmp; 89 90 /* normalize */ 91 if (usec >= 1000) { 92 tmo = usec / 1000; 93 tmo *= TIMER_HZ; 94 tmo /= 1000; 95 } 96 else { 97 if (usec >= 1) { 98 tmo = usec * TIMER_HZ; 99 tmo /= (1000*1000); 100 } 101 else 102 tmo = 1; 103 } 104 105 /* check for rollover during this delay */ 106 tmp = get_timer (0); 107 if ((tmp + tmo) < tmp ) 108 reset_timer_masked(); /* timer would roll over */ 109 else 110 tmo += tmp; 111 112 while (get_timer_masked () < tmo); 113 } 114 115 void udelay_masked (unsigned long usec) 116 { 117 unsigned long tmo; 118 unsigned long endtime; 119 signed long diff; 120 121 /* normalize */ 122 if (usec >= 1000) { 123 tmo = usec / 1000; 124 tmo *= TIMER_HZ; 125 tmo /= 1000; 126 } else { 127 if (usec > 1) { 128 tmo = usec * TIMER_HZ; 129 tmo /= (1000*1000); 130 } else { 131 tmo = 1; 132 } 133 } 134 135 endtime = get_timer_masked () + tmo; 136 137 do { 138 unsigned long now = get_timer_masked (); 139 diff = endtime - now; 140 } while (diff >= 0); 141 } 142 143 /* 144 * This function is derived from PowerPC code (read timebase as long long). 145 * On MIPS it just returns the timer value. 146 */ 147 unsigned long long get_ticks(void) 148 { 149 return get_timer(0); 150 } 151 152 /* 153 * This function is derived from PowerPC code (timebase clock frequency). 154 * On MIPS it returns the number of timer ticks per second. 155 */ 156 unsigned long get_tbclk (void) 157 { 158 return TIMER_HZ; 159 } 160 161 /* CPU-specific routines from U-Boot. 162 See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c 163 See: u-boot/arch/mips/include/asm/cacheops.h 164 */ 165 166 #define Index_Store_Tag_I 0x08 167 #define Index_Writeback_Inv_D 0x15 168 169 void flush_icache_all(void) 170 { 171 u32 addr, t = 0; 172 173 asm volatile ("mtc0 $0, $28"); /* Clear Taglo */ 174 asm volatile ("mtc0 $0, $29"); /* Clear TagHi */ 175 176 for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE; 177 addr += CONFIG_SYS_CACHELINE_SIZE) { 178 asm volatile ( 179 ".set mips3\n\t" 180 " cache %0, 0(%1)\n\t" 181 ".set mips2\n\t" 182 : 183 : "I" (Index_Store_Tag_I), "r"(addr)); 184 } 185 186 /* invalicate btb */ 187 asm volatile ( 188 ".set mips32\n\t" 189 "mfc0 %0, $16, 7\n\t" 190 "nop\n\t" 191 "ori %0,2\n\t" 192 "mtc0 %0, $16, 7\n\t" 193 ".set mips2\n\t" 194 : 195 : "r" (t)); 196 } 197 198 void flush_dcache_all(void) 199 { 200 u32 addr; 201 202 for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; 203 addr += CONFIG_SYS_CACHELINE_SIZE) { 204 asm volatile ( 205 ".set mips3\n\t" 206 " cache %0, 0(%1)\n\t" 207 ".set mips2\n\t" 208 : 209 : "I" (Index_Writeback_Inv_D), "r"(addr)); 210 } 211 212 asm volatile ("sync"); 213 } 214 215 void flush_cache_all(void) 216 { 217 flush_dcache_all(); 218 flush_icache_all(); 219 }