[U-Boot] [PATCH 05/10] nds32: add nds32 board with common support

Macpaul Lin macpaul at andestech.com
Fri Jun 11 11:34:39 CEST 2010


	Add nds32 based common board related support.

Signed-off-by: Macpaul Lin <macpaul at andestech.com>
---
 board/AndesTech/common/env.c         |  138 ++++++
 board/AndesTech/common/flash.c       |  621 +++++++++++++++++++++++++++
 board/AndesTech/common/flib_flash.c  |  721 ++++++++++++++++++++++++++++++++
 board/AndesTech/common/flib_serial.c |  373 +++++++++++++++++
 board/AndesTech/common/fotg2xx.c     |   60 +++
 board/AndesTech/common/ftmac100.c    |  766 ++++++++++++++++++++++++++++++++++
 board/AndesTech/common/ftpci100.c    |  712 +++++++++++++++++++++++++++++++
 board/AndesTech/common/serial.c      |  141 +++++++
 8 files changed, 3532 insertions(+), 0 deletions(-)
 create mode 100644 board/AndesTech/common/env.c
 create mode 100644 board/AndesTech/common/flash.c
 create mode 100644 board/AndesTech/common/flib_flash.c
 create mode 100644 board/AndesTech/common/flib_serial.c
 create mode 100644 board/AndesTech/common/fotg2xx.c
 create mode 100644 board/AndesTech/common/ftmac100.c
 create mode 100644 board/AndesTech/common/ftpci100.c
 create mode 100644 board/AndesTech/common/serial.c

diff --git a/board/AndesTech/common/env.c b/board/AndesTech/common/env.c
new file mode 100644
index 0000000..55e2b66
--- /dev/null
+++ b/board/AndesTech/common/env.c
@@ -0,0 +1,138 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ *
+ * Copyright (C) 2006 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm/andesboot.h>
+
+static int check_crc(bd_t *bd)
+{
+	/* need to calculate crc? */
+	if (bd->bi_ext.env_crc_valid == 0)
+	{
+		env_t *env = (env_t *)CONFIG_ENV_ADDR;
+
+		if (crc32(0, env->data, sizeof(env->data)) == env->crc)
+			bd->bi_ext.env_crc_valid = 1;
+		else
+			bd->bi_ext.env_crc_valid = -1;
+	}
+	return bd->bi_ext.env_crc_valid > 0;
+}
+
+
+/*
+ * save environment buffer back to flash
+ * returns -1 on error, 0 if ok
+ */
+int board_env_save(bd_t *bd, env_t *env, int size)
+{
+	int rc;
+	ulong start_addr, end_addr;
+
+
+//no CONFIG_ENV_ADDR_REDUND
+#if CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE /* modified: <= to >, by Hill, 20090313 */
+#error Make sure that CONFIG_ENV_SIZE <= CONFIG_ENV_SECT_SIZE
+#endif
+
+	start_addr = CONFIG_ENV_ADDR;
+	end_addr   = start_addr + CONFIG_ENV_SIZE - 1;
+
+	rc = flash_sect_protect(0, CONFIG_ENV_ADDR, end_addr);
+	if (rc < 0)
+		return rc;
+
+	rc = flash_sect_erase(start_addr, end_addr);
+	if (rc < 0) {
+		flash_sect_protect(1, start_addr, end_addr);
+		flash_perror(rc);
+		return rc;
+	}
+
+	printf("Saving Environment to Flash...");
+	rc = flash_write((uchar*)env, start_addr, size);
+	if (rc < 0)
+		flash_perror(rc);
+	else
+		printf("done.\n");
+
+	(void)flash_sect_protect(1, start_addr, end_addr);
+
+	return 0;
+}
+
+/*
+ * copy environment to memory
+ * returns -1 on error, 0 if ok
+ */
+int board_env_copy(bd_t *bd, env_t *data, int size)
+{
+	env_t *env = (env_t *)CONFIG_ENV_ADDR;
+
+	if (check_crc(bd)) {
+		memcpy(data, env, sizeof(env_t));
+		return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * try to read env character at offset #index
+ *
+ * called before the environment is copied to ram
+ * returns -1 on error, 0 if ok
+ */
+int board_env_getchar(bd_t * bd, int index, uchar *c)
+{
+	env_t *env = (env_t *)CONFIG_ENV_ADDR;
+
+	/* check environment crc */
+	if (index < sizeof(env->data) && check_crc(bd)) {
+		*c = env->data[index];
+		return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * try to read env character at offset #index
+ *
+ * called before the environment is copied to ram
+ * returns -1 on error, 0 if ok
+ */
+uchar *board_env_getaddr(bd_t * bd, int index)
+{
+	env_t *env = (env_t *)CONFIG_ENV_ADDR;
+
+	/* check environment crc */
+	if (index < sizeof(env->data) && check_crc(bd))
+		return &env->data[index];
+
+	return 0;
+}
diff --git a/board/AndesTech/common/flash.c b/board/AndesTech/common/flash.c
new file mode 100644
index 0000000..4dc68c9
--- /dev/null
+++ b/board/AndesTech/common/flash.c
@@ -0,0 +1,621 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ *
+ * Copyright (C) 2006 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm/andesboot.h>
+#include "../include/porting.h"
+#include "../include/flib_flash.h"
+//#include <flash.h>
+//#include <andes.h>
+
+ulong myflush(void);
+
+#define FLASH_BANK_SIZE 0x800000
+#define MAIN_SECT_SIZE  0x20000
+#define PARAM_SECT_SIZE 0x4000
+
+#define MX_SECTOR_COUNT			19
+#define SST39VF080_SECTOR_COUNT		256
+#define SST39VF016_SECTOR_COUNT		512
+
+/* puzzle magic for lart
+ * data_*_flash are def'd in flashasm.S
+ */
+
+extern u32 data_from_flash(u32);
+extern u32 data_to_flash(u32);
+
+#define PUZZLE_FROM_FLASH(x)		(x)
+#define PUZZLE_TO_FLASH(x)		(x)
+
+flash_info_t	flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
+
+
+#define CMD_IDENTIFY			0x90909090
+#define CMD_ERASE_SETUP			0x20202020
+#define CMD_ERASE_CONFIRM		0xD0D0D0D0
+#define CMD_PROGRAM			0x40404040
+#define CMD_RESUME			0xD0D0D0D0
+#define CMD_SUSPEND			0xB0B0B0B0
+#define CMD_STATUS_READ			0x70707070
+#define CMD_STATUS_RESET		0x50505050
+
+#define BIT_BUSY			0x80808080
+#define BIT_ERASE_SUSPEND		0x40404040
+#define BIT_ERASE_ERROR			0x20202020
+#define BIT_PROGRAM_ERROR		0x10101010
+#define BIT_VPP_RANGE_ERROR		0x08080808
+#define BIT_PROGRAM_SUSPEND		0x04040404
+#define BIT_PROTECT_ERROR		0x02020202
+#define BIT_UNDEFINED			0x01010101
+
+#define BIT_SEQUENCE_ERROR		0x30303030
+#define BIT_TIMEOUT			0x80000000
+
+
+// --------------------------------------------------------------------
+//	In bytes
+// --------------------------------------------------------------------
+#define SRAM_BANK_SIZE_32K		0xb0
+#define SRAM_BANK_SIZE_64K		0xc0
+#define SRAM_BANK_SIZE_128K		0xd0
+#define SRAM_BANK_SIZE_256K		0xe0
+#define SRAM_BANK_SIZE_512K		0xf0
+#define SRAM_BANK_SIZE_1M		0x00
+#define SRAM_BANK_SIZE_2M		0x10
+#define SRAM_BANK_SIZE_4M		0x20
+#define SRAM_BANK_SIZE_8M		0x30
+#define SRAM_BANK_SIZE_16M		0x40
+#define SRAM_BANK_SIZE_32M		0x50
+
+
+#define SRAM_BUS_WIDTH_8		0
+#define SRAM_BUS_WIDTH_16		1
+#define SRAM_BUS_WIDTH_32		2
+
+#define K				(1024)
+
+ // pleaase change the timing parameter for different SRAM type
+#define TIMING_PARAMETER  (STMC_BANK_TM_AST3|STMC_BANK_TM_CTW3|STMC_BANK_TM_AT1_F|STMC_BANK_TM_AT2_3|STMC_BANK_TM_WTC3|STMC_BANK_TM_AHT3|STMC_BANK_TM_TRNA_F)
+
+// --------------------------------------------------------------------
+//	setting the config of ROM/flash/sram
+//	write_protect:	1 ==> write protect, 0 ==> should be readable/writable
+//	bank_base: 	==> only the last 24 bits is affect
+// --------------------------------------------------------------------
+void sram_config(int bank_num, u32 bank_base, int write_protect, int bank_type, int bank_size, int bus_width) {
+	u32 config_reg_val;
+
+	config_reg_val = (1UL<<28) | (bank_base & 0x0fffffff) | ((write_protect&0x01)<<11) | bank_type | bank_size | bus_width;
+
+	cpe_outl( NDS32_COMMON_SRAMC_BASE + bank_num*8, config_reg_val);
+}
+
+
+void sram_disable(int bank_num) {
+	cpe_outl( NDS32_COMMON_SRAMC_BASE + bank_num*8, cpe_inl( NDS32_COMMON_SRAMC_BASE + bank_num*8) & 0x0fffffff );
+}
+
+void sram_set_timing(int bank_num, unsigned long timing) {
+	cpe_outl( NDS32_COMMON_SRAMC_BASE + bank_num*8 + 4, timing );
+}
+
+void mx_flash_init(void)
+{
+	int j;
+
+	flash_info[0].flash_id = (MX_MANUFACT & FLASH_VENDMASK) | (MX_ID_29LV008B & FLASH_TYPEMASK);
+	flash_info[0].size = 0x400000;
+	flash_info[0].sector_count = MX_SECTOR_COUNT;
+	memset(flash_info[0].protect, 0, MX_SECTOR_COUNT);
+
+	for (j=0; j<flash_info[0].sector_count; ++j)
+	{
+		if (j==0) {
+			flash_info[0].start[j] = PHYS_FLASH_1;
+		} else if (j==1 || j==2) {
+			flash_info[0].start[j] = PHYS_FLASH_1 + 64*K + 32*K*(j-1);
+		} else if (j==3) {
+			flash_info[0].start[j] = PHYS_FLASH_1 + 128*K;
+		} else {
+			flash_info[0].start[j] = PHYS_FLASH_1 + 256*K + 256*K*(j-4);
+		}
+	}
+}
+
+void sst39vf080_flash_init(void)
+{
+	int j;
+
+	flash_info[0].flash_id =
+		(SST_MANUFACT & FLASH_VENDMASK) | (SST_ID_39VF080 & FLASH_TYPEMASK);
+	flash_info[0].size = 0x400000;
+	flash_info[0].sector_count = SST39VF080_SECTOR_COUNT;
+	memset(flash_info[0].protect, 0, SST39VF080_SECTOR_COUNT);
+
+	for (j=0; j<flash_info[0].sector_count; ++j) {
+		flash_info[0].start[j] = PHYS_FLASH_1 + 16*K*j;
+	}
+}
+
+void sst39vf016_flash_init(void)
+{
+	int j;
+
+	flash_info[0].flash_id =
+		(SST_MANUFACT & FLASH_VENDMASK) | (SST_ID_39VF016 & FLASH_TYPEMASK);
+	flash_info[0].size = 0x800000;
+	flash_info[0].sector_count = SST39VF016_SECTOR_COUNT;
+	memset(flash_info[0].protect, 0, SST39VF016_SECTOR_COUNT);
+
+	for (j=0; j<flash_info[0].sector_count; ++j) {
+		flash_info[0].start[j] = PHYS_FLASH_1 + 16*K*j;
+	}
+}
+
+/* add by Charles Tsai */
+void intel_mx_flash_init(void)
+{
+	int j;
+
+	flash_info[0].flash_id =
+		(INTEL_MANUFACT & FLASH_VENDMASK) | (INTEL_ID_E28F128 & FLASH_TYPEMASK);
+	flash_info[0].size = INTEL_E28F128_SIZE*2; /* 32 MB */
+	flash_info[0].sector_count = (INTEL_E28F128_SIZE*2)/0x40000;
+
+	//memset(flash_info[0].protect, 0, (INTEL_E28F128_SIZE*2)/0x40000); // <- bug
+	memset(flash_info[0].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
+
+	for (j=0; j<flash_info[0].sector_count; ++j)
+	{
+		flash_info[0].start[j] = PHYS_FLASH_1 + 256*K*j; /* sector size=256K */
+	}
+}
+/* end add */
+
+/*-----------------------------------------------------------------------
+ */
+//added by ivan
+#define FLASH_BANK CONFIG_FLASH_BANK // 1
+
+ulong flash_init(void)
+{
+	unsigned int DDI1=0;
+	unsigned int DDI2=0;
+	int i=0;
+
+	//added by ivan wang
+	sram_config(FLASH_BANK, CONFIG_FLASH_BASE, 0, 0, SRAM_BANK_SIZE_4M, SRAM_BUS_WIDTH_32);
+	//sram_config(FLASH_BANK, CONFIG_FLASH_BASE, 0, 0, SRAM_BANK_SIZE_8M, SRAM_BUS_WIDTH_32);
+
+	sram_set_timing(FLASH_BANK, TIMING_PARAMETER);
+	for(i=1;i<7;i++)  // modify by Charles Tsai, bank 0 can't be disabled
+		if(i!=FLASH_BANK)
+			sram_disable(i);
+
+//	fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+	fLib_Flash_ReadID(MX_Type, PHYS_FLASH_1, FLASH_FOUR, &DDI1, &DDI2);
+	//printf("DDI1 = %x, DDI2 = %x\n", DDI1, DDI2);
+	if (DDI1 == 0xc2c2c2c2 && DDI2 == 0x37373737)			// ©ô§» flash
+	{
+		fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+		mx_flash_init();
+	} else {
+		fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+		fLib_Flash_ReadID(SST_Type, PHYS_FLASH_1, FLASH_FOUR, &DDI1, &DDI2);
+		fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+		//printf("DDI1 = %x, DDI2 = %x\n", DDI1, DDI2);
+		if (DDI1 == 0xbfbfbfbf && DDI2 == 0xd8d8d8d8) {
+			sst39vf080_flash_init();
+		} else if(DDI1 == 0xbfbfbfbf && DDI2 == 0xd9d9d9d9) {
+			sram_config(FLASH_BANK, CONFIG_FLASH_BASE, 0, 0, SRAM_BANK_SIZE_8M, SRAM_BUS_WIDTH_32);
+			sst39vf016_flash_init();
+		} else {
+			/* add by Charles Tsai */
+			sram_set_timing(FLASH_BANK, TIMING_PARAMETER);
+			sram_config(FLASH_BANK, CONFIG_FLASH_BASE, 0, 0, SRAM_BANK_SIZE_32M, SRAM_BUS_WIDTH_32);
+			fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+			fLib_Flash_ReadID(Intel_Type, PHYS_FLASH_1, FLASH_FOUR, &DDI1, &DDI2);
+			fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+			printf(" ID1:%x, ID2:%x \n", DDI1, DDI2);
+			if ( (DDI1 == 0x00890089) && (DDI2 == 0x00180018)) {
+				printf("Find Intel flash\n");
+				intel_mx_flash_init();
+			} else
+				printf("can not found any flash\n");
+			/* end add */
+		}
+	}
+
+#ifdef not_complete_yet
+	/*
+	 * Protect monitor and environment sectors
+	 */
+	flash_protect(FLAG_PROTECT_SET,
+			  CONFIG_FLASH_BASE,
+			  CONFIG_FLASH_BASE + _armboot_end - _armboot_start,
+			  &flash_info[0]);
+
+	flash_protect(FLAG_PROTECT_SET,
+			  CONFIG_ENV_ADDR,
+			  CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
+			  &flash_info[0]);
+#endif /* end_of_not */
+
+	return flash_info[0].size;
+}
+
+/*
+ *
+ */
+void flash_print_info(flash_info_t *info)
+{
+	int i;
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+		case (MX_MANUFACT & FLASH_VENDMASK):
+			printf("Macronix: ");
+		break;
+
+		case (SST_MANUFACT & FLASH_VENDMASK):
+			printf("SST: ");
+		break;
+		case (INTEL_MANUFACT & FLASH_VENDMASK):
+			printf("Intel: ");
+		break;
+		default:
+			printf("Unknown Vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+		case (MX_ID_29LV008B & FLASH_TYPEMASK):
+			printf("4x 29LV008B(8Mbit)\n");
+		break;
+
+		case (SST_ID_39VF080 & FLASH_TYPEMASK):
+			printf("4x 39VF080(8Mbit)\n");
+		break;
+
+		case (SST_ID_39VF016 & FLASH_TYPEMASK):
+			printf("4x 39VF016(16Mbit)\n");
+		break;
+		case (INTEL_ID_E28F128&FLASH_TYPEMASK):
+			printf("2x E28F128(128Mbit)\n");
+		break;
+		default:
+			printf("Unknown Chip Type: %x\n", info->flash_id & FLASH_TYPEMASK);
+		goto Done;
+		break;
+	}
+
+	printf("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
+
+	printf("  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; i++) {
+		if ((i % 5) == 0) {
+			printf ("\n   ");
+		}
+		printf (" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : "	 ");
+	}
+	printf ("\n");
+
+Done:
+; //This is because new version of GCC doesn't take label at the end of the compound statement.
+}
+
+/*
+ *
+ */
+
+int flash_error (ulong code)
+{
+	/* Check bit patterns */
+	/* SR.7=0 is busy, SR.7=1 is ready */
+	/* all other flags indicate error on 1 */
+	/* SR.0 is undefined */
+	/* Timeout is our faked flag */
+
+	/* sequence is described in Intel 290644-005 document */
+
+	/* check Timeout */
+	if (code & BIT_TIMEOUT) {
+		printf ("Timeout\n");
+		return ERR_TIMOUT;
+	}
+
+	/* check Busy, SR.7 */
+	if (~code & BIT_BUSY) {
+		printf ("Busy\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Vpp low, SR.3 */
+	if (code & BIT_VPP_RANGE_ERROR) {
+		printf ("Vpp range error\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Device Protect Error, SR.1 */
+	if (code & BIT_PROTECT_ERROR) {
+		printf ("Device protect error\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Command Seq Error, SR.4 & SR.5 */
+	if (code & BIT_SEQUENCE_ERROR) {
+		printf ("Command seqence error\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Block Erase Error, SR.5 */
+	if (code & BIT_ERASE_ERROR) {
+		printf ("Block erase error\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Program Error, SR.4 */
+	if (code & BIT_PROGRAM_ERROR) {
+		printf ("Program error\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Block Erase Suspended, SR.6 */
+	if (code & BIT_ERASE_SUSPEND) {
+		printf ("Block erase suspended\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* check Program Suspended, SR.2 */
+	if (code & BIT_PROGRAM_SUSPEND) {
+		printf ("Program suspended\n");
+		return ERR_PROG_ERROR;
+	}
+
+	/* OK, no error */
+	return ERR_OK;
+}
+
+
+// --------------------------------------------------------------------
+//	erase the sectors between s_first to s_last
+// --------------------------------------------------------------------
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int iflag, cflag, prot, sect;
+	int rc = ERR_OK;
+
+	/* first look for protection bits */
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return ERR_UNKNOWN_FLASH_TYPE;
+	}
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		return ERR_INVAL;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) != (MX_MANUFACT & FLASH_VENDMASK) &&
+		(info->flash_id & FLASH_VENDMASK) != (SST_MANUFACT & FLASH_VENDMASK) ) {
+		if((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
+		return ERR_UNKNOWN_FLASH_VENDOR;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+	if (prot) {
+		// if there exist any sector was protected between s_first to s_last, than return error
+		return ERR_PROTECTED;
+	}
+
+	/*
+	 * Disable interrupts which might cause a timeout
+	 * here. Remember that our exception vectors are
+	 * at address 0 in the flash, and we don't want a
+	 * (ticker) exception to happen while the flash
+	 * chip is in programming mode.
+	 */
+
+	cflag = icache_status();
+	icache_disable();
+
+	iflag = disable_interrupts();
+	/* add  by Charles Tsai */
+	//fLib_Flash_ChipErase(Intel_Type, info->start[0], FLASH_FOUR);
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
+	{
+		int start_addr;
+		int end_addr;
+		printf("Erasing sector %2d ... ", sect);
+
+		if((info->flash_id & FLASH_VENDMASK) == (MX_MANUFACT&FLASH_VENDMASK) ) {
+			fLib_Flash_SectorErase(MX_Type, info->start[0],
+			FLASH_FOUR, (info->start[sect]-info->start[0])/4);
+		} else if((info->flash_id & FLASH_VENDMASK) == (SST_MANUFACT&FLASH_VENDMASK) ) {
+			fLib_Flash_SectorErase(SST_Type, info->start[0], FLASH_FOUR, (info->start[sect]-info->start[0])/4);
+		}
+		else if((info->flash_id & FLASH_VENDMASK) == (INTEL_MANUFACT&FLASH_VENDMASK) ) {
+			/* modify by Charles Tsai for test */
+			fLib_Flash_ChipErase(Intel_Type, info->start[sect], FLASH_FOUR);
+			fLib_Flash_Reset(PHYS_FLASH_1, FLASH_FOUR);
+		} else {
+			printf("unknown flash type\n");
+		return ERR_UNKNOWN_FLASH_TYPE;
+	}
+
+		reset_timer_masked();
+		start_addr = info->start[sect];
+		if (sect < flash_info[0].sector_count-1) {
+			end_addr = info->start[sect+1];
+		} else {
+			end_addr = info->start[0] + info->size;
+		}
+		for (; start_addr < end_addr; start_addr+=4) {
+			for (; *(unsigned long *)start_addr != 0xffffffff; ) {
+				if (get_timer_masked() > CONFIG_FLASH_ERASE_TOUT) {
+					printf("fail:0x%x\n",start_addr);
+					return ERR_PROG_ERROR;
+				}
+			}
+		}
+
+		printf("ok.\n");
+	}
+
+	if (ctrlc())
+		printf("User Interrupt!\n");
+
+outahere:
+	/* allow flash to settle - wait 10 ms */
+	udelay_masked(10000);
+
+	if (iflag)
+		enable_interrupts();
+
+	if (cflag)
+		icache_enable();
+
+	return rc;
+}
+
+/*
+ * Copy memory to flash
+ */
+// --------------------------------------------------------------------
+//	return
+//		ERR_OK ==> without error
+//		less than 0 ==> error code
+// --------------------------------------------------------------------
+volatile static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	volatile ulong new_data;
+	int flash_type;
+
+	if ( (info->flash_id & FLASH_VENDMASK) == (MX_MANUFACT & FLASH_VENDMASK) ) {
+		flash_type = MX_Type;
+	} else if( (info->flash_id & FLASH_VENDMASK) == (SST_MANUFACT & FLASH_VENDMASK) ) {
+		flash_type = SST_Type;
+	} else if( (info->flash_id & FLASH_VENDMASK) == (INTEL_MANUFACT & FLASH_VENDMASK) ) {
+		/* modify by charles Tsai only for test */
+		flash_type = Intel_Type;
+	} else {
+		printf("unknown flash type\n");
+		return ERR_UNKNOWN_FLASH_TYPE;
+	}
+
+	fLib_Flash_ProgramWord(flash_type, info->start[0], dest, data);
+	fLib_Flash_ReadWord(dest, &new_data);
+
+	if (new_data != data) {
+		printf("addr: %x write error: should %x ==> result %x\n", dest, data, new_data);
+		return ERR_PROG_ERROR;
+	}
+
+	return ERR_OK;
+}
+
+/*---------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+// --------------------------------------------------------------------
+//	src ==> source address
+//	addr ==> destination address
+//	return
+//	ERR_OK ==> without error
+//	less than 0 ==> error code
+// --------------------------------------------------------------------
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+
+	ulong cp, wp, data;
+	int l;
+	int i, rc;
+
+	wp = (addr & ~3);   /* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data >> 8) | (*(uchar *)cp << 24);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data >> 8) | (*src++ << 24);
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data >> 8) | (*(uchar *)cp << 24);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = *((vulong*)src);
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		src += 4;
+		wp  += 4;
+		cnt -= 4;
+		if((cnt&0xfff)==0x0)
+			printf(".");
+	}
+	printf("\n");
+	if (cnt == 0) {
+		return ERR_OK;
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data >> 8) | (*src++ << 24);
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data >> 8) | (*(uchar *)cp << 24);
+	}
+
+	return write_word(info, wp, data);
+
+}
diff --git a/board/AndesTech/common/flib_flash.c b/board/AndesTech/common/flib_flash.c
new file mode 100644
index 0000000..826b3bb
--- /dev/null
+++ b/board/AndesTech/common/flib_flash.c
@@ -0,0 +1,721 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ *
+ * Copyright (C) 2006 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/************************************************************************
+* Copyright  Faraday Technology Corp 2002-2003.  All rights reserved.	*
+*-----------------------------------------------------------------------*
+* Name:flash.c								*
+* Description: Flash library routine					*
+* Author: Fred Chien							*
+* Date: 2002/03/01							*
+* Version:1.0								*
+*-----------------------------------------------------------------------*
+************************************************************************/
+
+#include "../include/porting.h"
+#include "../include/flib_flash.h"
+//#include <flash.h>
+
+/* add by Charles Tsai */
+void Do_Delay(unsigned count);
+/* end add */
+void Check_Toggle_Ready(unsigned char  *Dst);
+void Check_Toggle_ReadyHalfWord(unsigned short  *Dst);
+void Check_Toggle_ReadyWord(unsigned  *Dst);
+
+void fLib_Flash_ReadID(unsigned flash_type, unsigned base, unsigned BusWidth, unsigned* DDI1, unsigned* DDI2)
+{
+	if (flash_type == MX_Type)
+	{
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x555,0xaa);
+			cpe_outb(base+0x2aa,0x55);
+			cpe_outb(base+0x555,0x90);
+			Check_Toggle_Ready(base+0x00);
+			*DDI1 = cpe_inb(base+0x00);
+
+			cpe_outb(base+0x555,0xaa);
+			cpe_outb(base+0x2aa,0x55);
+			cpe_outb(base+0x555,0x90);
+			Check_Toggle_Ready(base+0x01);
+			*DDI2 = cpe_inb(base+0x01);
+			break;
+
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x555*2,0xaaaa);
+			cpe_outw(base+0x2aa*2,0x5555);
+			cpe_outw(base+0x555*2,0x9090);
+			Check_Toggle_ReadyHalfWord(base+0x00);
+			*DDI1 = cpe_inw(base+0x00);
+
+			cpe_outw(base+0x555*2,0xaaaa);
+			cpe_outw(base+0x2aa*2,0x5555);
+			cpe_outw(base+0x555*2,0x9090);
+			Check_Toggle_ReadyHalfWord(base+0x02);
+			*DDI2 = cpe_inw(base+0x02);
+			break;
+
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x555*4,0xaaaaaaaa);	// 0x1554
+			cpe_outl(base+0x2aa*4,0x55555555);	// 0xaa8
+			cpe_outl(base+0x555*4,0x90909090);
+			Check_Toggle_ReadyWord(base+0x00);
+			*DDI1 = cpe_inl(base+0x00);
+
+			cpe_outl(base+0x555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aa*4,0x55555555);
+			cpe_outl(base+0x555*4,0x90909090);
+			Check_Toggle_ReadyWord(base+0x04);
+			*DDI2 = cpe_inl(base+0x04);
+			break;
+		}
+	}
+
+	if (flash_type == SST_Type)
+	{
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x5555,0xaa);
+			cpe_outb(base+0x2aaa,0x55);
+			cpe_outb(base+0x5555,0x90);
+			Check_Toggle_Ready(base+0x00);
+			*DDI1 = cpe_inb(base+0x00);
+
+			cpe_outb(base+0x5555,0xaa);
+			cpe_outb(base+0x2aaa,0x55);
+			cpe_outb(base+0x5555,0x90);
+			Check_Toggle_Ready(base+0x00);
+			*DDI2 = cpe_inb(base+0x01);
+			break;
+
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x5555*2,0xaaaa);
+			cpe_outw(base+0x2aaa*2,0x5555);
+			cpe_outw(base+0x5555*2,0x9090);
+			Check_Toggle_ReadyHalfWord(base+0x00);
+			*DDI1 = cpe_inw(base+0x00);
+
+			cpe_outw(base+0x5555*2,0xaaaa);
+			cpe_outw(base+0x2aaa*2,0x5555);
+			cpe_outw(base+0x5555*2,0x9090);
+			Check_Toggle_ReadyHalfWord(base+0x02);
+			*DDI2 = cpe_inw(base+0x02);
+			break;
+
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x5555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aaa*4,0x55555555);
+			cpe_outl(base+0x5555*4,0x90909090);
+			Check_Toggle_ReadyWord(base+0x00);
+			*DDI1 = cpe_inl(base+0x00);
+
+			cpe_outl(base+0x5555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aaa*4,0x55555555);
+			cpe_outl(base+0x5555*4,0x90909090);
+			Check_Toggle_ReadyWord(base+0x04);
+			*DDI2 = cpe_inl(base+0x04);
+			break;
+		}
+	}
+		/* add by Charles Tsai */
+	if (flash_type == Intel_Type)
+	{
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x100,0x90);
+			*DDI1 = cpe_inb(base+0x00);
+			*DDI2 = cpe_inb(base+0x01);
+			cpe_outb(base+0x100,0xff);
+			break;
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x100,0x9090);
+			*DDI1 = cpe_inw(base+0x00);
+			*DDI2 = cpe_inw(base+0x02);
+			cpe_outw(base+0x100,0xffff);
+			break;
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x100,0x00900090);
+			*DDI1 = cpe_inl(base+0x00);
+			*DDI2 = cpe_inl(base+0x04);
+			cpe_outl(base+0x100,0x00ff00ff);
+			break;
+		}
+	}
+		/* end add */
+
+
+}
+
+void fLib_Flash_Reset(unsigned base, unsigned BusWidth)
+{
+	switch(BusWidth)
+	{
+	case FLASH_SINGLE:
+		cpe_outb(base,0xf0);
+		break;
+	case FLASH_DOUBLE:
+		cpe_outw(base,0xf0f0);
+		break;
+	case FLASH_FOUR:
+		//cpe_outl(base,0xf0f0f0f0);
+		cpe_outl(base+0x100,0x00ff00ff); /* modify by Charles Tsai */
+		break;
+	}
+}
+
+void fLib_Flash_ChipErase(unsigned flash_type, unsigned base, unsigned BusWidth)
+{
+		unsigned data;
+
+	if (flash_type == MX_Type)
+	{
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x555,0xaa);
+			cpe_outb(base+0x2aa,0x55);
+			cpe_outb(base+0x555,0x80);
+			cpe_outb(base+0x555,0xaa);
+			cpe_outb(base+0x2aa,0x55);
+			cpe_outb(base+0x555,0x10);
+			break;
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x555*2,0xaaaa);
+			cpe_outw(base+0x2aa*2,0x5555);
+			cpe_outw(base+0x555*2,0x8080);
+			cpe_outw(base+0x555*2,0xaaaa);
+			cpe_outw(base+0x2aa*2,0x5555);
+			cpe_outw(base+0x555*2,0x1010);
+			break;
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aa*4,0x55555555);
+			cpe_outl(base+0x555*4,0x80808080);
+			cpe_outl(base+0x555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aa*4,0x55555555);
+			cpe_outl(base+0x555*4,0x10101010);
+			break;
+		}
+	}
+
+	if (flash_type == SST_Type)
+	{
+		switch(flash_type)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x5555,0xaa);
+			cpe_outb(base+0x2aaa,0x55);
+			cpe_outb(base+0x5555,0x80);
+			cpe_outb(base+0x5555,0xaa);
+			cpe_outb(base+0x2aaa,0x55);
+			cpe_outb(base+0x5555,0x10);
+			break;
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x5555*2,0xaaaa);
+			cpe_outw(base+0x2aaa*2,0x5555);
+			cpe_outw(base+0x5555*2,0x8080);
+			cpe_outw(base+0x5555*2,0xaaaa);
+			cpe_outw(base+0x2aaa*2,0x5555);
+			cpe_outw(base+0x5555*2,0x1010);
+			break;
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x5555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aaa*4,0x55555555);
+			cpe_outl(base+0x5555*4,0x80808080);
+			cpe_outl(base+0x5555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aaa*4,0x55555555);
+			cpe_outl(base+0x5555*4,0x10101010);
+			break;
+		}
+	}
+
+		/* add by Charles Tsai */
+	if (flash_type == Intel_Type)
+	{
+		// Only erase the first sector
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base,0x20);
+			cpe_outb(base,0xd0);
+			cpe_outb(base,0xff);
+
+		// read status register
+				//Do_Delay(0xffff);
+			cpe_outb(base,0x70);
+			data = cpe_inb(base);
+
+			while (data != 0x80) {
+				//Do_Delay(0xffff);
+				cpe_outb(base,0x70);
+				data=cpe_inb(base);
+			}
+			cpe_outb(base,0xff);
+
+			break;
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base,0x2020);
+			cpe_outw(base,0xd0d0);
+			cpe_outw(base,0xffff);
+
+		// read status register
+				//Do_Delay(0xffff);
+			cpe_outw(base,0x7070);
+			data = cpe_inw(base);
+
+			while (data != 0x8080) {
+				//Do_Delay(0xffff);
+				cpe_outw(base,0x7070);
+				data=cpe_inl(base);
+			}
+			cpe_outw(base,0xffff);
+
+			break;
+
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base,0x00200020);Do_Delay(0x30000);
+			cpe_outl(base,0x00d000d0);Do_Delay(0x30000);
+			cpe_outl(base,0x00ff00ff);Do_Delay(0x30000);
+
+			// read status register
+			Do_Delay(0x100000);
+			cpe_outl(base,0x00700070);
+			data = cpe_inl(base);
+			//ivan wang
+			while (data != 0x00800080) {
+			//while ( (data&0xff) != 0x80) {
+				//Do_Delay(0xffff);
+				cpe_outl(base,0x00700070);
+				data=cpe_inl(base);
+			}
+			cpe_outl(base,0x00ff00ff);
+			break;
+		}
+	}
+
+	/* end add */
+}
+
+void fLib_Flash_SectorErase(unsigned flash_type, unsigned base, unsigned BusWidth, unsigned sector) {
+	unsigned data;
+
+	if (flash_type == MX_Type) {
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x555,0xaa);
+			cpe_outb(base+0x2aa,0x55);
+			cpe_outb(base+0x555,0x80);
+			cpe_outb(base+0x555,0xaa);
+			cpe_outb(base+0x2aa,0x55);
+			cpe_outb(base+sector,0x30);
+			break;
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x555*2,0xaaaa);
+			cpe_outw(base+0x2aa*2,0x5555);
+			cpe_outw(base+0x555*2,0x8080);
+			cpe_outw(base+0x555*2,0xaaaa);
+			cpe_outw(base+0x2aa*2,0x5555);
+			cpe_outw(base+sector*2,0x3030);
+			break;
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aa*4,0x55555555);
+			cpe_outl(base+0x555*4,0x80808080);
+			cpe_outl(base+0x555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aa*4,0x55555555);
+			cpe_outl(base+sector*4,0x30303030);
+			break;
+		}
+	}
+
+	if (flash_type == SST_Type) {
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+0x5555,0xaa);
+			cpe_outb(base+0x2aaa,0x55);
+			cpe_outb(base+0x5555,0x80);
+			cpe_outb(base+0x5555,0xaa);
+			cpe_outb(base+0x2aaa,0x55);
+			cpe_outb(base+sector,0x30);
+			break;
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+0x5555*2,0xaaaa);
+			cpe_outw(base+0x2aaa*2,0x5555);
+			cpe_outw(base+0x5555*2,0x8080);
+			cpe_outw(base+0x5555*2,0xaaaa);
+			cpe_outw(base+0x2aaa*2,0x5555);
+			cpe_outw(base+sector*2,0x3030);
+			break;
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+0x5555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aaa*4,0x55555555);
+			cpe_outl(base+0x5555*4,0x80808080);
+			cpe_outl(base+0x5555*4,0xaaaaaaaa);
+			cpe_outl(base+0x2aaa*4,0x55555555);
+			cpe_outl(base+sector*4,0x30303030);
+			break;
+		}
+	}
+
+		/* add by Charles Tsai */
+	if (flash_type == Intel_Type) {
+		switch(BusWidth)
+		{
+		case FLASH_SINGLE: // 8 bit
+			cpe_outb(base+sector,0x20);
+			cpe_outb(base+sector,0xd0);
+
+			// read status register
+			//Do_Delay(0xff);
+			cpe_outb(base,0x70);
+			data = cpe_inb(base);
+
+			while (data != 0x80) {
+				//Do_Delay(0xff);
+				cpe_outb(base,0x70);
+				data=cpe_inb(base);
+			}
+			cpe_outb(base,0xff);
+			break;
+
+		case FLASH_DOUBLE: // double 16 bit
+			cpe_outw(base+sector,0x2020);
+			cpe_outw(base+sector,0xd0d0);
+
+			// read status register
+			//Do_Delay(0xff);
+			cpe_outw(base,0x7070);
+			data = cpe_inw(base);
+
+			while (data != 0x8080) {
+				//Do_Delay(0xff);
+				cpe_outw(base,0x7070);
+				data=cpe_inw(base);
+			}
+			cpe_outw(base,0xffff);
+
+			break;
+		case FLASH_FOUR:// four 32 bit
+			cpe_outl(base+sector,0x00200020);
+			cpe_outl(base+sector,0x00d000d0);
+
+			// read status register
+			//Do_Delay(0xff);
+			cpe_outl(base,0x00700070);
+			data = cpe_inl(base);
+//ivan
+			while (data != 0x00800080) {
+			//while ((data&0xff) != 0x80) {
+				//Do_Delay(0xff);
+				cpe_outl(base,0x00700070);
+				data=cpe_inl(base);
+			}
+			cpe_outl(base,0x00ff00ff);
+
+			break;
+		}
+	}
+		/* end add */
+
+}
+
+// this function only use in FLASH_SINGLE
+void fLib_Flash_ProgramByte(unsigned flash_type, unsigned base, unsigned address, unsigned char data) {
+	volatile unsigned int s_reg = 0; /* add by Charles Tsai */
+
+	if (flash_type == MX_Type)
+	{
+		cpe_outb(base+0x555,0xaa);
+		cpe_outb(base+0x2aa,0x55);
+		cpe_outb(base+0x555,0xa0);
+		cpe_outb(address,data);
+
+		Check_Toggle_Ready((unsigned char  *)address);
+	}
+
+	if (flash_type == SST_Type)
+	{
+		cpe_outb(base+0x5555,0xaa);
+		cpe_outb(base+0x2aaa,0x55);
+		cpe_outb(base+0x5555,0xa0);
+		cpe_outb(address,data);
+
+		Check_Toggle_Ready((unsigned char  *)address);
+	}
+
+		/* add by Charles Tsai */
+		if (flash_type == Intel_Type)
+	{
+		cpe_outb(base,0x40);
+		cpe_outb(address,data);
+
+		//Do_Delay(0xff);
+		cpe_outb(base,0x70);
+		s_reg=cpe_inb(base);
+
+//ivan
+//		while (s_reg != 0x80) {
+		while ((s_reg&0xff) != 0x80) {
+		  //Do_Delay(0xff);
+		  cpe_outb(base,0x70);
+		  s_reg=cpe_inb(base);
+		}
+
+		cpe_outl(base,0x00ff00ff);
+	}
+		/* end add */
+}
+/************************************************************************/
+/* PROCEDURE:	Check_Toggle_Ready					*/
+/*									*/
+/* During the internal program cycle, any consecutive read operation	*/
+/* on DQ6 will produce alternating 0's and 1's (i.e. toggling between	*/
+/* 0 and 1). When the program cycle is completed, DQ6 of the data will  */
+/* stop toggling. After the DQ6 data bit stops toggling, the device is  */
+/* ready for next operation.						*/
+/*									*/
+/* Input:								*/
+/*		Dst		must already be set-up by the caller	*/
+/*									*/
+/* Output:								*/
+/*		None							*/
+/************************************************************************/
+
+void Check_Toggle_Ready (unsigned char  *Dst)
+{
+	unsigned char Loop = 1;
+	unsigned char PreData;
+	unsigned char CurrData;
+	long long TimeOut = 0;
+
+	PreData = *Dst;
+	PreData = PreData & 0x40;
+	while ((TimeOut< 0x07FFFFFF) && (Loop)) {
+		CurrData = *Dst;
+		CurrData = CurrData & 0x40;
+		if (PreData == CurrData)
+			Loop = 0;	/* ready to exit the while loop */
+		PreData = CurrData;
+		TimeOut++;
+	}
+}
+
+// this function only use in FLASH_DOUBLE
+void fLib_Flash_ProgramHalfWord(unsigned flash_type, unsigned base, unsigned address, unsigned short data)
+{
+	volatile unsigned int s_reg = 0;
+
+	if (flash_type == MX_Type) {
+		cpe_outw(base+0x555*2,0xaaaa);
+		cpe_outw(base+0x2aa*2,0x5555);
+		cpe_outw(base+0x555*2,0xa0a0);
+		cpe_outw(address,data);
+		Check_Toggle_ReadyHalfWord((unsigned short *) (address));
+	}
+
+	if (flash_type == SST_Type) {
+
+		cpe_outw(base+0x5555*2,0xaaaa);
+		cpe_outw(base+0x2aaa*2,0x5555);
+		cpe_outw(base+0x5555*2,0xa0a0);
+		cpe_outw(address,data);
+
+		Check_Toggle_ReadyHalfWord((unsigned short *) (address));
+	}
+
+		/* add by Charles Tsai */
+	if (flash_type == Intel_Type) {
+		cpe_outw(base,0x4040);
+		cpe_outw(address,data);
+
+		//Do_Delay(0xff);
+		cpe_outw(base,0x7070);
+		s_reg=cpe_inw(base);
+//ivan
+//		while (s_reg != 0x8080) {
+		while ((s_reg&0xff) != 0x80) {
+			//Do_Delay(0xff);
+			cpe_outw(base,0x7070);
+			s_reg=cpe_inw(base);
+		}
+
+		cpe_outw(base,0xffff);
+	}
+		/* end add */
+}
+
+void Check_Toggle_ReadyHalfWord(unsigned short  *Dst)
+{
+	unsigned char Loop = 1;
+	short PreData;
+	short CurrData;
+	long long TimeOut = 0;
+
+	PreData = *Dst;
+	PreData = PreData & 0x4040;
+	while ((TimeOut< 0x07FFFFFF) && (Loop)) {
+		CurrData = *Dst;
+		CurrData = CurrData & 0x4040;
+		if (PreData == CurrData)
+			Loop = 0;	/* ready to exit the while loop */
+		PreData = CurrData;
+		TimeOut++;
+	}
+}
+
+// this function only use in FLASH_FOUR
+void fLib_Flash_ProgramWord(unsigned flash_type, unsigned base, unsigned address, unsigned data)
+{
+		volatile unsigned int s_reg = 0;
+
+	if (flash_type == MX_Type) {
+		cpe_outl(base+0x555*4,0xaaaaaaaa);
+		cpe_outl(base+0x2aa*4,0x55555555);
+		cpe_outl(base+0x555*4,0xa0a0a0a0);
+		cpe_outl(address,data);
+
+		Check_Toggle_ReadyWord((unsigned  *) (address));
+	}
+
+	if (flash_type == SST_Type) {
+		cpe_outl(base+0x5555*4,0xaaaaaaaa);
+		cpe_outl(base+0x2aaa*4,0x55555555);
+		cpe_outl(base+0x5555*4,0xa0a0a0a0);
+
+		cpe_outl(address,data);
+
+		Check_Toggle_ReadyWord((unsigned  *) (address));
+	}
+
+		/* add by Charles Tsai */
+	if (flash_type == Intel_Type)
+	{
+		cpe_outl(base,0x00400040);
+		cpe_outl(address,data);
+
+		//Do_Delay(0xf);
+		cpe_outl(base,0x00700070);
+		s_reg=cpe_inl(base);
+
+//ivan
+		while (s_reg != 0x00800080) {
+		//while ((s_reg&0xff) != 0x80) {
+		  //Do_Delay(0xf);
+		  cpe_outl(base,0x00700070);
+		  s_reg=cpe_inl(base);
+		}
+
+		cpe_outl(base,0x00ff00ff);
+	}
+		/* end add */
+}
+
+void Check_Toggle_ReadyWord(unsigned  *Dst)
+{
+	unsigned char Loop = 2;
+	unsigned PreData;
+	unsigned CurrData;
+	long long TimeOut = 0;
+
+
+	PreData = *Dst;
+	PreData = PreData & 0x40404040;
+	while (Loop) {
+		CurrData = *Dst;
+		CurrData = CurrData & 0x40404040;
+		if (PreData == CurrData)
+			Loop--;	/* ready to exit the while loop */
+		PreData = CurrData;
+		TimeOut++;
+	}
+
+}
+
+int Check_Toggle_ReadyWord1(unsigned base, unsigned programmed_Data, unsigned  *Dst)
+{
+	unsigned loopCounter;
+	unsigned TimeOutFlag;
+	unsigned ProgramOkFlag;
+	unsigned read_Data;
+	unsigned return_status;
+	unsigned i;
+
+	loopCounter = 0;
+	TimeOutFlag = 0;
+	ProgramOkFlag = 1;
+
+
+	while(1) {
+		read_Data = *Dst;
+		if (read_Data == programmed_Data) {
+			return_status = PROGRAM_OK;
+			break;
+		}
+
+		// delay
+		for (i = 0; i < FLASH_PROGRAM_DELAY_CYCLE; i++);
+
+		if (loopCounter >= FLASH_PROGRAM_LOOP_COUNTER) {
+			return_status = PROGRAM_NOT_OK;
+			break;
+		}
+
+		loopCounter++;
+	}// end of while
+
+	return return_status;
+}
+
+void fLib_Flash_ReadWord(unsigned address, unsigned* data)
+{
+	*data = cpe_inl(address);
+}
+
+void fLib_Flash_ReadHalfWord(unsigned address, unsigned short* data)
+{
+	*data = cpe_inw(address);
+}
+
+void fLib_Flash_ReadByte(unsigned address, unsigned char* data)
+{
+	*data = cpe_inb(address);
+}
+
+
+void Do_Delay(unsigned count)
+{
+	unsigned i;
+
+	for ( i = count; i>0; i--);
+}
diff --git a/board/AndesTech/common/flib_serial.c b/board/AndesTech/common/flib_serial.c
new file mode 100644
index 0000000..2b3df24
--- /dev/null
+++ b/board/AndesTech/common/flib_serial.c
@@ -0,0 +1,373 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ *
+ * Copyright (C) 2006 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/************************************************************************
+* Copyright  Faraday Technology Corp 2002-2003.  All rights reserved.	*
+*-----------------------------------------------------------------------*
+* Name:serial.c								*
+* Description: serial library routine					*
+* Author: Fred Chien							*
+************************************************************************/
+
+#include <nds32_common.h>
+#include "../include/symbol.h"
+#include "../include/serial.h"
+#include "../include/porting.h"
+
+#define outw 				cpe_outl
+#define inw				cpe_inl
+
+void LED_ShowHex(UINT32 u32HexValue)
+{
+	cpe_outl(NDS32_COMMON_DBG_ALPHA, u32HexValue);
+}
+
+UINT64 fLib_CurrentT1Tick()
+{
+	return 0;
+}
+
+#ifdef not_complete_yet
+UINT32 DebugSerialPort = NDS32_COMMON_UART1_BASE;
+UINT32 SystemSerialPort = NDS32_COMMON_UART2_BASE;
+#endif /* end_of_not */
+
+void fLib_SetSerialMode(UINT32 port, UINT32 mode)
+{
+	UINT32 mdr;
+
+	mdr = inw(port + SERIAL_MDR);
+	mdr &= ~SERIAL_MDR_MODE_SEL;
+	outw(port + SERIAL_MDR, mdr | mode);
+}
+
+
+void fLib_EnableIRMode(UINT32 port, UINT32 TxEnable, UINT32 RxEnable)
+{
+	UINT32 acr;
+
+	acr = inw(port + SERIAL_ACR);
+	acr &= ~(SERIAL_ACR_TXENABLE | SERIAL_ACR_RXENABLE);
+	if(TxEnable)
+		acr |= SERIAL_ACR_TXENABLE;
+	if(RxEnable)
+		acr |= SERIAL_ACR_RXENABLE;
+	outw(port + SERIAL_ACR, acr);
+}
+
+/*****************************************************************************/
+
+void fLib_SerialInit(UINT32 port, UINT32 baudrate, UINT32 parity,UINT32 num,UINT32 len)
+{
+	UINT32 lcr;
+
+	lcr = inw(port + SERIAL_LCR) & ~SERIAL_LCR_DLAB;
+	/* Set DLAB=1 */
+	outw(port + SERIAL_LCR,SERIAL_LCR_DLAB);
+	/* Set baud rate */
+	outw(port + SERIAL_DLM, ((baudrate & 0xf00) >> 8));
+	outw(port + SERIAL_DLL, (baudrate & 0xff));
+
+	//clear orignal parity setting
+	lcr &= 0xc0;
+
+	switch (parity)
+	{
+		case PARITY_NONE:
+			//do nothing
+			break;
+		case PARITY_ODD:
+			lcr|=SERIAL_LCR_ODD;
+			break;
+		case PARITY_EVEN:
+			lcr|=SERIAL_LCR_EVEN;
+			break;
+		case PARITY_MARK:
+			lcr|=(SERIAL_LCR_STICKPARITY|SERIAL_LCR_ODD);
+			break;
+		case PARITY_SPACE:
+			lcr|=(SERIAL_LCR_STICKPARITY|SERIAL_LCR_EVEN);
+			break;
+
+		default:
+			break;
+	}
+
+	if(num==2)
+		lcr|=SERIAL_LCR_STOP;
+
+	len-=5;
+
+	lcr|=len;
+
+	outw(port+SERIAL_LCR,lcr);
+}
+
+
+void fLib_SetSerialLoopback(UINT32 port, UINT32 onoff)
+{
+	UINT32 temp;
+
+	temp=inw(port+SERIAL_MCR);
+	if(onoff==ON)
+		temp|=SERIAL_MCR_LPBK;
+	else
+		temp&=~(SERIAL_MCR_LPBK);
+
+	outw(port+SERIAL_MCR,temp);
+}
+
+void fLib_SetSerialFifoCtrl(UINT32 port, UINT32 level, UINT32 resettx, UINT32 resetrx)
+{
+	UINT8 fcr = 0;
+
+	fcr |= SERIAL_FCR_FE;
+
+	switch(level)
+	{
+		case 4:
+			fcr|=0x40;
+			break;
+		case 8:
+			fcr|=0x80;
+			break;
+		case 14:
+			fcr|=0xc0;
+			break;
+		default:
+			break;
+	}
+
+	if(resettx)
+		fcr|=SERIAL_FCR_TXFR;
+
+	if(resetrx)
+		fcr|=SERIAL_FCR_RXFR;
+
+	outw(port+SERIAL_FCR,fcr);
+}
+
+
+void fLib_DisableSerialFifo(UINT32 port)
+{
+	outw(port+SERIAL_FCR,0);
+}
+
+
+void fLib_SetSerialInt(UINT32 port, UINT32 IntMask)
+{
+	outw(port + SERIAL_IER, IntMask);
+}
+
+
+char fLib_GetSerialChar(UINT32 port)
+{
+	char Ch;
+	UINT32 status;
+
+	do
+	{
+		status=inw(port+SERIAL_LSR);
+	}
+	while (!((status & SERIAL_LSR_DR)==SERIAL_LSR_DR));	// wait until Rx ready
+	Ch = inw(port + SERIAL_RBR);
+	return (Ch);
+}
+
+void fLib_PutSerialChar(UINT32 port, char Ch)
+{
+	UINT32 status;
+
+	do
+	{
+		status=inw(port+SERIAL_LSR);
+	} while (!((status & SERIAL_LSR_THRE)==SERIAL_LSR_THRE));	// wait until Tx ready
+	outw(port + SERIAL_THR,Ch);
+}
+
+void fLib_PutSerialStr(UINT32 port, char *Str)
+{
+	char *cp;
+
+	for(cp = Str; *cp != 0; cp++)
+		fLib_PutSerialChar(port, *cp);
+}
+
+void fLib_Modem_waitcall(UINT32 port)
+{
+	fLib_PutSerialStr(port, "ATS0=2\r");
+}
+
+void fLib_Modem_call(UINT32 port, char *tel)
+{
+	fLib_PutSerialStr(port, "ATDT");
+	fLib_PutSerialStr(port,  tel);
+	fLib_PutSerialStr(port, "\r");
+}
+
+int fLib_Modem_getchar(UINT32 port,int TIMEOUT)
+{
+	UINT64 start_time, middle_time, dead_time;
+	UINT32 status;
+	INT8 ch;
+	UINT32 n=0;
+
+	start_time = fLib_CurrentT1Tick();
+	dead_time = start_time + TIMEOUT;
+
+	do
+	{
+		if(n>1000)
+		{
+			middle_time = fLib_CurrentT1Tick();
+			if (middle_time > dead_time)
+				return 0x100;
+		}
+		status = inw(port + SERIAL_LSR);
+		n++;
+	}while (!((status & SERIAL_LSR_DR)==SERIAL_LSR_DR));
+
+	ch = inw(port + SERIAL_RBR);
+	return (ch);
+}
+
+BOOL fLib_Modem_putchar(UINT32 port, INT8 Ch)
+{
+	UINT64 start_time, middle_time, dead_time;
+	UINT32 status;
+	UINT32 n=0;
+
+	start_time = fLib_CurrentT1Tick();
+	dead_time = start_time + 5;
+
+	do
+	{
+		if(n>1000)
+		{
+			middle_time = fLib_CurrentT1Tick();
+			if (middle_time > dead_time)
+				return FALSE;
+		}
+		status = inw(port + SERIAL_LSR);
+		n++;
+	} while (!((status & SERIAL_LSR_THRE)==SERIAL_LSR_THRE));
+
+	outw(port + SERIAL_THR, Ch);
+
+	return TRUE;
+}
+
+void fLib_EnableSerialInt(UINT32 port, UINT32 mode)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_IER);
+	outw(port + SERIAL_IER, data | mode);
+}
+
+
+void fLib_DisableSerialInt(UINT32 port, UINT32 mode)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_IER);
+	mode = data & (~mode);
+	outw(port + SERIAL_IER, mode);
+}
+
+UINT32 fLib_SerialIntIdentification(UINT32 port)
+{
+	return inw(port + SERIAL_IIR);
+}
+
+void fLib_SetSerialLineBreak(UINT32 port)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_LCR);
+	outw(port + SERIAL_LCR, data | SERIAL_LCR_SETBREAK);
+}
+
+void fLib_SetSerialLoopBack(UINT32 port,UINT32 onoff)
+{
+UINT32 temp;
+
+	temp = inw(port+SERIAL_MCR);
+	if(onoff == ON)
+		temp |= SERIAL_MCR_LPBK;
+	else
+		temp &= ~(SERIAL_MCR_LPBK);
+
+	outw(port+SERIAL_MCR,temp);
+}
+
+void fLib_SerialRequestToSend(UINT32 port)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_MCR);
+	outw(port + SERIAL_MCR, data | SERIAL_MCR_RTS);
+}
+
+void fLib_SerialStopToSend(UINT32 port)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_MCR);
+	data &= ~(SERIAL_MCR_RTS);
+	outw(port + SERIAL_MCR, data);
+}
+
+void fLib_SerialDataTerminalReady(UINT32 port)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_MCR);
+	outw(port + SERIAL_MCR, data | SERIAL_MCR_DTR);
+}
+
+void fLib_SerialDataTerminalNotReady(UINT32 port)
+{
+UINT32 data;
+
+	data = inw(port + SERIAL_MCR);
+	data &= ~(SERIAL_MCR_DTR);
+	outw(port + SERIAL_MCR, data);
+}
+
+UINT32 fLib_ReadSerialLineStatus(UINT32 port)
+{
+	return inw(port + SERIAL_LSR);
+}
+
+UINT32 fLib_ReadSerialModemStatus(UINT32 port)
+{
+	return inw(port + SERIAL_MSR);
+}
+// End of file - serial.c
+
diff --git a/board/AndesTech/common/fotg2xx.c b/board/AndesTech/common/fotg2xx.c
new file mode 100644
index 0000000..8fa6c9c
--- /dev/null
+++ b/board/AndesTech/common/fotg2xx.c
@@ -0,0 +1,60 @@
+/*
+ * FOTG2xx (Host Controller Driver) for USB on the Andes.
+ *
+ * Copyright (C) 2009 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * IMPORTANT NOTES
+ * 1 - you MUST define LITTLEENDIAN in the configuration file for the
+ *	 board or this driver will NOT work!
+ * 2 - this driver is intended for use with USB Mass Storage Devices
+ *	 (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <common.h>
+#include <usb.h>
+
+#if defined(CONFIG_CMD_USB) && !defined(CONFIG_PCI_OHCI) && !defined(CONFIG_USB_OHCI_NEW)
+
+int usb_lowlevel_init(void)
+{
+}
+
+int usb_lowlevel_stop(void)
+{
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len)
+{
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+			int transfer_len,struct devrequest *setup)
+{
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+			int transfer_len, int interval)
+{
+}
+
+
+#endif // CONFIG_CMD_USB
diff --git a/board/AndesTech/common/ftmac100.c b/board/AndesTech/common/ftmac100.c
new file mode 100644
index 0000000..825031d
--- /dev/null
+++ b/board/AndesTech/common/ftmac100.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright (C) 2009 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+// --------------------------------------------------------------------
+//	lmc83:	modified from smc91111.c (2002-11-29)
+// --------------------------------------------------------------------
+
+
+#include <common.h>
+#include <asm/andesboot.h>
+#include <malloc.h>
+#include <command.h>
+#include "../include/porting.h"
+#include "../include/ftmac100.h"
+#include <net.h>
+
+
+#ifdef CONFIG_DRIVER_FTMAC100
+
+// Use power-down feature of the chip
+#define POWER_DOWN	0
+
+static unsigned char ftmac100_mac_addr[] = {0x00, 0x41, 0x71, 0x99, 0x00, 0x00};
+
+static const char version[] =
+	"Faraday FTMAC100 Driver, (Linux Kernel 2.4) 10/18/02 - by Faraday\n";
+
+#define inl(addr) 			(*((volatile u32 *)(addr)))
+#define inw(addr)			(*((volatile u16 *)(addr)))
+#define outl(value, addr)  	(*((volatile u32 *)(addr)) = value)
+#define outb(value, addr)	(*((volatile u8 *)(addr)) = value)
+
+struct net_device dev_eth0;
+int tx_rx_cnt = 0;
+/*
+ *
+ * Configuration options, for the experienced user to change.
+ *
+ */
+/*
+ * DEBUGGING LEVELS
+ *
+ * 0 for normal operation
+ * 1 for slightly more details
+ * >2 for various levels of increasingly useless information
+ *	2 for interrupt tracking, status flags
+ *	3 for packet info
+ *	4 for complete packet dumps
+ */
+
+#define DO_PRINT(args...) printk(args)
+
+//#define FTMAC100_DEBUG 5 // Must be defined in makefile
+
+#if (FTMAC100_DEBUG > 2 )
+#define PRINTK3(args...) DO_PRINT(args)
+#else
+#define PRINTK3(args...)
+#endif
+
+#if FTMAC100_DEBUG > 1
+#define PRINTK2(args...) DO_PRINT(args)
+#else
+#define PRINTK2(args...)
+#endif
+
+#ifdef FTMAC100_DEBUG
+#define PRINTK(args...) DO_PRINT(args)
+#else
+#define PRINTK(args...)
+#endif
+
+
+///#define FTMAC100_TIMER
+
+/*
+ *
+ * The internal workings of the driver.  If you are changing anything
+ * here with the SMC stuff, you should have the datasheet and know
+ * what you are doing.
+ *
+ */
+#define CARDNAME "FTMAC100"
+
+#ifdef FTMAC100_TIMER
+	static struct timer_list ftmac100_timer;
+#endif
+
+#define ETH_ZLEN 60
+
+#ifdef  CONFIG_SMC_USE_32_BIT
+#define USE_32_BIT
+#else
+#undef USE_32_BIT
+#endif
+/*
+ *
+ * The driver can be entered at any of the following entry points.
+ *
+ */
+
+extern int eth_init(bd_t *bd);
+extern void eth_halt(void);
+extern int eth_rx(void);
+extern int eth_send(volatile void *packet, int length);
+
+
+int initialized = 0;
+/*
+ * This is called by  register_netdev().  It is responsible for
+ * checking the portlist for the FTMAC100 series chipset.  If it finds
+ * one, then it will initialize the device, find the hardware information,
+ * and sets up the appropriate device parameters.
+ * NOTE: Interrupts are *OFF* when this procedure is called.
+ *
+ * NB:This shouldn't be static since it is referred to externally.
+ */
+int ftmac100_init(struct net_device *dev);
+
+/*
+ * This is called by  unregister_netdev().  It is responsible for
+ * cleaning up before the driver is finally unregistered and discarded.
+ */
+void ftmac100_destructor(struct net_device *dev);
+
+/*
+ * The kernel calls this function when someone wants to use the net_device,
+ * typically 'ifconfig ethX up'.
+ */
+static int ftmac100_open(struct net_device *dev);
+
+
+/*
+ * This is called by the kernel in response to 'ifconfig ethX down'.  It
+ * is responsible for cleaning up everything that the open routine
+ * does, and maybe putting the card into a powerdown state.
+ */
+static int ftmac100_close(struct net_device *dev);
+
+
+/*
+ * This is a separate procedure to handle the receipt of a packet, to
+ * leave the interrupt code looking slightly cleaner
+ */
+inline static int ftmac100_rcv( struct net_device *dev );
+
+
+
+/*
+ * Internal routines
+ */
+
+
+
+/*
+ * A rather simple routine to print out a packet for debugging purposes.
+ */
+#if FTMAC100_DEBUG > 2
+static void print_packet( byte *, int );
+#endif
+
+
+
+
+/* this does a soft reset on the device */
+static void ftmac100_reset( struct net_device *dev );
+
+/* Enable Interrupts, Receive, and Transmit */
+static void ftmac100_enable( struct net_device *dev );
+
+/* this puts the device in an inactive state */
+static void ftmac100_shutdown( unsigned int ioaddr );
+
+/*
+ * Routines to Read and Write the PHY Registers across the
+ * MII Management Interface
+ */
+
+void print_mac(unsigned char *);
+
+void put_mac(int base, unsigned char *mac_addr)
+{
+	int val;
+
+	val = ((u32)mac_addr[0])<<8 | (u32)mac_addr[1];
+	outl(val, base + MAC_MADR_REG);
+	val = ((((u32)mac_addr[2])<<24)&0xff000000) |
+		((((u32)mac_addr[3])<<16)&0xff0000) |
+		((((u32)mac_addr[4])<<8)&0xff00)  |
+		((((u32)mac_addr[5])<<0)&0xff);
+	outl(val, base + MAC_LADR_REG);
+}
+
+void get_mac(int base, unsigned char *mac_addr)
+{
+	int val;
+	val = inl(base + MAC_MADR_REG);
+	mac_addr[0] = (val>>8)&0xff;
+	mac_addr[1] = val&0xff;
+	val = inl(base + MAC_LADR_REG);
+	mac_addr[2] = (val>>24)&0xff;
+	mac_addr[3] = (val>>16)&0xff;
+	mac_addr[4] = (val>>8)&0xff;
+	mac_addr[5] = val&0xff;
+}
+
+/*
+ * Print the Ethernet address
+ */
+void print_mac(unsigned char *mac_addr)
+{
+	int i;
+
+	DO_PRINT("ADDR: ");
+	for (i = 0; i < 5; i++)
+	{
+		DO_PRINT("%2.2x:", mac_addr[i] );
+	}
+	DO_PRINT("%2.2x \n", mac_addr[5] );
+}
+
+
+
+
+#ifdef FTMAC100_TIMER
+static void ftmac100_timer_func(unsigned long dummy)
+{
+	struct net_device *dev = (struct net_device *)ftmac100_timer.data;
+	struct ftmac100_local *lp = (struct ftmac100_local *)dev->priv;
+	int i;
+	int rxdma_own = 0;
+
+	DO_PRINT("lp->rx_idx = %d\n", lp->rx_idx);
+	for (i=0; i<RXDES_NUM; ++i)
+	{
+		rxdma_own += lp->rx_descs[i].RXDMA_OWN;
+		DO_PRINT("%d ", lp->rx_descs[i].RXDMA_OWN);
+		if (i%10==9)
+		{
+			DO_PRINT("\n");
+		}
+	}
+	DO_PRINT("\n");
+
+	mod_timer(&ftmac100_timer, jiffies + FTMAC100_STROBE_TIME);
+}
+
+#endif
+
+/*
+ * Function: ftmac100_reset( struct device* dev )
+ * Purpose:
+ *	This sets the SMC91111 chip to its normal state, hopefully from whatever
+ *	mess that any other DOS driver has put it in.
+ *
+ * Maybe I should reset more registers to defaults in here?  SOFTRST  should
+ * do that for me.
+ *
+ * Method:
+ *	1.  send a SOFT RESET
+ *	2.  wait for it to finish
+ *	3.  enable autorelease mode
+ *	4.  reset the memory management unit
+ *	5.  clear all interrupts
+ */
+static void ftmac100_reset( struct net_device* dev )
+{
+	//struct ftmac100_local *lp 	= (struct ftmac100_local *)dev->priv;
+	unsigned int	ioaddr = dev->base_addr;
+
+	PRINTK2("%s:ftmac100_reset\n", dev->name);
+
+	outl( SW_RST_bit, ioaddr + MACCR_REG );
+
+#ifdef not_complete_yet
+	/* Setup for fast accesses if requested */
+	/* If the card/system can't handle it then there will */
+	/* be no recovery except for a hard reset or power cycle */
+	if (dev->dma) {
+		outw( inw( ioaddr + CONFIG_REG ) | CONFIG_NO_WAIT,	ioaddr + CONFIG_REG );
+	}
+#endif /* end_of_not */
+
+	/* this should pause enough for the chip to be happy */
+	for (; (inl( ioaddr + MACCR_REG ) & SW_RST_bit) != 0; ) {
+		mdelay(10);
+		PRINTK3("RESET: reset not complete yet\n" );
+	}
+
+	/* Disable all interrupts */
+	outl( 0, ioaddr + IMR_REG );
+}
+
+
+/*
+ * Function: ftmac100_enable
+ * Purpose: let the chip talk to the outside work
+ * Method:
+ *	1.  Enable the transmitter
+ *	2.  Enable the receiver
+ *	3.  Enable interrupts
+ */
+static void ftmac100_enable( struct net_device *dev )
+{
+	unsigned int ioaddr 	= dev->base_addr;
+	int i;
+	struct ftmac100_local *lp 	= (struct ftmac100_local *)dev->priv;
+
+	PRINTK2("%s:ftmac100_enable\n", dev->name);
+
+	for (i=0; i<RXDES_NUM; ++i) {
+		lp->rx_descs[i].RXDMA_OWN = OWNBY_FTMAC100;			// owned by FTMAC100
+	}
+	lp->rx_idx = 0;
+
+	for (i=0; i<TXDES_NUM; ++i) {
+		lp->tx_descs[i].TXDMA_OWN = OWNBY_SOFTWARE;			// owned by software
+	}
+	lp->tx_idx = 0;
+
+
+	/* set the MAC address */
+	put_mac(ioaddr, dev->dev_addr);
+
+	outl( lp->rx_descs_dma, ioaddr + RXR_BADR_REG);
+	outl( lp->tx_descs_dma, ioaddr + TXR_BADR_REG);
+	outl( 0x00001010, ioaddr + ITC_REG);					// this value is recommend by document
+	///outl( 0x0, ioaddr + ITC_REG);
+	///outl( (1UL<<TXPOLL_CNT)|(1UL<<RXPOLL_CNT), ioaddr + APTC_REG);
+	outl( (0UL<<TXPOLL_CNT)|(0x1<<RXPOLL_CNT), ioaddr + APTC_REG);
+	outl( 0x1df, ioaddr + DBLAC_REG );					// this value is recommend by document
+	outl( inl(FCR_REG)|0x1, ioaddr + FCR_REG );				// enable flow control
+	outl( inl(BPR_REG)|0x1, ioaddr + BPR_REG );				// enable back pressure register
+
+	/* now, enable interrupts */
+	outl (
+			PHYSTS_CHG_bit	|
+			AHB_ERR_bit		|
+///			RPKT_LOST_bit	|
+///			RPKT_SAV_bit	|
+///			XPKT_LOST_bit	|
+///			XPKT_OK_bit		|
+///			NOTXBUF_bit		|
+///			XPKT_FINISH_bit	|
+///			NORXBUF_bit		|
+			RPKT_FINISH_bit
+			,ioaddr + IMR_REG
+	);
+
+	/// enable trans/recv,...
+	outl(lp->maccr_val, ioaddr + MACCR_REG );
+
+#ifdef FTMAC100_TIMER
+	/// waiting to do: ¨â­Ó¥H¤Wªººô¸ô¥d
+	init_timer(&ftmac100_timer);
+	ftmac100_timer.function = ftmac100_timer_func;
+	ftmac100_timer.data = (unsigned long)dev;
+	mod_timer(&ftmac100_timer, jiffies + FTMAC100_STROBE_TIME);
+#endif
+}
+
+/*
+ * Function: ftmac100_shutdown
+ * Purpose:  closes down the SMC91xxx chip.
+ * Method:
+ *	1. zero the interrupt mask
+ *	2. clear the enable receive flag
+ *	3. clear the enable xmit flags
+ *
+ * TODO:
+ *   (1) maybe utilize power down mode.
+ *	Why not yet?  Because while the chip will go into power down mode,
+ *	the manual says that it will wake up in response to any I/O requests
+ *	in the register space.   Empirical results do not show this working.
+ */
+static void ftmac100_shutdown( unsigned int ioaddr )
+{
+	/// ³]©w interrupt mask register
+	outl( 0, ioaddr + IMR_REG );
+
+	/// enable trans/recv,...
+	outl( 0, ioaddr + MACCR_REG );
+}
+
+
+
+static int ftmac100_send_packet( void *packet, int length, struct net_device *dev )
+{
+	struct ftmac100_local *lp 	= (struct ftmac100_local *)dev->priv;
+	unsigned int ioaddr 	= dev->base_addr;
+	volatile TX_DESC *cur_desc;
+
+
+	PRINTK3("%s:ftmac100_wait_to_send_packet\n", dev->name);
+	cur_desc = &lp->tx_descs[lp->tx_idx];
+
+	/* there is no empty transmit descriptor */
+	for (; cur_desc->TXDMA_OWN != OWNBY_SOFTWARE; )
+	{
+		DO_PRINT("Transmitting busy\n");
+		udelay(10);
+	}
+	length = ETH_ZLEN < length ? length : ETH_ZLEN;
+	length = length > TX_BUF_SIZE ? TX_BUF_SIZE : length;
+
+#if FTMAC100_DEBUG > 2
+///	DO_PRINT("Transmitting Packet\n");
+///	print_packet( packet, length );
+#endif
+	/* waiting to do: slice data into many segments*/
+	memcpy((char *)cur_desc->VIR_TXBUF_BADR, packet, length);
+
+	cur_desc->TXBUF_Size = length;
+	cur_desc->LTS = 1;
+	cur_desc->FTS = 1;
+	cur_desc->TX2FIC = 0;
+	cur_desc->TXIC = 0;
+	cur_desc->TXDMA_OWN = OWNBY_FTMAC100;
+	outl( 0xffffffff, ioaddr + TXPD_REG);
+	lp->tx_idx = (lp->tx_idx + 1) % TXDES_NUM;
+
+
+	return length;
+}
+
+/*
+ * smc_destructor( struct net_device * dev )
+ *   Input parameters:
+ *	dev, pointer to the device structure
+ *
+ *   Output:
+ *	None.
+ */
+void ftmac100_destructor(struct net_device *dev)
+{
+	PRINTK3("%s:ftmac100_destructor\n", dev->name);
+}
+
+/*
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc ..
+ *
+ */
+static int ftmac100_open(struct net_device *dev)
+{
+	unsigned int	ioaddr = dev->base_addr;
+
+	PRINTK2("%s:ftmac100_open\n", dev->name);
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+
+	/* reset the hardware */
+	ftmac100_reset( dev );
+	ftmac100_enable( dev );
+
+	/* set the MAC address */
+	put_mac(ioaddr, dev->dev_addr);
+
+	return 0;
+}
+
+#ifdef USE_32_BIT
+void
+insl32(r,b,l)
+{
+	int __i ;
+	dword *__b2;
+
+	__b2 = (dword *) b;
+	for (__i = 0; __i < l; __i++) {
+		*(__b2 + __i) = *(dword *)(r+0x10000300);
+	}
+}
+#endif
+
+/*
+ * ftmac100_rcv -  receive a packet from the card
+ *
+ * There is ( at least ) a packet waiting to be read from
+ * chip-memory.
+ *
+ * o Read the status
+ * o If an error, record it
+ * o otherwise, read in the packet
+ */
+static int ftmac100_rcv(struct net_device *dev)
+{
+	struct ftmac100_local *lp = (struct ftmac100_local *)dev->priv;
+	int 	packet_length;
+	volatile RX_DESC *cur_desc;
+	int 	cpy_length;
+	int		start_idx;
+	int		seg_length;
+	int 	rcv_cnt;
+
+	///PRINTK3("%s:ftmac100_rcv\n", dev->name);
+	for (rcv_cnt=0; rcv_cnt<1; ++rcv_cnt) {
+		packet_length = 0;
+		start_idx = lp->rx_idx;
+
+		for (; (cur_desc = &lp->rx_descs[lp->rx_idx])->RXDMA_OWN==0; ) {
+			lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM;
+			if (cur_desc->FRS) {
+				if (cur_desc->RX_ERR || cur_desc->CRC_ERR || cur_desc->FTL || cur_desc->RUNT || cur_desc->RX_ODD_NB) {
+					cur_desc->RXDMA_OWN = 1;	// this frame has been processed, return this to hardware
+					return 0;
+				}
+				packet_length = cur_desc->ReceiveFrameLength;		// normal frame
+			}
+
+			// packet's last frame
+			if ( cur_desc->LRS ) {
+				break;
+			}
+		}
+
+		if (packet_length>0)			// received one packet
+		{
+			byte		* data;
+
+			data = NetRxPackets[0];
+			cpy_length = 0;
+			for (; start_idx!=lp->rx_idx; start_idx=(start_idx+1)%RXDES_NUM) {
+				seg_length = min(packet_length - cpy_length, RX_BUF_SIZE);
+				memcpy(data+cpy_length, (char *)lp->rx_descs[start_idx].VIR_RXBUF_BADR, seg_length);
+				cpy_length += seg_length;
+				lp->rx_descs[start_idx].RXDMA_OWN = 1;		// this frame has been processed, return this to hardware
+			}
+			NetReceive(NetRxPackets[0], packet_length);
+#if	FTMAC100_DEBUG > 4
+			DO_PRINT("Receiving Packet\n");
+			print_packet( data, packet_length );
+#endif
+			return packet_length;
+		}
+	}
+	return 0;
+}
+
+
+
+/*
+ * ftmac100_close
+ *
+ * this makes the board clean up everything that it can
+ * and not talk to the outside world.   Caused by
+ * an 'ifconfig ethX down'
+ *
+ */
+static int ftmac100_close(struct net_device *dev)
+{
+	//netif_stop_queue(dev);
+	//dev->start = 0;
+
+	PRINTK2("%s:ftmac100_close\n", dev->name);
+
+	/* clear everything */
+	ftmac100_shutdown( dev->base_addr );
+
+	/* Update the statistics here. */
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+
+	return 0;
+}
+
+
+/* PHY CONTROL AND CONFIGURATION */
+
+
+
+#if FTMAC100_DEBUG > 2
+static void print_packet( byte * buf, int length )
+{
+#if 1
+#if FTMAC100_DEBUG > 3
+	int i;
+	int remainder;
+	int lines;
+#endif
+
+	DO_PRINT("Packet of length %d \n", length );
+
+#if FTMAC100_DEBUG > 3
+	lines = length / 16;
+	remainder = length % 16;
+
+	for ( i = 0; i < lines ; i ++ ) {
+		int cur;
+
+		for ( cur = 0; cur < 8; cur ++ ) {
+			byte a, b;
+
+			a = *(buf ++ );
+			b = *(buf ++ );
+			DO_PRINT("%02x%02x ", a, b );
+		}
+		DO_PRINT("\n");
+	}
+	for ( i = 0; i < remainder/2 ; i++ ) {
+		byte a, b;
+
+		a = *(buf ++ );
+		b = *(buf ++ );
+		DO_PRINT("%02x%02x ", a, b );
+	}
+	DO_PRINT("\n");
+#endif
+#endif
+}
+#endif
+
+
+void ftmac100_ringbuf_alloc(struct ftmac100_local *lp)
+{
+	int i;
+
+	lp->rx_descs = kmalloc( sizeof(RX_DESC)*(RXDES_NUM+1), GFP_DMA|GFP_KERNEL );
+	if (lp->rx_descs == NULL) {
+		DO_PRINT("Receive Ring Buffer allocation error\n");
+		BUG();
+	}
+	lp->rx_descs =  (RX_DESC *)((int)(((char *)lp->rx_descs)+sizeof(RX_DESC)-1)&0xfffffff0);
+	lp->rx_descs_dma = virt_to_phys(lp->rx_descs);
+	memset(lp->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM);
+
+
+	lp->rx_buf = kmalloc( RX_BUF_SIZE*RXDES_NUM, GFP_DMA|GFP_KERNEL );
+	if (lp->rx_buf == NULL || (( (u32)lp->rx_buf % 4)!=0)) {
+		DO_PRINT("Receive Ring Buffer allocation error, lp->rx_buf = %x\n", lp->rx_buf);
+		BUG();
+	}
+	lp->rx_buf_dma = virt_to_phys(lp->rx_buf);
+
+
+	for (i=0; i<RXDES_NUM; ++i) {
+		lp->rx_descs[i].RXBUF_Size = RX_BUF_SIZE;
+		lp->rx_descs[i].EDOTR = 0;			// not last descriptor
+		lp->rx_descs[i].RXBUF_BADR = lp->rx_buf_dma+RX_BUF_SIZE*i;
+		lp->rx_descs[i].VIR_RXBUF_BADR = virt_to_phys( lp->rx_descs[i].RXBUF_BADR );
+	}
+	lp->rx_descs[RXDES_NUM-1].EDOTR = 1;			// is last descriptor
+
+
+	lp->tx_descs = kmalloc( sizeof(TX_DESC)*(TXDES_NUM+1), GFP_DMA|GFP_KERNEL );
+	if (lp->tx_descs == NULL) {
+		DO_PRINT("Transmit Ring Buffer allocation error\n");
+		BUG();
+	}
+	lp->tx_descs =  (TX_DESC *)((int)(((char *)lp->tx_descs)+sizeof(TX_DESC)-1)&0xfffffff0);
+	lp->tx_descs_dma = virt_to_phys(lp->tx_descs);
+	memset(lp->tx_descs, 0, sizeof(TX_DESC)*TXDES_NUM);
+
+	lp->tx_buf = kmalloc( TX_BUF_SIZE*TXDES_NUM, GFP_DMA|GFP_KERNEL );
+	if (lp->tx_buf == NULL || (( (u32)lp->tx_buf % 4)!=0)) {
+		DO_PRINT("Transmit Ring Buffer allocation error\n");
+		BUG();
+	}
+	lp->tx_buf_dma = virt_to_phys(lp->tx_buf);
+
+	for (i=0; i<TXDES_NUM; ++i) {
+		lp->tx_descs[i].EDOTR = 0;					// not last descriptor
+		lp->tx_descs[i].TXBUF_BADR = lp->tx_buf_dma+TX_BUF_SIZE*i;
+		lp->tx_descs[i].VIR_TXBUF_BADR = virt_to_phys( lp->tx_descs[i].TXBUF_BADR );
+	}
+	lp->tx_descs[TXDES_NUM-1].EDOTR = 1;					// is last descriptor
+	PRINTK("lp->rx_descs = %x, lp->rx_rx_descs_dma = %x\n", lp->rx_descs, lp->rx_descs_dma);
+	PRINTK("lp->rx_buf = %x, lp->rx_buf_dma = %x\n", lp->rx_buf, lp->rx_buf_dma);
+	PRINTK("lp->tx_descs = %x, lp->tx_rx_descs_dma = %x\n", lp->tx_descs, lp->tx_descs_dma);
+	PRINTK("lp->tx_buf = %x, lp->tx_buf_dma = %x\n", lp->tx_buf, lp->tx_buf_dma);
+}
+
+//added by ivan
+void ahb_init()
+{
+#ifdef CONFIG_ADP_AG101_110_PLATFORM
+	*(unsigned int *)0x90100040=0x96700000;
+#endif
+}
+
+int eth_init(bd_t *bd)
+{
+	struct ftmac100_local *lp;
+	int i;
+
+	ahb_init();
+
+	if (initialized == 0)
+	{
+		initialized = 1;
+
+		dev_eth0.base_addr = NDS32_COMMON_FTMAC100_BASE;
+		/* Initialize the private structure. */
+		dev_eth0.priv = (void *)malloc(sizeof(struct ftmac100_local));
+		if (dev_eth0.priv == NULL)
+		{
+			DO_PRINT("out of memory\n");
+			return 0;
+		}
+
+
+		/* initialize ftmac100_local */
+		memset(dev_eth0.priv, 0, sizeof(struct ftmac100_local));
+		strcpy(dev_eth0.name, "eth0");
+		lp = (struct ftmac100_local *)dev_eth0.priv;
+		lp->maccr_val = FULLDUP_bit | CRC_APD_bit | MDC_SEL_bit | RCV_EN_bit | XMT_EN_bit  | RDMA_EN_bit	| XDMA_EN_bit;
+		///lp->maccr_val = FULLDUP_bit | CRC_APD_bit | MDC_SEL_bit | RCV_EN_bit | RDMA_EN_bit ;		// receive only
+
+		ftmac100_ringbuf_alloc(lp);
+	}
+	if (memcmp(bd->bi_enetaddr, "\0\0\0\0\0\0", 6) == 0)
+		get_mac(NDS32_COMMON_FTMAC100_BASE, bd->bi_enetaddr);
+	else
+		put_mac(NDS32_COMMON_FTMAC100_BASE, bd->bi_enetaddr);
+	for (i=0; i<6; ++i)
+		dev_eth0.dev_addr[i] = bd->bi_enetaddr[i];
+	print_mac(bd->bi_enetaddr);
+	ftmac100_open(&dev_eth0);
+
+	return 0;
+}
+
+void eth_halt()
+{
+	if (initialized == 1) {
+		ftmac100_close(&dev_eth0);
+	}
+}
+
+int eth_rx()
+{
+	return ftmac100_rcv(&dev_eth0);
+}
+
+int eth_send(volatile void *packet, int length)
+{
+	return ftmac100_send_packet(packet, length, &dev_eth0);
+}
+
+void ftmac100_dummy()
+{
+	printf("enter ftmac100_dummy\n");
+}
+#endif
diff --git a/board/AndesTech/common/ftpci100.c b/board/AndesTech/common/ftpci100.c
new file mode 100644
index 0000000..b117d3c
--- /dev/null
+++ b/board/AndesTech/common/ftpci100.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright (C) 2005 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at andestech.com>
+ *
+ * filename: ftpci100.c
+ * description: the low-level code for FTPCI100 AHB-PCI Bridge,
+ *		implement to meet the u-boot/driver/pci/pci.c.
+ *
+ * history:
+ *	- 2009.04.02, move the code from bootrom to u-boot (Hill).
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ftpci100.h>
+#include <common.h>
+#include <asm/andesboot.h>
+#include <malloc.h>
+#include <command.h>
+
+#if defined(CONFIG_CMD_PCI) && defined (CONFIG_DRIVER_FTPCI100)
+
+/*
+ * register IOs
+ */
+typedef struct
+{
+	volatile unsigned int offset[4096];	 /* 4K * 4 = SZ_16K */
+} __regbase32;
+
+typedef struct
+{
+	volatile unsigned short offset[4096];	/* 4K * 2 = SZ_8K */
+} __regbase16;
+
+typedef struct
+{
+	volatile unsigned char offset[4096];	/* 4K * 1 = SZ_4K */
+} __regbase8;
+
+#define REG32(a)		((__regbase32 *)((a)&~4095))->offset[((a)&4095)>>2]
+#define REG16(a)		((__regbase16 *)((a)&~4095))->offset[((a)&4095)>>1]
+#define REG8(a)			((__regbase8  *)((a)&~4095))->offset[((a)&4095)>>0]
+
+#define inb(a)			REG8(a)
+#define inhw(a)			REG16(a)
+#define inw(a)			REG32(a)
+
+#define outb(a,v)		(REG8(a) = (unsigned char)(v))
+#define outhw(a,v)		(REG16(a) = (unsigned short)(v))
+#define outw(a,v)		(REG32(a) = (unsigned int)(v))
+
+static struct pci_controller sg_PCIHost; //[PCI_MAX_BUS_NUM];
+/*
+ * static members
+ */
+static UINT32 flib_ReadPCICfgSpaceWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg);
+static UINT16 flib_ReadPCICfgSpaceHalfWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg);
+static UINT8 flib_ReadPCICfgSpaceByte(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg);
+static void flib_WritePCICfgSpaceWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg, UINT32 dt);
+static void flib_WritePCICfgSpaceHalfWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg, UINT16 dt);
+static void flib_WritePCICfgSpaceByte(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg, UINT8 dt);
+
+static UINT32 sg_PCIRegBase;
+static PCIResourceMapStruct sg_PCIRscMap_s;
+static PCIBridgeDMAResourceMapStruct sg_PCI_Bridge_DMA_s;
+
+
+static void flib_PCI_INT_Init(void)
+{
+#if 0
+	unsigned int u32i, *pu32;
+
+	pu32 = (unsigned int*)PCI_CARD_MEM_BASE;
+
+	printf("test start \r\n");
+	for(u32i=0; u32i<0x1000; u32i++)
+		pu32[u32i] = u32i;
+	for(u32i=0; u32i<0x1000; u32i++)
+		if(pu32[u32i] != u32i)
+			printf("err: %08Xh	W:%04Xh	R:%04Xh \r\n", &pu32[u32i], u32i, pu32[u32i]);
+	printf("test finish \r\n");
+#endif
+#if 0
+	PCIBridgeINTPollingIndex=0;
+//opened by Howard at 2007-4-23
+	fLib_CloseInt(FIQ_PCI);
+	//Ext_CloseInt(FIQ_PCI);
+
+
+#ifdef PCI_INT_USE_ACTIVE_H
+//opened by Howard at 2007-4-23
+		fLib_SetIntTrig(FIQ_PCI,LEVEL,H_ACTIVE);
+		//Ext_SetIntTrig(FIQ_PCI,LEVEL,H_ACTIVE);
+
+#else
+//opened by Howard at 2007-4-23
+		fLib_SetIntTrig(FIQ_PCI,LEVEL,L_ACTIVE);
+		//Ext_SetIntTrig(FIQ_PCI,LEVEL,L_ACTIVE);
+#endif
+//opened by Howard at 2007-4-23
+	fLib_ConnectInt(FIQ_PCI, (PrHandler)flib_PCI_IntHandler);
+	//Ext_ConnectInt(FIQ_PCI, (PrHandler)flib_PCI_IntHandler);
+//opened by Howard at 2007-4-23
+	fLib_EnableInt(FIQ_PCI);
+	//Ext_EnableInt(FIQ_PCI);
+#endif
+}
+
+
+static void InitPCIBridge(UINT32 RegBase)
+{
+	UINT32 u32TestValue1;
+
+	// 1.Set the PCI Reg Base
+	sg_PCIRegBase = RegBase;
+
+	// 2.disable the Interrupt Mask (INTA/INTB/INTC/INTD)
+	outw(NDS32_COMMON_PCI_IO_BASE+PCI_CONFIG_ADDR_REG ,(PCI_BRIDGE_CFG_SPACE_CONTROL|0x80000000));
+	u32TestValue1 = inw(NDS32_COMMON_PCI_IO_BASE+PCI_CONFIG_DATA_REG);
+
+#if 0
+	u32TestValue1 |= PCI_ENABLE_INTA_INTB_INTC_INTD;
+#else
+	u32TestValue1 &= ~PCI_ALL_INTs_MASK; // disable INTs
+#endif
+	outw(NDS32_COMMON_PCI_IO_BASE+PCI_CONFIG_ADDR_REG, (PCI_BRIDGE_CFG_SPACE_CONTROL|0x80000000));
+	outw(NDS32_COMMON_PCI_IO_BASE+PCI_CONFIG_DATA_REG, u32TestValue1);
+
+	// 3.Init PCI Bridge INT (do nothing)
+	flib_PCI_INT_Init();
+
+}
+
+
+
+/*
+ * * Function Name:	flib_PCIBridgeMemoryRequest
+ * * Description: 	1.Fix mem for the DMA (PCI.h)
+ *			2.Set the PCI Bridge Configuration Space
+ */
+static void flib_PCIBridgeMemoryRequest(void)
+{
+	PCIDeviceIDStruct PCIDeviceID;
+
+	sg_PCI_Bridge_DMA_s.PCI_DMA_Base_Address = PCI_BRIDGE_DMA_START_ADDRESS;
+	PCIDeviceID.BusNum = PCIDeviceID.DevNum = PCIDeviceID.FunNum = 0x00;
+	flib_WritePCICfgSpaceWord(PCIDeviceID, PCI_BRIDGE_CFG_SPACE_MEM1_BA,
+		PCI_BRIDGE_DMA_START_SIZE_VALUE);
+
+	sg_PCI_Bridge_DMA_s.PCI_DMA_Start_Pointer = (UINT8*)PCI_BRIDGE_DMA_START_ADDRESS;
+	sg_PCI_Bridge_DMA_s.PCI_DMA_Size_Remain = PCI_BRIDGE_DMA_SIZE*1024*1024;
+}
+
+
+void flib_DisablePCIDevice(PCIDeviceIDStruct PCIDeviceID)
+{
+	UINT32 CMDType;
+	PCIDeviceID.RegNum = PCI_CSH_COMMAND_REG;
+	CMDType = flib_ReadPCICfgSpaceByte(PCIDeviceID, PCI_CSH_COMMAND_REG);
+	flib_WritePCICfgSpaceByte(PCIDeviceID, PCI_CSH_COMMAND_REG, CMDType & ~(UINT32)(PCI_CMD_IO_ENABLE|PCI_CMD_MEM_ENABLE));
+}
+
+
+void flib_EnablePCIDevice(PCIDeviceIDStruct PCIDeviceID)
+{
+	UINT32 CMDType;
+	PCIDeviceID.RegNum = PCI_CSH_COMMAND_REG;
+	CMDType = flib_ReadPCICfgSpaceByte(PCIDeviceID, PCI_CSH_COMMAND_REG);
+	flib_WritePCICfgSpaceByte(PCIDeviceID, PCI_CSH_COMMAND_REG, CMDType | PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE);
+}
+
+
+void flib_SetPCIMaster(PCIDeviceIDStruct PCIDeviceID)
+{
+	UINT32 CMDType;
+	PCIDeviceID.RegNum = PCI_CSH_COMMAND_REG;
+	CMDType = flib_ReadPCICfgSpaceByte(PCIDeviceID, PCI_CSH_COMMAND_REG);
+	flib_WritePCICfgSpaceByte(PCIDeviceID, PCI_CSH_COMMAND_REG, CMDType | PCI_CMD_BUS_MASTER_ENABLE);
+}
+
+
+/*
+ * * Function Name: flib_AssignPCIResource
+ * * Description: It will assign the PCI Device resource of the:
+ *				1.IO Resourse
+ *				2.Mem Resource
+ */
+void flib_AssignPCIResource
+(
+	PCIDeviceIDStruct PCIDeviceID , UINT32 *PciMemStart, UINT32 *PciIoStart
+)
+{
+	UINT32	lw, i, j, Reg, BaseAddrReg, BaseSize;
+	UINT32	dwAlignmentSize;
+
+	for (i = 0 ; i < PCI_MAX_BAR_NUM ; i++)
+	{
+		Reg = PCI_CSH_BASE_ADDR_REG + (i * 4);
+		flib_WritePCICfgSpaceWord(PCIDeviceID, Reg, 0xFFFFFFFF);
+		lw = flib_ReadPCICfgSpaceWord(PCIDeviceID, Reg);
+		print_pci("%08Xh \r\n", lw);
+
+		if ((lw == 0) || ((lw & 0xffffffff) == 0xffffffff))
+		{
+			continue;
+		}
+		else
+		{
+			if ((lw & 0x01) != 0x00)		 /* it's IO base */
+			{
+				print_pci("it's IO base\n\r");//Howard at 2007-4-23
+				lw >>= 2;
+				for (j=2; j < 32; j++)
+				{
+					if ((lw & 0x01) == 0x01) // Harry at Dec.30.2006
+						break;
+					lw >>= 1;
+				}
+				BaseSize = 1 << j;
+				if (BaseSize>=PCI_IO_SPACE_ALIGNMENT)
+						dwAlignmentSize=BaseSize;
+				else	dwAlignmentSize=PCI_IO_SPACE_ALIGNMENT;
+
+				if ((*PciIoStart % dwAlignmentSize) != 0)
+					*PciIoStart = ((*PciIoStart / dwAlignmentSize) + 1) * dwAlignmentSize;
+
+				BaseAddrReg = *PciIoStart;
+				*PciIoStart += BaseSize;
+				flib_WritePCICfgSpaceWord(PCIDeviceID, Reg, BaseAddrReg);
+				print_pci("	B:%02u.D:%02u.F:%02u	Reg:%08Xh	BaseAddrReg:%08Xh\r\n",
+					PCIDeviceID.BusNum, PCIDeviceID.DevNum, PCIDeviceID.FunNum, Reg, BaseAddrReg);
+			}
+			else if ((lw & 0x01) != 0x01)		/* it's Memory base */
+			{
+				print_pci("it's Memory base\n\r");//Howard at 2007-4-23
+				lw >>= 4;
+				for (j=4; j < 32; j++)
+				{
+					if ((lw & 0x01) == 0x01) // Harry at Dec.30.2006
+						break;
+					lw >>= 1;
+				}
+				BaseSize = 1 << j;
+
+				if (BaseSize>=PCI_MEM_SPACE_ALIGNMENT)
+						dwAlignmentSize=BaseSize;
+				else	dwAlignmentSize=PCI_MEM_SPACE_ALIGNMENT;
+
+				if ((*PciMemStart % dwAlignmentSize) != 0)
+					*PciMemStart = ((*PciMemStart / dwAlignmentSize) + 1) * dwAlignmentSize;
+
+				BaseAddrReg = *PciMemStart;
+				flib_WritePCICfgSpaceWord(PCIDeviceID, Reg, BaseAddrReg);
+				print_pci("	B:%02u.D:%02u.F:%02u	Reg:%08Xh	BaseAddrReg:%08Xh\r\n",
+					PCIDeviceID.BusNum, PCIDeviceID.DevNum, PCIDeviceID.FunNum, Reg, BaseAddrReg);
+
+				*PciMemStart += BaseSize;
+			}
+		}
+	}
+}
+
+BOOL flib_FindNextPCIDevice(PCIDeviceIDStruct CurrDevID,PCIDeviceIDStruct *NextDevID)
+{
+	UINT16 VendorID;
+	UINT8 HeaderType;
+
+	/* read vendor id to check whether this PCI device exists or not */
+	VendorID = flib_ReadPCICfgSpaceHalfWord(CurrDevID, PCI_CSH_VENDOR_ID_REG);
+	if ((VendorID != 0x0) && (VendorID != 0xFFFF))
+	{
+		//This device is exist, then it will get the counter of the Dev number and Fun number
+		printf("\r\n+ FindNextPCIDev,	B:%02u.D:%02u.F:%02u	VID: %04Xh \r\n",
+			CurrDevID.BusNum, CurrDevID.DevNum, CurrDevID.FunNum, VendorID);
+
+		//1.To determine single_function/multi_function
+		HeaderType = flib_ReadPCICfgSpaceByte(CurrDevID, PCI_CSH_HEADER_TYPE_REG);
+		/* the bit 7 of header type is 1, it it multi function device */
+		if (HeaderType & PCI_HEADER_TYPE_MULTI_FUNCTION)
+		{
+			printf("multi-func \r\n");
+			CurrDevID.FunNum++;
+			if (CurrDevID.FunNum >= PCI_MAX_FUNCTION_NUM)
+				CurrDevID.DevNum++;
+		}
+		else
+		{
+			printf("single-func \r\n");
+			CurrDevID.DevNum++;
+			CurrDevID.FunNum = 0;
+		}
+
+		printf("\r\n- FindNextPCIDev,	B:%02u.D:%02u.F:%02u	VID: %04Xh \r\n",
+			CurrDevID.BusNum, CurrDevID.DevNum, CurrDevID.FunNum, VendorID);
+
+	}
+	else
+	{
+		//printf("%s[Ln.%u] invalid Vendor ID: %04Xh /r/n", __FILE__, __LINE__, VendorID);
+		/* if this PCI device does not exist, find PCI device from the beginning */
+		CurrDevID.BusNum = 0;
+		CurrDevID.DevNum = 0;
+		CurrDevID.FunNum = 0;
+	}
+
+	for (;CurrDevID.BusNum < PCI_MAX_BUS_NUM; CurrDevID.BusNum++, CurrDevID.DevNum=0)
+		for (;CurrDevID.DevNum < PCI_MAX_DEVICE_NUM; CurrDevID.DevNum++, CurrDevID.FunNum=0)
+			for (;CurrDevID.FunNum < PCI_MAX_FUNCTION_NUM; CurrDevID.FunNum++)
+			{
+				VendorID = flib_ReadPCICfgSpaceHalfWord(CurrDevID, PCI_CSH_VENDOR_ID_REG);
+
+				if ((VendorID != 0x0) && (VendorID != 0xFFFF))
+				{
+					*NextDevID = CurrDevID;
+					return TRUE;
+				}
+			}
+
+	return FALSE;
+}
+
+
+
+static void flib_AssignPCIResource_hill(void)
+{
+	PCIDeviceIDStruct CurrDevID_st;
+	UINT16 VendorID;
+	UINT8 HeaderType;
+
+	CurrDevID_st.BusNum = 0;
+	CurrDevID_st.DevNum = 1;
+	CurrDevID_st.FunNum = 0;
+
+	/* read vendor id to check whether this PCI device exists or not */
+	for (;CurrDevID_st.BusNum < PCI_MAX_BUS_NUM; CurrDevID_st.BusNum++, CurrDevID_st.DevNum=0)
+		for (;CurrDevID_st.DevNum < PCI_MAX_DEVICE_NUM; CurrDevID_st.DevNum++, CurrDevID_st.FunNum=0)
+			for (;CurrDevID_st.FunNum < PCI_MAX_FUNCTION_NUM; CurrDevID_st.FunNum++)
+			{
+				VendorID = flib_ReadPCICfgSpaceHalfWord(CurrDevID_st, PCI_CSH_VENDOR_ID_REG);
+				if ((VendorID != 0x0) && (VendorID != 0xFFFF))
+				{
+					flib_DisablePCIDevice(CurrDevID_st);
+					print_pci("\r\n	B:%02u.D:%02u.F:%02u	VID: %04Xh \r\n",
+						CurrDevID_st.BusNum, CurrDevID_st.DevNum, CurrDevID_st.FunNum, VendorID);
+					flib_AssignPCIResource(CurrDevID_st,
+						&sg_PCIRscMap_s.PciMem0Addr, &sg_PCIRscMap_s.PciIOAddr);
+
+					flib_EnablePCIDevice(CurrDevID_st);
+					flib_SetPCIMaster(CurrDevID_st);
+				}
+			}
+
+}
+
+
+// scan device and print the Vendor ID / Device ID
+static void flib_scan_device(void)
+{
+	UINT16 u16VendorID, u16DevID;
+	PCIDeviceIDStruct CurrDevID;
+	UINT8 u8HeadType;
+
+	for(CurrDevID.BusNum=0; CurrDevID.BusNum < PCI_MAX_BUS_NUM; CurrDevID.BusNum++)
+		for (CurrDevID.DevNum=0; CurrDevID.DevNum < PCI_MAX_DEVICE_NUM; CurrDevID.DevNum++)
+			for (CurrDevID.FunNum=0;CurrDevID.FunNum < PCI_MAX_FUNCTION_NUM; CurrDevID.FunNum++)
+			{
+				u16VendorID = flib_ReadPCICfgSpaceHalfWord(CurrDevID, PCI_CSH_VENDOR_ID_REG);
+				u16DevID = flib_ReadPCICfgSpaceHalfWord(CurrDevID, PCI_CSH_DEVICE_ID_REG);
+				u8HeadType = flib_ReadPCICfgSpaceByte(CurrDevID, PCI_CSH_HEADER_TYPE_REG);
+
+				if(0 == u16VendorID)
+					printf("VID == 0 \r\n");
+				else if(0xFFFF != u16DevID)
+				{
+					printf("Bus: %02Xh	Dev: %02Xh	Func: %02Xh \r\n",
+						CurrDevID.BusNum, CurrDevID.DevNum, CurrDevID.FunNum);
+					printf("	VID: %04Xh	DevID: %04Xh	%s\r\n", u16VendorID, u16DevID,
+						(u8HeadType&0x80)?"Multi-Fun":"Single-Fun");
+				}
+			}
+}
+
+static void flib_PCI_InitPCIDevice(void)
+{
+	PCIDeviceIDStruct PCIDeviceID;
+
+	// 1.Init InitPCIBridge
+	InitPCIBridge(NDS32_COMMON_PCI_IO_BASE);
+
+	// 2.Set start Address of the I/O and Mem
+	sg_PCIRscMap_s.PciIOAddr=PCI_CARD_IO_BASE;
+	sg_PCIRscMap_s.PciMem0Addr=PCI_CARD_MEM_BASE;
+
+#if 0
+	// 3.Reserve Mem for DMA, write Base/Size to the PCI Bridge Configuration Space
+	flib_PCIBridgeMemoryRequest();
+
+	// 4.Assign the Resource & Enable PCI DEVICE & Start PCI Device
+	PCIDeviceID.BusNum = PCIDeviceID.DevNum = PCIDeviceID.FunNum = 0;
+	// device 0 has been assigned resource in step.3.
+	while(flib_FindNextPCIDevice(PCIDeviceID, &PCIDeviceID))
+	{
+		flib_AssignPCIResource(PCIDeviceID, &sg_PCIRscMap_s.PciMem0Addr, &sg_PCIRscMap_s.PciIOAddr);
+		flib_EnablePCIDevice(PCIDeviceID);
+		flib_SetPCIMaster(PCIDeviceID);
+	}
+#else
+	PCIDeviceID.BusNum = 0;
+	PCIDeviceID.DevNum = 0;
+	PCIDeviceID.FunNum = 0;
+	flib_WritePCICfgSpaceWord(PCIDeviceID, PCI_BRIDGE_CFG_SPACE_MEM1_BA,
+		PCI_INBOUND_MEM_BASE & (~0xFFF0000) | PCI_INBOUND_MEM_256MB);
+	print_pci("%X \r\n", PCI_INBOUND_MEM_BASE & (~0xFFF0000) | PCI_INBOUND_MEM_256MB);
+
+	//flib_scan_device();
+	flib_AssignPCIResource_hill();
+#endif
+}
+
+static UINT32 flib_ReadPCICfgSpaceWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg)
+{
+	PCIDeviceID.RegNum = Reg;
+	PCIDeviceID.Enable = 1;
+	outw(sg_PCIRegBase + PCI_CONFIG_ADDR_REG, *(UINT32 *)((void *)&PCIDeviceID)); // Harry at Dec.30.2006
+	return inw(sg_PCIRegBase+PCI_CONFIG_DATA_REG);
+}
+
+static UINT16 flib_ReadPCICfgSpaceHalfWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg)
+{
+	UINT32 lw;
+
+	lw = flib_ReadPCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc));
+	switch(Reg % 4)
+	{
+		case 0:
+		case 1:
+			lw &= 0x0000FFFF;
+			break;
+		case 2:
+		case 3:
+			lw &= 0xFFFF0000;
+			lw = lw >> 16;
+			break;
+	}
+
+	return (UINT16)lw;
+}
+
+
+static UINT8 flib_ReadPCICfgSpaceByte(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg)
+{
+	UINT32 lw;
+
+	lw = flib_ReadPCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc));
+	switch(Reg % 4)
+	{
+		case 0:
+			lw &= 0x000000FF;
+			break;
+		case 1:
+			lw &= 0x0000FF00;
+			lw = lw >> 8;
+			break;
+		case 2:
+			lw &= 0x00FF0000;
+			lw = lw >> 16;
+			break;
+		case 3:
+			lw &= 0xFF000000;
+			lw = lw >> 24;
+			break;
+	}
+
+	return (UINT8)lw;
+}
+
+static void flib_WritePCICfgSpaceWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg, UINT32 dt)
+{
+	PCIDeviceID.RegNum = Reg;
+	PCIDeviceID.Enable = 1;
+
+	outw(sg_PCIRegBase + PCI_CONFIG_ADDR_REG,	*(UINT32 *)((void *)&PCIDeviceID));
+	outw(sg_PCIRegBase + PCI_CONFIG_DATA_REG, dt);
+}
+
+static void flib_WritePCICfgSpaceHalfWord(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg, UINT16 dt)
+{
+	UINT32 lw;
+
+	lw = flib_ReadPCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc));
+	switch(Reg % 4)
+	{
+		case 0:
+		case 1:
+			lw &= 0xFFFF0000;
+			lw += dt;
+			flib_WritePCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc), lw);
+			break;
+		case 2:
+		case 3:
+			lw &= 0x0000FFFF;
+			lw += (UINT32)(((UINT32)dt) << 16);
+			flib_WritePCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc), lw);
+			break;
+	}
+}
+
+static void flib_WritePCICfgSpaceByte(PCIDeviceIDStruct PCIDeviceID, UINT32 Reg, UINT8 dt)
+{
+	UINT32 lw;
+
+	lw = flib_ReadPCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc));
+	switch(Reg % 4)
+	{
+		case 0:
+			lw &= 0xFFFFFF00;
+			lw += dt;
+			flib_WritePCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc), lw);
+			break;
+		case 1:
+			lw &= 0xFFFF00FF;
+			lw += (UINT32)(((UINT32)dt) << 8);
+			flib_WritePCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc), lw);
+			break;
+		case 2:
+			lw &= 0xFF00FFFF;
+			lw += (UINT32)(((UINT32)dt) << 16);
+			flib_WritePCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc), lw);
+			break;
+		case 3:
+			lw &= 0x00FFFFFF;
+			lw += (UINT32)(((UINT32)dt) << 24);
+			flib_WritePCICfgSpaceWord(PCIDeviceID, (Reg&0xfffffffc), lw);
+			break;
+	}
+}
+
+int flib_read_byte(struct pci_controller *pPciHC, pci_dev_t PciDev, int where, u8 *pu8Dat)
+{
+	PCIDeviceIDStruct DevId;
+
+	DevId.BusNum = PCI_BUS(PciDev);
+	DevId.DevNum= PCI_DEV(PciDev);
+	DevId.FunNum = PCI_FUNC(PciDev);
+	*pu8Dat = flib_ReadPCICfgSpaceByte(DevId, where);
+	return 0;
+}
+
+int flib_read_word(struct pci_controller *pPciHC, pci_dev_t PciDev, int where, u16 *pu16Dat)
+{
+	PCIDeviceIDStruct DevId;
+
+	DevId.BusNum = PCI_BUS(PciDev);
+	DevId.DevNum= PCI_DEV(PciDev);
+	DevId.FunNum = PCI_FUNC(PciDev);
+	*pu16Dat = flib_ReadPCICfgSpaceHalfWord(DevId, where);
+	return 0;
+}
+
+int flib_read_dword(struct pci_controller *pPciHC, pci_dev_t PciDev, int where, u32 *pu32Dat)
+{
+	PCIDeviceIDStruct DevId;
+
+	DevId.BusNum = PCI_BUS(PciDev);
+	DevId.DevNum= PCI_DEV(PciDev);
+	DevId.FunNum = PCI_FUNC(PciDev);
+	*pu32Dat = flib_ReadPCICfgSpaceWord(DevId, where);
+	return 0;
+}
+
+int flib_write_byte(struct pci_controller *pPciHC, pci_dev_t PciDev, int where, u8 u8Dat)
+{
+	PCIDeviceIDStruct DevId;
+
+	DevId.BusNum = PCI_BUS(PciDev);
+	DevId.DevNum= PCI_DEV(PciDev);
+	DevId.FunNum = PCI_FUNC(PciDev);
+	flib_WritePCICfgSpaceByte(DevId, where, u8Dat);
+	return 0;
+}
+
+int flib_write_word(struct pci_controller *pPciHC, pci_dev_t PciDev, int where, u16 u16Dat)
+{
+	PCIDeviceIDStruct DevId;
+
+	DevId.BusNum = PCI_BUS(PciDev);
+	DevId.DevNum= PCI_DEV(PciDev);
+	DevId.FunNum = PCI_FUNC(PciDev);
+	flib_WritePCICfgSpaceHalfWord(DevId, where, u16Dat);
+	return 0;
+}
+
+int flib_write_dword(struct pci_controller *pPciHC, pci_dev_t PciDev, int where, u32 u32Dat)
+{
+	PCIDeviceIDStruct DevId;
+
+	DevId.BusNum = PCI_BUS(PciDev);
+	DevId.DevNum= PCI_DEV(PciDev);
+	DevId.FunNum = PCI_FUNC(PciDev);
+	flib_WritePCICfgSpaceWord(DevId, where, u32Dat);
+	return 0;
+}
+
+/*
+ * exposed APIs
+ */
+
+// low-level init routine, called by /drivers/pci/pci.c - pci_init.
+void pci_init_board(void)
+{
+	struct pci_controller *host = &sg_PCIHost;
+
+	flib_PCI_InitPCIDevice();
+
+	memset(host, 0, sizeof(struct pci_controller));
+
+	/*
+	 * Register the hose
+	 */
+	host->first_busno = 0;
+	host->last_busno = 0xff;
+
+	/*pci_setup_indirect(host,
+			(sg_PCIRegBase + PCI_CONFIG_ADDR_REG),
+			(sg_PCIRegBase + PCI_CONFIG_DATA_REG));
+	*/
+
+#if 0
+	/* System memory space */
+	pci_set_region (host->regions + 0,
+			AP1000_SYS_MEM_START, AP1000_SYS_MEM_START,
+			AP1000_SYS_MEM_SIZE,
+			PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	/* PCI Memory space */
+	pci_set_region (host->regions + 1,
+			PSII_PCI_MEM_BASE, PSII_PCI_MEM_BASE,
+			PSII_PCI_MEM_SIZE, PCI_REGION_MEM);
+
+	host->region_count = 2;
+#else
+	#if 0
+	/* PCI memory space */
+	pci_set_region(host->regions + 1,
+				PCI_CARD_MEM_BASE,
+				PCI_CARD_MEM_BASE,
+				PCI_CARD_MEM_TOTAL_SIZE,
+				PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(host->regions + 2,
+				PCI_CARD_IO_BASE,
+				PCI_CARD_IO_BASE,
+				0x100000-0x1000,
+				PCI_REGION_IO);
+
+	host->region_count = 2;
+	#else
+	/* System space */
+	pci_set_region(host->regions + 0,
+				PCI_BRIDGE_DMA_START_ADDRESS,
+				PCI_BRIDGE_DMA_START_ADDRESS,
+				PCI_BRIDGE_DMA_START_SIZE_VALUE - PCI_BRIDGE_DMA_START_ADDRESS,
+				PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	/* PCI memory space */
+	pci_set_region(host->regions + 1,
+				PCI_CARD_MEM_BASE,
+				PCI_CARD_MEM_BASE,
+				PCI_CARD_MEM_TOTAL_SIZE,
+				PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(host->regions + 2,
+				PCI_CARD_IO_BASE,
+				PCI_CARD_IO_BASE,
+				0x100000-0x1000,
+				PCI_REGION_IO);
+
+	host->region_count = 3;
+#endif
+#endif
+
+	/* No IO Memory space	- for now */
+	pci_set_ops (host,
+			 flib_read_byte, flib_read_word, flib_read_dword,
+			 flib_write_byte, flib_write_word, flib_write_dword);
+
+	pci_register_hose (host);
+
+	host->last_busno = pci_hose_scan (host);
+}
+
+#endif
diff --git a/board/AndesTech/common/serial.c b/board/AndesTech/common/serial.c
new file mode 100644
index 0000000..ebd6c52
--- /dev/null
+++ b/board/AndesTech/common/serial.c
@@ -0,0 +1,141 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj at denx.de>
+ *
+ * Copyright (C) 2009 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <asm/andesboot.h>
+#include <asm/global_data.h>
+#include "../include/symbol.h"
+#include "../include/porting.h"
+#include "../include/serial.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * librarys copy from flib
+ */
+
+#ifdef CONFIG_SERIAL1
+	UINT32 DebugSerialPort = NDS32_COMMON_UART1_BASE;
+#elif CONFIG_SERIAL2
+	UINT32 DebugSerialPort = NDS32_COMMON_UART2_BASE;
+#else
+	#error "Bad: you didn't configure serial ..."
+#endif
+
+
+unsigned int br[] = {1562, 780, 390, 194, 32, 15};
+void serial_setbrg(void)
+{
+	unsigned int reg = 0;
+
+	if (gd->baudrate == 9600)
+	{
+		reg = NDS32_COMMON_BAUD_9600;
+	}
+	else if (gd->baudrate == 19200)
+	{
+		reg = NDS32_COMMON_BAUD_19200;
+	}
+	else if (gd->baudrate == 38400)
+	{
+		reg = NDS32_COMMON_BAUD_38400;
+	}
+	else if (gd->baudrate == 57600)
+	{
+		reg = NDS32_COMMON_BAUD_57600;
+	}
+#if (SYS_CLK == 22118400)
+	else if (gd->baudrate == 115200)
+	{
+		reg = NDS32_COMMON_BAUD_115200;
+	}
+#endif
+	else
+	{
+		hang();
+	}
+	fLib_SetSerialMode( DebugSerialPort, SERIAL_MDR_UART );
+	fLib_SerialInit( DebugSerialPort, reg, PARITY_NONE, 0, 8 );
+	fLib_SetSerialFifoCtrl(DebugSerialPort, 1, ENABLE, ENABLE);
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init(void)
+{
+	const char *baudrate;
+
+	gd->baudrate = CONFIG_BAUDRATE;
+	if ((baudrate = getenv("baudrate")) != 0)
+	{
+		//printf("serial_init> baudrate: %s \n", baudrate);
+		gd->baudrate = simple_strtoul(baudrate, NULL, 10);
+	}
+	//serial_setbrg();
+
+	return 0;
+}
+
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc(void)
+{
+	return fLib_GetSerialChar( DebugSerialPort );
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc(const char c)
+{
+
+	if(c == '\n')
+		serial_putc('\r');
+	fLib_PutSerialChar( DebugSerialPort, c );
+
+	/* If \n, also do \r */
+//	if(c == '\n')
+//	  	serial_putc('\r');
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int serial_tstc(void)
+{
+	return ( cpe_inl( DebugSerialPort + SERIAL_LSR ) & SERIAL_LSR_DR ) == SERIAL_LSR_DR;
+}
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
-- 
1.7.1



More information about the U-Boot mailing list