1 /* 2 * (C) Copyright 2002 3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 4 * Marius Groeger <mgroeger@sysgo.de> 5 * 6 * (C) Copyright 2002 7 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> 8 * 9 * Copyright (C) 2011 Andes Technology Corporation 10 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> 11 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> 12 * 13 * See file CREDITS for list of people who contributed to this 14 * project. 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of 19 * the License, or (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 29 * MA 02111-1307 USA 30 */ 31 32 /* CPU specific code */ 33 #include <common.h> 34 #include <command.h> 35 #include <watchdog.h> 36 #include <asm/cache.h> 37 38 #include <faraday/ftwdt010_wdt.h> 39 40 /* 41 * cleanup_before_linux() is called just before we call linux 42 * it prepares the processor for linux 43 * 44 * we disable interrupt and caches. 45 */ 46 int cleanup_before_linux(void) 47 { 48 #ifdef CONFIG_MMU 49 unsigned long i; 50 #endif 51 52 disable_interrupts(); 53 54 #ifdef CONFIG_MMU 55 /* turn off I/D-cache */ 56 icache_disable(); 57 dcache_disable(); 58 59 /* flush I/D-cache */ 60 invalidate_icac(); 61 invalidate_dcac(); 62 #endif 63 64 return 0; 65 } 66 67 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 68 { 69 disable_interrupts(); 70 71 /* 72 * reset to the base addr of andesboot. 73 * currently no ROM loader at addr 0. 74 * do not use reset_cpu(0); 75 */ 76 #ifdef CONFIG_FTWDT010_WATCHDOG 77 /* 78 * workaround: if we use CONFIG_HW_WATCHDOG with ftwdt010, will lead 79 * automatic hardware reset when booting Linux. 80 * Please do not use CONFIG_HW_WATCHDOG and WATCHDOG_RESET() here. 81 */ 82 ftwdt010_wdt_reset(); 83 while (1) 84 ; 85 #endif /* CONFIG_FTWDT010_WATCHDOG */ 86 87 /*NOTREACHED*/ 88 } 89 90 static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) 91 { 92 if (cache == ICACHE) 93 return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ 94 >> ICM_CFG_OFF_ISZ) - 1); 95 else 96 return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ 97 >> DCM_CFG_OFF_DSZ) - 1); 98 } 99 100 void dcache_flush_range(unsigned long start, unsigned long end) 101 { 102 unsigned long line_size; 103 104 line_size = CACHE_LINE_SIZE(DCACHE); 105 106 while (end > start) { 107 __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start)); 108 __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); 109 start += line_size; 110 } 111 } 112 113 void icache_inval_range(unsigned long start, unsigned long end) 114 { 115 unsigned long line_size; 116 117 line_size = CACHE_LINE_SIZE(ICACHE); 118 while (end > start) { 119 __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start)); 120 start += line_size; 121 } 122 } 123 124 void flush_cache(unsigned long addr, unsigned long size) 125 { 126 dcache_flush_range(addr , addr + size); 127 icache_inval_range(addr , addr + size); 128 } 129 130 void icache_enable(void) 131 { 132 __asm__ __volatile__ ( 133 "mfsr $p0, $mr8\n\t" 134 "ori $p0, $p0, 0x01\n\t" 135 "mtsr $p0, $mr8\n\t" 136 "isb\n\t" 137 ); 138 } 139 140 void icache_disable(void) 141 { 142 __asm__ __volatile__ ( 143 "mfsr $p0, $mr8\n\t" 144 "li $p1, ~0x01\n\t" 145 "and $p0, $p0, $p1\n\t" 146 "mtsr $p0, $mr8\n\t" 147 "isb\n\t" 148 ); 149 } 150 151 int icache_status(void) 152 { 153 int ret; 154 155 __asm__ __volatile__ ( 156 "mfsr $p0, $mr8\n\t" 157 "andi %0, $p0, 0x01\n\t" 158 : "=r" (ret) 159 : 160 : "memory" 161 ); 162 163 return ret; 164 } 165 166 void dcache_enable(void) 167 { 168 __asm__ __volatile__ ( 169 "mfsr $p0, $mr8\n\t" 170 "ori $p0, $p0, 0x02\n\t" 171 "mtsr $p0, $mr8\n\t" 172 "isb\n\t" 173 ); 174 } 175 176 void dcache_disable(void) 177 { 178 __asm__ __volatile__ ( 179 "mfsr $p0, $mr8\n\t" 180 "li $p1, ~0x02\n\t" 181 "and $p0, $p0, $p1\n\t" 182 "mtsr $p0, $mr8\n\t" 183 "isb\n\t" 184 ); 185 } 186 187 int dcache_status(void) 188 { 189 int ret; 190 191 __asm__ __volatile__ ( 192 "mfsr $p0, $mr8\n\t" 193 "andi %0, $p0, 0x02\n\t" 194 : "=r" (ret) 195 : 196 : "memory" 197 ); 198 199 return ret; 200 } 201