2107 lines
62 KiB
C
Executable File
2107 lines
62 KiB
C
Executable File
/*
|
|
* linux/init/main.c
|
|
*
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
|
*
|
|
* GK 2/5/95 - Changed to support mounting root fs via NFS
|
|
* Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
|
|
* Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
|
|
* Simplified starting of init: Michael A. Griffith <grif@acm.org>
|
|
*/
|
|
#include <linux/errno.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel_stat.h>
|
|
#include <linux/types.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/random.h>
|
|
#include <linux/string.h>
|
|
|
|
#include <asm/bitops.h>
|
|
#include <asm/bootinfo.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/mipsregs.h>
|
|
#include <asm/system.h>
|
|
#include <linux/circ_buf.h>
|
|
#include <asm/tc3162.h>
|
|
#include <asm/io.h>
|
|
|
|
#include "../../../version/tcversion.h"
|
|
#include "../../../tools/trx/trx.h"
|
|
|
|
/* frankliao added 20101215 */
|
|
#include <flashhal.h>
|
|
#include "common.h"
|
|
#include "commands.h"
|
|
#include "./banner/mk_time"
|
|
#include "../net/eth.h"
|
|
#if defined(CONFIG_DUAL_IMAGE) || defined(TR068_LED)
|
|
#include "spiflash.h"
|
|
#endif
|
|
#if defined (TCSUPPORT_GPON_DUAL_IMAGE) || defined (TCSUPPORT_EPON_DUAL_IMAGE)
|
|
#include "flash_layout/tc_partition.h"
|
|
struct mtd_info {
|
|
unsigned long offset; /* Offset within the memory */
|
|
unsigned long size; /* Total size of the MTD */
|
|
unsigned long erasesize;
|
|
};
|
|
|
|
extern struct mtd_info mtd;
|
|
#endif
|
|
#ifdef TCSUPPORT_BB_NAND
|
|
#include <mt7510_nandflash.h>
|
|
extern flashdev_info devinfo;
|
|
#endif
|
|
|
|
#ifdef TCSUPPORT_MTD_PARTITIONS_CMDLINE
|
|
#include "mtd_partition_parse.h"
|
|
#endif
|
|
|
|
#define __KERNEL_SYSCALLS__
|
|
|
|
#define SYS_STACK_SIZE (4096 * 2)
|
|
//#define BOOLOADER_VERSION "1.0"
|
|
|
|
#define FLASH_ETH_MAC (0xff48 | flash_base)
|
|
#ifdef TR068_LED
|
|
#define FLASH_POWERLED_GPIO (0xff66 | flash_base)
|
|
#define POWER_LED_GREEN 0
|
|
#define POWER_LED_RED 1
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_NAND_RT63368)
|
|
#define NAND_KERNEL_OFFSET 0x40000
|
|
#endif
|
|
|
|
#ifdef TR068_LED
|
|
#define LED_OEN(x) do { if(x > 31){ \
|
|
if(x > 47){ \
|
|
regWrite32(CR_GPIO_CTRL3,regRead32(CR_GPIO_CTRL3)|(1<<((x-48)*2))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_CTRL2,regRead32(CR_GPIO_CTRL2)|(1<<((x-32)*2))); \
|
|
} \
|
|
regWrite32(CR_GPIO_ODRAIN1,regRead32(CR_GPIO_ODRAIN1)|(1<<(x-32))); \
|
|
} \
|
|
else{ \
|
|
if(x > 15){ \
|
|
regWrite32(CR_GPIO_CTRL1,regRead32(CR_GPIO_CTRL1)|(1<<((x-16)*2))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_CTRL,regRead32(CR_GPIO_CTRL)|(1<<(x*2))); \
|
|
} \
|
|
regWrite32(CR_GPIO_ODRAIN,regRead32(CR_GPIO_ODRAIN)|(1<<(x))); \
|
|
} \
|
|
} while(0)
|
|
|
|
#define LED_OFF(x) do { \
|
|
if(x > 31){ \
|
|
regWrite32(CR_GPIO_DATA1,regRead32(CR_GPIO_DATA1)|(1<<(x-32))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_DATA,regRead32(CR_GPIO_DATA)|(1<<x)); \
|
|
} \
|
|
} while (0)
|
|
#define LED_ON(x) do { \
|
|
if(x > 31){ \
|
|
regWrite32(CR_GPIO_DATA1,regRead32(CR_GPIO_DATA1)& ~(1<<(x-32))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_DATA,regRead32(CR_GPIO_DATA)& ~(1<<x)); \
|
|
} \
|
|
} while (0)
|
|
#endif
|
|
unsigned char init_task_union[SYS_STACK_SIZE];
|
|
|
|
unsigned long kernelsp;
|
|
#if defined(TCSUPPORT_CT_BOOTLOADER_UPGRADE)
|
|
int authed=0; /*flag for tftp upload*/
|
|
#endif
|
|
|
|
extern void __init exception_init(void);
|
|
extern void init_IRQ(void);
|
|
|
|
extern void uart_init(void);
|
|
#ifdef TCSUPPORT_UART2
|
|
extern void uart2_init(void);
|
|
#endif
|
|
extern int eth_init(unsigned char *mac_addr);
|
|
extern int arp_init(void);
|
|
extern int ip_init(unsigned long ip);
|
|
extern int udp_init(void);
|
|
extern int arp_add_entry(unsigned char *ha, unsigned long ip);
|
|
|
|
#ifdef TR068_LED
|
|
void power_gpioInit(uint8 ledColor);
|
|
#endif
|
|
|
|
#ifdef MT7505_SWITCH_TBL_VERIRY
|
|
extern void MT7505_Switch_Tbl_Test(void);
|
|
#endif
|
|
|
|
/*<< BosaZhong@30Apr2014, add, for led */
|
|
unsigned int led_init(void);
|
|
void led_restore(unsigned int restoreReg);
|
|
void led_all_mode(int ledOn);
|
|
/*>> endof BosaZhong@30Apr2014, add, for led */
|
|
|
|
#if defined(TCSUPPORT_ETH4_WAN_PORT)
|
|
#define tcMiiStationRead(x, y) miiStationRead(x, y)
|
|
#define tcMiiStationWrite(x, y, z) miiStationWrite(x, y, z)
|
|
#endif
|
|
static unsigned char mac_addr[6] = {0x00, 0xaa, 0xbb, 0x01, 0x23, 0x45};
|
|
//static unsigned long ip_addr = 0xc0a801fe;
|
|
static unsigned long ip_addr = 0xc0a80101;
|
|
|
|
extern unsigned long Jiffies;
|
|
|
|
/* frankliao modify 20100806 */
|
|
extern int set_lzma_addr(char* lzma_data_start, char* lzma_data_end);
|
|
extern unsigned long decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p);
|
|
/* frankliao modify 20100805 for bootloader checksum */
|
|
#if defined(CONFIG_DUAL_IMAGE) || defined(TR068_LED) || defined(BOOT_LZMA_SUPPORT) || defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
|
|
/**********************************************************************/
|
|
/* The following was grabbed and tweaked from the old snippets collection
|
|
* of public domain C code. */
|
|
|
|
/**********************************************************************\
|
|
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|
|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|
|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|
|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|
|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|
|
|* this polynomial is or will be included in CCITT V.41, which *|
|
|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|
|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|
|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
|
|
\**********************************************************************/
|
|
|
|
/* Copyright (C) 1986 Gary S. Brown. You may use this program, or
|
|
code or tables extracted from it, as desired without restriction.*/
|
|
|
|
/* First, the polynomial itself and its table of feedback terms. The */
|
|
/* polynomial is */
|
|
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
|
|
/* Note that we take it "backwards" and put the highest-order term in */
|
|
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
|
|
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
|
|
/* the MSB being 1. */
|
|
|
|
/* Note that the usual hardware shift register implementation, which */
|
|
/* is what we're using (we're merely optimizing it by doing eight-bit */
|
|
/* chunks at a time) shifts bits into the lowest-order term. In our */
|
|
/* implementation, that means shifting towards the right. Why do we */
|
|
/* do it this way? Because the calculated CRC must be transmitted in */
|
|
/* order from highest-order term to lowest-order term. UARTs transmit */
|
|
/* characters in order from LSB to MSB. By storing the CRC this way, */
|
|
/* we hand it to the UART in the order low-byte to high-byte; the UART */
|
|
/* sends each low-bit to hight-bit; and the result is transmission bit */
|
|
/* by bit from highest- to lowest-order term without requiring any bit */
|
|
/* shuffling on our part. Reception works similarly. */
|
|
|
|
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
|
|
/* */
|
|
/* 1. The table can be generated at runtime if desired; code to do so */
|
|
/* is shown later. It might not be obvious, but the feedback */
|
|
/* terms simply represent the results of eight shift/xor opera- */
|
|
/* tions for all combinations of data and CRC register values. */
|
|
/* */
|
|
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
|
|
/* be they sixteen or thirty-two bits wide. You simply choose the */
|
|
/* appropriate table. Alternatively, because the table can be */
|
|
/* generated at runtime, you can start by generating the table for */
|
|
/* the polynomial in question and use exactly the same "updcrc", */
|
|
/* if your application needn't simultaneously handle two CRC */
|
|
/* polynomials. (Note, however, that XMODEM is strange.) */
|
|
/* */
|
|
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
|
|
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
|
|
/* */
|
|
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
|
|
/* logic; the shift must be unsigned (bring in zeroes). On some */
|
|
/* hardware you could probably optimize the shift in assembler by */
|
|
/* using byte-swap instructions. */
|
|
static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
|
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
|
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
|
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
|
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
|
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
|
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
|
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
|
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
|
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
|
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
|
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
|
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
|
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
|
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
|
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
|
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
|
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
|
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
|
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
|
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
|
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
|
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
|
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
|
};
|
|
|
|
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
|
|
|
|
uint32_t crc32buf(char *buf, size_t len, int flags)
|
|
{
|
|
uint32_t crc;
|
|
/* frank added 20101208 */
|
|
char ch;
|
|
#ifdef TCSUPPORT_NEW_SPIFLASH
|
|
#define READBUFSIZE 4096
|
|
unsigned long retlen=0;
|
|
unsigned char membuf[READBUFSIZE];
|
|
uint32 i=0, index=0;
|
|
uint32 curLen= len;
|
|
uint32 from = buf;
|
|
#endif
|
|
|
|
crc = 0xFFFFFFFF;
|
|
|
|
/* for read data from flash */
|
|
if (flags == 0) {
|
|
#ifdef TCSUPPORT_NEW_SPIFLASH
|
|
from &= 0x03FFFFFF;
|
|
curLen = len % READBUFSIZE;
|
|
index = 0;
|
|
while(len) {
|
|
flash_read((unsigned long)(from+index), curLen, &retlen, membuf);
|
|
for (i=0; i<curLen; i++)
|
|
{
|
|
crc = UPDC32(membuf[i], crc);
|
|
}
|
|
len -= curLen;
|
|
index += curLen;
|
|
curLen = READBUFSIZE;
|
|
}
|
|
#else
|
|
for ( ; len; --len, ++buf)
|
|
{
|
|
ch = READ_FLASH_CACHE(buf);
|
|
crc = UPDC32(ch, crc);
|
|
// crc = UPDC32(*buf, crc);
|
|
}
|
|
#endif
|
|
/* for read data from sdram */
|
|
} else {
|
|
for ( ; len; --len, ++buf)
|
|
{
|
|
crc = UPDC32(*buf, crc);
|
|
}
|
|
}
|
|
return (uint32_t)crc;
|
|
}
|
|
#endif
|
|
unsigned long calculate_dram_size(void){
|
|
#ifdef TC3262
|
|
if(isEN751221){
|
|
if( isFPGA){
|
|
return 8 * (1 << (((VPint(0xbfb0008c) >> 13) & 0x7) - 1));
|
|
}else{
|
|
return GET_DRAM_SIZE;
|
|
}
|
|
}else if(isMT751020){
|
|
return 8 * (1 << (((VPint(0xbfb0008c) >> 13) & 0x7) - 1));
|
|
}else if(isMT7505){
|
|
if( isFPGA){
|
|
return 8 * (1 << (((VPint(0xbfb0008c) >> 13) & 0x7) - 1));
|
|
}
|
|
else
|
|
{
|
|
if(VPint(CR_AHB_HWCONF) & (1<<10))
|
|
{
|
|
/* DDR1 */
|
|
return 64 / (1 << ((VPint(CR_AHB_HWCONF) >> 11) & 0x3));
|
|
}
|
|
else{
|
|
/* DDR2 */
|
|
if(!((VPint(CR_AHB_HWCONF) >> 11) & 0x3))
|
|
return 256;
|
|
if(((VPint(CR_AHB_HWCONF) >> 11) & 0x3) == 0x1)
|
|
return 32;
|
|
if(((VPint(CR_AHB_HWCONF) >> 11) & 0x3) == 0x2)
|
|
return 128;
|
|
else
|
|
return 64;
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (isRT63165 || isRT63365) {
|
|
//if (VPint(CR_AHB_HWCONF) & (0x3<<24)) {
|
|
if (VPint(CR_AHB_HWCONF) & (1<<25)) {
|
|
return 8 * (1 << (((VPint(CR_DMC_DDR_CFG1) >> 18) & 0x7) - 1));
|
|
|
|
/* SDRAM */
|
|
} else {
|
|
unsigned long sdram_cfg1;
|
|
unsigned long col;
|
|
unsigned long row;
|
|
unsigned long bank = 4;
|
|
|
|
/* calculate SDRAM size */
|
|
sdram_cfg1 = VPint(0xbfb20004);
|
|
row = 11 + ((sdram_cfg1>>16) & 0x3);
|
|
col = 8 + ((sdram_cfg1>>20) & 0x3);
|
|
if ((row == 11) && (col == 8))
|
|
bank = 2;
|
|
/* 4 banks and 16 bit width */
|
|
return (((1 << row) * (1 << col) * bank * 2)>>20);
|
|
}
|
|
} else {
|
|
return (8 * (1 << (((VPint(CR_DMC_CTL1) >> 18) & 0x7) - 1)));
|
|
}
|
|
#else
|
|
unsigned long memsize;
|
|
unsigned char samt;
|
|
unsigned long col;
|
|
unsigned long row;
|
|
|
|
/* calculate SDRAM size */
|
|
samt = VPchar(CR_DMC_SAMT);
|
|
row = 8 + (samt & 0x3);
|
|
col = 11 + ((samt>>2) & 0x3);
|
|
/* 4 bands and 16 bit width */
|
|
memsize = (1 << row) * (1 << col) * 4 * 2;
|
|
|
|
return (memsize>>20);
|
|
#endif
|
|
}
|
|
|
|
#if defined(CONFIG_DUAL_IMAGE) || defined(TR068_LED)
|
|
int checkimage(int imageflag)
|
|
{
|
|
struct trx_header *trx = NULL;
|
|
char *input_data = NULL;
|
|
char *trx_addr; //frankliao added
|
|
unsigned int len, crc32, magic; // frankliao added 20101208
|
|
|
|
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
|
|
input_data = (char *) (flash_base + 0x280000);
|
|
#elif defined(TCSUPPORT_NAND_RT63368)
|
|
input_data = (char *) (flash_base + NAND_KERNEL_OFFSET);
|
|
#else
|
|
#if defined(TCSUPPORT_CPU_EN7512)||defined(TCSUPPORT_CPU_EN7521)
|
|
|
|
if(IS_SPIFLASH)
|
|
{
|
|
flash_tclinux_start = 0x30000;
|
|
}
|
|
#endif
|
|
|
|
input_data = (char *) (flash_base + flash_tclinux_start);
|
|
#endif
|
|
|
|
if(MAIN_IMAGE == imageflag)
|
|
{
|
|
// input_data = (char *) 0xb0020000;
|
|
trx = (struct trx_header *)input_data;
|
|
trx_addr = &(trx->len);
|
|
len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx->crc32);
|
|
crc32 = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx->magic);
|
|
magic = READ_FLASH_DWORD(trx_addr);
|
|
|
|
// if ((trx->magic != TRX_MAGIC2) || (trx->len < sizeof(struct trx_header)))
|
|
if ((magic != TRX_MAGIC2) || (len < sizeof(struct trx_header)))
|
|
{
|
|
prom_printf("\r\n main tclinux.bin magic or len check error!");
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
// if(trx->crc32 != crc32buf((char *)(input_data+sizeof(struct trx_header)), (trx->len-sizeof(struct trx_header))))
|
|
if(crc32 != crc32buf((char *)(input_data+sizeof(struct trx_header)), (len-sizeof(struct trx_header)), 0))
|
|
{
|
|
prom_printf("\r\n main tclinux.bin crc check error!");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
else if(SLAVE_IMAGE == imageflag)
|
|
{
|
|
//input_data = (char *) (0xb0020000+0x500000);
|
|
#ifdef TCSUPPORT_DUAL_IMAGE_ENHANCE
|
|
#ifdef TCSUPPORT_NAND_RT63368
|
|
input_data = (char *) (input_data + offset - 0x20000);
|
|
#else
|
|
input_data = (char *) (input_data+offset);
|
|
#endif
|
|
#elif defined(TCSUPPORT_NAND_BADBLOCK_CHECK)
|
|
input_data = (char *) (flash_base + 0x2280000);
|
|
#else
|
|
input_data = (char *) (input_data+TCLINUX_SLAVE_FLASH_START);
|
|
#endif
|
|
trx = (struct trx_header *)input_data;
|
|
trx_addr = &(trx->len);
|
|
len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx->crc32);
|
|
crc32 = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx->magic);
|
|
magic = READ_FLASH_DWORD(trx_addr);
|
|
|
|
// if ((trx->magic != TRX_MAGIC2) || (trx->len < sizeof(struct trx_header)))
|
|
if ((magic != TRX_MAGIC2) || (len < sizeof(struct trx_header)))
|
|
{
|
|
prom_printf("\r\n slave tclinux.bin magic or len check error!");
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
// if(trx->crc32 != crc32buf((char *)(input_data+sizeof(struct trx_header)), (trx->len-sizeof(struct trx_header))))
|
|
if(crc32 != crc32buf((char *)(input_data+sizeof(struct trx_header)), (len-sizeof(struct trx_header)), 0))
|
|
{
|
|
prom_printf("\r\n slave tclinux.bin crc check error!");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prom_printf("\r\n no choose any image ,error!");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#if defined(TCSUPPORT_DUAL_IMAGE_ENHANCE) || defined(TCSUPPORT_NAND_BADBLOCK_CHECK)
|
|
unsigned short CheckSum(unsigned short *szBUF,int iSize)
|
|
{
|
|
unsigned long ckSum=0;
|
|
for(;iSize>1;iSize-=sizeof(unsigned short))
|
|
ckSum+=*szBUF++;
|
|
if(iSize==1)
|
|
ckSum+=*(unsigned char *)szBUF;
|
|
ckSum=(ckSum>>16)+(ckSum&0xffff);
|
|
ckSum+=(ckSum>>16);
|
|
return(unsigned short )(~ckSum);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#if defined (TCSUPPORT_GPON_DUAL_IMAGE) || defined (TCSUPPORT_EPON_DUAL_IMAGE)
|
|
#ifdef TCSUPPORT_BB_NAND
|
|
#if defined(TCSUPPORT_CT_PON)
|
|
extern int nand_logic_size;
|
|
extern int nand_flash_avalable_size;
|
|
extern u32 reservearea_size;
|
|
#endif
|
|
#endif
|
|
char readBootFlagFromFlash(void)
|
|
{
|
|
unsigned long retlen = 0;
|
|
unsigned int boot_flag_addr = 0;
|
|
char flag = 0;
|
|
#if defined(TCSUPPORT_CT)
|
|
#ifdef TCSUPPORT_BB_NAND
|
|
#if defined(TCSUPPORT_CT_PON)
|
|
boot_flag_addr = flash_base + nand_flash_avalable_size - reservearea_size * TCSUPPORT_RESERVEAREA_BLOCK + IMG_BOOT_FLAG_OFFSET;
|
|
#else
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + CERM1_RA_OFFSET -1;
|
|
#endif
|
|
#else
|
|
#if defined(TCSUPPORT_RESERVEAREA_EXTEND)
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + IMG_BOOT_FLAG_OFFSET;
|
|
#else
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + CERM1_RA_OFFSET -1;
|
|
#endif
|
|
#endif
|
|
#else
|
|
#ifdef TCSUPPORT_BB_NAND
|
|
if (IS_NANDFLASH)
|
|
boot_flag_addr = flash_base + (devinfo.totalsize << MB_SHIFT) - (devinfo.blocksize << KB_SHIFT) * TCSUPPORT_RESERVEAREA_BLOCK + MRD_RA_OFFSET -1;
|
|
else
|
|
#endif
|
|
#if (TCSUPPORT_RESERVEAREA_BLOCK==4)
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + DEFAULTROMFILE_RA_OFFSET;
|
|
#else
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + MRD_RA_OFFSET -1;
|
|
#endif
|
|
#endif
|
|
#if 0
|
|
prom_printf("\n>>>> CTC: flash_base: %x; mtd.size: %x, erasesize: %x, block size: %d, MRD_RA_OFFSET: %x\n",\
|
|
flash_base, mtd.size, mtd.erasesize, TCSUPPORT_RESERVEAREA_BLOCK, MRD_RA_OFFSET);
|
|
#endif
|
|
if (IS_NANDFLASH)
|
|
flash_read(boot_flag_addr, 1, &retlen, &flag);
|
|
else
|
|
memcpy(&flag, boot_flag_addr, 1);
|
|
|
|
flag = flag - '0';
|
|
// prom_printf("\n>>>> CTC: boot_flag_addr: %x; flag: %d\n", boot_flag_addr, flag);
|
|
if (flag != 0 && flag != 1){
|
|
flag = 0;
|
|
}
|
|
|
|
return flag;
|
|
}
|
|
|
|
|
|
#define COMMIT_FLAG_ADDR 0x80001ffe
|
|
#define DEFAULTROMFILE_RA_SIZE 0x10000
|
|
#define DEFAULTROMFILE_RA_OFFSET 0x10000
|
|
|
|
|
|
void exchange_fw(char boot_flag, char commit_flag)
|
|
{
|
|
unsigned int flash_dr_addr = 0;
|
|
unsigned long retlen = 0;
|
|
/*set default romfile physical address*/
|
|
flash_dr_addr = 0xFD0000;
|
|
boot_flag = boot_flag + '0';
|
|
commit_flag = commit_flag + '0';
|
|
prom_printf("\n>>>> MSTC exchange: 3_from %x; len: %d\n", flash_dr_addr, DEFAULTROMFILE_RA_SIZE);
|
|
flash_erase(flash_dr_addr,DEFAULTROMFILE_RA_SIZE);
|
|
/*write boot flag -- image0*/
|
|
flash_write(flash_dr_addr, 1, &retlen, &boot_flag);
|
|
/*write commit flag ---image0*/
|
|
flash_write(flash_dr_addr + 1, 1, &retlen, &commit_flag);
|
|
}
|
|
unsigned char readCommitFlagFromFlash(void)
|
|
{
|
|
unsigned long retlen = 0;
|
|
unsigned int commit_flag_addr = 0;
|
|
unsigned char flag = 0;
|
|
|
|
commit_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + DEFAULTROMFILE_RA_OFFSET + 1;
|
|
|
|
memcpy(&flag, commit_flag_addr, 1);
|
|
|
|
flag = flag - '0';
|
|
prom_printf("\n>>>> MSTC read commit: commit_flag_addr: %x; flag: %d\n", commit_flag_addr, flag);
|
|
if (flag != 0 && flag != 1){
|
|
flag = 0;
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
void writeCommitFlagToFlash(char flag)
|
|
{
|
|
unsigned int flash_dr_addr = 0;
|
|
unsigned long retlen = 0;
|
|
/*set default romfile physical address*/
|
|
flash_dr_addr = 0xFD0000;
|
|
flag = flag + '0';
|
|
prom_printf("\n>>>> MSTC exchange: 2_from %x; len: %d\n", flash_dr_addr, DEFAULTROMFILE_RA_SIZE);
|
|
flash_erase(flash_dr_addr,DEFAULTROMFILE_RA_SIZE);
|
|
|
|
/*write commit flag ---image0*/
|
|
flash_write(flash_dr_addr + 1, 1, &retlen, &flag);
|
|
prom_printf("\n>>>> MSTC write flag: commit_flag_addr: %x; flag: %d\n", flash_dr_addr, flag);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_CT_UPG_PINGPONG)
|
|
void writeBootFlagtoFlash(char flag)
|
|
{
|
|
unsigned long retlen = 0;
|
|
unsigned int boot_flag_addr = 0;
|
|
|
|
//prom_printf("\n>>>> CTC write flag: boot_flag_addr: %x; flag: %d\n", boot_flag_addr, flag);
|
|
if (flag != 0 && flag != 1){
|
|
prom_printf("\n>>>> boot flag illegal: %d\n", flag);
|
|
return;
|
|
}
|
|
flag = flag + '0';
|
|
|
|
#if defined(TCSUPPORT_CT)
|
|
#ifdef TCSUPPORT_BB_NAND
|
|
#if defined(TCSUPPORT_CT_PON)
|
|
boot_flag_addr = flash_base + nand_flash_avalable_size - reservearea_size * TCSUPPORT_RESERVEAREA_BLOCK + IMG_BOOT_FLAG_OFFSET;
|
|
#else
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + CERM1_RA_OFFSET -1;
|
|
#endif
|
|
#else
|
|
//boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + CERM1_RA_OFFSET -1;
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + IMG_BOOT_FLAG_OFFSET;
|
|
#endif
|
|
#else
|
|
#ifdef TCSUPPORT_BB_NAND
|
|
if (IS_NANDFLASH)
|
|
boot_flag_addr = flash_base + (devinfo.totalsize << MB_SHIFT) - (devinfo.blocksize << KB_SHIFT) * TCSUPPORT_RESERVEAREA_BLOCK + MRD_RA_OFFSET -1;
|
|
else
|
|
#endif
|
|
boot_flag_addr = flash_base + mtd.size - mtd.erasesize * TCSUPPORT_RESERVEAREA_BLOCK + MRD_RA_OFFSET -1;
|
|
#endif
|
|
|
|
#if 0
|
|
prom_printf("\n>>>> CTC: flash_base: %x; mtd.size: %x, erasesize: %x, block size: %d, MRD_RA_OFFSET: %x\n",\
|
|
flash_base, mtd.size, mtd.erasesize, TCSUPPORT_RESERVEAREA_BLOCK, MRD_RA_OFFSET);
|
|
#endif
|
|
if (IS_NANDFLASH)
|
|
flash_write(boot_flag_addr, 1, &retlen, &flag);
|
|
else
|
|
memcpy(boot_flag_addr, &flag, 1);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_IS_FH_PON) || defined(TCSUPPORT_FWC_ENV)
|
|
#if defined(TCSUPPORT_FWC_ENV)
|
|
static E_FH_NW_PRODUCT_CRC_CHECK_T check_fh_nw_product_kernel_crc(E_FH_NW_PRODUCT_PARTITION_T info)
|
|
{
|
|
unsigned long base_addr = 0;
|
|
unsigned long retlen = 0;
|
|
char *input_data = NULL;
|
|
unsigned int len = 0;
|
|
unsigned int kernel_len = 0;
|
|
unsigned int crc_check_sum = 0;
|
|
struct trx_header trx;
|
|
unsigned char str_name[32];
|
|
memset(str_name, 0, sizeof(str_name));
|
|
switch(info)
|
|
{
|
|
case E_FH_NW_PRODUCT_KERNEL_A:
|
|
{
|
|
input_data = (char *) (flash_base + FH_NW_PRODUCT_KERNELA_ADDR);
|
|
base_addr = flash_base + FH_NW_PRODUCT_KERNELA_ADDR;
|
|
strcpy(str_name, "kernel A");
|
|
break;
|
|
}
|
|
case E_FH_NW_PRODUCT_KERNEL_B:
|
|
{
|
|
input_data = (char *) (flash_base + FH_NW_PRODUCT_KERNELB_ADDR);
|
|
base_addr = flash_base + FH_NW_PRODUCT_KERNELB_ADDR;
|
|
strcpy(str_name, "kernel B");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
prom_printf("\n crc can't support info = %d. line = %d.\n", info, __LINE__);
|
|
return E_FH_NW_PRODUCT_CHECK_WRONG;
|
|
}
|
|
}
|
|
|
|
memset(&trx, 0, sizeof(trx));
|
|
flash_read(base_addr, sizeof(struct trx_header), &retlen, (unsigned char *)&trx);
|
|
crc_check_sum = trx.crc32;
|
|
len = trx.len;
|
|
|
|
if((0xFFFFFFFF == len) || (0xFFFFFFFF == crc_check_sum) || (len <= sizeof(struct trx_header)))
|
|
{
|
|
return E_FH_NW_PRODUCT_CHECK_WRONG;
|
|
}
|
|
if(crc_check_sum != crc32buf((char *)(input_data+sizeof(struct trx_header)), (len-sizeof(struct trx_header)), 0))
|
|
{
|
|
prom_printf("\n %s crc check wrong. line = %d.\n", str_name, __LINE__);
|
|
return E_FH_NW_PRODUCT_CHECK_WRONG;
|
|
}
|
|
else
|
|
{
|
|
prom_printf("\n %s crc check right. line = %d.\n", str_name, __LINE__);
|
|
}
|
|
|
|
return E_FH_NW_PRODUCT_CHECK_RIGHT;
|
|
}
|
|
|
|
static int kernel_try_start(E_FH_NW_PRODUCT_START_UP_MARK_T flag)
|
|
{
|
|
int iret = 0;
|
|
unsigned char str_name[32];
|
|
unsigned long output_data = KERNEL_START_ADDR;;
|
|
unsigned long free_mem_ptr = KERNEL_RAM_START;
|
|
unsigned long free_mem_ptr_end = KERNEL_RAM_END;
|
|
unsigned char k_decompress_ret = 0;
|
|
E_FH_NW_PRODUCT_CRC_CHECK_T crc_ret = E_FH_NW_PRODUCT_CHECK_RIGHT;
|
|
E_FH_NW_PRODUCT_PARTITION_T info = E_FH_NW_PRODUCT_KERNEL_A;
|
|
|
|
memset(str_name, 0, sizeof(str_name));
|
|
if(E_FH_NW_PRODUCT_START_UP_B == flag)
|
|
{
|
|
info = E_FH_NW_PRODUCT_KERNEL_B;
|
|
strcpy(str_name, "kernel B");
|
|
}
|
|
else
|
|
{
|
|
info = E_FH_NW_PRODUCT_KERNEL_A;
|
|
strcpy(str_name, "kernel A");
|
|
}
|
|
|
|
crc_ret = check_fh_nw_product_kernel_crc(info);
|
|
if(E_FH_NW_PRODUCT_CHECK_RIGHT != crc_ret)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if(E_FH_NW_PRODUCT_KERNEL_B == info)
|
|
{
|
|
set_lzma_addr((flash_base+FH_NW_PRODUCT_KERNELB_ADDR+sizeof(struct trx_header)), (flash_base+FH_NW_PRODUCT_KERNELB_ADDR+FH_NW_PRODUCT_KERNEL_SIZE-sizeof(struct trx_header)));
|
|
k_decompress_ret = decompress_kernel(output_data, free_mem_ptr, free_mem_ptr_end);
|
|
if(E_FH_NW_PRODUCT_DECOMPRESS_RIGHT != k_decompress_ret)
|
|
{
|
|
prom_printf("\n decompress_kernel %s fail. line = %d.\n", str_name, __LINE__);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
set_lzma_addr((flash_base+FH_NW_PRODUCT_KERNELA_ADDR+sizeof(struct trx_header)),(flash_base+FH_NW_PRODUCT_KERNELA_ADDR+FH_NW_PRODUCT_KERNEL_SIZE-sizeof(struct trx_header)));
|
|
k_decompress_ret = decompress_kernel(output_data, free_mem_ptr, free_mem_ptr_end);
|
|
if(E_FH_NW_PRODUCT_DECOMPRESS_RIGHT != k_decompress_ret)
|
|
{
|
|
prom_printf("\n decompress_kernel %s fail. line = %d.\n", str_name, __LINE__);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
prom_printf("Decompress to %X free_mem_ptr=%X free_mem_ptr_end=%X\n", output_data, free_mem_ptr, free_mem_ptr_end);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int get_partition_start_up_flag(E_FH_NW_PRODUCT_ACTIVE_MARK_T active_flag, E_FH_NW_PRODUCT_COMMIT_MARK_T commit_flag)
|
|
{
|
|
E_FH_NW_PRODUCT_START_UP_MARK_T start_up_flag = E_FH_NW_PRODUCT_START_UP_A;
|
|
|
|
if(E_FH_NW_PRODUCT_ACTIVE_DEFAULT == active_flag)
|
|
{
|
|
if(E_FH_NW_PRODUCT_COMMIT_B == commit_flag)
|
|
{
|
|
start_up_flag = E_FH_NW_PRODUCT_START_UP_B;
|
|
}
|
|
else
|
|
{
|
|
start_up_flag = E_FH_NW_PRODUCT_START_UP_A;
|
|
}
|
|
}
|
|
else if(E_FH_NW_PRODUCT_ACTIVE_B == active_flag)
|
|
{
|
|
start_up_flag = E_FH_NW_PRODUCT_START_UP_B;
|
|
}
|
|
else
|
|
{
|
|
start_up_flag = E_FH_NW_PRODUCT_START_UP_A;
|
|
}
|
|
|
|
return start_up_flag;
|
|
}
|
|
|
|
static void prepare_bootenv_2_kernel(void)
|
|
{
|
|
int iret = 0;
|
|
dual_image_flag_t dual_image_env;
|
|
personality_parm_flash_env_t flash_env;
|
|
personality_parm_memory_env_t memory_env;
|
|
personality_parm_boot_to_kernel_info_t to_kernel_env;
|
|
personality_parm_boot_to_kernel_info_t *to_kernel_env_addr = (personality_parm_boot_to_kernel_info_t *) FH_NW_PRODUCT_BOOT2KRENEL_ENV_ADDR;
|
|
|
|
memset(&to_kernel_env, 0, sizeof(to_kernel_env));
|
|
/*prepare dual image flag env info*/
|
|
memset(&dual_image_env, 0, sizeof(dual_image_env));
|
|
iret = read_fh_nw_product_dual_image_flag_env(&dual_image_env);
|
|
if(0 != iret)
|
|
{
|
|
memset(&dual_image_env, 0, sizeof(dual_image_env));
|
|
}
|
|
to_kernel_env.realtime_env.app1_active = dual_image_env.app1_active;
|
|
to_kernel_env.realtime_env.app1_commit = dual_image_env.app1_commit;
|
|
to_kernel_env.realtime_env.app2_active = dual_image_env.app2_active;
|
|
to_kernel_env.realtime_env.app2_commit = dual_image_env.app2_commit;
|
|
to_kernel_env.realtime_env.kernel_active = dual_image_env.kernel_active;
|
|
to_kernel_env.realtime_env.kernel_commit = dual_image_env.kernel_commit;
|
|
to_kernel_env.realtime_env.rootfs_active = dual_image_env.rootfs_active;
|
|
to_kernel_env.realtime_env.rootfs_commit = dual_image_env.rootfs_commit;
|
|
|
|
/*prepare flash env info*/
|
|
memset(&flash_env, 0, sizeof(flash_env));
|
|
iret = read_fh_nw_product_flash_env(&flash_env);
|
|
if(0 != iret)
|
|
{
|
|
memset(&flash_env, 0, sizeof(flash_env));
|
|
strcpy(flash_env.eth_addr, "00:0A:C2:12:34:56");
|
|
strcpy(flash_env.hw_cfg, "0x77");
|
|
strcpy(flash_env.sn_oui, "00");
|
|
}
|
|
memcpy((char *)&to_kernel_env+sizeof(realtime_dual_image_env_t), &flash_env, sizeof(flash_env));
|
|
|
|
/*prepare memory env info*/
|
|
memset(&memory_env, 0, sizeof(memory_env));
|
|
iret = read_fh_nw_product_memory_env(&memory_env);
|
|
if(0 != iret)
|
|
{
|
|
memset(&memory_env, 0, sizeof(memory_env));
|
|
strcpy(memory_env.boot_version, "V1");
|
|
strcpy(memory_env.m_reserve0, PERSONALITY_PARM_DUAL_IMAGE_WRITE_PARTITION);
|
|
}
|
|
|
|
memcpy((char *)&to_kernel_env+sizeof(dual_image_env)+sizeof(flash_env), &memory_env ,sizeof(memory_env));
|
|
|
|
/*prepare env info 2 kernel*/
|
|
memcpy(to_kernel_env_addr, &to_kernel_env, sizeof(to_kernel_env));
|
|
|
|
return ;
|
|
}
|
|
void boot_kernel(void)
|
|
{
|
|
int iret = 0;
|
|
unsigned long startAddr = 0x0;
|
|
unsigned int kernel_size = 0;
|
|
E_FH_NW_PRODUCT_COMMIT_MARK_T kernel_commit = E_FH_NW_PRODUCT_COMMIT_A;
|
|
E_FH_NW_PRODUCT_ACTIVE_MARK_T kernel_active = E_FH_NW_PRODUCT_ACTIVE_DEFAULT;
|
|
E_FH_NW_PRODUCT_COMMIT_MARK_T rootfs_commit = E_FH_NW_PRODUCT_COMMIT_A;
|
|
E_FH_NW_PRODUCT_ACTIVE_MARK_T rootfs_active = E_FH_NW_PRODUCT_ACTIVE_DEFAULT;
|
|
E_FH_NW_PRODUCT_START_UP_MARK_T kernel_run = E_FH_NW_PRODUCT_START_UP_A;
|
|
E_FH_NW_PRODUCT_START_UP_MARK_T rootfs_run = E_FH_NW_PRODUCT_START_UP_A;
|
|
E_FH_NW_PRODUCT_ROOLBACK_MARK_T kernel_roolback = E_FH_NW_PRODUCT_ROOLBACK_FALSE;
|
|
personality_parm_boot_to_kernel_info_t *to_kernel_env_addr = (personality_parm_boot_to_kernel_info_t *) FH_NW_PRODUCT_BOOT2KRENEL_ENV_ADDR;
|
|
|
|
void (*jumpAddr)();
|
|
/* Disable all hardware interrupts */
|
|
change_cp0_status(ST0_IM, 0x00);
|
|
|
|
tc_outl(CR_INTC_IMR, 0x0);
|
|
tc_outl(CR_TIMER_CTL, 0x0);
|
|
tc_outl(CR_MAC_MACCR, 0x0);
|
|
|
|
/*prepare boot2kernel env*/
|
|
prepare_bootenv_2_kernel();
|
|
kernel_commit = to_kernel_env_addr->realtime_env.kernel_commit;
|
|
kernel_active = to_kernel_env_addr->realtime_env.kernel_active;
|
|
rootfs_commit = to_kernel_env_addr->realtime_env.rootfs_commit;
|
|
rootfs_active = to_kernel_env_addr->realtime_env.rootfs_active;
|
|
|
|
/*try start kernel from active && commit flag*/
|
|
kernel_run = get_partition_start_up_flag(kernel_active, kernel_commit);
|
|
iret = kernel_try_start(kernel_run);
|
|
if(0 != iret)
|
|
{
|
|
kernel_roolback = E_FH_NW_PRODUCT_ROOLBACK_TRUE;
|
|
if(E_FH_NW_PRODUCT_START_UP_A == kernel_run)
|
|
{
|
|
kernel_run = E_FH_NW_PRODUCT_START_UP_B;
|
|
}
|
|
else
|
|
{
|
|
kernel_run = E_FH_NW_PRODUCT_START_UP_A;
|
|
}
|
|
|
|
iret = kernel_try_start(kernel_run);
|
|
{
|
|
if(0 != iret)
|
|
{
|
|
prom_printf("kernel A && B can't start up.\n");
|
|
prom_printf("\n -- System halted");
|
|
while(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*decide mount master/slave rootfs*/
|
|
rootfs_run = get_partition_start_up_flag(rootfs_active, rootfs_commit);
|
|
/*boot2kernel env change*/
|
|
to_kernel_env_addr->realtime_env.kernel_run = kernel_run;
|
|
to_kernel_env_addr->realtime_env.kernel_roolback = kernel_roolback;
|
|
to_kernel_env_addr->realtime_env.rootfs_run = rootfs_run;
|
|
|
|
kernel_size = FH_NW_PRODUCT_KERNEL_SIZE - sizeof(struct trx_header);
|
|
startAddr = 0x80002000;
|
|
VPint(0xbfb00240) = 0;
|
|
prom_printf("75xx: 0x%x\n",0);
|
|
|
|
if(startAddr != 0)
|
|
{
|
|
jumpAddr = (void (*)(void))(startAddr);
|
|
}
|
|
else
|
|
{
|
|
jumpAddr = (void (*)(void))(0x80020000);
|
|
}
|
|
|
|
#ifdef TC3262
|
|
if (IS_NANDFLASH )
|
|
flush_icache_range(startAddr, startAddr + kernel_size*4);
|
|
#endif
|
|
|
|
(*jumpAddr)();
|
|
}
|
|
|
|
#else
|
|
char readBootFlagFromFlash_FH(void)
|
|
{
|
|
unsigned long retlen = 0;
|
|
unsigned int boot_flag_addr = 0x1e0000;
|
|
unsigned char flag = 1;
|
|
int i=0 ;
|
|
char buf[16];
|
|
|
|
flash_read(boot_flag_addr, 1, &retlen, &flag);
|
|
|
|
flag = flag - '0';
|
|
|
|
if (flag != 0 && flag != 1){
|
|
flag = 0;
|
|
}
|
|
|
|
return flag;
|
|
}
|
|
|
|
char readRootFlagFromFlash_FH(void)
|
|
{
|
|
unsigned long retlen = 0;
|
|
unsigned int root_flag_addr = 0x1e0004;
|
|
unsigned char flag = 1;
|
|
int i=0 ;
|
|
char buf[16];
|
|
|
|
flash_read(root_flag_addr, 1, &retlen, &flag);
|
|
|
|
flag = flag - '0';
|
|
|
|
if (flag != 0 && flag != 1){
|
|
flag = 0;
|
|
}
|
|
|
|
return flag;
|
|
}
|
|
|
|
void boot_kernel(void)
|
|
{
|
|
unsigned long output_data;
|
|
unsigned long free_mem_ptr;
|
|
unsigned long free_mem_ptr_end;
|
|
void (*jumpAddr)();
|
|
|
|
output_data = KERNEL_START_ADDR;
|
|
free_mem_ptr = KERNEL_RAM_START;
|
|
free_mem_ptr_end = KERNEL_RAM_END;
|
|
unsigned long retlen;
|
|
|
|
/* Disable all hardware interrupts */
|
|
change_cp0_status(ST0_IM, 0x00);
|
|
|
|
tc_outl(CR_INTC_IMR, 0x0);
|
|
tc_outl(CR_TIMER_CTL, 0x0);
|
|
tc_outl(CR_MAC_MACCR, 0x0);
|
|
|
|
prom_printf("Decompress to %X free_mem_ptr=%X free_mem_ptr_end=%X\n", output_data, free_mem_ptr, free_mem_ptr_end);
|
|
//modify by ywxing 2015-05-05 for dual image
|
|
if(readBootFlagFromFlash_FH()==1)//bootfromB
|
|
{
|
|
if (IS_NANDFLASH)
|
|
flash_read(flash_base+FH_KERNELB_ADDR, FH_KERNEL_LENS, &retlen, 0x80020000);
|
|
else
|
|
memcpy(0x80020000,flash_base+0x20000, 0x200000);
|
|
|
|
|
|
set_lzma_addr(flash_base + FH_KERNELB_ADDR,flash_base+FH_KERNELB_ADDR+FH_KERNEL_LENS);
|
|
}
|
|
else
|
|
{
|
|
if (IS_NANDFLASH)
|
|
flash_read(flash_base+FH_KERNELA_ADDR, FH_KERNEL_LENS, &retlen, 0x80020000);
|
|
else
|
|
memcpy(0x80020000,flash_base+0x20000, 0x200000);
|
|
|
|
|
|
set_lzma_addr(flash_base + FH_KERNELA_ADDR,flash_base+FH_KERNELA_ADDR+FH_KERNEL_LENS);
|
|
}
|
|
char *bufaddr = (char*)FH_ROOTFLAG_ADDR;
|
|
*bufaddr = readRootFlagFromFlash_FH();
|
|
prom_printf("bootflag=%s\nrootflag=%s\n",readBootFlagFromFlash_FH(),readRootFlagFromFlash_FH() );
|
|
//modify end
|
|
#if defined(TCSUPPORT_CPU_MT7510)||defined(TCSUPPORT_CPU_MT7520)
|
|
uint32 tmpId = 0;
|
|
uint8 idx = 0;
|
|
|
|
idx = READ_FLASH_BYTE( (0xff9b | flash_base));
|
|
switch(idx){
|
|
case 1: // 7510 F
|
|
tmpId = 0x80;
|
|
break;
|
|
case 2: // 7520 F
|
|
tmpId = 0x100;
|
|
break;
|
|
case 3: // 7525G 7520G 7510 7511
|
|
tmpId = 0x53;
|
|
break;
|
|
case 4: // 7511G
|
|
tmpId = 0x4;
|
|
break;
|
|
case 5: // 7525 7520
|
|
tmpId = 0x28;
|
|
break;
|
|
case 6: // 7520 F External
|
|
tmpId = 0x200;
|
|
default:
|
|
break;
|
|
}
|
|
prom_printf("75xx: 0x%x\n",tmpId);
|
|
VPint(0xbfb00240) = tmpId;
|
|
#elif defined(TCSUPPORT_CPU_MT7505)
|
|
VPint(0xbfb00240) = 0;
|
|
#endif//MT7510
|
|
|
|
output_data = 0x80002000;
|
|
decompress_kernel(output_data, free_mem_ptr, free_mem_ptr_end);
|
|
|
|
jumpAddr = (void (*)(void))(0x80002000);
|
|
|
|
#ifdef TC3262
|
|
if (IS_NANDFLASH )
|
|
flush_icache_range(0x80002000, 0x80002000 + FH_KERNEL_LENS*4);
|
|
#endif
|
|
(*jumpAddr)();
|
|
}
|
|
#endif
|
|
#else
|
|
void boot_kernel(void)
|
|
{
|
|
unsigned long output_data;
|
|
unsigned long free_mem_ptr;
|
|
unsigned long free_mem_ptr_end;
|
|
void (*jumpAddr)();
|
|
unsigned long retlen = 0;
|
|
|
|
#ifdef CONFIG_DUAL_IMAGE
|
|
int retflag = 0;
|
|
char *bufaddr = (char*)FLAG_ADDR;
|
|
char flag = 0;
|
|
|
|
unsigned char commit_flag = 0;
|
|
char *commit_buf_addr = NULL;
|
|
|
|
#if defined(TCSUPPORT_DUAL_IMAGE_ENHANCE) || defined(TCSUPPORT_NAND_BADBLOCK_CHECK)
|
|
char* trx_addr = NULL;
|
|
unsigned char slave_ver[32], main_ver[32];
|
|
int index;
|
|
unsigned int header_len, rootfs_len, kernel_len;
|
|
int binlen = 0;
|
|
struct trx_header *trx_main = NULL;
|
|
struct trx_header *trx_slave = NULL;
|
|
unsigned short checkSum_main = 0;
|
|
unsigned short checkSum_slave = 0;
|
|
char checkflag = 0;
|
|
#endif
|
|
#endif
|
|
struct trx_header *trx_temp = NULL;
|
|
char* temp_addr = NULL;
|
|
unsigned long startAddr = 0x0;
|
|
unsigned int kernel_size = 0;
|
|
int trx_header_len = sizeof(struct trx_header);
|
|
|
|
output_data = KERNEL_START_ADDR;
|
|
free_mem_ptr = KERNEL_RAM_START;
|
|
free_mem_ptr_end = KERNEL_RAM_END;
|
|
|
|
/* Disable all hardware interrupts */
|
|
change_cp0_status(ST0_IM, 0x00);
|
|
|
|
tc_outl(CR_INTC_IMR, 0x0);
|
|
tc_outl(CR_TIMER_CTL, 0x0);
|
|
tc_outl(CR_MAC_MACCR, 0x0);
|
|
|
|
#ifdef TR068_LED
|
|
#if !defined(TCSUPPORT_C1_MS)
|
|
power_gpioInit(POWER_LED_RED);
|
|
#endif
|
|
#endif
|
|
#if !defined(CONFIG_DUAL_IMAGE) && defined(TR068_LED)
|
|
if( checkimage(MAIN_IMAGE) < 0 ) {
|
|
prom_printf("\r\n==>Main image check failed, turn on red led!");
|
|
#if defined(TCSUPPORT_CT)
|
|
power_gpioInit(POWER_LED_RED);//main image CRC check failed, power led turn on red
|
|
#endif
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_DUAL_IMAGE
|
|
if(checkimage(MAIN_IMAGE) < 0)
|
|
#ifdef TCSUPPORT_DUAL_IMAGE_ENHANCE
|
|
trx_temp = (struct trx_header*)(flash_base+flash_tclinux_start+offset);
|
|
#elif defined(TCSUPPORT_NAND_BADBLOCK_CHECK)
|
|
trx_temp = (struct trx_header*)(flash_base+0x2280000); //tclinux.bin slave offset
|
|
#else
|
|
trx_temp = (struct trx_header*)(flash_base+flash_tclinux_start+TCLINUX_SLAVE_FLASH_START);
|
|
#endif
|
|
else
|
|
#endif
|
|
|
|
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
|
|
trx_temp = (struct trx_header*)(flash_base+0x280000);
|
|
#elif defined(TCSUPPORT_NAND_RT63368)
|
|
trx_temp = (struct trx_header*)(flash_base + NAND_KERNEL_OFFSET);
|
|
#else
|
|
trx_temp = (struct trx_header*)(flash_base+flash_tclinux_start);
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_NAND_BADBLOCK_CHECK) || defined(TCSUPPORT_NAND_RT63368)
|
|
temp_addr = &(trx_temp->kernel_len);
|
|
kernel_size = READ_FLASH_DWORD(temp_addr) + 0x100;
|
|
#else
|
|
temp_addr = &(trx_temp->kernel_len);
|
|
kernel_size = READ_FLASH_DWORD(temp_addr) + 0x100;
|
|
kernel_size = (kernel_size+0x10000)&~(0x10000-1);
|
|
#endif
|
|
temp_addr = &(trx_temp->decompAddr);
|
|
startAddr = READ_FLASH_DWORD(temp_addr);
|
|
if(startAddr != 0)
|
|
{
|
|
output_data = startAddr;
|
|
#ifdef CONFIG_DUAL_IMAGE
|
|
bufaddr = (char*)(startAddr-1);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
output_data = 0x80020000;
|
|
#ifdef CONFIG_DUAL_IMAGE
|
|
bufaddr = (char*)(0x8001ffff);
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_DUAL_IMAGE
|
|
#if defined (TCSUPPORT_GPON_DUAL_IMAGE) || defined (TCSUPPORT_EPON_DUAL_IMAGE)
|
|
flag = readBootFlagFromFlash();
|
|
|
|
prom_printf("\r\n==> boot flag = %d",flag);
|
|
|
|
if(flag == 0)
|
|
{
|
|
#endif /*TCSUPPORT_GPON_DUAL_IMAGE||TCSUPPORT_EPON_DUAL_IMAGE*/
|
|
retflag = checkimage(MAIN_IMAGE);
|
|
if(retflag < 0)
|
|
{
|
|
flag = 1;
|
|
retflag = checkimage(SLAVE_IMAGE);
|
|
if(retflag < 0) {
|
|
#ifdef TR068_LED
|
|
prom_printf("\r\n==>Dual image check failed, turn on red led!");
|
|
#if defined(TCSUPPORT_CT)
|
|
power_gpioInit(POWER_LED_RED);//both images CRC check are failed, power led turn on red
|
|
#endif
|
|
#endif
|
|
return;
|
|
}
|
|
#if defined(TCSUPPORT_CT_UPG_PINGPONG)
|
|
writeBootFlagtoFlash(flag);
|
|
#endif
|
|
|
|
|
|
}
|
|
#if defined (TCSUPPORT_GPON_DUAL_IMAGE) || defined (TCSUPPORT_EPON_DUAL_IMAGE)
|
|
}
|
|
else
|
|
{
|
|
retflag = checkimage(SLAVE_IMAGE);
|
|
if(retflag < 0)
|
|
{
|
|
flag = 0;
|
|
retflag = checkimage(MAIN_IMAGE);
|
|
if(retflag < 0) {
|
|
#ifdef TR068_LED
|
|
prom_printf("\r\n==>Dual image check failed, turn on red led!");
|
|
#if defined(TCSUPPORT_CT)
|
|
power_gpioInit(POWER_LED_RED);//both images CRC check are failed, power led turn on red
|
|
#endif
|
|
#endif
|
|
return;
|
|
}
|
|
#if defined(TCSUPPORT_CT_UPG_PINGPONG)
|
|
writeBootFlagtoFlash(flag);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
#endif /*TCSUPPORT_GPON_DUAL_IMAGE||TCSUPPORT_EPON_DUAL_IMAGE*/
|
|
|
|
//store flag information to 0x8001ffff
|
|
*bufaddr = flag;
|
|
|
|
|
|
#endif
|
|
prom_printf("Decompress to %X free_mem_ptr=%X free_mem_ptr_end=%X\n", output_data, free_mem_ptr, free_mem_ptr_end);
|
|
|
|
#ifdef CONFIG_DUAL_IMAGE
|
|
/*flag 0:main image;1:backup image*/
|
|
/* frankliao added 20101215 */
|
|
if (flag==1){
|
|
prom_printf("from slave\n");
|
|
#ifdef TCSUPPORT_DUAL_IMAGE_ENHANCE
|
|
// set_lzma_addr(0xb0020100+offset, 0xb0120000+offset);
|
|
// set_lzma_addr(flash_base+0x20100+offset, flash_base+0x120000+offset);
|
|
set_lzma_addr(flash_base+flash_tclinux_start+trx_header_len+offset, flash_base+flash_tclinux_start+kernel_size+offset);
|
|
#if !defined(TCSUPPORT_EPON_DUAL_IMAGE) && !defined(TCSUPPORT_GPON_DUAL_IMAGE)
|
|
//copy slave to main
|
|
// trx_slave = (struct trx_header *)(0xb0000000+0x20000+offset);
|
|
trx_slave = (struct trx_header*)(flash_base+flash_tclinux_start+offset);
|
|
trx_addr = &(trx_slave->header_len);
|
|
header_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_slave->kernel_len);
|
|
kernel_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_slave->rootfs_len);
|
|
rootfs_len = READ_FLASH_DWORD(trx_addr);
|
|
// binlen = trx_slave->header_len + trx_slave->kernel_len + trx_slave->rootfs_len;
|
|
binlen = header_len + kernel_len + rootfs_len;
|
|
#ifdef TCSUPPORT_NAND_RT63368
|
|
flash_erase(NAND_KERNEL_OFFSET, binlen);
|
|
#else
|
|
flash_erase(flash_tclinux_start, binlen);
|
|
#endif
|
|
if (IS_NANDFLASH)
|
|
flash_read(flash_base+flash_tclinux_start+offset, binlen, &retlen, 0x80020000);
|
|
else
|
|
memcpy(0x80020000, flash_base+flash_tclinux_start+offset, binlen);
|
|
#ifdef TCSUPPORT_NAND_RT63368
|
|
flash_write(NAND_KERNEL_OFFSET, binlen, &retlen, 0x80020000);
|
|
#else
|
|
flash_write(flash_tclinux_start, binlen, &retlen, 0x80020000);
|
|
#endif
|
|
#endif /*!TCSUPPORT_EPON_DUAL_IMAGE*/
|
|
|
|
#elif defined(TCSUPPORT_NAND_BADBLOCK_CHECK)
|
|
set_lzma_addr(flash_base+0x2280000+0x100, flash_base+0x2280000+kernel_size);
|
|
|
|
trx_slave = (struct trx_header*)(flash_base+0x2280000);
|
|
trx_addr = &(trx_slave->header_len);
|
|
header_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_slave->kernel_len);
|
|
kernel_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_slave->rootfs_len);
|
|
rootfs_len = READ_FLASH_DWORD(trx_addr);
|
|
binlen = header_len + kernel_len + rootfs_len;
|
|
|
|
flash_erase(0x280000, binlen);
|
|
flash_read(flash_base+0x2280000, binlen, &retlen, 0x80020000);
|
|
flash_write(0x280000, binlen, &retlen, 0x80020000);
|
|
|
|
#else
|
|
// set_lzma_addr(0xb0020100+0x500000, 0xb0120000+0x500000);
|
|
// set_lzma_addr( (flash_base + 0x20100 + 0x500000), (flash_base + 0x120000 + 0x500000) );
|
|
set_lzma_addr(flash_base + flash_tclinux_start+trx_header_len+ TCLINUX_SLAVE_FLASH_START, flash_base + flash_tclinux_start+kernel_size+ TCLINUX_SLAVE_FLASH_START);
|
|
|
|
#endif
|
|
} else {
|
|
prom_printf("from main\n");
|
|
// set_lzma_addr( (flash_base + 0x20100), (flash_base + 0x120000) );
|
|
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
|
|
set_lzma_addr( (flash_base + 0x280000 + 0x100), (flash_base + 0x280000 + kernel_size) ); //Pomelo
|
|
#elif defined(TCSUPPORT_NAND_RT63368)
|
|
set_lzma_addr( (flash_base + NAND_KERNEL_OFFSET + 0x100), (flash_base + NAND_KERNEL_OFFSET + kernel_size) );
|
|
#else
|
|
set_lzma_addr( (flash_base + flash_tclinux_start+trx_header_len), (flash_base + flash_tclinux_start + kernel_size) );
|
|
#endif
|
|
|
|
#if defined (TCSUPPORT_DUAL_IMAGE_ENHANCE) && !defined (TCSUPPORT_EPON_DUAL_IMAGE) && !defined (TCSUPPORT_GPON_DUAL_IMAGE)
|
|
//copy main to slave
|
|
// trx_main = (struct trx_header *)(0xb0000000+0x20000);
|
|
#ifdef TCSUPPORT_NAND_RT63368
|
|
trx_main = (struct trx_header*)(flash_base+NAND_KERNEL_OFFSET);
|
|
#else
|
|
trx_main = (struct trx_header*)(flash_base+flash_tclinux_start);
|
|
#endif
|
|
trx_addr = &(trx_main->header_len);
|
|
header_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_main->kernel_len);
|
|
kernel_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_main->rootfs_len);
|
|
rootfs_len = READ_FLASH_DWORD(trx_addr);
|
|
// binlen = trx_main->header_len + trx_main->kernel_len + trx_main->rootfs_len;
|
|
binlen = header_len + kernel_len + rootfs_len;
|
|
// trx_slave = (struct trx_header *)(0xb0000000+0x20000+offset);
|
|
trx_slave = (struct trx_header *)(flash_base+flash_tclinux_start+offset);
|
|
trx_addr = &(trx_slave->version);
|
|
for (index=0; index<32; index++, trx_addr++){
|
|
slave_ver[index] = READ_FLASH_BYTE(trx_addr);
|
|
}
|
|
trx_addr = &(trx_main->version);
|
|
for (index=0; index<32; index++, trx_addr++){
|
|
main_ver[index] = READ_FLASH_BYTE(trx_addr);
|
|
}
|
|
|
|
// if((checkimage(SLAVE_IMAGE) < 0) || (strcmp(trx_main->version,trx_slave->version) != 0)) {
|
|
if((checkimage(SLAVE_IMAGE) < 0) || (strcmp(main_ver, slave_ver) != 0)) {
|
|
checkflag = 1;
|
|
}
|
|
if(checkflag == 0){
|
|
if (IS_NANDFLASH)
|
|
#ifdef TCSUPPORT_NAND_RT63368
|
|
flash_read(flash_base+NAND_KERNEL_OFFSET, binlen, &retlen, 0x80020000);
|
|
#else
|
|
flash_read(flash_base+flash_tclinux_start, binlen, &retlen, 0x80020000);
|
|
#endif
|
|
else
|
|
memcpy(0x80020000, flash_base+flash_tclinux_start, binlen);
|
|
checkSum_main = CheckSum(0x80020000,binlen);
|
|
if (IS_NANDFLASH)
|
|
flash_read(flash_base+flash_tclinux_start+offset, binlen, &retlen, 0x80020000);
|
|
else
|
|
memcpy(0x80020000, flash_base+flash_tclinux_start+offset, binlen);
|
|
checkSum_slave = CheckSum(0x80020000,binlen);
|
|
if(checkSum_main != checkSum_slave){
|
|
checkflag = 1;
|
|
}
|
|
}
|
|
if(checkflag == 1){
|
|
flash_erase(flash_tclinux_start+offset, binlen);
|
|
if (IS_NANDFLASH)
|
|
#ifdef TCSUPPORT_NAND_RT63368
|
|
flash_read(flash_base+NAND_KERNEL_OFFSET, binlen, &retlen, 0x80020000);
|
|
#else
|
|
flash_read(flash_base+flash_tclinux_start, binlen, &retlen, 0x80020000);
|
|
#endif
|
|
else
|
|
memcpy(0x80020000, flash_base+flash_tclinux_start, binlen);
|
|
flash_write(flash_tclinux_start+offset, binlen, &retlen, 0x80020000);
|
|
}
|
|
#elif defined(TCSUPPORT_NAND_BADBLOCK_CHECK)
|
|
trx_main = (struct trx_header*)(flash_base+0x280000);
|
|
trx_addr = &(trx_main->header_len);
|
|
header_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_main->kernel_len);
|
|
kernel_len = READ_FLASH_DWORD(trx_addr);
|
|
trx_addr = &(trx_main->rootfs_len);
|
|
rootfs_len = READ_FLASH_DWORD(trx_addr);
|
|
binlen = header_len + kernel_len + rootfs_len;
|
|
|
|
trx_slave = (struct trx_header *)(flash_base+0x2280000);
|
|
|
|
trx_addr = &(trx_slave->version);
|
|
|
|
for (index=0; index<32; index++, trx_addr++){
|
|
slave_ver[index] = READ_FLASH_BYTE(trx_addr);
|
|
}
|
|
trx_addr = &(trx_main->version);
|
|
for (index=0; index<32; index++, trx_addr++){
|
|
main_ver[index] = READ_FLASH_BYTE(trx_addr);
|
|
}
|
|
|
|
if((checkimage(SLAVE_IMAGE) < 0) || (strcmp(main_ver, slave_ver) != 0)) {
|
|
checkflag = 1;
|
|
}
|
|
|
|
if(checkflag == 0){
|
|
flash_read(flash_base+0x280000, binlen, &retlen, 0x80020000);
|
|
|
|
checkSum_main = CheckSum(0x80020000,binlen);
|
|
|
|
flash_read(flash_base+0x2280000, binlen, &retlen, 0x80020000);
|
|
|
|
checkSum_slave = CheckSum(0x80020000,binlen);
|
|
if(checkSum_main != checkSum_slave){
|
|
checkflag = 1;
|
|
}
|
|
}
|
|
|
|
if(checkflag == 1){
|
|
flash_erase(0x2280000, binlen);
|
|
flash_read(flash_base+0x280000, binlen, &retlen, 0x80020000);
|
|
flash_write(0x2280000, binlen, &retlen, 0x80020000);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
#else
|
|
// set_lzma_addr(KERNEL_FLASH_START, KERNEL_FLASH_END);
|
|
|
|
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
|
|
set_lzma_addr( (flash_base + 0x280000 + 0x100), (flash_base + 0x280000 + 0x180000) );
|
|
#elif defined(TCSUPPORT_NAND_RT63368)
|
|
set_lzma_addr( (flash_base + NAND_KERNEL_OFFSET + 0x100), (flash_base + NAND_KERNEL_OFFSET + 0x1a0000) );
|
|
#else
|
|
set_lzma_addr( (flash_base + flash_tclinux_start+trx_header_len), (flash_base + + flash_tclinux_start + kernel_size) );
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_CPU_MT7510)||defined(TCSUPPORT_CPU_MT7520)
|
|
uint32 tmpId = 0;
|
|
uint8 idx = 0;
|
|
|
|
idx = READ_FLASH_BYTE( (0xff9b | flash_base));
|
|
switch(idx){
|
|
case 1: // 7510 F
|
|
tmpId = 0x80;
|
|
break;
|
|
case 2: // 7520 F
|
|
tmpId = 0x100;
|
|
break;
|
|
case 3: // 7525G 7520G 7510 7511
|
|
tmpId = 0x53;
|
|
break;
|
|
case 4: // 7511G
|
|
tmpId = 0x4;
|
|
break;
|
|
case 5: // 7525 7520
|
|
tmpId = 0x28;
|
|
break;
|
|
case 6: // 7520 F External
|
|
tmpId = 0x200;
|
|
default:
|
|
break;
|
|
}
|
|
prom_printf("75xx: 0x%x\n",tmpId);
|
|
VPint(0xbfb00240) = tmpId;
|
|
#elif defined(TCSUPPORT_CPU_MT7505)
|
|
VPint(0xbfb00240) = 0;
|
|
#endif//MT7510
|
|
#endif
|
|
|
|
decompress_kernel(output_data, free_mem_ptr, free_mem_ptr_end);
|
|
|
|
/* FIXME */
|
|
/*Unify the kernel address to jump for all chip, shnwind*/
|
|
//#ifdef TC3262
|
|
// jumpAddr = (void (*)(void))0x80020000;
|
|
//#else
|
|
// if (isTC3162L3P3 || isTC3162L4P4 || isTC3162L5P5) {
|
|
|
|
//jumpAddr = (void (*)(void))KERNEL_START_ADDR;
|
|
if(startAddr != 0)
|
|
jumpAddr = (void (*)(void))(startAddr);
|
|
else
|
|
jumpAddr = (void (*)(void))(0x80020000);
|
|
// } else {
|
|
//jumpAddr = (void (*)(void))0x80020404;
|
|
//jumpAddr = (void (*)(void))0x80020420;
|
|
//jumpAddr = (void (*)(void))0x800203fc;
|
|
// jumpAddr = (void (*)(void))0x800205bc;
|
|
// }
|
|
//#endif
|
|
#ifdef TC3262
|
|
if (IS_NANDFLASH )
|
|
flush_icache_range(startAddr, startAddr + kernel_size*4);
|
|
#endif
|
|
(*jumpAddr)();
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE)
|
|
/*
|
|
this flag will be set when the first multicast packet is received
|
|
*/
|
|
extern char startMultiUpgrade;
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_MULTI_BOOT)
|
|
extern char startMultiBoot;
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
|
|
#ifdef TC3262
|
|
extern void resetSwMAC3262(void);
|
|
#else
|
|
extern void resetSwMAC(void);
|
|
#endif
|
|
#endif
|
|
|
|
static int tc3162wdog_reset()
|
|
{
|
|
unsigned int word;
|
|
|
|
if (isRT63365){
|
|
/* check if not e1 chip */
|
|
if ((VPint(0xbfb00064) & 0xffff) != 0x0){
|
|
/* check if do watch do reset */
|
|
if (!(VPint(0xbfb00080) >> 31)){
|
|
|
|
/* set delay counter */
|
|
VPint(CR_TIMER5_LDV) = 1000;
|
|
|
|
/* enable watch dog timer */
|
|
word = VPint(CR_TIMER_CTL);
|
|
word |= ( (1<<5) | (1<<25) );
|
|
VPint (CR_TIMER_CTL) = word;
|
|
|
|
while(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MT7550_GPIO
|
|
//SUC
|
|
//normal mode control mt7505+7550 pll
|
|
#define RG_SCU_BASE 0xBFA20000
|
|
#define RG_DSLPLL_EN_SCU (RG_SCU_BASE + 0x01*4)
|
|
#define RG_DSL_HRDDS_PCW_NCP0_SCU (RG_SCU_BASE + 0x04*4)
|
|
#define RG_DSL_HRDDS_PCW_NCP0_CHG_SCU (RG_SCU_BASE + 0x05*4)
|
|
#define RG_DMT_CTRL 0xBFB00084
|
|
#endif
|
|
|
|
void start_kernel(void)
|
|
{
|
|
int i;
|
|
unsigned long start, current, old_current;
|
|
/* frankliao modify 20101208 */
|
|
// uint8 *flash_mac_addr = (uint8 *)FLASH_ETH_MAC;
|
|
uint8 flash_mac_addr[6];
|
|
|
|
#ifdef TCSUPPORT_AUTOBENCH
|
|
unsigned long val;
|
|
#endif
|
|
if(isEN751221){
|
|
if (((VPint(0xbfa20000) & (0x1)) != 0)) {
|
|
VPint(0xbfa20000) &= ~(0x01);
|
|
}
|
|
/*Disable FE Share Memory*/
|
|
VPint(0xbfb00958) = 0;
|
|
}
|
|
|
|
tc3162wdog_reset();
|
|
led_init();
|
|
led_all_mode(0);
|
|
|
|
trap_init();
|
|
uart_init();
|
|
#ifdef TCSUPPORT_UART2
|
|
uart2_init();
|
|
#endif
|
|
prom_printf("\n\n");
|
|
|
|
#if defined(MT7505_SWITCH_TBL_VERIRY)
|
|
MT7505_Switch_Tbl_Test();
|
|
#endif
|
|
|
|
#ifdef TC3262
|
|
if (isTC3182)
|
|
prom_printf("TC3182");
|
|
else if (isRT65168)
|
|
prom_printf("RT65168");
|
|
else if (isRT63165)
|
|
prom_printf("RT63165");
|
|
else if (isRT63365)
|
|
prom_printf("RT63365");
|
|
else if (isMT751020)
|
|
prom_printf("MT751020");
|
|
else if(isMT7505)
|
|
prom_printf("MT7505");
|
|
else if(isEN751221)
|
|
prom_printf("EN751221");
|
|
else
|
|
prom_printf("TC3169");
|
|
#else
|
|
if (isRT63260)
|
|
prom_printf("RT63260");
|
|
else if (isTC3162U)
|
|
prom_printf("TC3162U");
|
|
else if (isTC3162L5P5)
|
|
prom_printf("TC3162L5/P5");
|
|
else if (isTC3162L4P4)
|
|
prom_printf("TC3162L4/P4");
|
|
else if (isTC3162L3P3)
|
|
prom_printf("TC3162L2F/P2F");
|
|
else if (isTC3162L2P2)
|
|
prom_printf("TC3162L2/P2");
|
|
else
|
|
prom_printf("TC3162");
|
|
#endif
|
|
#ifdef TCSUPPORT_FREE_BOOTBASE
|
|
prom_printf(" at %s version %s free bootbase\n\n",BOOT_CODE_TIME,BOOLOADER_VERSION);
|
|
#else
|
|
prom_printf(" at %s version %s\n\n",BOOT_CODE_TIME,BOOLOADER_VERSION);
|
|
#endif
|
|
|
|
#ifdef TCSUPPORT_AUTOBENCH
|
|
if(isRT63365){
|
|
val = tc_inl(0xbfb00860);
|
|
tc_outl(0xbfb00860, (val & (~((1<<12) | (1<<13) | (1<<10) | (1<<11) | (1<<9)))));
|
|
}
|
|
#endif
|
|
|
|
#ifdef SIS_DDR_PHY
|
|
if (!isRT63165 && !isRT63365 && !isMT751020 && !isMT7505 && !isEN751221) {
|
|
prom_printf("DDR EDQS scan min=%d max=%d choose EDQS=%d\n\n",
|
|
VPint(0x8001fffc), VPint(0x8001fff8), VPint(0x8001fff4));
|
|
}
|
|
#else
|
|
#ifdef PLL_AUTO_SCAN
|
|
prom_printf("DDR PLL possible bitmap=0x%08x choose PLL=%d\n\n",
|
|
VPint(0x8001fffc), VPint(0x8001fff8));
|
|
#endif
|
|
#endif
|
|
|
|
prom_printf("Memory size %dMB\n\n",calculate_dram_size());
|
|
|
|
#if defined(TCSUPPORT_POWERSAVE_ENABLE)
|
|
// enable DDR self refresh
|
|
if((!isMT751020) && ((VPint(CR_AHB_HWCONF)&(1<<25))!=0))
|
|
{
|
|
VPint(CR_DMC_DDR_SR_CNT) &= 0xff000000;
|
|
VPint(CR_DMC_DDR_SR_CNT) |= 0x1;
|
|
}
|
|
#endif
|
|
#if 0
|
|
#ifdef TC3262
|
|
prom_printf("Memory size %dMB\n\n",
|
|
8 * (1 << (((VPint(CR_DMC_CTL1) >> 18) & 0x7) - 1)));
|
|
#else
|
|
{
|
|
unsigned long memsize;
|
|
unsigned char samt;
|
|
unsigned long col;
|
|
unsigned long row;
|
|
|
|
/* calculate SDRAM size */
|
|
samt = VPchar(CR_DMC_SAMT);
|
|
row = 8 + (samt & 0x3);
|
|
col = 11 + ((samt>>2) & 0x3);
|
|
/* 4 bands and 16 bit width */
|
|
memsize = (1 << row) * (1 << col) * 4 * 2;
|
|
|
|
prom_printf("Memory size %dMB\n\n", memsize>>20);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
setup_arch(); /*setup the BEV0,and IRQ */
|
|
exception_init();/*Copy handler to 0x80000080*/
|
|
init_IRQ(); /*Allocate IRQfinder to Exception 0*/
|
|
/* frankliao added 20101215 */
|
|
flash_init(flash_base);
|
|
#ifndef TCSUPPORT_MTD_PARTITIONS_CMDLINE
|
|
#ifdef BOOTROM_LARGE_SIZE
|
|
flash_firmware_base_init();
|
|
#endif
|
|
#else
|
|
ecnt_parse_cmdline_partitions();
|
|
#endif
|
|
|
|
for (i=0; i<6; i++) {
|
|
flash_mac_addr[i] = READ_FLASH_BYTE(FLASH_ETH_MAC + i);
|
|
}
|
|
|
|
#ifdef TR068_LED
|
|
#if defined(TCSUPPORT_CT) || defined(TCSUPPORT_C1_MS)
|
|
power_gpioInit(POWER_LED_GREEN);/*Power led turn green first*/
|
|
#endif
|
|
#endif
|
|
|
|
time_init();
|
|
|
|
if(isMT7505){
|
|
|
|
/*MT7505 input crystall is 40Mhz*/
|
|
if(VPint(CR_AHB_HWCONF)&(1<<1)){
|
|
VPint(0xbfaf2400) = (VPint(0xbfaf2400) | 0x100); /*force mode enable xtal type*/
|
|
#ifdef MT7550_GPIO
|
|
VPint(RG_DSL_HRDDS_PCW_NCP0_SCU) = 0x54c985f0;
|
|
#endif
|
|
}
|
|
|
|
#ifdef MT7550_GPIO
|
|
/* enable DMT FNPLL */
|
|
VPint(RG_DSLPLL_EN_SCU) = (VPint(RG_DSLPLL_EN_SCU) | 0x01);
|
|
/* change DMT state from reset to normal */
|
|
VPint(RG_DMT_CTRL) = (VPint(RG_DMT_CTRL) & 0xfffffffe);
|
|
#endif
|
|
|
|
#if !defined(TCSUPPORT_AUTOBENCH)
|
|
/*MT7505 lan led mode enable, set share pin */
|
|
VPint(0xbfa2007c) = (VPint(0xbfa2007c) | 0x3e00);
|
|
#else
|
|
prom_printf("MT7505_SLT\n");
|
|
#endif
|
|
}
|
|
#if !defined(TCSUPPORT_AUTOBENCH)
|
|
#ifdef TC3262
|
|
#ifdef RT63365
|
|
if (isRT63365)
|
|
pcie_init();
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
eth_latsch_up();
|
|
|
|
prom_printf("\n");
|
|
#if defined(TCSUPPORT_ETH4_WAN_PORT) || defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
|
|
if( (flash_mac_addr[0] == 0) && (flash_mac_addr[1] == 0) && (flash_mac_addr[2] == 0) &&
|
|
(flash_mac_addr[3] == 0) && (flash_mac_addr[4] == 0) && (flash_mac_addr[5] == 0) )
|
|
prom_printf("The MAC address in flash is null!\n");
|
|
else
|
|
memcpy(mac_addr, flash_mac_addr, 6);
|
|
|
|
/*Decide skb start addr according to memory size. shnwind*/
|
|
skb_init();
|
|
eth_init(mac_addr);
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_ETH4_WAN_PORT)
|
|
//set pvid
|
|
tcMiiStationWrite(20, 17, 0x4001);
|
|
tcMiiStationWrite(20, 18, 0x4002);
|
|
tcMiiStationWrite(20, 19, 0x4003);
|
|
tcMiiStationWrite(20, 20, 0x4004);
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
|
|
/*
|
|
init network for multi-upgrade
|
|
*/
|
|
arp_init();
|
|
ip_init(ip_addr);
|
|
udp_init();
|
|
arp_add_entry(mac_addr, ip_addr);
|
|
#endif
|
|
|
|
#if defined(MT7530_SLT)
|
|
// MT7530 SLT Test Program Start
|
|
MT7530_SLT_Test();
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE)
|
|
#if !defined(TCSUPPORT_C1_TRUE)
|
|
prom_printf("Press any key in 3 secs to enter boot command mode.\n");
|
|
#endif
|
|
#else
|
|
#if !defined(TCSUPPORT_C1_OBM)
|
|
prom_printf("Press any key in 3 secs to enter boot command mode.\n");
|
|
#endif
|
|
#endif
|
|
start = old_current = Jiffies;
|
|
#ifndef PLL_AUTO_SCAN
|
|
while (serial_tstc() == 0) {
|
|
current = Jiffies;
|
|
|
|
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE)
|
|
/*
|
|
wait for the first packet of image
|
|
*/
|
|
if(startMultiUpgrade == 1){
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(TCSUPPORT_MULTI_BOOT)
|
|
if( startMultiBoot == 1){
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
|
|
if (((current - start) % 5) == 0 && (current != old_current)) {
|
|
old_current = current;
|
|
prom_printf(".");
|
|
}
|
|
|
|
/* check timeout value */
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE)
|
|
#if !defined(TCSUPPORT_C1_TRUE)
|
|
if ((current - start) > 300) {
|
|
#endif
|
|
#else
|
|
#ifndef TCSUPPORT_AUTOBENCH
|
|
#if !defined(TCSUPPORT_C1_OBM)
|
|
if ((current - start) > 300) {
|
|
#endif
|
|
#else
|
|
if ((current - start) > 50) {
|
|
#endif
|
|
#endif
|
|
/* timeout! */
|
|
prom_printf("\n\n");
|
|
if(isRT65168){
|
|
#if !defined(MT7530_SUPPORT) && !defined(MT7530_SLT)
|
|
VPint(0xbfb00084) = 0x1; //reset DMT
|
|
pause(20);
|
|
VPint(0xbfb00084) = 0x0; //reset DMT
|
|
pause(1);
|
|
VPint(0xbf500424) = 0x6004; //write AFE reg4
|
|
#endif
|
|
}
|
|
#if defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
|
|
/*
|
|
close mac before decompress
|
|
*/
|
|
|
|
tc_outl(CR_INTC_IMR, 0x0);
|
|
#if !defined(TCSUPPORT_CPU_MT7505)
|
|
tc_outl(CR_TIMER_CTL, 0x0);
|
|
#endif
|
|
|
|
tc_outl(CR_MAC_MACCR, 0x0);
|
|
|
|
#ifdef TC3262
|
|
|
|
resetSwMAC3262();
|
|
#else
|
|
resetSwMAC();
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_CPU_MT7505)
|
|
tc_outl(CR_TIMER_CTL, 0x0);
|
|
#endif
|
|
boot_kernel();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* boot command mode */
|
|
serial_inc();
|
|
#endif
|
|
prom_printf("\n");
|
|
/*Read the mac address from flash*/
|
|
|
|
#if !defined(TCSUPPORT_MULTI_UPGRADE) && !defined(TCSUPPORT_MULTI_BOOT)
|
|
if( (flash_mac_addr[0] == 0) && (flash_mac_addr[1] == 0) && (flash_mac_addr[2] == 0) &&
|
|
(flash_mac_addr[3] == 0) && (flash_mac_addr[4] == 0) && (flash_mac_addr[5] == 0) )
|
|
prom_printf("The MAC address in flash is null!\n");
|
|
else
|
|
memcpy(mac_addr, flash_mac_addr, 6);
|
|
|
|
/*Decide skb start addr according to memory size. shnwind*/
|
|
skb_init();
|
|
eth_init(mac_addr);
|
|
arp_init();
|
|
ip_init(ip_addr);
|
|
udp_init();
|
|
arp_add_entry(mac_addr, ip_addr);
|
|
#endif
|
|
|
|
#if defined(TCSUPPORT_CT_BOOTLOADER_UPGRADE)
|
|
user_Auth();
|
|
#endif
|
|
cmd_proc();
|
|
}
|
|
|
|
void IP_change(uint32 ipaddr){
|
|
ip_addr = ipaddr;
|
|
arp_init();
|
|
ip_init(ip_addr);
|
|
arp_add_entry(mac_addr, ip_addr);
|
|
}
|
|
|
|
#ifdef TR068_LED
|
|
/*_____________________________________________________________________________
|
|
** function name: power_gpioInit
|
|
** descriptions:
|
|
** Accroding the mi.conf gpio value to init power led.
|
|
**
|
|
** parameters:
|
|
** none
|
|
**
|
|
** global:
|
|
** None
|
|
**
|
|
** return:
|
|
** None
|
|
**
|
|
** call:
|
|
** None
|
|
**
|
|
** revision:
|
|
** 1. yzwang 2010/03/10
|
|
**____________________________________________________________________________
|
|
*/
|
|
void
|
|
power_gpioInit(uint8 ledColor)
|
|
{
|
|
/*Get the Power GPIO Number*/
|
|
/* frankliao modify 20101208 */
|
|
// uint8 *flash_power_gpio_addr = (uint8 *)FLASH_POWERLED_GPIO;
|
|
uint8 power_gpio_1 = 255;
|
|
uint8 power_gpio_2 = 255;
|
|
|
|
power_gpio_1 = READ_FLASH_BYTE(FLASH_POWERLED_GPIO + 0);
|
|
power_gpio_2 = READ_FLASH_BYTE(FLASH_POWERLED_GPIO + 1);
|
|
|
|
if( power_gpio_1 == 255 || power_gpio_2 == 255 ) {
|
|
prom_printf("\nInvalid Power GPIO, just return and don't turn on Power LED \n");
|
|
return;
|
|
}
|
|
/*configure gpio as ouput*/
|
|
#if defined(TCSUPPORT_CPU_MT7510) || defined(TCSUPPORT_CPU_MT7520) || defined(TCSUPPORT_CPU_MT7505)
|
|
LED_OEN(power_gpio_1);
|
|
LED_OEN(power_gpio_2);
|
|
|
|
if(ledColor == POWER_LED_GREEN) {
|
|
/*turn on green led*/
|
|
LED_OFF(power_gpio_2);
|
|
LED_ON(power_gpio_1);
|
|
}
|
|
else if(ledColor == POWER_LED_RED) {
|
|
/*turn on red led */
|
|
LED_OFF(power_gpio_1);
|
|
LED_ON(power_gpio_2);
|
|
}
|
|
#else
|
|
VPint(CR_GPIO_CTRL) |= (1<<(power_gpio_1<<1));
|
|
VPint(CR_GPIO_CTRL) |= (1<<(power_gpio_2<<1));
|
|
|
|
/*set it as open drain*/
|
|
VPint(CR_GPIO_ODRAIN) |= (1<<power_gpio_1);
|
|
VPint(CR_GPIO_ODRAIN) |= (1<<power_gpio_2);
|
|
|
|
if(ledColor == POWER_LED_GREEN) {
|
|
/*turn on green led*/
|
|
VPint(CR_GPIO_DATA) &= ~(1<<power_gpio_1);//turn on green led
|
|
VPint(CR_GPIO_DATA) |= (1<<power_gpio_2);//turn off red led
|
|
}
|
|
else if(ledColor == POWER_LED_RED) {
|
|
/*turn on red led */
|
|
VPint(CR_GPIO_DATA) |= (1<<power_gpio_1);//turn off green led
|
|
VPint(CR_GPIO_DATA) &= ~(1<<power_gpio_2);//turn on red led
|
|
}
|
|
#endif
|
|
|
|
}/*end power_gpioInit*/
|
|
#endif
|
|
|
|
/*<< BosaZhong@30Apr2014, add, led control */
|
|
#define LED_PIN_PON 15
|
|
#define LED_PIN_ALARM 17
|
|
#define LED_PIN_LAN2 43
|
|
#define LED_PIN_LAN1 42
|
|
#define LED_PIN_FXS1 19
|
|
|
|
#ifndef CR_AHB_BASE
|
|
#define CR_AHB_BASE 0xBFB00000
|
|
#endif
|
|
#ifndef CR_GPIO_SHR
|
|
#define CR_GPIO_SHR (CR_AHB_BASE + 0x860)
|
|
#endif
|
|
|
|
#ifndef LED_OEN(x)
|
|
#define LED_OEN(x) do { \
|
|
if(x > 31){ \
|
|
if(x > 47){ \
|
|
regWrite32(CR_GPIO_CTRL3,regRead32(CR_GPIO_CTRL3)|(1<<((x-48)*2))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_CTRL2,regRead32(CR_GPIO_CTRL2)|(1<<((x-32)*2))); \
|
|
} \
|
|
\
|
|
regWrite32(CR_GPIO_ODRAIN1,regRead32(CR_GPIO_ODRAIN1)|(1<<(x-32))); \
|
|
}else{ \
|
|
if(x > 15){ \
|
|
regWrite32(CR_GPIO_CTRL1,regRead32(CR_GPIO_CTRL1)|(1<<((x-16)*2))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_CTRL,regRead32(CR_GPIO_CTRL)|(1<<(x*2))); \
|
|
} \
|
|
regWrite32(CR_GPIO_ODRAIN,regRead32(CR_GPIO_ODRAIN)|(1<<(x))); \
|
|
} \
|
|
}while(0)
|
|
#endif /* LED_OEN */
|
|
|
|
#ifndef LED_ON(x)
|
|
#define LED_ON(x) do { \
|
|
if(x > 31) \
|
|
{ \
|
|
regWrite32(CR_GPIO_DATA1, regRead32(CR_GPIO_DATA1) & ~(1 << (x-32))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_DATA, regRead32(CR_GPIO_DATA) & ~(1 << x)); \
|
|
} \
|
|
}while(0)
|
|
#endif /* LED_ON */
|
|
|
|
#ifndef LED_OFF(x)
|
|
#define LED_OFF(x) do { \
|
|
if(x > 31) \
|
|
{ \
|
|
regWrite32(CR_GPIO_DATA1, regRead32(CR_GPIO_DATA1) | (1<<(x-32))); \
|
|
}else{ \
|
|
regWrite32(CR_GPIO_DATA, regRead32(CR_GPIO_DATA) | (1<<x)); \
|
|
} \
|
|
}while(0)
|
|
#endif /* LED_OFF */
|
|
|
|
|
|
unsigned int led_init(void)
|
|
{
|
|
unsigned int word;
|
|
unsigned int ret;
|
|
|
|
word = regRead32(CR_GPIO_SHR);
|
|
ret = word;
|
|
word |= (1<<14);
|
|
|
|
// enable software control ether led.
|
|
word &= ~(0x1F<<9);
|
|
|
|
regWrite32(CR_GPIO_SHR,word);
|
|
|
|
LED_OEN(LED_PIN_PON); /* PON LED */
|
|
LED_OEN(LED_PIN_ALARM); /* Alarm LED */
|
|
LED_OEN(LED_PIN_FXS1); /* FXS1 */
|
|
LED_OEN(LED_PIN_LAN1); /* LAN1 */
|
|
LED_OEN(LED_PIN_LAN2); /* LAN2 */
|
|
|
|
return ret;
|
|
}
|
|
|
|
void led_restore(unsigned int restoreReg)
|
|
{
|
|
regWrite32(CR_GPIO_SHR, restoreReg);
|
|
}
|
|
|
|
|
|
void led_all_mode(int ledOn)
|
|
{
|
|
if (ledOn)
|
|
{
|
|
/* LED ON */
|
|
/* power */
|
|
|
|
/* PON */
|
|
LED_OFF(LED_PIN_PON);
|
|
|
|
/* ALARM */
|
|
LED_OFF(LED_PIN_ALARM);
|
|
|
|
/* LAN2 */
|
|
LED_ON(LED_PIN_LAN2);
|
|
|
|
/* LAN1 */
|
|
LED_ON(LED_PIN_LAN1);
|
|
|
|
/* FXS1 */
|
|
LED_OFF(LED_PIN_FXS1);
|
|
}
|
|
else
|
|
{
|
|
/* LED OFF */
|
|
/* power */
|
|
|
|
/* PON */
|
|
LED_ON(LED_PIN_PON);
|
|
|
|
/* ALARM */
|
|
LED_ON(LED_PIN_ALARM);
|
|
|
|
/* LAN2 */
|
|
LED_OFF(LED_PIN_LAN2);
|
|
|
|
/* LAN1 */
|
|
LED_OFF(LED_PIN_LAN1);
|
|
|
|
/* FXS1 */
|
|
LED_ON(LED_PIN_FXS1);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
/*>> endof BosaZhong@30Apr2014, add, led control */
|
|
|