1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/stage2/board.c Tue Jun 09 21:10:40 2015 +0200
1.3 @@ -0,0 +1,219 @@
1.4 +/*
1.5 + * Common routines supporting board initialisation.
1.6 + *
1.7 + * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
1.8 + * Copyright (C) 2005-2006 Ingenic Semiconductor, <jlwei@ingenic.cn>
1.9 + * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com>
1.10 + * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify it under
1.13 + * the terms of the GNU General Public License as published by the Free Software
1.14 + * Foundation; either version 3 of the License, or (at your option) any later
1.15 + * version.
1.16 + *
1.17 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.19 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.20 + * details.
1.21 + *
1.22 + * You should have received a copy of the GNU General Public License along with
1.23 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.24 + */
1.25 +
1.26 +#include "sdram.h"
1.27 +#include "board.h"
1.28 +
1.29 +unsigned long get_memory_size(void)
1.30 +{
1.31 + unsigned int dmcr;
1.32 + unsigned int rows, cols, dw, banks;
1.33 + unsigned long size;
1.34 +
1.35 + dmcr = REG_EMC_DMCR;
1.36 + rows = SDRAM_ROW0 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
1.37 + cols = SDRAM_COL0 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT);
1.38 + dw = (dmcr & EMC_DMCR_BW) ? 2 : 4;
1.39 + banks = (dmcr & EMC_DMCR_BA) ? 4 : 2;
1.40 +
1.41 + size = (1 << (rows + cols)) * dw * banks;
1.42 +
1.43 + return size;
1.44 +}
1.45 +
1.46 +/* Timer routines. */
1.47 +
1.48 +extern unsigned long timestamp;
1.49 +extern unsigned long lastdec;
1.50 +
1.51 +unsigned long get_timer_masked (void)
1.52 +{
1.53 + unsigned long now = READ_TIMER;
1.54 +
1.55 + if (lastdec <= now) {
1.56 + /* normal mode */
1.57 + timestamp += (now - lastdec);
1.58 + } else {
1.59 + /* we have an overflow ... */
1.60 + timestamp += TIMER_FDATA + now - lastdec;
1.61 + }
1.62 + lastdec = now;
1.63 +
1.64 + return timestamp;
1.65 +}
1.66 +
1.67 +void reset_timer_masked (void)
1.68 +{
1.69 + /* reset time */
1.70 + lastdec = READ_TIMER;
1.71 + timestamp = 0;
1.72 +}
1.73 +
1.74 +void reset_timer(void)
1.75 +{
1.76 + reset_timer_masked ();
1.77 +}
1.78 +
1.79 +unsigned long get_timer(unsigned long base)
1.80 +{
1.81 + return get_timer_masked () - base;
1.82 +}
1.83 +
1.84 +void set_timer(unsigned long t)
1.85 +{
1.86 + timestamp = t;
1.87 +}
1.88 +
1.89 +void udelay (unsigned long usec)
1.90 +{
1.91 + unsigned long tmo,tmp;
1.92 +
1.93 + /* normalize */
1.94 + if (usec >= 1000) {
1.95 + tmo = usec / 1000;
1.96 + tmo *= TIMER_HZ;
1.97 + tmo /= 1000;
1.98 + }
1.99 + else {
1.100 + if (usec >= 1) {
1.101 + tmo = usec * TIMER_HZ;
1.102 + tmo /= (1000*1000);
1.103 + }
1.104 + else
1.105 + tmo = 1;
1.106 + }
1.107 +
1.108 + /* check for rollover during this delay */
1.109 + tmp = get_timer (0);
1.110 + if ((tmp + tmo) < tmp )
1.111 + reset_timer_masked(); /* timer would roll over */
1.112 + else
1.113 + tmo += tmp;
1.114 +
1.115 + while (get_timer_masked () < tmo);
1.116 +}
1.117 +
1.118 +void udelay_masked (unsigned long usec)
1.119 +{
1.120 + unsigned long tmo;
1.121 + unsigned long endtime;
1.122 + signed long diff;
1.123 +
1.124 + /* normalize */
1.125 + if (usec >= 1000) {
1.126 + tmo = usec / 1000;
1.127 + tmo *= TIMER_HZ;
1.128 + tmo /= 1000;
1.129 + } else {
1.130 + if (usec > 1) {
1.131 + tmo = usec * TIMER_HZ;
1.132 + tmo /= (1000*1000);
1.133 + } else {
1.134 + tmo = 1;
1.135 + }
1.136 + }
1.137 +
1.138 + endtime = get_timer_masked () + tmo;
1.139 +
1.140 + do {
1.141 + unsigned long now = get_timer_masked ();
1.142 + diff = endtime - now;
1.143 + } while (diff >= 0);
1.144 +}
1.145 +
1.146 +/*
1.147 + * This function is derived from PowerPC code (read timebase as long long).
1.148 + * On MIPS it just returns the timer value.
1.149 + */
1.150 +unsigned long long get_ticks(void)
1.151 +{
1.152 + return get_timer(0);
1.153 +}
1.154 +
1.155 +/*
1.156 + * This function is derived from PowerPC code (timebase clock frequency).
1.157 + * On MIPS it returns the number of timer ticks per second.
1.158 + */
1.159 +unsigned long get_tbclk (void)
1.160 +{
1.161 + return TIMER_HZ;
1.162 +}
1.163 +
1.164 +/* CPU-specific routines from U-Boot.
1.165 + See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c
1.166 + See: u-boot/arch/mips/include/asm/cacheops.h
1.167 +*/
1.168 +
1.169 +#define Index_Store_Tag_I 0x08
1.170 +#define Index_Writeback_Inv_D 0x15
1.171 +
1.172 +void flush_icache_all(void)
1.173 +{
1.174 + u32 addr, t = 0;
1.175 +
1.176 + asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
1.177 + asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
1.178 +
1.179 + for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE;
1.180 + addr += CONFIG_SYS_CACHELINE_SIZE) {
1.181 + asm volatile (
1.182 + ".set mips3\n\t"
1.183 + " cache %0, 0(%1)\n\t"
1.184 + ".set mips2\n\t"
1.185 + :
1.186 + : "I" (Index_Store_Tag_I), "r"(addr));
1.187 + }
1.188 +
1.189 + /* invalicate btb */
1.190 + asm volatile (
1.191 + ".set mips32\n\t"
1.192 + "mfc0 %0, $16, 7\n\t"
1.193 + "nop\n\t"
1.194 + "ori %0,2\n\t"
1.195 + "mtc0 %0, $16, 7\n\t"
1.196 + ".set mips2\n\t"
1.197 + :
1.198 + : "r" (t));
1.199 +}
1.200 +
1.201 +void flush_dcache_all(void)
1.202 +{
1.203 + u32 addr;
1.204 +
1.205 + for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE;
1.206 + addr += CONFIG_SYS_CACHELINE_SIZE) {
1.207 + asm volatile (
1.208 + ".set mips3\n\t"
1.209 + " cache %0, 0(%1)\n\t"
1.210 + ".set mips2\n\t"
1.211 + :
1.212 + : "I" (Index_Writeback_Inv_D), "r"(addr));
1.213 + }
1.214 +
1.215 + asm volatile ("sync");
1.216 +}
1.217 +
1.218 +void flush_cache_all(void)
1.219 +{
1.220 + flush_dcache_all();
1.221 + flush_icache_all();
1.222 +}