[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