NanoPayload

Annotated board-nanonote.c

14:cf7f6d0ea74f
2015-06-07 Paul Boddie Tidied up and added a memory size measurement function from U-Boot.
paul@0 1
/*
paul@0 2
 * Ben NanoNote board initialisation, based on uboot-xburst and xburst-tools.
paul@0 3
 *
paul@0 4
 * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
paul@0 5
 * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com>
paul@9 6
 * Copyright (C) 2006 Ingenic Semiconductor, <jlwei@ingenic.cn>
paul@14 7
 * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
paul@0 8
 *
paul@0 9
 * This program is free software; you can redistribute it and/or modify it under
paul@0 10
 * the terms of the GNU General Public License as published by the Free Software
paul@0 11
 * Foundation; either version 3 of the License, or (at your option) any later
paul@0 12
 * version.
paul@0 13
 *
paul@0 14
 * This program is distributed in the hope that it will be useful, but WITHOUT
paul@0 15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@0 16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@0 17
 * details.
paul@0 18
 *
paul@0 19
 * You should have received a copy of the GNU General Public License along with
paul@0 20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
paul@0 21
 */
paul@0 22
paul@0 23
#include "jz4740.h"
paul@0 24
#include "configs.h"
paul@2 25
#include "nanonote.h"
paul@10 26
#include "usb_boot_defines.h"
paul@10 27
paul@10 28
/* These arguments are initialised by usbboot and are defined in...
paul@10 29
   /etc/xburst-tools/usbboot.cfg. */
paul@10 30
paul@10 31
struct fw_args *fw_args;
paul@10 32
volatile u32 CPU_ID;
paul@10 33
volatile u32 UART_BASE;
paul@10 34
volatile u32 CONFIG_BAUDRATE;
paul@10 35
volatile u8 SDRAM_BW16;
paul@10 36
volatile u8 SDRAM_BANK4;
paul@10 37
volatile u8 SDRAM_ROW;
paul@10 38
volatile u8 SDRAM_COL;
paul@10 39
volatile u8 CONFIG_MOBILE_SDRAM;
paul@10 40
volatile u32 CFG_CPU_SPEED;
paul@10 41
volatile u32 CFG_EXTAL;
paul@10 42
volatile u8 PHM_DIV;
paul@10 43
volatile u8 IS_SHARE;
paul@10 44
paul@10 45
void load_args(void)
paul@10 46
{
paul@10 47
	/* Get the fw args from memory. See head.S for the memory layout. */
paul@10 48
paul@10 49
        fw_args = (struct fw_args *)0x80002008;
paul@10 50
        CPU_ID = fw_args->cpu_id ;
paul@10 51
        CFG_EXTAL = (u32)fw_args->ext_clk * 1000000;
paul@10 52
        CFG_CPU_SPEED = (u32)fw_args->cpu_speed * CFG_EXTAL ;
paul@10 53
        if (CFG_EXTAL == 19000000) {
paul@10 54
                CFG_EXTAL = 19200000;
paul@10 55
                CFG_CPU_SPEED = 192000000;
paul@10 56
        }
paul@10 57
        PHM_DIV = fw_args->phm_div;
paul@10 58
        UART_BASE = UART0_BASE + fw_args->use_uart * 0x1000;
paul@10 59
        CONFIG_BAUDRATE = fw_args->boudrate;
paul@10 60
        SDRAM_BW16 = fw_args->bus_width;
paul@10 61
        SDRAM_BANK4 = fw_args->bank_num;
paul@10 62
        SDRAM_ROW = fw_args->row_addr;
paul@10 63
        SDRAM_COL = fw_args->col_addr;
paul@10 64
        CONFIG_MOBILE_SDRAM = fw_args->is_mobile;
paul@10 65
        IS_SHARE = fw_args->is_busshare;
paul@10 66
}
paul@10 67
paul@10 68
/* Initialisation functions. */
paul@0 69
paul@0 70
void gpio_init(void)
paul@0 71
{
paul@0 72
	/*
paul@0 73
	 * Initialize NAND Flash Pins
paul@0 74
	 */
paul@0 75
	__gpio_as_nand();
paul@0 76
paul@0 77
	/*
paul@0 78
	 * Initialize SDRAM pins
paul@0 79
	 */
paul@0 80
	__gpio_as_sdram_32bit();
paul@6 81
}
paul@0 82
paul@6 83
void gpio_init2(void)
paul@6 84
{
paul@0 85
	/*
paul@0 86
	 * Initialize LCD pins
paul@0 87
	 */
paul@2 88
	__gpio_as_slcd_8bit();
paul@0 89
paul@0 90
	/*
paul@0 91
	 * Initialize MSC pins
paul@0 92
	 */
paul@0 93
	__gpio_as_msc();
paul@0 94
paul@0 95
	/*
paul@0 96
	 * Initialize Other pins
paul@0 97
	 */
paul@0 98
	unsigned int i;
paul@0 99
	for (i = 0; i < 7; i++){
paul@0 100
		__gpio_as_input(GPIO_KEYIN_BASE + i);
paul@0 101
		__gpio_enable_pull(GPIO_KEYIN_BASE + i);
paul@0 102
	}
paul@0 103
paul@0 104
	for (i = 0; i < 8; i++) {
paul@0 105
		__gpio_as_output(GPIO_KEYOUT_BASE + i);
paul@0 106
		__gpio_clear_pin(GPIO_KEYOUT_BASE + i);
paul@0 107
	}
paul@0 108
paul@0 109
	/* enable the TP4, TP5 as UART0 */
paul@0 110
	__gpio_jtag_to_uart0();
paul@0 111
paul@0 112
	__gpio_as_input(GPIO_KEYIN_8);
paul@0 113
	__gpio_enable_pull(GPIO_KEYIN_8);
paul@0 114
paul@0 115
	__gpio_as_output(GPIO_AUDIO_POP);
paul@0 116
	__gpio_set_pin(GPIO_AUDIO_POP);
paul@0 117
paul@0 118
	__gpio_as_output(GPIO_LCD_CS);
paul@0 119
	__gpio_clear_pin(GPIO_LCD_CS);
paul@0 120
paul@0 121
	__gpio_as_output(GPIO_AMP_EN);
paul@0 122
	__gpio_clear_pin(GPIO_AMP_EN);
paul@0 123
paul@0 124
	__gpio_as_output(GPIO_SDPW_EN);
paul@0 125
	__gpio_disable_pull(GPIO_SDPW_EN);
paul@0 126
	__gpio_clear_pin(GPIO_SDPW_EN);
paul@0 127
paul@0 128
	__gpio_as_input(GPIO_SD_DETECT);
paul@0 129
	__gpio_disable_pull(GPIO_SD_DETECT);
paul@0 130
paul@0 131
	__gpio_as_input(GPIO_USB_DETECT);
paul@0 132
	__gpio_enable_pull(GPIO_USB_DETECT);
paul@0 133
}
paul@0 134
paul@0 135
void cpm_init(void)
paul@0 136
{
paul@0 137
	__cpm_stop_ipu();
paul@0 138
	__cpm_stop_cim();
paul@0 139
	__cpm_stop_i2c();
paul@0 140
	__cpm_stop_ssi();
paul@0 141
	__cpm_stop_uart1();
paul@0 142
	__cpm_stop_sadc();
paul@0 143
	__cpm_stop_uhc();
paul@0 144
	__cpm_stop_udc();
paul@0 145
	__cpm_stop_aic1();
paul@0 146
/*	__cpm_stop_aic2();*/
paul@0 147
}
paul@0 148
paul@0 149
void pll_init(void)
paul@0 150
{
paul@0 151
	register unsigned int cfcr, plcr1;
paul@0 152
	int n2FR[33] = {
paul@0 153
		0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
paul@0 154
		7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
paul@0 155
		9
paul@0 156
	};
paul@0 157
	int nf, pllout2;
paul@0 158
paul@0 159
	cfcr = CPM_CPCCR_CLKOEN |
paul@0 160
		(n2FR[PHM_DIV] << CPM_CPCCR_CDIV_BIT) |
paul@0 161
		(n2FR[PHM_DIV] << CPM_CPCCR_HDIV_BIT) |
paul@0 162
		(n2FR[PHM_DIV] << CPM_CPCCR_PDIV_BIT) |
paul@0 163
		(n2FR[PHM_DIV] << CPM_CPCCR_MDIV_BIT) |
paul@0 164
		(n2FR[PHM_DIV] << CPM_CPCCR_LDIV_BIT);
paul@0 165
paul@0 166
	pllout2 = (cfcr & CPM_CPCCR_PCS) ? CFG_CPU_SPEED : (CFG_CPU_SPEED / 2);
paul@0 167
paul@0 168
	/* Init USB Host clock, pllout2 must be n*48MHz */
paul@0 169
	REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
paul@0 170
paul@0 171
	nf = CFG_CPU_SPEED * 2 / CFG_EXTAL;
paul@0 172
	plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
paul@0 173
		(0 << CPM_CPPCR_PLLN_BIT) |	/* RD=0, NR=2 */
paul@0 174
		(0 << CPM_CPPCR_PLLOD_BIT) |    /* OD=0, NO=1 */
paul@0 175
		(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
paul@0 176
		CPM_CPPCR_PLLEN;                /* enable PLL */
paul@0 177
paul@0 178
	/* init PLL */
paul@0 179
	REG_CPM_CPCCR = cfcr;
paul@0 180
	REG_CPM_CPPCR = plcr1;
paul@0 181
}
paul@0 182
paul@0 183
void sdram_init(void)
paul@0 184
{
paul@0 185
	register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
paul@0 186
paul@0 187
	unsigned int cas_latency_sdmr[2] = {
paul@0 188
		EMC_SDMR_CAS_2,
paul@0 189
		EMC_SDMR_CAS_3,
paul@0 190
	};
paul@0 191
paul@0 192
	unsigned int cas_latency_dmcr[2] = {
paul@0 193
		1 << EMC_DMCR_TCL_BIT,	/* CAS latency is 2 */
paul@0 194
		2 << EMC_DMCR_TCL_BIT	/* CAS latency is 3 */
paul@0 195
	};
paul@0 196
paul@0 197
	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
paul@0 198
paul@0 199
	cpu_clk = CFG_CPU_SPEED;
paul@0 200
	mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
paul@0 201
paul@0 202
	REG_EMC_BCR = 0;	/* Disable bus release */
paul@0 203
	REG_EMC_RTCSR = 0;	/* Disable clock for counting */
paul@0 204
paul@0 205
	/* Fault DMCR value for mode register setting*/
paul@0 206
#define SDRAM_ROW0    11
paul@0 207
#define SDRAM_COL0     8
paul@0 208
#define SDRAM_BANK40   0
paul@0 209
paul@0 210
	dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
paul@0 211
		((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
paul@0 212
		(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
paul@0 213
		(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
paul@0 214
		EMC_DMCR_EPIN |
paul@0 215
		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
paul@0 216
paul@0 217
	/* Basic DMCR value */
paul@0 218
	dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
paul@0 219
		((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
paul@0 220
		(SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
paul@0 221
		(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
paul@0 222
		EMC_DMCR_EPIN |
paul@0 223
		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
paul@0 224
paul@0 225
	/* SDRAM timimg */
paul@0 226
	ns = 1000000000 / mem_clk;
paul@0 227
	tmp = SDRAM_TRAS/ns;
paul@0 228
	if (tmp < 4) tmp = 4;
paul@0 229
	if (tmp > 11) tmp = 11;
paul@0 230
	dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
paul@0 231
	tmp = SDRAM_RCD/ns;
paul@0 232
	if (tmp > 3) tmp = 3;
paul@0 233
	dmcr |= (tmp << EMC_DMCR_RCD_BIT);
paul@0 234
	tmp = SDRAM_TPC/ns;
paul@0 235
	if (tmp > 7) tmp = 7;
paul@0 236
	dmcr |= (tmp << EMC_DMCR_TPC_BIT);
paul@0 237
	tmp = SDRAM_TRWL/ns;
paul@0 238
	if (tmp > 3) tmp = 3;
paul@0 239
	dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
paul@0 240
	tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
paul@0 241
	if (tmp > 14) tmp = 14;
paul@0 242
	dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
paul@0 243
paul@0 244
	/* SDRAM mode value */
paul@0 245
	sdmode = EMC_SDMR_BT_SEQ | 
paul@0 246
		 EMC_SDMR_OM_NORMAL |
paul@0 247
		 EMC_SDMR_BL_4 | 
paul@0 248
		 cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
paul@0 249
paul@0 250
	/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
paul@0 251
	REG_EMC_DMCR = dmcr;
paul@0 252
	REG8(EMC_SDMR0|sdmode) = 0;
paul@0 253
paul@0 254
	/* Wait for precharge, > 200us */
paul@0 255
	tmp = (cpu_clk / 1000000) * 1000;
paul@0 256
	while (tmp--);
paul@0 257
paul@0 258
	/* Stage 2. Enable auto-refresh */
paul@0 259
	REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
paul@0 260
paul@0 261
	tmp = SDRAM_TREF/ns;
paul@0 262
	tmp = tmp/64 + 1;
paul@0 263
	if (tmp > 0xff) tmp = 0xff;
paul@0 264
	REG_EMC_RTCOR = tmp;
paul@0 265
	REG_EMC_RTCNT = 0;
paul@0 266
	REG_EMC_RTCSR = EMC_RTCSR_CKS_64;	/* Divisor is 64, CKO/64 */
paul@0 267
paul@0 268
	/* Wait for number of auto-refresh cycles */
paul@0 269
	tmp = (cpu_clk / 1000000) * 1000;
paul@0 270
	while (tmp--);
paul@0 271
paul@0 272
 	/* Stage 3. Mode Register Set */
paul@0 273
	REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
paul@0 274
	REG8(EMC_SDMR0|sdmode) = 0;
paul@0 275
paul@0 276
        /* Set back to basic DMCR value */
paul@0 277
	REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
paul@0 278
paul@0 279
	/* everything is ok now */
paul@0 280
}
paul@9 281
paul@9 282
void rtc_init(void)
paul@9 283
{
paul@14 284
	while ( !__rtc_write_ready());
paul@9 285
	__rtc_enable_alarm();	/* enable alarm */
paul@9 286
paul@14 287
	while ( !__rtc_write_ready());
paul@9 288
	REG_RTC_RGR   = 0x00007fff; /* type value */
paul@9 289
paul@14 290
	while ( !__rtc_write_ready());
paul@9 291
	REG_RTC_HWFCR = 0x0000ffe0; /* Power on delay 2s */
paul@9 292
paul@14 293
	while ( !__rtc_write_ready());
paul@9 294
	REG_RTC_HRCR  = 0x00000fe0; /* reset delay 125ms */
paul@9 295
}
paul@9 296
paul@14 297
unsigned long get_memory_size(void)
paul@14 298
{
paul@14 299
	unsigned int dmcr;
paul@14 300
	unsigned int rows, cols, dw, banks;
paul@14 301
	unsigned long size;
paul@14 302
paul@14 303
	dmcr = REG_EMC_DMCR;
paul@14 304
	rows = 11 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
paul@14 305
	cols = 8 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT);
paul@14 306
	dw = (dmcr & EMC_DMCR_BW) ? 2 : 4;
paul@14 307
	banks = (dmcr & EMC_DMCR_BA) ? 4 : 2;
paul@14 308
paul@14 309
	size = (1 << (rows + cols)) * dw * banks;
paul@14 310
paul@14 311
	return size;
paul@14 312
}
paul@14 313
paul@14 314
/* Timer routines. */
paul@9 315
paul@9 316
#define TIMER_CHAN  0
paul@9 317
#define TIMER_FDATA 0xffff  /* Timer full data value */
paul@9 318
#define TIMER_HZ    CONFIG_SYS_HZ
paul@9 319
paul@9 320
#define READ_TIMER  REG_TCU_TCNT(TIMER_CHAN)  /* macro to read the 16 bit timer */
paul@9 321
paul@9 322
static unsigned long timestamp;
paul@9 323
static unsigned long lastdec;
paul@9 324
paul@9 325
void reset_timer_masked(void);
paul@9 326
unsigned long get_timer_masked(void);
paul@9 327
void udelay_masked(unsigned long usec);
paul@9 328
paul@9 329
/*
paul@9 330
 * timer without interrupts
paul@9 331
 */
paul@9 332
paul@9 333
int timer_init(void)
paul@9 334
{
paul@9 335
	REG_TCU_TCSR(TIMER_CHAN) = TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN;
paul@9 336
	REG_TCU_TCNT(TIMER_CHAN) = 0;
paul@9 337
	REG_TCU_TDHR(TIMER_CHAN) = 0;
paul@9 338
	REG_TCU_TDFR(TIMER_CHAN) = TIMER_FDATA;
paul@9 339
paul@9 340
	REG_TCU_TMSR = (1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)); /* mask irqs */
paul@9 341
	REG_TCU_TSCR = (1 << TIMER_CHAN); /* enable timer clock */
paul@9 342
	REG_TCU_TESR = (1 << TIMER_CHAN); /* start counting up */
paul@9 343
paul@9 344
	lastdec = 0;
paul@9 345
	timestamp = 0;
paul@9 346
paul@9 347
	return 0;
paul@9 348
}
paul@9 349
paul@9 350
void reset_timer(void)
paul@9 351
{
paul@9 352
	reset_timer_masked ();
paul@9 353
}
paul@9 354
paul@9 355
unsigned long get_timer(unsigned long base)
paul@9 356
{
paul@9 357
	return get_timer_masked () - base;
paul@9 358
}
paul@9 359
paul@9 360
void set_timer(unsigned long t)
paul@9 361
{
paul@9 362
	timestamp = t;
paul@9 363
}
paul@9 364
paul@9 365
void udelay (unsigned long usec)
paul@9 366
{
paul@9 367
	unsigned long tmo,tmp;
paul@9 368
paul@9 369
	/* normalize */
paul@9 370
	if (usec >= 1000) {
paul@9 371
		tmo = usec / 1000;
paul@9 372
		tmo *= TIMER_HZ;
paul@9 373
		tmo /= 1000;
paul@9 374
	}
paul@9 375
	else {
paul@9 376
		if (usec >= 1) {
paul@9 377
			tmo = usec * TIMER_HZ;
paul@9 378
			tmo /= (1000*1000);
paul@9 379
		}
paul@9 380
		else
paul@9 381
			tmo = 1;
paul@9 382
	}
paul@9 383
paul@9 384
	/* check for rollover during this delay */
paul@9 385
	tmp = get_timer (0);
paul@9 386
	if ((tmp + tmo) < tmp )
paul@9 387
		reset_timer_masked();  /* timer would roll over */
paul@9 388
	else
paul@9 389
		tmo += tmp;
paul@9 390
paul@9 391
	while (get_timer_masked () < tmo);
paul@9 392
}
paul@9 393
paul@9 394
void reset_timer_masked (void)
paul@9 395
{
paul@9 396
	/* reset time */
paul@9 397
	lastdec = READ_TIMER;
paul@9 398
	timestamp = 0;
paul@9 399
}
paul@9 400
paul@9 401
unsigned long get_timer_masked (void)
paul@9 402
{
paul@9 403
	unsigned long now = READ_TIMER;
paul@9 404
paul@9 405
	if (lastdec <= now) {
paul@9 406
		/* normal mode */
paul@9 407
		timestamp += (now - lastdec);
paul@9 408
	} else {
paul@9 409
		/* we have an overflow ... */
paul@9 410
		timestamp += TIMER_FDATA + now - lastdec;
paul@9 411
	}
paul@9 412
	lastdec = now;
paul@9 413
paul@9 414
	return timestamp;
paul@9 415
}
paul@9 416
paul@9 417
void udelay_masked (unsigned long usec)
paul@9 418
{
paul@9 419
	unsigned long tmo;
paul@9 420
	unsigned long endtime;
paul@9 421
	signed long diff;
paul@9 422
paul@9 423
	/* normalize */
paul@9 424
	if (usec >= 1000) {
paul@9 425
		tmo = usec / 1000;
paul@9 426
		tmo *= TIMER_HZ;
paul@9 427
		tmo /= 1000;
paul@9 428
	} else {
paul@9 429
		if (usec > 1) {
paul@9 430
			tmo = usec * TIMER_HZ;
paul@9 431
			tmo /= (1000*1000);
paul@9 432
		} else {
paul@9 433
			tmo = 1;
paul@9 434
		}
paul@9 435
	}
paul@9 436
paul@9 437
	endtime = get_timer_masked () + tmo;
paul@9 438
paul@9 439
	do {
paul@9 440
		unsigned long now = get_timer_masked ();
paul@9 441
		diff = endtime - now;
paul@9 442
	} while (diff >= 0);
paul@9 443
}
paul@9 444
paul@9 445
/*
paul@9 446
 * This function is derived from PowerPC code (read timebase as long long).
paul@9 447
 * On MIPS it just returns the timer value.
paul@9 448
 */
paul@9 449
unsigned long long get_ticks(void)
paul@9 450
{
paul@9 451
	return get_timer(0);
paul@9 452
}
paul@9 453
paul@9 454
/*
paul@9 455
 * This function is derived from PowerPC code (timebase clock frequency).
paul@9 456
 * On MIPS it returns the number of timer ticks per second.
paul@9 457
 */
paul@9 458
unsigned long get_tbclk (void)
paul@9 459
{
paul@9 460
	return TIMER_HZ;
paul@9 461
}
paul@9 462
paul@9 463
/* CPU-specific routines from U-Boot.
paul@9 464
   See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c
paul@9 465
   See: u-boot/arch/mips/include/asm/cacheops.h
paul@9 466
*/
paul@9 467
paul@9 468
#define Index_Store_Tag_I	0x08
paul@9 469
#define Index_Writeback_Inv_D	0x15
paul@9 470
paul@9 471
void flush_icache_all(void)
paul@9 472
{
paul@9 473
	u32 addr, t = 0;
paul@9 474
paul@9 475
	asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
paul@9 476
	asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
paul@9 477
paul@9 478
	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE;
paul@9 479
	     addr += CONFIG_SYS_CACHELINE_SIZE) {
paul@9 480
		asm volatile (
paul@9 481
			".set mips3\n\t"
paul@9 482
			" cache %0, 0(%1)\n\t"
paul@9 483
			".set mips2\n\t"
paul@9 484
			:
paul@9 485
			: "I" (Index_Store_Tag_I), "r"(addr));
paul@9 486
	}
paul@9 487
paul@9 488
	/* invalicate btb */
paul@9 489
	asm volatile (
paul@9 490
		".set mips32\n\t"
paul@9 491
		"mfc0 %0, $16, 7\n\t"
paul@9 492
		"nop\n\t"
paul@9 493
		"ori %0,2\n\t"
paul@9 494
		"mtc0 %0, $16, 7\n\t"
paul@9 495
		".set mips2\n\t"
paul@9 496
		:
paul@9 497
		: "r" (t));
paul@9 498
}
paul@9 499
paul@9 500
void flush_dcache_all(void)
paul@9 501
{
paul@9 502
	u32 addr;
paul@9 503
paul@9 504
	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; 
paul@9 505
	     addr += CONFIG_SYS_CACHELINE_SIZE) {
paul@9 506
		asm volatile (
paul@9 507
			".set mips3\n\t"
paul@9 508
			" cache %0, 0(%1)\n\t"
paul@9 509
			".set mips2\n\t"
paul@9 510
			:
paul@9 511
			: "I" (Index_Writeback_Inv_D), "r"(addr));
paul@9 512
	}
paul@9 513
paul@9 514
	asm volatile ("sync");
paul@9 515
}
paul@9 516
paul@9 517
void flush_cache_all(void)
paul@9 518
{
paul@9 519
	flush_dcache_all();
paul@9 520
	flush_icache_all();
paul@9 521
}