| 1 |
/* |
|---|
| 2 |
* misc_lzma.c |
|---|
| 3 |
* originally written for xscale based linux kernel decompression |
|---|
| 4 |
* now adapted for AR531X based redboot stub and kernel loader |
|---|
| 5 |
* copyright 2009 Sebastian Gottschall / NewMedia-NET GmbH / DD-WRT.COM |
|---|
| 6 |
* licensed under GPL conditions |
|---|
| 7 |
* this stub will load and decompress redboot if the reset button is pushed, otherwise it parses the redboot directory for a partition named linux*, vmlinux* or kernel* |
|---|
| 8 |
* if such a partition has been found, it will be decompressed and executed, if not. redboot is started. if a decompression error occures while loading the linux partition, |
|---|
| 9 |
* the redboot is started too. |
|---|
| 10 |
* take care about the ramconfig.h header since it must contain the correct ram size and gpio button value for the reset button |
|---|
| 11 |
* this code is partially based on redboot and linux sources |
|---|
| 12 |
*/ |
|---|
| 13 |
|
|---|
| 14 |
#ifdef STANDALONE_DEBUG |
|---|
| 15 |
#define putstr printf |
|---|
| 16 |
#else |
|---|
| 17 |
|
|---|
| 18 |
#include <linux/kernel.h> |
|---|
| 19 |
|
|---|
| 20 |
#include <asm/uaccess.h> |
|---|
| 21 |
#include "ramconfig.h" |
|---|
| 22 |
#ifdef AR5312 |
|---|
| 23 |
#include "uncompress-ar5312.h" |
|---|
| 24 |
#else |
|---|
| 25 |
#include "uncompress-ar5315.h" |
|---|
| 26 |
#endif |
|---|
| 27 |
#include "spiflash.h" |
|---|
| 28 |
#include "printf.h" |
|---|
| 29 |
|
|---|
| 30 |
#endif |
|---|
| 31 |
|
|---|
| 32 |
#define __ptr_t void * |
|---|
| 33 |
|
|---|
| 34 |
typedef unsigned char uch; |
|---|
| 35 |
typedef unsigned short ush; |
|---|
| 36 |
typedef unsigned long ulg; |
|---|
| 37 |
|
|---|
| 38 |
static uch *inbuf; /* input buffer */ |
|---|
| 39 |
static unsigned int nvramdetect = 0; |
|---|
| 40 |
|
|---|
| 41 |
static unsigned insize = 0; /* valid bytes in inbuf */ |
|---|
| 42 |
static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ |
|---|
| 43 |
static unsigned outcnt; /* bytes in output buffer */ |
|---|
| 44 |
|
|---|
| 45 |
static void fill_inbuf(void); |
|---|
| 46 |
|
|---|
| 47 |
static inline unsigned char get_byte(void) |
|---|
| 48 |
{ |
|---|
| 49 |
static unsigned int vall; |
|---|
| 50 |
|
|---|
| 51 |
if (((unsigned int)inptr % 4) == 0) { |
|---|
| 52 |
vall = *(unsigned int *)inbuf; |
|---|
| 53 |
inbuf += 4; |
|---|
| 54 |
} |
|---|
| 55 |
return *(((unsigned char *)&vall) + (inptr++ & 3)); |
|---|
| 56 |
} |
|---|
| 57 |
|
|---|
| 58 |
//#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) |
|---|
| 59 |
|
|---|
| 60 |
static void flush_window(void); |
|---|
| 61 |
static void error(char *m); |
|---|
| 62 |
|
|---|
| 63 |
extern unsigned char input_data[]; |
|---|
| 64 |
extern unsigned char input_data_end[]; |
|---|
| 65 |
|
|---|
| 66 |
static ulg output_ptr = 0; |
|---|
| 67 |
static uch *output_data; |
|---|
| 68 |
static ulg bytes_out; |
|---|
| 69 |
|
|---|
| 70 |
extern int end; |
|---|
| 71 |
static ulg free_mem_ptr; |
|---|
| 72 |
static ulg free_mem_ptr_end; |
|---|
| 73 |
|
|---|
| 74 |
#define _LZMA_IN_CB |
|---|
| 75 |
|
|---|
| 76 |
#include "lib/LzmaDecode.h" |
|---|
| 77 |
static unsigned int icnt = 0; |
|---|
| 78 |
static inline int read_byte(unsigned char **buffer, UInt32 * bufferSize) |
|---|
| 79 |
{ |
|---|
| 80 |
static unsigned char val; |
|---|
| 81 |
*bufferSize = 1; |
|---|
| 82 |
val = get_byte(); |
|---|
| 83 |
*buffer = &val; |
|---|
| 84 |
if (icnt++ % (1024 * 10) == 0) |
|---|
| 85 |
putc('.'); |
|---|
| 86 |
return LZMA_RESULT_OK; |
|---|
| 87 |
} |
|---|
| 88 |
|
|---|
| 89 |
#include "lib/LzmaDecode.c" |
|---|
| 90 |
|
|---|
| 91 |
int bootoffset = 0x800004bc; |
|---|
| 92 |
|
|---|
| 93 |
/* |
|---|
| 94 |
* Do the lzma decompression |
|---|
| 95 |
*/ |
|---|
| 96 |
|
|---|
| 97 |
static int disaster = 0; |
|---|
| 98 |
static int lzma_unzip(void) |
|---|
| 99 |
{ |
|---|
| 100 |
|
|---|
| 101 |
unsigned int i; |
|---|
| 102 |
unsigned int uncompressedSize = 0; |
|---|
| 103 |
unsigned char *workspace; |
|---|
| 104 |
unsigned int lc, lp, pb; |
|---|
| 105 |
if (inptr >= insize) |
|---|
| 106 |
fill_inbuf(); |
|---|
| 107 |
|
|---|
| 108 |
// lzma args |
|---|
| 109 |
i = get_byte(); |
|---|
| 110 |
lc = i % 9, i = i / 9; |
|---|
| 111 |
lp = i % 5, pb = i / 5; |
|---|
| 112 |
|
|---|
| 113 |
// skip dictionary size |
|---|
| 114 |
for (i = 0; i < 4; i++) |
|---|
| 115 |
get_byte(); |
|---|
| 116 |
// get uncompressed size |
|---|
| 117 |
int a, b, c, d; |
|---|
| 118 |
a = get_byte(); |
|---|
| 119 |
b = get_byte(); |
|---|
| 120 |
c = get_byte(); |
|---|
| 121 |
d = get_byte(); |
|---|
| 122 |
uncompressedSize = (a) + (b << 8) + (c << 16) + (d << 24); |
|---|
| 123 |
if (uncompressedSize > 0x400000 || lc > 3 || pb > 3 || lp > 3) { |
|---|
| 124 |
if (disaster) { |
|---|
| 125 |
error |
|---|
| 126 |
("\ndata corrupted in recovery RedBoot too, this is a disaster condition. please re-jtag\n"); |
|---|
| 127 |
} |
|---|
| 128 |
disaster = 1; |
|---|
| 129 |
puts("\ndata corrupted!\nswitching to recovery RedBoot\nloading"); |
|---|
| 130 |
inbuf = input_data; |
|---|
| 131 |
insize = &input_data_end[0] - &input_data[0]; |
|---|
| 132 |
inptr = 0; |
|---|
| 133 |
output_data = (uch *) 0x80000400; |
|---|
| 134 |
bootoffset = 0x800004bc; |
|---|
| 135 |
return lzma_unzip(); |
|---|
| 136 |
|
|---|
| 137 |
} |
|---|
| 138 |
workspace = output_data + uncompressedSize; |
|---|
| 139 |
// skip high order bytes |
|---|
| 140 |
for (i = 0; i < 4; i++) |
|---|
| 141 |
get_byte(); |
|---|
| 142 |
// decompress kernel |
|---|
| 143 |
if (LzmaDecode |
|---|
| 144 |
(workspace, ~0, lc, lp, pb, (unsigned char *)output_data, |
|---|
| 145 |
uncompressedSize, &i) == LZMA_RESULT_OK) { |
|---|
| 146 |
if (i != uncompressedSize) { |
|---|
| 147 |
if (disaster) { |
|---|
| 148 |
error |
|---|
| 149 |
("data corrupted in recovery RedBoot too, this is a disaster condition. please re-jtag\n"); |
|---|
| 150 |
} |
|---|
| 151 |
disaster = 1; |
|---|
| 152 |
puts("\ndata corrupted!\nswitching to recovery RedBoot\nloading"); |
|---|
| 153 |
inbuf = input_data; |
|---|
| 154 |
insize = &input_data_end[0] - &input_data[0]; |
|---|
| 155 |
inptr = 0; |
|---|
| 156 |
output_data = (uch *) 0x80000400; |
|---|
| 157 |
bootoffset = 0x800004bc; |
|---|
| 158 |
return lzma_unzip(); |
|---|
| 159 |
} |
|---|
| 160 |
//copy it back to low_buffer |
|---|
| 161 |
bytes_out = i; |
|---|
| 162 |
output_ptr = i; |
|---|
| 163 |
return 0; |
|---|
| 164 |
} |
|---|
| 165 |
return 1; |
|---|
| 166 |
} |
|---|
| 167 |
|
|---|
| 168 |
/*if (((unsigned int)offset % 4) == 0) { |
|---|
| 169 |
vall = *(unsigned int *)buffer; |
|---|
| 170 |
buffer += 4; |
|---|
| 171 |
} |
|---|
| 172 |
if (buffer>=BufferLim) |
|---|
| 173 |
{ |
|---|
| 174 |
ExtraBytes=1; |
|---|
| 175 |
return 0xff; |
|---|
| 176 |
} |
|---|
| 177 |
return *(((unsigned char *)&vall) + (offset++ & 3)); |
|---|
| 178 |
*/ |
|---|
| 179 |
|
|---|
| 180 |
struct fis_image_desc { |
|---|
| 181 |
unsigned char name[16]; // Null terminated name |
|---|
| 182 |
unsigned long flash_base; // Address within FLASH of image |
|---|
| 183 |
unsigned long mem_base; // Address in memory where it executes |
|---|
| 184 |
unsigned long size; // Length of image |
|---|
| 185 |
unsigned long entry_point; // Execution entry point |
|---|
| 186 |
unsigned long data_length; // Length of actual data |
|---|
| 187 |
unsigned char _pad[256 - (16 + 7 * sizeof(unsigned long))]; |
|---|
| 188 |
unsigned long desc_cksum; // Checksum over image descriptor |
|---|
| 189 |
unsigned long file_cksum; // Checksum over image data |
|---|
| 190 |
}; |
|---|
| 191 |
|
|---|
| 192 |
#ifdef AR5312 |
|---|
| 193 |
static unsigned int sectorsize = 0x10000; |
|---|
| 194 |
static unsigned int linuxaddr = 0xbe010000; |
|---|
| 195 |
static unsigned int flashbase = 0xbe000000; |
|---|
| 196 |
static unsigned int flashsize = 0x800000; |
|---|
| 197 |
#else |
|---|
| 198 |
static unsigned int sectorsize = 0x10000; |
|---|
| 199 |
static unsigned int linuxaddr = 0xbfc10000; |
|---|
| 200 |
static unsigned int flashbase = 0xa8000000; |
|---|
| 201 |
static unsigned int flashsize = 0x800000; |
|---|
| 202 |
#endif |
|---|
| 203 |
/* |
|---|
| 204 |
* searches for a directory entry named linux* vmlinux* or kernel and returns its flash address (it also initializes entrypoint and load address) |
|---|
| 205 |
*/ |
|---|
| 206 |
static unsigned int getLinux(void) |
|---|
| 207 |
{ |
|---|
| 208 |
int count = 0; |
|---|
| 209 |
unsigned char *p = |
|---|
| 210 |
(unsigned char *)(flashbase + flashsize - (sectorsize * 2)); |
|---|
| 211 |
struct fis_image_desc *fis = (struct fis_image_desc *)p; |
|---|
| 212 |
while (fis->name[0] != 0xff && count < 10) { |
|---|
| 213 |
if (!strncmp(fis->name, "linux", 5) |
|---|
| 214 |
|| !strncmp(fis->name, "vmlinux", 7) |
|---|
| 215 |
|| !strcmp(fis->name, "kernel")) { |
|---|
| 216 |
printf |
|---|
| 217 |
("found bootable image: [%s] at [0x%08X] EP [0x%08X]\n", |
|---|
| 218 |
fis->name, fis->flash_base, fis->entry_point); |
|---|
| 219 |
bootoffset = fis->entry_point; |
|---|
| 220 |
output_data = (uch *) fis->mem_base; |
|---|
| 221 |
//#ifdef AR5312 |
|---|
| 222 |
return fis->flash_base; |
|---|
| 223 |
//#else |
|---|
| 224 |
// memcpy((unsigned char *)ZCACHEADDR, |
|---|
| 225 |
// (unsigned char *)fis->flash_base, |
|---|
| 226 |
// 1 * 1024 * 1024); |
|---|
| 227 |
// return ZCACHEADDR; |
|---|
| 228 |
//#endif |
|---|
| 229 |
} |
|---|
| 230 |
p += 256; |
|---|
| 231 |
fis = (struct fis_image_desc *)p; |
|---|
| 232 |
count++; |
|---|
| 233 |
} |
|---|
| 234 |
puts("no bootable image found, try default location 0xbfc10000\n"); |
|---|
| 235 |
bootoffset = 0x80041000; |
|---|
| 236 |
output_data = (uch *) 0x80041000; |
|---|
| 237 |
return 0xbfc10000; |
|---|
| 238 |
} |
|---|
| 239 |
|
|---|
| 240 |
/* =========================================================================== |
|---|
| 241 |
* Fill the input buffer. This is called only when the buffer is empty |
|---|
| 242 |
* and at least one byte is really needed. |
|---|
| 243 |
*/ |
|---|
| 244 |
static int resettrigger = 0; |
|---|
| 245 |
|
|---|
| 246 |
static void fill_inbuf(void) |
|---|
| 247 |
{ |
|---|
| 248 |
if (insize != 0) |
|---|
| 249 |
error("ran out of input data"); |
|---|
| 250 |
if (resettrigger) { |
|---|
| 251 |
inbuf = (uch *) linuxaddr; |
|---|
| 252 |
insize = 0x400000; |
|---|
| 253 |
inptr = 0; |
|---|
| 254 |
} else { |
|---|
| 255 |
inbuf = input_data; |
|---|
| 256 |
insize = &input_data_end[0] - &input_data[0]; |
|---|
| 257 |
inptr = 0; |
|---|
| 258 |
} |
|---|
| 259 |
return; |
|---|
| 260 |
} |
|---|
| 261 |
|
|---|
| 262 |
/* =========================================================================== |
|---|
| 263 |
* Write the output window window[0..outcnt-1] and update crc and bytes_out. |
|---|
| 264 |
* (Used for the decompressed data only.) |
|---|
| 265 |
*/ |
|---|
| 266 |
|
|---|
| 267 |
#ifndef arch_error |
|---|
| 268 |
#define arch_error(x) |
|---|
| 269 |
#endif |
|---|
| 270 |
|
|---|
| 271 |
static void error(char *x) |
|---|
| 272 |
{ |
|---|
| 273 |
arch_error(x); |
|---|
| 274 |
|
|---|
| 275 |
printf("\n\n%s\n\n -- System halted", x); |
|---|
| 276 |
|
|---|
| 277 |
while (1) ; /* Halt */ |
|---|
| 278 |
} |
|---|
| 279 |
|
|---|
| 280 |
/*void __div0(void) |
|---|
| 281 |
{ |
|---|
| 282 |
error("division by zero"); |
|---|
| 283 |
}*/ |
|---|
| 284 |
|
|---|
| 285 |
#ifdef AR5312 |
|---|
| 286 |
|
|---|
| 287 |
#define AR531X_APBBASE 0xbc000000 |
|---|
| 288 |
#define AR531X_GPIO (AR531X_APBBASE + 0x2000) |
|---|
| 289 |
#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) |
|---|
| 290 |
|
|---|
| 291 |
static int getGPIO(int nr) |
|---|
| 292 |
{ |
|---|
| 293 |
volatile unsigned int *gpio = (unsigned int *)AR531X_GPIO_DI; |
|---|
| 294 |
if ((*gpio & 1 << nr) == (1 << nr)) |
|---|
| 295 |
return 1; |
|---|
| 296 |
return 0; |
|---|
| 297 |
} |
|---|
| 298 |
|
|---|
| 299 |
#else |
|---|
| 300 |
|
|---|
| 301 |
#define AR2316_DSLBASE 0xB1000000 /* RESET CONTROL MMR */ |
|---|
| 302 |
#define AR2316_GPIO_DI (AR2316_DSLBASE + 0x0088) |
|---|
| 303 |
|
|---|
| 304 |
static int getGPIO(int nr) |
|---|
| 305 |
{ |
|---|
| 306 |
volatile unsigned int *gpio = (unsigned int *)AR2316_GPIO_DI; |
|---|
| 307 |
if ((*gpio & 1 << nr) == (1 << nr)) |
|---|
| 308 |
return 1; |
|---|
| 309 |
return 0; |
|---|
| 310 |
} |
|---|
| 311 |
#endif |
|---|
| 312 |
/* |
|---|
| 313 |
* checks if the reset button is pressed, return 1 if the button is pressed and 0 if not |
|---|
| 314 |
*/ |
|---|
| 315 |
static int resetTouched(void) |
|---|
| 316 |
{ |
|---|
| 317 |
int trigger = getGPIO(RESETBUTTON & 0x0f); |
|---|
| 318 |
if (RESETBUTTON & 0xf0) |
|---|
| 319 |
trigger = 1 - trigger; |
|---|
| 320 |
return trigger; |
|---|
| 321 |
} |
|---|
| 322 |
|
|---|
| 323 |
#define RTC_DENOMINATOR 100 |
|---|
| 324 |
#define RTC_PERIOD 110000000 / RTC_DENOMINATOR |
|---|
| 325 |
|
|---|
| 326 |
#define MACRO_START do { |
|---|
| 327 |
#define MACRO_END } while (0) |
|---|
| 328 |
static unsigned int cyg_hal_clock_period; |
|---|
| 329 |
|
|---|
| 330 |
#define HAL_CLOCK_INITIALIZE( _period_ ) \ |
|---|
| 331 |
MACRO_START \ |
|---|
| 332 |
asm volatile ( \ |
|---|
| 333 |
"mtc0 $0,$9\n" \ |
|---|
| 334 |
"nop; nop; nop\n" \ |
|---|
| 335 |
"mtc0 %0,$11\n" \ |
|---|
| 336 |
"nop; nop; nop\n" \ |
|---|
| 337 |
: \ |
|---|
| 338 |
: "r"(_period_) \ |
|---|
| 339 |
); \ |
|---|
| 340 |
cyg_hal_clock_period = _period_; \ |
|---|
| 341 |
MACRO_END |
|---|
| 342 |
|
|---|
| 343 |
#define HAL_CLOCK_RESET( _vector_, _period_ ) \ |
|---|
| 344 |
MACRO_START \ |
|---|
| 345 |
asm volatile ( \ |
|---|
| 346 |
"mtc0 $0,$9\n" \ |
|---|
| 347 |
"nop; nop; nop\n" \ |
|---|
| 348 |
"mtc0 %0,$11\n" \ |
|---|
| 349 |
"nop; nop; nop\n" \ |
|---|
| 350 |
: \ |
|---|
| 351 |
: "r"(_period_) \ |
|---|
| 352 |
); \ |
|---|
| 353 |
MACRO_END |
|---|
| 354 |
|
|---|
| 355 |
#define HAL_CLOCK_READ( _pvalue_ ) \ |
|---|
| 356 |
MACRO_START \ |
|---|
| 357 |
register unsigned int result; \ |
|---|
| 358 |
asm volatile ( \ |
|---|
| 359 |
"mfc0 %0,$9\n" \ |
|---|
| 360 |
: "=r"(result) \ |
|---|
| 361 |
); \ |
|---|
| 362 |
*(_pvalue_) = result; \ |
|---|
| 363 |
MACRO_END |
|---|
| 364 |
|
|---|
| 365 |
/* |
|---|
| 366 |
* udelay implementation based on cpu cycle counter |
|---|
| 367 |
*/ |
|---|
| 368 |
static void udelay(int us) |
|---|
| 369 |
{ |
|---|
| 370 |
unsigned int val1, val2; |
|---|
| 371 |
int diff; |
|---|
| 372 |
long usticks; |
|---|
| 373 |
long ticks; |
|---|
| 374 |
|
|---|
| 375 |
// Calculate the number of counter register ticks per microsecond. |
|---|
| 376 |
|
|---|
| 377 |
usticks = (RTC_PERIOD * RTC_DENOMINATOR) / 1000000; |
|---|
| 378 |
|
|---|
| 379 |
// Make sure that the value is not zero. This will only happen if the |
|---|
| 380 |
// CPU is running at < 2MHz. |
|---|
| 381 |
if (usticks == 0) |
|---|
| 382 |
usticks = 1; |
|---|
| 383 |
|
|---|
| 384 |
while (us > 0) { |
|---|
| 385 |
int us1 = us; |
|---|
| 386 |
|
|---|
| 387 |
// Wait in bursts of less than 10000us to avoid any overflow |
|---|
| 388 |
// problems in the multiply. |
|---|
| 389 |
if (us1 > 10000) |
|---|
| 390 |
us1 = 10000; |
|---|
| 391 |
|
|---|
| 392 |
us -= us1; |
|---|
| 393 |
|
|---|
| 394 |
ticks = us1 * usticks; |
|---|
| 395 |
|
|---|
| 396 |
HAL_CLOCK_READ(&val1); |
|---|
| 397 |
while (ticks > 0) { |
|---|
| 398 |
do { |
|---|
| 399 |
HAL_CLOCK_READ(&val2); |
|---|
| 400 |
} |
|---|
| 401 |
while (val1 == val2); |
|---|
| 402 |
diff = val2 - val1; |
|---|
| 403 |
if (diff < 0) |
|---|
| 404 |
diff += RTC_PERIOD; |
|---|
| 405 |
ticks -= diff; |
|---|
| 406 |
val1 = val2; |
|---|
| 407 |
} |
|---|
| 408 |
} |
|---|
| 409 |
} |
|---|
| 410 |
|
|---|
| 411 |
#ifndef STANDALONE_DEBUG |
|---|
| 412 |
|
|---|
| 413 |
typedef unsigned int AR531X_REG; |
|---|
| 414 |
|
|---|
| 415 |
#undef sysRegRead |
|---|
| 416 |
#undef sysRegWrite |
|---|
| 417 |
#define sysRegRead(phys) \ |
|---|
| 418 |
(*(volatile AR531X_REG *)(KSEG1|phys)) |
|---|
| 419 |
|
|---|
| 420 |
#define sysRegWrite(phys, val) \ |
|---|
| 421 |
((*(volatile AR531X_REG *)(KSEG1|phys)) = (val)) |
|---|
| 422 |
|
|---|
| 423 |
#ifndef AR5312 |
|---|
| 424 |
|
|---|
| 425 |
#define RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */ |
|---|
| 426 |
#define RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */ |
|---|
| 427 |
#define RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */ |
|---|
| 428 |
#define RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */ |
|---|
| 429 |
#define RESET_MEMCTL 0x00000010 /* warm reset memory controller */ |
|---|
| 430 |
#define RESET_LOCAL 0x00000020 /* warm reset local bus */ |
|---|
| 431 |
#define RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */ |
|---|
| 432 |
#define RESET_SPI 0x00000080 /* warm reset SPI interface */ |
|---|
| 433 |
#define RESET_UART0 0x00000100 /* warm reset UART0 */ |
|---|
| 434 |
#define RESET_IR_RSVD 0x00000200 /* warm reset IR interface */ |
|---|
| 435 |
#define RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */ |
|---|
| 436 |
#define RESET_ENET0 0x00000800 /* cold reset ENET0 mac */ |
|---|
| 437 |
|
|---|
| 438 |
#define IF_TS_LOCAL 2 |
|---|
| 439 |
#define AR2316_DSLBASE 0xB1000000 /* RESET CONTROL MMR */ |
|---|
| 440 |
#define AR2316_RESET (AR2316_DSLBASE + 0x0004) |
|---|
| 441 |
#define AR2316_IF_CTL (AR2316_DSLBASE + 0x0018) |
|---|
| 442 |
#define AR2316_ENDIAN_CTL (AR2316_DSLBASE + 0x000c) |
|---|
| 443 |
|
|---|
| 444 |
#define CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */ |
|---|
| 445 |
|
|---|
| 446 |
#define AR2316_AHB_ARB_CTL (AR2316_DSLBASE + 0x0008) |
|---|
| 447 |
#define ARB_CPU 0x00000001 /* CPU, default */ |
|---|
| 448 |
#define ARB_WLAN 0x00000002 /* WLAN */ |
|---|
| 449 |
#define ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */ |
|---|
| 450 |
#define ARB_LOCAL 0x00000008 /* LOCAL */ |
|---|
| 451 |
#define ARB_PCI 0x00000010 /* PCI */ |
|---|
| 452 |
#define ARB_ETHERNET 0x00000020 /* Ethernet */ |
|---|
| 453 |
#define ARB_RETRY 0x00000100 /* retry policy, debug only */ |
|---|
| 454 |
|
|---|
| 455 |
#define AR531XPLUS_SPI 0xB1300000 /* SPI FLASH MMR */ |
|---|
| 456 |
|
|---|
| 457 |
#define FLASH_1MB 1 |
|---|
| 458 |
#define FLASH_2MB 2 |
|---|
| 459 |
#define FLASH_4MB 3 |
|---|
| 460 |
#define FLASH_8MB 4 |
|---|
| 461 |
#define FLASH_16MB 5 |
|---|
| 462 |
#define MAX_FLASH 6 |
|---|
| 463 |
|
|---|
| 464 |
#define STM_PAGE_SIZE 256 |
|---|
| 465 |
|
|---|
| 466 |
#define SFI_WRITE_BUFFER_SIZE 4 |
|---|
| 467 |
#define SFI_FLASH_ADDR_MASK 0x00ffffff |
|---|
| 468 |
|
|---|
| 469 |
#define STM_8MBIT_SIGNATURE 0x13 |
|---|
| 470 |
#define STM_M25P80_BYTE_COUNT 1048576 |
|---|
| 471 |
#define STM_M25P80_SECTOR_COUNT 16 |
|---|
| 472 |
#define STM_M25P80_SECTOR_SIZE 0x10000 |
|---|
| 473 |
|
|---|
| 474 |
#define STM_16MBIT_SIGNATURE 0x14 |
|---|
| 475 |
#define STM_M25P16_BYTE_COUNT 2097152 |
|---|
| 476 |
#define STM_M25P16_SECTOR_COUNT 32 |
|---|
| 477 |
#define STM_M25P16_SECTOR_SIZE 0x10000 |
|---|
| 478 |
|
|---|
| 479 |
#define STM_32MBIT_SIGNATURE 0x15 |
|---|
| 480 |
#define STM_M25P32_BYTE_COUNT 4194304 |
|---|
| 481 |
#define STM_M25P32_SECTOR_COUNT 64 |
|---|
| 482 |
#define STM_M25P32_SECTOR_SIZE 0x10000 |
|---|
| 483 |
|
|---|
| 484 |
#define STM_64MBIT_SIGNATURE 0x16 |
|---|
| 485 |
#define STM_M25P64_BYTE_COUNT 8388608 |
|---|
| 486 |
#define STM_M25P64_SECTOR_COUNT 128 |
|---|
| 487 |
#define STM_M25P64_SECTOR_SIZE 0x10000 |
|---|
| 488 |
|
|---|
| 489 |
#define STM_128MBIT_SIGNATURE 0x17 |
|---|
| 490 |
#define STM_M25P128_BYTE_COUNT 16777216 |
|---|
| 491 |
#define STM_M25P128_SECTOR_COUNT 256 |
|---|
| 492 |
#define STM_M25P128_SECTOR_SIZE 0x10000 |
|---|
| 493 |
|
|---|
| 494 |
#define STM_1MB_BYTE_COUNT STM_M25P80_BYTE_COUNT |
|---|
| 495 |
#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT |
|---|
| 496 |
#define STM_1MB_SECTOR_SIZE STM_M25P80_SECTOR_SIZE |
|---|
| 497 |
#define STM_2MB_BYTE_COUNT STM_M25P16_BYTE_COUNT |
|---|
| 498 |
#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT |
|---|
| 499 |
#define STM_2MB_SECTOR_SIZE STM_M25P16_SECTOR_SIZE |
|---|
| 500 |
#define STM_4MB_BYTE_COUNT STM_M25P32_BYTE_COUNT |
|---|
| 501 |
#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT |
|---|
| 502 |
#define STM_4MB_SECTOR_SIZE STM_M25P32_SECTOR_SIZE |
|---|
| 503 |
#define STM_8MB_BYTE_COUNT STM_M25P64_BYTE_COUNT |
|---|
| 504 |
#define STM_8MB_SECTOR_COUNT STM_M25P64_SECTOR_COUNT |
|---|
| 505 |
#define STM_8MB_SECTOR_SIZE STM_M25P64_SECTOR_SIZE |
|---|
| 506 |
#define STM_16MB_BYTE_COUNT STM_M25P128_BYTE_COUNT |
|---|
| 507 |
#define STM_16MB_SECTOR_COUNT STM_M25P128_SECTOR_COUNT |
|---|
| 508 |
#define STM_16MB_SECTOR_SIZE STM_M25P128_SECTOR_SIZE |
|---|
| 509 |
|
|---|
| 510 |
#define SPI_FLASH_MMR AR531XPLUS_SPI_MMR |
|---|
| 511 |
|
|---|
| 512 |
#define SPI_WRITE_ENABLE 0 |
|---|
| 513 |
#define SPI_WRITE_DISABLE 1 |
|---|
| 514 |
#define SPI_RD_STATUS 2 |
|---|
| 515 |
#define SPI_WR_STATUS 3 |
|---|
| 516 |
#define SPI_RD_DATA 4 |
|---|
| 517 |
#define SPI_FAST_RD_DATA 5 |
|---|
| 518 |
#define SPI_PAGE_PROGRAM 6 |
|---|
| 519 |
#define SPI_SECTOR_ERASE 7 |
|---|
| 520 |
#define SPI_BULK_ERASE 8 |
|---|
| 521 |
#define SPI_DEEP_PWRDOWN 9 |
|---|
| 522 |
#define SPI_RD_SIG 10 |
|---|
| 523 |
#define SPI_MAX_OPCODES 11 |
|---|
| 524 |
|
|---|
| 525 |
struct flashconfig { |
|---|
| 526 |
__u32 byte_cnt; |
|---|
| 527 |
__u32 sector_cnt; |
|---|
| 528 |
__u32 sector_size; |
|---|
| 529 |
__u32 cs_addrmask; |
|---|
| 530 |
} static flashconfig_tbl[MAX_FLASH] = { |
|---|
| 531 |
{0, 0, 0, 0}, // |
|---|
| 532 |
{STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0}, // |
|---|
| 533 |
{STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0}, // |
|---|
| 534 |
{STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0}, // |
|---|
| 535 |
{STM_8MB_BYTE_COUNT, STM_8MB_SECTOR_COUNT, STM_8MB_SECTOR_SIZE, 0x0}, // |
|---|
| 536 |
{STM_16MB_BYTE_COUNT, STM_16MB_SECTOR_COUNT, STM_16MB_SECTOR_SIZE, 0x0} // |
|---|
| 537 |
}; |
|---|
| 538 |
|
|---|
| 539 |
struct opcodes { |
|---|
| 540 |
__u16 code; |
|---|
| 541 |
__s8 tx_cnt; |
|---|
| 542 |
__s8 rx_cnt; |
|---|
| 543 |
} static stm_opcodes[] = { |
|---|
| 544 |
{STM_OP_WR_ENABLE, 1, 0}, // |
|---|
| 545 |
{STM_OP_WR_DISABLE, 1, 0}, // |
|---|
| 546 |
{STM_OP_RD_STATUS, 1, 1}, // |
|---|
| 547 |
{STM_OP_WR_STATUS, 1, 0}, // |
|---|
| 548 |
{STM_OP_RD_DATA, 4, 4}, // |
|---|
| 549 |
{STM_OP_FAST_RD_DATA, 5, 0}, // |
|---|
| 550 |
{STM_OP_PAGE_PGRM, 8, 0}, // |
|---|
| 551 |
{STM_OP_SECTOR_ERASE, 4, 0}, // |
|---|
| 552 |
{STM_OP_BULK_ERASE, 1, 0}, // |
|---|
| 553 |
{STM_OP_DEEP_PWRDOWN, 1, 0}, // |
|---|
| 554 |
{STM_OP_RD_SIG, 4, 1}, // |
|---|
| 555 |
}; |
|---|
| 556 |
|
|---|
| 557 |
static __u32 spiflash_regread32(int reg) |
|---|
| 558 |
{ |
|---|
| 559 |
volatile __u32 *data = (__u32 *)(AR531XPLUS_SPI + reg); |
|---|
| 560 |
|
|---|
| 561 |
return (*data); |
|---|
| 562 |
} |
|---|
| 563 |
|
|---|
| 564 |
static void spiflash_regwrite32(int reg, __u32 data) |
|---|
| 565 |
{ |
|---|
| 566 |
volatile __u32 *addr = (__u32 *)(AR531XPLUS_SPI + reg); |
|---|
| 567 |
|
|---|
| 568 |
*addr = data; |
|---|
| 569 |
return; |
|---|
| 570 |
} |
|---|
| 571 |
|
|---|
| 572 |
#define busy_wait(condition, wait) \ |
|---|
| 573 |
do { \ |
|---|
| 574 |
while (condition) { \ |
|---|
| 575 |
if (!wait) \ |
|---|
| 576 |
udelay(1); \ |
|---|
| 577 |
else \ |
|---|
| 578 |
udelay(wait*1000); \ |
|---|
| 579 |
} \ |
|---|
| 580 |
} while (0) |
|---|
| 581 |
|
|---|
| 582 |
static __u32 spiflash_sendcmd(int op, u32 addr) |
|---|
| 583 |
{ |
|---|
| 584 |
u32 reg; |
|---|
| 585 |
u32 mask; |
|---|
| 586 |
struct opcodes *ptr_opcode; |
|---|
| 587 |
|
|---|
| 588 |
ptr_opcode = &stm_opcodes[op]; |
|---|
| 589 |
busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0); |
|---|
| 590 |
|
|---|
| 591 |
spiflash_regwrite32(SPI_FLASH_OPCODE, |
|---|
| 592 |
((u32)ptr_opcode->code) | (addr << 8)); |
|---|
| 593 |
|
|---|
| 594 |
reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | |
|---|
| 595 |
(ptr_opcode->rx_cnt << 4) | SPI_CTL_START; |
|---|
| 596 |
|
|---|
| 597 |
spiflash_regwrite32(SPI_FLASH_CTL, reg); |
|---|
| 598 |
|
|---|
| 599 |
busy_wait(spiflash_regread32(SPI_FLASH_CTL) & SPI_CTL_BUSY, 0); |
|---|
| 600 |
|
|---|
| 601 |
if (!ptr_opcode->rx_cnt) |
|---|
| 602 |
return 0; |
|---|
| 603 |
|
|---|
| 604 |
reg = (__u32)spiflash_regread32(SPI_FLASH_DATA); |
|---|
| 605 |
|
|---|
| 606 |
switch (ptr_opcode->rx_cnt) { |
|---|
| 607 |
case 1: |
|---|
| 608 |
mask = 0x000000ff; |
|---|
| 609 |
break; |
|---|
| 610 |
case 2: |
|---|
| 611 |
mask = 0x0000ffff; |
|---|
| 612 |
break; |
|---|
| 613 |
case 3: |
|---|
| 614 |
mask = 0x00ffffff; |
|---|
| 615 |
break; |
|---|
| 616 |
default: |
|---|
| 617 |
mask = 0xffffffff; |
|---|
| 618 |
break; |
|---|
| 619 |
} |
|---|
| 620 |
reg &= mask; |
|---|
| 621 |
|
|---|
| 622 |
return reg; |
|---|
| 623 |
} |
|---|
| 624 |
|
|---|
| 625 |
static int spiflash_probe_chip(void) |
|---|
| 626 |
{ |
|---|
| 627 |
unsigned int sig; |
|---|
| 628 |
int flash_size; |
|---|
| 629 |
|
|---|
| 630 |
sig = spiflash_sendcmd(SPI_RD_SIG, 0); |
|---|
| 631 |
|
|---|
| 632 |
switch (sig) { |
|---|
| 633 |
case STM_8MBIT_SIGNATURE: |
|---|
| 634 |
flash_size = FLASH_1MB; |
|---|
| 635 |
break; |
|---|
| 636 |
case STM_16MBIT_SIGNATURE: |
|---|
| 637 |
flash_size = FLASH_2MB; |
|---|
| 638 |
break; |
|---|
| 639 |
case STM_32MBIT_SIGNATURE: |
|---|
| 640 |
flash_size = FLASH_4MB; |
|---|
| 641 |
break; |
|---|
| 642 |
case STM_64MBIT_SIGNATURE: |
|---|
| 643 |
flash_size = FLASH_8MB; |
|---|
| 644 |
break; |
|---|
| 645 |
case STM_128MBIT_SIGNATURE: |
|---|
| 646 |
flash_size = FLASH_16MB; |
|---|
| 647 |
break; |
|---|
| 648 |
default: |
|---|
| 649 |
puts("Read of flash device signature failed!\n"); |
|---|
| 650 |
return (0); |
|---|
| 651 |
} |
|---|
| 652 |
|
|---|
| 653 |
return (flash_size); |
|---|
| 654 |
} |
|---|
| 655 |
|
|---|
| 656 |
static int flash_erase_nvram(unsigned int flashsize, unsigned int blocksize) |
|---|
| 657 |
{ |
|---|
| 658 |
unsigned int res; |
|---|
| 659 |
unsigned int offset = nvramdetect; |
|---|
| 660 |
struct opcodes *ptr_opcode; |
|---|
| 661 |
__u32 temp, reg; |
|---|
| 662 |
if (!nvramdetect) { |
|---|
| 663 |
puts("nvram can and will not erased, since nvram was not detected on this device (maybe dd-wrt isnt installed)!\n"); |
|---|
| 664 |
return; |
|---|
| 665 |
} |
|---|
| 666 |
printf("erasing nvram at [0x%08X]\n", nvramdetect); |
|---|
| 667 |
|
|---|
| 668 |
ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE]; |
|---|
| 669 |
|
|---|
| 670 |
temp = ((__u32)offset << 8) | (__u32)(ptr_opcode->code); |
|---|
| 671 |
spiflash_sendcmd(SPI_WRITE_ENABLE, 0); |
|---|
| 672 |
busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0); |
|---|
| 673 |
|
|---|
| 674 |
spiflash_regwrite32(SPI_FLASH_OPCODE, temp); |
|---|
| 675 |
|
|---|
| 676 |
reg = |
|---|
| 677 |
(reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | |
|---|
| 678 |
SPI_CTL_START; |
|---|
| 679 |
spiflash_regwrite32(SPI_FLASH_CTL, reg); |
|---|
| 680 |
|
|---|
| 681 |
busy_wait(spiflash_sendcmd(SPI_RD_STATUS, 0) & SPI_STATUS_WIP, 20); |
|---|
| 682 |
|
|---|
| 683 |
puts("done\n"); |
|---|
| 684 |
return 0; |
|---|
| 685 |
} |
|---|
| 686 |
|
|---|
| 687 |
static int flashdetected = 0; |
|---|
| 688 |
static int flashdetect(void) |
|---|
| 689 |
{ |
|---|
| 690 |
if (flashdetected) |
|---|
| 691 |
return 0; |
|---|
| 692 |
flashsize = 8 * 1024 * 1024; |
|---|
| 693 |
flashbase = 0xa8000000; |
|---|
| 694 |
int index = 0; |
|---|
| 695 |
if (!(index = spiflash_probe_chip())) { |
|---|
| 696 |
puts("Found no serial flash device, cannot reset to factory defaults\n"); |
|---|
| 697 |
return -1; |
|---|
| 698 |
} else { |
|---|
| 699 |
flashsize = flashconfig_tbl[index].byte_cnt; |
|---|
| 700 |
sectorsize = flashconfig_tbl[index].sector_size; |
|---|
| 701 |
if (flashsize == 8 * 1024 * 1024) |
|---|
| 702 |
flashbase = 0xa8000000; |
|---|
| 703 |
else |
|---|
| 704 |
flashbase = 0xbfc00000; |
|---|
| 705 |
printf |
|---|
| 706 |
("Found Flash device SIZE=0x%08X SECTORSIZE=0x%08X FLASHBASE=0x%08X\n", |
|---|
| 707 |
flashsize, sectorsize, flashbase); |
|---|
| 708 |
} |
|---|
| 709 |
flashdetected = 1; |
|---|
| 710 |
return 0; |
|---|
| 711 |
|
|---|
| 712 |
} |
|---|
| 713 |
#else |
|---|
| 714 |
|
|---|
| 715 |
typedef unsigned char FLASH_DATA_T; |
|---|
| 716 |
#define FLASH_P2V( _a_ ) ((volatile FLASH_DATA_T *)((unsigned int)((_a_)))) |
|---|
| 717 |
#define FLASH_BLANKVALUE (FLASH_DATA_T)(0xff) |
|---|
| 718 |
#define FLASHWORD(x) ((FLASH_DATA_T)(x)) |
|---|
| 719 |
#define FLASH_POLLING_TIMEOUT (3000000) |
|---|
| 720 |
#define FLASH_READ_ID FLASHWORD( 0x90 ) |
|---|
| 721 |
#define FLASH_WP_STATE FLASHWORD( 0x90 ) |
|---|
| 722 |
#define FLASH_RESET FLASHWORD( 0xF0 ) |
|---|
| 723 |
#define FLASH_PROGRAM FLASHWORD( 0xA0 ) |
|---|
| 724 |
#define FLASH_BLOCK_ERASE FLASHWORD( 0x30 ) |
|---|
| 725 |
#define FLASH_Query FLASHWORD( 0x98 ) // Add by Jason for CFI support |
|---|
| 726 |
|
|---|
| 727 |
#define FLASH_DATA FLASHWORD( 0x80 ) // Data complement |
|---|
| 728 |
#define FLASH_BUSY FLASHWORD( 0x40 ) // "Toggle" bit |
|---|
| 729 |
#define FLASH_ERR FLASHWORD( 0x20 ) |
|---|
| 730 |
#define FLASH_SECTOR_ERASE_TIMER FLASHWORD( 0x08 ) |
|---|
| 731 |
|
|---|
| 732 |
#define FLASH_UNLOCKED FLASHWORD( 0x00 ) |
|---|
| 733 |
#define FLASH_WP_ADDR (4) |
|---|
| 734 |
|
|---|
| 735 |
#define FLASH_SETUP_ADDR1 (0xAAA) |
|---|
| 736 |
#define FLASH_SETUP_ADDR2 (0x555) |
|---|
| 737 |
#define FLASH_VENDORID_ADDR (0x0) |
|---|
| 738 |
#define FLASH_DEVICEID_ADDR (0x2) |
|---|
| 739 |
#define FLASH_DEVICEID_ADDR2 (0x1c) |
|---|
| 740 |
#define FLASH_DEVICEID_ADDR3 (0x1e) |
|---|
| 741 |
//#define FLASH_WP_ADDR (0x12) |
|---|
| 742 |
#define FLASH_SETUP_CODE1 FLASHWORD( 0xAA ) |
|---|
| 743 |
#define FLASH_SETUP_CODE2 FLASHWORD( 0x55 ) |
|---|
| 744 |
#define FLASH_SETUP_ERASE FLASHWORD( 0x80 ) |
|---|
| 745 |
#define FLASH_ERR_OK 0x0 |
|---|
| 746 |
#define FLASH_ERR_DRV_TIMEOUT -1 |
|---|
| 747 |
|
|---|
| 748 |
/*static void |
|---|
| 749 |
flash_query(void* data) |
|---|
| 750 |
{ |
|---|
| 751 |
volatile FLASH_DATA_T *ROM; |
|---|
| 752 |
volatile FLASH_DATA_T *f_s1, *f_s2; |
|---|
| 753 |
FLASH_DATA_T* id = (FLASH_DATA_T*) data; |
|---|
| 754 |
FLASH_DATA_T w; |
|---|
| 755 |
long timeout = 50000; |
|---|
| 756 |
|
|---|
| 757 |
ROM = (volatile FLASH_DATA_T*) ((unsigned int)nvramdetect & ~(0x800000-1)); |
|---|
| 758 |
*(FLASH_P2V(ROM)) = FLASH_RESET; |
|---|
| 759 |
|
|---|
| 760 |
f_s1 = FLASH_P2V(ROM+FLASH_SETUP_ADDR1); |
|---|
| 761 |
f_s2 = FLASH_P2V(ROM+FLASH_SETUP_ADDR2); |
|---|
| 762 |
|
|---|
| 763 |
*f_s1 = FLASH_RESET; |
|---|
| 764 |
w = *(FLASH_P2V(ROM)); |
|---|
| 765 |
|
|---|
| 766 |
*f_s1 = FLASH_SETUP_CODE1; |
|---|
| 767 |
*f_s2 = FLASH_SETUP_CODE2; |
|---|
| 768 |
*f_s1 = FLASH_READ_ID; |
|---|
| 769 |
|
|---|
| 770 |
id[0] = -1; |
|---|
| 771 |
id[1] = -1; |
|---|
| 772 |
|
|---|
| 773 |
// Manufacturers' code |
|---|
| 774 |
id[0] = *(FLASH_P2V(ROM+FLASH_VENDORID_ADDR)); |
|---|
| 775 |
// Part number |
|---|
| 776 |
id[1] = *(FLASH_P2V(ROM+FLASH_DEVICEID_ADDR)); |
|---|
| 777 |
id[2] = *(FLASH_P2V(ROM+FLASH_DEVICEID_ADDR2)); |
|---|
| 778 |
id[3] = *(FLASH_P2V(ROM+FLASH_DEVICEID_ADDR3)); |
|---|
| 779 |
|
|---|
| 780 |
*(FLASH_P2V(ROM)) = FLASH_RESET; |
|---|
| 781 |
|
|---|
| 782 |
// Stall, waiting for flash to return to read mode. |
|---|
| 783 |
while ((--timeout != 0) && (w != *(FLASH_P2V(ROM)))) ; |
|---|
| 784 |
} |
|---|
| 785 |
*/ |
|---|
| 786 |
|
|---|
| 787 |
#define AR531X_FLASHCTL 0xb8400000 |
|---|
| 788 |
#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00) |
|---|
| 789 |
#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04) |
|---|
| 790 |
#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08) |
|---|
| 791 |
#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */ |
|---|
| 792 |
#define FLASHCTL_IDCY_S 0 |
|---|
| 793 |
#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */ |
|---|
| 794 |
#define FLASHCTL_WST1_S 5 |
|---|
| 795 |
#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */ |
|---|
| 796 |
#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */ |
|---|
| 797 |
#define FLASHCTL_WST2_S 11 |
|---|
| 798 |
#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */ |
|---|
| 799 |
#define FLASHCTL_AC_S 16 |
|---|
| 800 |
#define FLASHCTL_AC_128K 0x00000000 |
|---|
| 801 |
#define FLASHCTL_AC_256K 0x00010000 |
|---|
| 802 |
#define FLASHCTL_AC_512K 0x00020000 |
|---|
| 803 |
#define FLASHCTL_AC_1M 0x00030000 |
|---|
| 804 |
#define FLASHCTL_AC_2M 0x00040000 |
|---|
| 805 |
#define FLASHCTL_AC_4M 0x00050000 |
|---|
| 806 |
#define FLASHCTL_AC_8M 0x00060000 |
|---|
| 807 |
#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */ |
|---|
| 808 |
#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */ |
|---|
| 809 |
#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */ |
|---|
| 810 |
#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */ |
|---|
| 811 |
#define FLASHCTL_WP 0x04000000 /* Write protect */ |
|---|
| 812 |
#define FLASHCTL_BM 0x08000000 /* Burst mode */ |
|---|
| 813 |
#define FLASHCTL_MW 0x30000000 /* Memory width */ |
|---|
| 814 |
#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ |
|---|
| 815 |
#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ |
|---|
| 816 |
#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ |
|---|
| 817 |
#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */ |
|---|
| 818 |
#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */ |
|---|
| 819 |
#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */ |
|---|
| 820 |
|
|---|
| 821 |
static int flash_erase_nvram(unsigned int flashsize, unsigned int blocksize) |
|---|
| 822 |
{ |
|---|
| 823 |
int i, ticks; |
|---|
| 824 |
unsigned short val; |
|---|
| 825 |
if (!nvramdetect) { |
|---|
| 826 |
puts("nvram can and will not erased, since nvram was not detected on this device (maybe dd-wrt isnt installed)!\n"); |
|---|
| 827 |
return; |
|---|
| 828 |
} |
|---|
| 829 |
unsigned int flash_ctl = sysRegRead(AR531X_FLASHCTL0); |
|---|
| 830 |
|
|---|
| 831 |
FLASH_DATA_T id[4]; |
|---|
| 832 |
// puts("read id\n"); |
|---|
| 833 |
// flash_query(id); |
|---|
| 834 |
// printf("FLASH MANID: %X DEVID: %X DEVID2: %X DEVID3: %X\n",id[0],id[1],id[2],id[3]); |
|---|
| 835 |
|
|---|
| 836 |
printf("erasing nvram at [0x%08X]\n", nvramdetect); |
|---|
| 837 |
|
|---|
| 838 |
volatile FLASH_DATA_T *ROM, *BANK; |
|---|
| 839 |
volatile FLASH_DATA_T *b_p = (FLASH_DATA_T *) (nvramdetect); |
|---|
| 840 |
volatile FLASH_DATA_T *b_v; |
|---|
| 841 |
volatile FLASH_DATA_T *f_s0, *f_s1, *f_s2; |
|---|
| 842 |
int timeout = 50000; |
|---|
| 843 |
FLASH_DATA_T state; |
|---|
| 844 |
int len; |
|---|
| 845 |
BANK = ROM = |
|---|
| 846 |
(volatile FLASH_DATA_T *)((unsigned long)nvramdetect & |
|---|
| 847 |
~(0x800000 - 1)); |
|---|
| 848 |
f_s0 = FLASH_P2V(BANK); |
|---|
| 849 |
f_s1 = FLASH_P2V(BANK + FLASH_SETUP_ADDR1); |
|---|
| 850 |
f_s2 = FLASH_P2V(BANK + FLASH_SETUP_ADDR2); |
|---|
| 851 |
len = blocksize; |
|---|
| 852 |
int res = FLASH_ERR_OK; |
|---|
| 853 |
|
|---|
| 854 |
*f_s1 = FLASH_SETUP_CODE1; |
|---|
| 855 |
*f_s2 = FLASH_SETUP_CODE2; |
|---|
| 856 |
*f_s1 = FLASH_WP_STATE; |
|---|
| 857 |
state = *FLASH_P2V(b_p + FLASH_WP_ADDR); |
|---|
| 858 |
*f_s0 = FLASH_RESET; |
|---|
| 859 |
|
|---|
| 860 |
if (FLASH_UNLOCKED != state) { |
|---|
| 861 |
*FLASH_P2V(ROM) = FLASH_RESET; |
|---|
| 862 |
} |
|---|
| 863 |
|
|---|
| 864 |
b_v = FLASH_P2V(b_p); |
|---|
| 865 |
|
|---|
| 866 |
*f_s1 = FLASH_SETUP_CODE1; |
|---|
| 867 |
*f_s2 = FLASH_SETUP_CODE2; |
|---|
| 868 |
*f_s1 = FLASH_SETUP_ERASE; |
|---|
| 869 |
*f_s1 = FLASH_SETUP_CODE1; |
|---|
| 870 |
*f_s2 = FLASH_SETUP_CODE2; |
|---|
| 871 |
*b_v = FLASH_BLOCK_ERASE; |
|---|
| 872 |
timeout = FLASH_POLLING_TIMEOUT; |
|---|
| 873 |
while (1) { |
|---|
| 874 |
state = *b_v; |
|---|
| 875 |
if ((state & FLASH_SECTOR_ERASE_TIMER) |
|---|
| 876 |
== FLASH_SECTOR_ERASE_TIMER) |
|---|
| 877 |
break; |
|---|
| 878 |
udelay(1); |
|---|
| 879 |
if (--timeout == 0) { |
|---|
| 880 |
puts("flash erase timeout\n"); |
|---|
| 881 |
res = FLASH_ERR_DRV_TIMEOUT; |
|---|
| 882 |
break; |
|---|
| 883 |
} |
|---|
| 884 |
} |
|---|
| 885 |
if (FLASH_ERR_OK == res) { |
|---|
| 886 |
timeout = FLASH_POLLING_TIMEOUT; |
|---|
| 887 |
while (1) { |
|---|
| 888 |
state = *b_v; |
|---|
| 889 |
if (FLASH_BLANKVALUE == state) { |
|---|
| 890 |
break; |
|---|
| 891 |
} |
|---|
| 892 |
udelay(1); |
|---|
| 893 |
if (--timeout == 0) { |
|---|
| 894 |
puts("flash erase timeout while waiting for erase complete\n"); |
|---|
| 895 |
res = FLASH_ERR_DRV_TIMEOUT; |
|---|
| 896 |
break; |
|---|
| 897 |
} |
|---|
| 898 |
} |
|---|
| 899 |
} |
|---|
| 900 |
|
|---|
| 901 |
if (FLASH_ERR_OK != res) |
|---|
| 902 |
*FLASH_P2V(ROM) = FLASH_RESET; |
|---|
| 903 |
|
|---|
| 904 |
b_v = FLASH_P2V(b_p++); |
|---|
| 905 |
if (*b_v != FLASH_BLANKVALUE) { |
|---|
| 906 |
if (FLASH_ERR_OK == res) { |
|---|
| 907 |
puts("erase verify failed\n"); |
|---|
| 908 |
} else { |
|---|
| 909 |
puts("nvram erase done\n"); |
|---|
| 910 |
} |
|---|
| 911 |
return 0; |
|---|
| 912 |
} |
|---|
| 913 |
|
|---|
| 914 |
} |
|---|
| 915 |
|
|---|
| 916 |
#endif |
|---|
| 917 |
struct nvram_header { |
|---|
| 918 |
__u32 magic; |
|---|
| 919 |
__u32 len; |
|---|
| 920 |
__u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:27 init, mem. test 28, 29-31 reserved */ |
|---|
| 921 |
__u32 config_refresh; /* 0:15 config, 16:31 refresh */ |
|---|
| 922 |
__u32 config_ncdl; /* ncdl values for memc */ |
|---|
| 923 |
}; |
|---|
| 924 |
|
|---|
| 925 |
struct nvram_tuple { |
|---|
| 926 |
char *name; |
|---|
| 927 |
char *value; |
|---|
| 928 |
struct nvram_tuple *next; |
|---|
| 929 |
}; |
|---|
| 930 |
|
|---|
| 931 |
#define NVRAM_SPACE 0x10000 |
|---|
| 932 |
#define NVRAM_MAGIC 0x48534C46 /* 'NVFL' */ |
|---|
| 933 |
|
|---|
| 934 |
static char nvram_buf[65536] __attribute__((aligned(4096))) = { |
|---|
| 935 |
0}; // |
|---|
| 936 |
|
|---|
| 937 |
/* |
|---|
| 938 |
* simple dd-wrt nvram implementation (read only) |
|---|
| 939 |
*/ |
|---|
| 940 |
static void nvram_init(void) |
|---|
| 941 |
{ |
|---|
| 942 |
struct nvram_header *header; |
|---|
| 943 |
__u32 off, lim; |
|---|
| 944 |
int i; |
|---|
| 945 |
#ifndef AR5312 |
|---|
| 946 |
flashdetect(); |
|---|
| 947 |
#endif |
|---|
| 948 |
for (i = 0; i < 4; i++) { |
|---|
| 949 |
header = |
|---|
| 950 |
(struct nvram_header *)(flashbase + flashsize - |
|---|
| 951 |
(sectorsize * (3 + i))); |
|---|
| 952 |
if (header->magic == NVRAM_MAGIC && header->len > 0 |
|---|
| 953 |
&& header->len <= NVRAM_SPACE) { |
|---|
| 954 |
printf |
|---|
| 955 |
("DD-WRT NVRAM with size = %d found on [0x%08X]\n", |
|---|
| 956 |
header->len, header); |
|---|
| 957 |
nvramdetect = (unsigned int)header; |
|---|
| 958 |
unsigned int *src = header; |
|---|
| 959 |
unsigned int *dst = nvram_buf; |
|---|
| 960 |
for (i = 0; i < NVRAM_SPACE / 4; i++) |
|---|
| 961 |
dst[i] = src[i]; |
|---|
| 962 |
return; |
|---|
| 963 |
} |
|---|
| 964 |
} |
|---|
| 965 |
} |
|---|
| 966 |
|
|---|
| 967 |
static char *nvram_get(const char *name) |
|---|
| 968 |
{ |
|---|
| 969 |
char *var, *value, *end, *eq; |
|---|
| 970 |
|
|---|
| 971 |
if (!name) |
|---|
| 972 |
return NULL; |
|---|
| 973 |
|
|---|
| 974 |
if (!nvram_buf[0]) |
|---|
| 975 |
nvram_init(); |
|---|
| 976 |
|
|---|
| 977 |
/* Look for name=value and return value */ |
|---|
| 978 |
var = &nvram_buf[sizeof(struct nvram_header)]; |
|---|
| 979 |
end = nvram_buf + sizeof(nvram_buf) - 2; |
|---|
| 980 |
end[0] = end[1] = '\0'; |
|---|
| 981 |
for (; *var; var = value + strlen(value) + 1) { |
|---|
| 982 |
if (!(eq = strchr(var, '='))) |
|---|
| 983 |
break; |
|---|
| 984 |
value = eq + 1; |
|---|
| 985 |
if ((eq - var) == strlen(name) |
|---|
| 986 |
&& strncmp(var, name, (eq - var)) == 0) |
|---|
| 987 |
return value; |
|---|
| 988 |
} |
|---|
| 989 |
|
|---|
| 990 |
return NULL; |
|---|
| 991 |
} |
|---|
| 992 |
|
|---|
| 993 |
ulg |
|---|
| 994 |
decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p) |
|---|
| 995 |
{ |
|---|
| 996 |
output_data = (uch *) output_start; |
|---|
| 997 |
free_mem_ptr = free_mem_ptr_p; |
|---|
| 998 |
free_mem_ptr_end = free_mem_ptr_end_p; |
|---|
| 999 |
#ifdef AR5312 |
|---|
| 1000 |
#define AR531X_APBBASE 0xbc000000 |
|---|
| 1001 |
#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000) |
|---|
| 1002 |
#define AR531X_WDC (AR531X_RESETTMR + 0x0008) |
|---|
| 1003 |
sysRegWrite(AR531X_WDC, 0); |
|---|
| 1004 |
#endif |
|---|
| 1005 |
arch_decomp_setup(); |
|---|
| 1006 |
printf("MicroRedBoot v1.2, (c) 2009 DD-WRT.COM (%s)\n", __DATE__); |
|---|
| 1007 |
nvram_init(); |
|---|
| 1008 |
char *ddboard = nvram_get("DD_BOARD"); |
|---|
| 1009 |
if (ddboard) |
|---|
| 1010 |
printf("Board: %s\n", ddboard); |
|---|
| 1011 |
char *resetbutton = nvram_get("resetbutton_enable"); |
|---|
| 1012 |
if (resetbutton && !strcmp(resetbutton, "1")) |
|---|
| 1013 |
puts("reset button manual override detected! (nvram var resetbutton_enable=1)\n"); |
|---|
| 1014 |
if (resetTouched() || (resetbutton && !strcmp(resetbutton, "1"))) { |
|---|
| 1015 |
puts("Reset Button triggered\nBooting Recovery RedBoot\n"); |
|---|
| 1016 |
|
|---|
| 1017 |
int count = 5; |
|---|
| 1018 |
while (count--) { |
|---|
| 1019 |
if (!resetTouched()) // check if reset button is unpressed again |
|---|
| 1020 |
break; |
|---|
| 1021 |
udelay(1000000); |
|---|
| 1022 |
} |
|---|
| 1023 |
if (count <= 0) { |
|---|
| 1024 |
puts("reset button 5 seconds pushed, erasing nvram\n"); |
|---|
| 1025 |
|
|---|
| 1026 |
#ifndef AR5312 |
|---|
| 1027 |
if (!flashdetect()) |
|---|
| 1028 |
#endif |
|---|
| 1029 |
flash_erase_nvram(flashsize, sectorsize); |
|---|
| 1030 |
} |
|---|
| 1031 |
|
|---|
| 1032 |
bootoffset = 0x800004bc; |
|---|
| 1033 |
resettrigger = 0; |
|---|
| 1034 |
} else { |
|---|
| 1035 |
#ifndef AR5312 |
|---|
| 1036 |
flashdetect(); |
|---|
| 1037 |
#endif |
|---|
| 1038 |
linuxaddr = getLinux(); |
|---|
| 1039 |
puts("Booting Linux\n"); |
|---|
| 1040 |
resettrigger = 1; |
|---|
| 1041 |
/* initialize clock */ |
|---|
| 1042 |
HAL_CLOCK_INITIALIZE(RTC_PERIOD); |
|---|
| 1043 |
|
|---|
| 1044 |
/* important, enable ethernet bus, if the following lines are not initialized linux will not be able to use the ethernet mac, taken from redboot source */ |
|---|
| 1045 |
#ifdef AR5312 |
|---|
| 1046 |
#define RESET_ENET0 0x00000020 /* cold reset ENET0 mac */ |
|---|
| 1047 |
#define RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ |
|---|
| 1048 |
unsigned int mask = RESET_ENET0 | RESET_EPHY0; |
|---|
| 1049 |
unsigned int regtmp; |
|---|
| 1050 |
#define AR531X_APBBASE 0xbc000000 |
|---|
| 1051 |
#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000) |
|---|
| 1052 |
#define AR531X_RESET (AR531X_RESETTMR + 0x0020) |
|---|
| 1053 |
#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) |
|---|
| 1054 |
#define ENABLE_ENET0 0x0002 |
|---|
| 1055 |
|
|---|
| 1056 |
regtmp = sysRegRead(AR531X_RESET); |
|---|
| 1057 |
sysRegWrite(AR531X_RESET, regtmp | mask); |
|---|
| 1058 |
udelay(15000); |
|---|
| 1059 |
|
|---|
| 1060 |
/* Pull out of reset */ |
|---|
| 1061 |
regtmp = sysRegRead(AR531X_RESET); |
|---|
| 1062 |
sysRegWrite(AR531X_RESET, regtmp & ~mask); |
|---|
| 1063 |
udelay(25); |
|---|
| 1064 |
mask = ENABLE_ENET0; |
|---|
| 1065 |
regtmp = sysRegRead(AR531X_ENABLE); |
|---|
| 1066 |
sysRegWrite(AR531X_ENABLE, regtmp | mask); |
|---|
| 1067 |
|
|---|
| 1068 |
#else |
|---|
| 1069 |
unsigned int mask = RESET_ENET0 | RESET_EPHY0; |
|---|
| 1070 |
unsigned int regtmp; |
|---|
| 1071 |
regtmp = sysRegRead(AR2316_AHB_ARB_CTL); |
|---|
| 1072 |
regtmp |= ARB_ETHERNET; |
|---|
| 1073 |
sysRegWrite(AR2316_AHB_ARB_CTL, regtmp); |
|---|
| 1074 |
|
|---|
| 1075 |
regtmp = sysRegRead(AR2316_RESET); |
|---|
| 1076 |
sysRegWrite(AR2316_RESET, regtmp | mask); |
|---|
| 1077 |
udelay(10000); |
|---|
| 1078 |
|
|---|
| 1079 |
regtmp = sysRegRead(AR2316_RESET); |
|---|
| 1080 |
sysRegWrite(AR2316_RESET, regtmp & ~mask); |
|---|
| 1081 |
udelay(10000); |
|---|
| 1082 |
|
|---|
| 1083 |
regtmp = sysRegRead(AR2316_IF_CTL); |
|---|
| 1084 |
regtmp |= IF_TS_LOCAL; |
|---|
| 1085 |
sysRegWrite(AR2316_IF_CTL, regtmp); |
|---|
| 1086 |
|
|---|
| 1087 |
regtmp = sysRegRead(AR2316_ENDIAN_CTL); |
|---|
| 1088 |
regtmp &= ~CONFIG_ETHERNET; |
|---|
| 1089 |
sysRegWrite(AR2316_ENDIAN_CTL, regtmp); |
|---|
| 1090 |
#endif |
|---|
| 1091 |
|
|---|
| 1092 |
} |
|---|
| 1093 |
puts("loading"); |
|---|
| 1094 |
lzma_unzip(); |
|---|
| 1095 |
puts("\n\n\n"); |
|---|
| 1096 |
|
|---|
| 1097 |
return output_ptr; |
|---|
| 1098 |
} |
|---|
| 1099 |
#else |
|---|
| 1100 |
|
|---|
| 1101 |
char output_buffer[1500 * 1024]; |
|---|
| 1102 |
|
|---|
| 1103 |
int main() |
|---|
| 1104 |
{ |
|---|
| 1105 |
output_data = output_buffer; |
|---|
| 1106 |
puts("Uncompressing Linux..."); |
|---|
| 1107 |
lzma_unzip(); |
|---|
| 1108 |
puts("done.\r\n"); |
|---|
| 1109 |
return 0; |
|---|
| 1110 |
} |
|---|
| 1111 |
#endif |
|---|