From 7521af1c7d95ff087a4f7636ed050f4d4be91b59 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sun, 9 Oct 2005 01:04:33 +0200 Subject: [PATCH] Add support for AP1000 board. Patch by James MacAulay, 07 Oct 2005 --- CHANGELOG | 3 + CREDITS | 5 + MAKEALL | 24 +- Makefile | 3 + README | 77 +-- board/amirix/ap1000/Makefile | 47 ++ board/amirix/ap1000/ap1000.c | 672 +++++++++++++++++++++++++ board/amirix/ap1000/ap1000.h | 173 +++++++ board/amirix/ap1000/config.mk | 27 + board/amirix/ap1000/flash.c | 853 ++++++++++++++++++++++++++++++++ board/amirix/ap1000/init.S | 34 ++ board/amirix/ap1000/pci.c | 346 +++++++++++++ board/amirix/ap1000/powerspan.c | 712 ++++++++++++++++++++++++++ board/amirix/ap1000/powerspan.h | 170 +++++++ board/amirix/ap1000/serial.c | 128 +++++ board/amirix/ap1000/u-boot.lds | 144 ++++++ cpu/ppc4xx/speed.c | 7 + drivers/e1000.c | 37 ++ include/configs/AP1000.h | 255 ++++++++++ net/eth.c | 2 +- 20 files changed, 3668 insertions(+), 51 deletions(-) create mode 100644 board/amirix/ap1000/Makefile create mode 100644 board/amirix/ap1000/ap1000.c create mode 100644 board/amirix/ap1000/ap1000.h create mode 100644 board/amirix/ap1000/config.mk create mode 100644 board/amirix/ap1000/flash.c create mode 100644 board/amirix/ap1000/init.S create mode 100644 board/amirix/ap1000/pci.c create mode 100644 board/amirix/ap1000/powerspan.c create mode 100644 board/amirix/ap1000/powerspan.h create mode 100644 board/amirix/ap1000/serial.c create mode 100644 board/amirix/ap1000/u-boot.lds create mode 100644 include/configs/AP1000.h diff --git a/CHANGELOG b/CHANGELOG index 496a3b6e6..66994b8ba 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ Changes for U-Boot 1.1.4: ====================================================================== +* Add support for AP1000 board. + Patch by James MacAulay, 07 Oct 2005 + * Eliminate hard-coded address of Ethernet transfer buffer on at91rm9200 Patch by Anders Larsen, 07 Oct 2005 diff --git a/CREDITS b/CREDITS index 4ea3c744c..23055cbaf 100644 --- a/CREDITS +++ b/CREDITS @@ -443,3 +443,8 @@ N: Alex Zuepke E: azu@sysgo.de D: Overall improvements on StrongARM, ARM720TDMI; Support for Tuxscreen; initial PCMCIA support for ARM W: www.elinos.com + +N: James MacAulay +E: james.macaulay@amirix.com +D: Suppport for Amirix AP1000 +W: www.amirix.com diff --git a/MAKEALL b/MAKEALL index 0472cfb1a..79be0d8b2 100755 --- a/MAKEALL +++ b/MAKEALL @@ -61,18 +61,18 @@ LIST_8xx=" \ ######################################################################### LIST_4xx=" \ - ADCIOP AR405 ASH405 bubinga \ - CANBT CPCI2DP CPCI405 CPCI4052 \ - CPCI405AB CPCI440 CPCIISER4 CRAYL1 \ - csb272 csb472 DASA_SIM DP405 \ - DU405 ebony ERIC EXBITGEN \ - G2000 HUB405 JSE KAREF \ - METROBOX MIP405 MIP405T ML2 \ - ml300 ocotea OCRTC ORSG \ - PCI405 PIP405 PLU405 PMC405 \ - PPChameleonEVB sbc405 VOH405 W7OLMC \ - W7OLMG walnut WUH405 XPEDITE1K \ - yellowstone yosemite \ + ADCIOP AP1000 AR405 ASH405 \ + bubinga CANBT CPCI2DP CPCI405 \ + CPCI4052 CPCI405AB CPCI440 CPCIISER4 \ + CRAYL1 csb272 csb472 DASA_SIM \ + DP405 DU405 ebony ERIC \ + EXBITGEN G2000 HUB405 JSE \ + KAREF METROBOX MIP405 MIP405T \ + ML2 ml300 ocotea OCRTC \ + ORSG PCI405 PIP405 PLU405 \ + PMC405 PPChameleonEVB sbc405 VOH405 \ + W7OLMC W7OLMG walnut WUH405 \ + XPEDITE1K yellowstone yosemite \ " ######################################################################### diff --git a/Makefile b/Makefile index 86cb6a805..6ce541690 100644 --- a/Makefile +++ b/Makefile @@ -721,6 +721,9 @@ xtract_4xx = $(subst _25,,$(subst _33,,$(subst _BA,,$(subst _ME,,$(subst _HI,,$( ADCIOP_config: unconfig @./mkconfig $(@:_config=) ppc ppc4xx adciop esd +AP1000_config:unconfig + @./mkconfig $(@:_config=) ppc ppc4xx ap1000 amirix + APC405_config: unconfig @./mkconfig $(@:_config=) ppc ppc4xx apc405 esd diff --git a/README b/README index 419ae0df4..71e9dc91a 100644 --- a/README +++ b/README @@ -261,44 +261,45 @@ The following options need to be configured: PowerPC based boards: --------------------- - CONFIG_ADCIOP CONFIG_GEN860T CONFIG_PCI405 - CONFIG_ADS860 CONFIG_GENIETV CONFIG_PCIPPC2 - CONFIG_AMX860 CONFIG_GTH CONFIG_PCIPPC6 - CONFIG_AR405 CONFIG_gw8260 CONFIG_pcu_e - CONFIG_BAB7xx CONFIG_hermes CONFIG_PIP405 - CONFIG_c2mon CONFIG_hymod CONFIG_PM826 - CONFIG_CANBT CONFIG_IAD210 CONFIG_ppmc8260 - CONFIG_CCM CONFIG_ICU862 CONFIG_QS823 - CONFIG_CMI CONFIG_IP860 CONFIG_QS850 - CONFIG_cogent_mpc8260 CONFIG_IPHASE4539 CONFIG_QS860T - CONFIG_cogent_mpc8xx CONFIG_IVML24 CONFIG_RBC823 - CONFIG_CPCI405 CONFIG_IVML24_128 CONFIG_RPXClassic - CONFIG_CPCI4052 CONFIG_IVML24_256 CONFIG_RPXlite - CONFIG_CPCIISER4 CONFIG_IVMS8 CONFIG_RPXsuper - CONFIG_CPU86 CONFIG_IVMS8_128 CONFIG_rsdproto - CONFIG_CRAYL1 CONFIG_IVMS8_256 CONFIG_sacsng - CONFIG_CSB272 CONFIG_JSE CONFIG_Sandpoint8240 - CONFIG_CU824 CONFIG_LANTEC CONFIG_Sandpoint8245 - CONFIG_DASA_SIM CONFIG_lwmon CONFIG_sbc8260 - CONFIG_DB64360 CONFIG_MBX CONFIG_sbc8560 - CONFIG_DB64460 CONFIG_MBX860T CONFIG_SM850 - CONFIG_DU405 CONFIG_MHPC CONFIG_SPD823TS - CONFIG_DUET_ADS CONFIG_MIP405 CONFIG_STXGP3 - CONFIG_EBONY CONFIG_MOUSSE CONFIG_SXNI855T - CONFIG_ELPPC CONFIG_MPC8260ADS CONFIG_TQM823L - CONFIG_ELPT860 CONFIG_MPC8540ADS CONFIG_TQM8260 - CONFIG_ep8260 CONFIG_MPC8540EVAL CONFIG_TQM850L - CONFIG_ERIC CONFIG_MPC8560ADS CONFIG_TQM855L - CONFIG_ESTEEM192E CONFIG_MUSENKI CONFIG_TQM860L - CONFIG_ETX094 CONFIG_MVS1 CONFIG_TTTech - CONFIG_EVB64260 CONFIG_NETPHONE CONFIG_UTX8245 - CONFIG_FADS823 CONFIG_NETTA CONFIG_V37 - CONFIG_FADS850SAR CONFIG_NETVIA CONFIG_W7OLMC - CONFIG_FADS860T CONFIG_NX823 CONFIG_W7OLMG - CONFIG_FLAGADM CONFIG_OCRTC CONFIG_WALNUT - CONFIG_FPS850L CONFIG_ORSG CONFIG_ZPC1900 - CONFIG_FPS860L CONFIG_OXC CONFIG_ZUMA - + CONFIG_ADCIOP CONFIG_GEN860T CONFIG_PCIPPC2 + CONFIG_ADS860 CONFIG_GENIETV CONFIG_PCIPPC6 + CONFIG_AMX860 CONFIG_GTH CONFIG_pcu_e + CONFIG_AP1000 CONFIG_gw8260 CONFIG_PIP405 + CONFIG_AR405 CONFIG_hermes CONFIG_PM826 + CONFIG_BAB7xx CONFIG_hymod CONFIG_ppmc8260 + CONFIG_c2mon CONFIG_IAD210 CONFIG_QS823 + CONFIG_CANBT CONFIG_ICU862 CONFIG_QS850 + CONFIG_CCM CONFIG_IP860 CONFIG_QS860T + CONFIG_CMI CONFIG_IPHASE4539 CONFIG_RBC823 + CONFIG_cogent_mpc8260 CONFIG_IVML24 CONFIG_RPXClassic + CONFIG_cogent_mpc8xx CONFIG_IVML24_128 CONFIG_RPXlite + CONFIG_CPCI405 CONFIG_IVML24_256 CONFIG_RPXsuper + CONFIG_CPCI4052 CONFIG_IVMS8 CONFIG_rsdproto + CONFIG_CPCIISER4 CONFIG_IVMS8_128 CONFIG_sacsng + CONFIG_CPU86 CONFIG_IVMS8_256 CONFIG_Sandpoint8240 + CONFIG_CRAYL1 CONFIG_JSE CONFIG_Sandpoint8245 + CONFIG_CSB272 CONFIG_LANTEC CONFIG_sbc8260 + CONFIG_CU824 CONFIG_lwmon CONFIG_sbc8560 + CONFIG_DASA_SIM CONFIG_MBX CONFIG_SM850 + CONFIG_DB64360 CONFIG_MBX860T CONFIG_SPD823TS + CONFIG_DB64460 CONFIG_MHPC CONFIG_STXGP3 + CONFIG_DU405 CONFIG_MIP405 CONFIG_SXNI855T + CONFIG_DUET_ADS CONFIG_MOUSSE CONFIG_TQM823L + CONFIG_EBONY CONFIG_MPC8260ADS CONFIG_TQM8260 + CONFIG_ELPPC CONFIG_MPC8540ADS CONFIG_TQM850L + CONFIG_ELPT860 CONFIG_MPC8540EVAL CONFIG_TQM855L + CONFIG_ep8260 CONFIG_MPC8560ADS CONFIG_TQM860L + CONFIG_ERIC CONFIG_MUSENKI CONFIG_TTTech + CONFIG_ESTEEM192E CONFIG_MVS1 CONFIG_UTX8245 + CONFIG_ETX094 CONFIG_NETPHONE CONFIG_V37 + CONFIG_EVB64260 CONFIG_NETTA CONFIG_W7OLMC + CONFIG_FADS823 CONFIG_NETVIA CONFIG_W7OLMG + CONFIG_FADS850SAR CONFIG_NX823 CONFIG_WALNUT + CONFIG_FADS860T CONFIG_OCRTC CONFIG_ZPC1900 + CONFIG_FLAGADM CONFIG_ORSG CONFIG_ZUMA + CONFIG_FPS850L CONFIG_OXC + CONFIG_FPS860L CONFIG_PCI405 + ARM based boards: ----------------- diff --git a/board/amirix/ap1000/Makefile b/board/amirix/ap1000/Makefile new file mode 100644 index 000000000..4e1ef217c --- /dev/null +++ b/board/amirix/ap1000/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o serial.o pci.o powerspan.o +SOBJS = init.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/amirix/ap1000/ap1000.c b/board/amirix/ap1000/ap1000.c new file mode 100644 index 000000000..743211fa9 --- /dev/null +++ b/board/amirix/ap1000/ap1000.c @@ -0,0 +1,672 @@ +/* + * amirix.c: ppcboot platform support for AMIRIX board + * + * Copyright 2002 Mind NV + * Copyright 2003 AMIRIX Systems Inc. + * + * http://www.mind.be/ + * http://www.amirix.com/ + * + * Author : Peter De Schrijver (p2@mind.be) + * Frank Smith (smith@amirix.com) + * + * Derived from : Other platform support files in this tree, ml2 + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire + * program is licensed under the GPL. + * + */ + +#include +#include +#include + +#include "powerspan.h" +#include "ap1000.h" + +int board_pre_init (void) +{ + return 0; +} + +/** serial number and platform display at startup */ +int checkboard (void) +{ + unsigned char *s = getenv ("serial#"); + unsigned char *e; + + /* After a loadace command, the SystemAce control register is left in a wonky state. */ + /* this code did not work in board_pre_init */ + unsigned char* p = (unsigned char*)AP1000_SYSACE_REGBASE; + p[SYSACE_CTRLREG0] = 0x0; + + /* add platform and device to banner */ + switch(get_device()){ + case AP1xx_AP107_TARGET:{ + puts(AP1xx_AP107_TARGET_STR); + break; + } + case AP1xx_AP120_TARGET:{ + puts(AP1xx_AP120_TARGET_STR); + break; + } + case AP1xx_AP130_TARGET:{ + puts(AP1xx_AP130_TARGET_STR); + break; + } + case AP1xx_AP1070_TARGET:{ + puts(AP1xx_AP1070_TARGET_STR); + break; + } + case AP1xx_AP1100_TARGET:{ + puts(AP1xx_AP1100_TARGET_STR); + break; + } + default:{ + puts(AP1xx_UNKNOWN_STR); + break; + } + } + puts(AP1xx_TARGET_STR); + puts(" with "); + + switch(get_platform()){ + case AP100_BASELINE_PLATFORM: + case AP1000_BASELINE_PLATFORM:{ + puts(AP1xx_BASELINE_PLATFORM_STR); + break; + } + case AP1xx_QUADGE_PLATFORM:{ + puts(AP1xx_QUADGE_PLATFORM_STR); + break; + } + case AP1xx_MGT_REF_PLATFORM:{ + puts(AP1xx_MGT_REF_PLATFORM_STR); + break; + } + case AP1xx_STANDARD_PLATFORM:{ + puts(AP1xx_STANDARD_PLATFORM_STR); + break; + } + case AP1xx_DUAL_PLATFORM:{ + puts(AP1xx_DUAL_PLATFORM_STR); + break; + } + case AP1xx_BASE_SRAM_PLATFORM:{ + puts(AP1xx_BASE_SRAM_PLATFORM_STR); + break; + } + case AP1xx_PCI_PCB_TESTPLATFORM: + case AP1000_PCI_PCB_TESTPLATFORM:{ + puts(AP1xx_PCI_PCB_TESTPLATFORM_STR); + break; + } + case AP1xx_DUAL_GE_MEZZ_TESTPLATFORM:{ + puts(AP1xx_DUAL_GE_MEZZ_TESTPLATFORM_STR); + break; + } + case AP1xx_SFP_MEZZ_TESTPLATFORM:{ + puts(AP1xx_SFP_MEZZ_TESTPLATFORM_STR); + break; + } + default:{ + puts(AP1xx_UNKNOWN_STR); + break; + } + } + + if((get_platform() & AP1xx_TESTPLATFORM_MASK) != 0){ + puts(AP1xx_TESTPLATFORM_STR); + } + else{ + puts(AP1xx_PLATFORM_STR); + } + + putc('\n'); + + puts ("Serial#: "); + + if (!s) { + printf ("### No HW ID - assuming AMIRIX"); + } else { + for (e = s; *e; ++e) { + if (*e == ' ') + break; + } + + for (; s < e; ++s) { + putc (*s); + } + } + + putc ('\n'); + + return (0); +} + + +long int initdram (int board_type) +{ + unsigned char *s = getenv ("dramsize"); + + if(s != NULL){ + if((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))){ + s += 2; + } + return simple_strtoul(s, NULL, 16); + } + else{ + /* give all 64 MB */ + return 64 * 1024 * 1024; + } +} + +unsigned int get_platform(void){ + unsigned int *revision_reg_ptr = (unsigned int *)AP1xx_FPGA_REV_ADDR; + return (*revision_reg_ptr & AP1xx_PLATFORM_MASK); +} + +unsigned int get_device(void){ + unsigned int *revision_reg_ptr = (unsigned int *)AP1xx_FPGA_REV_ADDR; + + return (*revision_reg_ptr & AP1xx_TARGET_MASK); +} + +#if 0 // loadace is not working; it appears to be a hardware issue with the system ace. +/* + This function loads FPGA configurations from the SystemACE CompactFlash +*/ +int do_loadace (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unsigned char *p = (unsigned char *)AP1000_SYSACE_REGBASE; + int cfg; + + if((p[SYSACE_STATREG0] & 0x10) == 0) { + p[SYSACE_CTRLREG0] = 0x80; + printf ("\nNo CompactFlash Detected\n\n"); + p[SYSACE_CTRLREG0] = 0x00; + return 1; + } + + // reset configuration controller: | 0x80 + // select cpflash & ~0x40 + // cfg start | 0x20 + // wait for cfgstart & ~0x10 + // force cfgmode: | 0x08 + // do no force cfgaddr: & ~0x04 + // clear mpulock: & ~0x02 + // do not force lock request & ~0x01 + + p[SYSACE_CTRLREG0] = 0x80 | 0x20 | 0x08; + p[SYSACE_CTRLREG1] = 0x00; + + // force config address if arg2 exists + if (argc == 2) { + cfg = simple_strtoul(argv[1], NULL, 10); + + if(cfg > 7) { + printf ("\nInvalid Configuration\n\n"); + p[SYSACE_CTRLREG0] = 0x00; + return 1; + } + // Set config address + p[SYSACE_CTRLREG1] = (cfg << 5); + // force cfgaddr + p[SYSACE_CTRLREG0] |= 0x04; + + } else { + cfg = (p[SYSACE_STATREG1] & 0xE0) >> 5; + } + + /* release configuration controller */ + printf("\nLoading V2PRO with config %d...\n", cfg); + p[SYSACE_CTRLREG0] &= ~0x80; + + + while((p[SYSACE_STATREG1] & 0x01) == 0) { + + if(p[SYSACE_ERRREG0] & 0x80) { + // attempting to load an invalid configuration makes the cpflash + // appear to be removed. Reset here to avoid that problem + p[SYSACE_CTRLREG0] = 0x80; + printf("\nConfiguration %d Read Error\n\n", cfg); + p[SYSACE_CTRLREG0] = 0x00; + return 1; + } + } + + p[SYSACE_CTRLREG0] |= 0x20; + + return 0; +} +#endif + +/** Console command to display and set the software reconfigure byte + *
+  * swconfig        - display the current value of the software reconfigure byte
+  * swconfig [#]    - change the software reconfigure byte to #
+  * 
+ * @param *cmdtp [IN] as passed by run_command (ignored) + * @param flag [IN] as passed by run_command (ignored) + * @param argc [IN] as passed by run_command if 1, display, if 2 change + * @param *argv[] [IN] contains the parameters to use + * @return + *
+  *      0 if passed
+  *     -1 if failed
+  * 
+ */ +int do_swconfigbyte(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ + unsigned char *sector_buffer = NULL; + unsigned char input_char; + int write_result; + unsigned int input_uint; + + /* display value if no argument */ + if(argc < 2){ + printf("Software configuration byte is currently: 0x%02x\n", + *((unsigned char *) (SW_BYTE_SECTOR_ADDR + SW_BYTE_SECTOR_OFFSET))); + return 0; + } + else if(argc > 3){ + printf("Too many arguments\n"); + return -1; + } + + /* if 3 arguments, 3rd argument is the address to use */ + if(argc == 3){ + input_uint = simple_strtoul(argv[1], NULL, 16); + sector_buffer = (unsigned char *)input_uint; + } + else{ + sector_buffer = (unsigned char *)DEFAULT_TEMP_ADDR; + } + + input_char = simple_strtoul(argv[1], NULL, 0); + if((input_char & ~SW_BYTE_MASK) != 0){ + printf("Input of 0x%02x will be masked to 0x%02x\n", + input_char, (input_char & SW_BYTE_MASK)); + input_char = input_char & SW_BYTE_MASK; + } + + memcpy(sector_buffer, (void *)SW_BYTE_SECTOR_ADDR, SW_BYTE_SECTOR_SIZE); + sector_buffer[SW_BYTE_SECTOR_OFFSET] = input_char; + + + printf("Erasing Flash..."); + if (flash_sect_erase (SW_BYTE_SECTOR_ADDR, (SW_BYTE_SECTOR_ADDR + SW_BYTE_SECTOR_OFFSET))){ + return -1; + } + + printf("Writing to Flash... "); + write_result = flash_write(sector_buffer, SW_BYTE_SECTOR_ADDR, SW_BYTE_SECTOR_SIZE); + if (write_result != 0) { + flash_perror (write_result); + return -1; + } + else{ + printf("done\n"); + printf("Software configuration byte is now: 0x%02x\n", + *((unsigned char *) (SW_BYTE_SECTOR_ADDR + SW_BYTE_SECTOR_OFFSET))); + } + + return 0; +} + +#define ONE_SECOND 1000000 + +int do_pause(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ + int pause_time; + unsigned int delay_time; + int break_loop = 0; + + /* display value if no argument */ + if(argc < 2){ + pause_time = 1; + } + + else if(argc > 2){ + printf("Too many arguments\n"); + return -1; + } + else{ + pause_time = simple_strtoul(argv[1], NULL, 0); + } + + printf("Pausing with a poll time of %d, press any key to reactivate\n", pause_time); + delay_time = pause_time * ONE_SECOND; + while(break_loop == 0){ + udelay(delay_time); + if(serial_tstc() != 0){ + break_loop = 1; + /* eat user key presses */ + while(serial_tstc() != 0){ + serial_getc(); + } + } + } + + return 0; +} + +int do_swreconfig(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ + printf("Triggering software reconfigure (software config byte is 0x%02x)...\n", + *((unsigned char *) (SW_BYTE_SECTOR_ADDR + SW_BYTE_SECTOR_OFFSET))); + udelay (1000); + *((unsigned char*)AP1000_CPLD_BASE) = 1; + + return 0; +} + +#define GET_DECIMAL(low_byte) ((low_byte >> 5) * 125) +#define TEMP_BUSY_BIT 0x80 +#define TEMP_LHIGH_BIT 0x40 +#define TEMP_LLOW_BIT 0x20 +#define TEMP_EHIGH_BIT 0x10 +#define TEMP_ELOW_BIT 0x08 +#define TEMP_OPEN_BIT 0x04 +#define TEMP_ETHERM_BIT 0x02 +#define TEMP_LTHERM_BIT 0x01 + +int do_temp_sensor(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ + char cmd; + int ret_val = 0; + unsigned char temp_byte; + int temp; + int temp_low; + int low; + int low_low; + int high; + int high_low; + int therm; + unsigned char user_data[4] = { 0 }; + int user_data_count = 0; + int ii; + + if(argc > 1){ + cmd = argv[1][0]; + } + else{ + cmd = 's'; /* default to status */ + } + + user_data_count = argc - 2; + for(ii = 0;ii < user_data_count;ii++){ + user_data[ii] = simple_strtoul(argv[2 + ii], NULL, 0); + } + switch (cmd){ + case 's':{ + + if(I2CAccess(0x2, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + printf("Status : 0x%02x ", temp_byte); + if(temp_byte & TEMP_BUSY_BIT){ + printf("BUSY "); + } + + if(temp_byte & TEMP_LHIGH_BIT){ + printf("LHIGH "); + } + + if(temp_byte & TEMP_LLOW_BIT){ + printf("LLOW "); + } + + if(temp_byte & TEMP_EHIGH_BIT){ + printf("EHIGH "); + } + + if(temp_byte & TEMP_ELOW_BIT){ + printf("ELOW "); + } + + if(temp_byte & TEMP_OPEN_BIT){ + printf("OPEN "); + } + + if(temp_byte & TEMP_ETHERM_BIT){ + printf("ETHERM "); + } + + if(temp_byte & TEMP_LTHERM_BIT){ + printf("LTHERM"); + } + printf("\n"); + + if(I2CAccess(0x3, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + printf("Config : 0x%02x ", temp_byte); + + if(I2CAccess(0x4, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + printf("\n"); + goto fail; + } + printf("Conversion: 0x%02x\n", temp_byte); + if(I2CAccess(0x22, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + printf("Cons Alert: 0x%02x ", temp_byte); + + if(I2CAccess(0x21, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + printf("\n"); + goto fail; + } + printf("Therm Hyst: %d\n", temp_byte); + + if(I2CAccess(0x0, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + temp = temp_byte; + if(I2CAccess(0x6, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + low = temp_byte; + if(I2CAccess(0x5, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + high = temp_byte; + if(I2CAccess(0x20, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + therm = temp_byte; + printf("Local Temp: %2d Low: %2d High: %2d THERM: %2d\n", temp, low, high, therm); + + if(I2CAccess(0x1, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + temp = temp_byte; + if(I2CAccess(0x10, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + temp_low = temp_byte; + if(I2CAccess(0x8, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + low = temp_byte; + if(I2CAccess(0x14, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + low_low = temp_byte; + if(I2CAccess(0x7, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + high = temp_byte; + if(I2CAccess(0x13, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + high_low = temp_byte; + if(I2CAccess(0x19, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + therm = temp_byte; + if(I2CAccess(0x11, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &temp_byte, I2C_READ) != 0){ + goto fail; + } + printf("Ext Temp : %2d.%03d Low: %2d.%03d High: %2d.%03d THERM: %2d Offset: %2d\n", temp, GET_DECIMAL(temp_low), low, GET_DECIMAL(low_low), high, GET_DECIMAL(high_low), therm, temp_byte); + break; + } + case 'l':{ /* alter local limits : low, high, therm */ + if(argc < 3){ + goto usage; + } + + /* low */ + if(I2CAccess(0xC, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[0], I2C_WRITE) != 0){ + goto fail; + } + + if(user_data_count > 1){ + /* high */ + if(I2CAccess(0xB, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[1], I2C_WRITE) != 0){ + goto fail; + } + } + + if(user_data_count > 2){ + /* therm */ + if(I2CAccess(0x20, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[2], I2C_WRITE) != 0){ + goto fail; + } + } + break; + } + case 'e':{ /* alter external limits: low, high, therm, offset */ + if(argc < 3){ + goto usage; + } + + /* low */ + if(I2CAccess(0xE, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[0], I2C_WRITE) != 0){ + goto fail; + } + + if(user_data_count > 1){ + /* high */ + if(I2CAccess(0xD, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[1], I2C_WRITE) != 0){ + goto fail; + } + } + + if(user_data_count > 2){ + /* therm */ + if(I2CAccess(0x19, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[2], I2C_WRITE) != 0){ + goto fail; + } + } + + if(user_data_count > 3){ + /* offset */ + if(I2CAccess(0x11, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[3], I2C_WRITE) != 0){ + goto fail; + } + } + break; + } + case 'c':{ /* alter config settings: config, conv, cons alert, therm hyst */ + if(argc < 3){ + goto usage; + } + + /* config */ + if(I2CAccess(0x9, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[0], I2C_WRITE) != 0){ + goto fail; + } + + if(user_data_count > 1){ + /* conversion */ + if(I2CAccess(0xA, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[1], I2C_WRITE) != 0){ + goto fail; + } + } + + if(user_data_count > 2){ + /* cons alert */ + if(I2CAccess(0x22, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[2], I2C_WRITE) != 0){ + goto fail; + } + } + + if(user_data_count > 3){ + /* therm hyst */ + if(I2CAccess(0x21, I2C_SENSOR_DEV, I2C_SENSOR_CHIP_SEL, &user_data[3], I2C_WRITE) != 0){ + goto fail; + } + } + break; + } + default:{ + goto usage; + } + } + + goto done; + fail: + printf("Access to sensor failed\n"); + ret_val = -1; + goto done; + usage: + printf ("Usage:\n%s\n", cmdtp->help); + + done: + return ret_val; +} + +U_BOOT_CMD( + temp, 6, 0, do_temp_sensor, + "temp - interact with the temperature sensor\n", + "temp [s]\n" + " - Show status.\n" + "temp l LOW [HIGH] [THERM]\n" + " - Set local limits.\n" + "temp e LOW [HIGH] [THERM] [OFFSET]\n" + " - Set external limits.\n" + "temp c CONFIG [CONVERSION] [CONS. ALERT] [THERM HYST]\n" + " - Set config options.\n" + "\n" + "All values can be decimal or hex (hex preceded with 0x).\n" + "Only whole numbers are supported for external limits.\n" +); + +#if 0 +U_BOOT_CMD( + loadace, 2, 0, do_loadace, + "loadace - load fpga configuration from System ACE compact flash\n", + "N\n" + " - Load configuration N (0-7) from System ACE compact flash\n" + "loadace\n" + " - loads default configuration\n" +); +#endif + +U_BOOT_CMD( + swconfig, 2, 0, do_swconfigbyte, + "swconfig- display or modify the software configuration byte\n", + "N [ADDRESS]\n" + " - set software configuration byte to N, optionally use ADDRESS as\n" + " location of buffer for flash copy\n" + "swconfig\n" + " - display software configuration byte\n" +); + +U_BOOT_CMD( + pause, 2, 0, do_pause, + "pause - sleep processor until any key is pressed with poll time of N seconds\n", + "N\n" + " - sleep processor until any key is pressed with poll time of N seconds\n" + "pause\n" + " - sleep processor until any key is pressed with poll time of 1 second\n" +); + +U_BOOT_CMD( + swrecon, 1, 0, do_swreconfig, + "swrecon - trigger a board reconfigure to the software selected configuration\n", + "\n" + " - trigger a board reconfigure to the software selected configuration\n" +); + diff --git a/board/amirix/ap1000/ap1000.h b/board/amirix/ap1000/ap1000.h new file mode 100644 index 000000000..c93736f42 --- /dev/null +++ b/board/amirix/ap1000/ap1000.h @@ -0,0 +1,173 @@ +/* + * ap1000.h: AP1000 (e.g. AP1070, AP1100) board specific definitions and functions that are needed globally + * + * Author : James MacAulay + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire + * program is licensed under the GPL. + * + */ + +#ifndef __AP1000_H +#define __AP1000_H + +/* + * Revision Register stuff + */ +#define AP1xx_FPGA_REV_ADDR 0x29000000 + +#define AP1xx_PLATFORM_MASK 0xFF000000 +#define AP100_BASELINE_PLATFORM 0x01000000 +#define AP1xx_QUADGE_PLATFORM 0x02000000 +#define AP1xx_MGT_REF_PLATFORM 0x03000000 +#define AP1xx_STANDARD_PLATFORM 0x04000000 +#define AP1xx_DUAL_PLATFORM 0x05000000 +#define AP1xx_BASE_SRAM_PLATFORM 0x06000000 + +#define AP1000_BASELINE_PLATFORM 0x21000000 + +#define AP1xx_TESTPLATFORM_MASK 0xC0000000 +#define AP1xx_PCI_PCB_TESTPLATFORM 0xC0000000 +#define AP1xx_DUAL_GE_MEZZ_TESTPLATFORM 0xC1000000 +#define AP1xx_SFP_MEZZ_TESTPLATFORM 0xC2000000 + +#define AP1000_PCI_PCB_TESTPLATFORM 0xC3000000 + +#define AP1xx_TARGET_MASK 0x00FF0000 +#define AP1xx_AP107_TARGET 0x00010000 +#define AP1xx_AP120_TARGET 0x00020000 +#define AP1xx_AP130_TARGET 0x00030000 +#define AP1xx_AP1070_TARGET 0x00040000 +#define AP1xx_AP1100_TARGET 0x00050000 + +#define AP1xx_UNKNOWN_STR "Unknown" + +#define AP1xx_PLATFORM_STR " Platform" +#define AP1xx_BASELINE_PLATFORM_STR "Baseline" +#define AP1xx_QUADGE_PLATFORM_STR "Quad GE" +#define AP1xx_MGT_REF_PLATFORM_STR "MGT Reference" +#define AP1xx_STANDARD_PLATFORM_STR "Standard" +#define AP1xx_DUAL_PLATFORM_STR "Dual" +#define AP1xx_BASE_SRAM_PLATFORM_STR "Baseline with SRAM" + +#define AP1xx_TESTPLATFORM_STR " Test Platform" +#define AP1xx_PCI_PCB_TESTPLATFORM_STR "Base" +#define AP1xx_DUAL_GE_MEZZ_TESTPLATFORM_STR "Dual GE Mezzanine" +#define AP1xx_SFP_MEZZ_TESTPLATFORM_STR "SFP Mezzanine" + +#define AP1xx_TARGET_STR " Board" +#define AP1xx_AP107_TARGET_STR "AP107" +#define AP1xx_AP120_TARGET_STR "AP120" +#define AP1xx_AP130_TARGET_STR "AP130" + +#define AP1xx_AP1070_TARGET_STR "AP1070" +#define AP1xx_AP1100_TARGET_STR "AP1100" + +/* + * Flash Stuff + */ +#define AP1xx_PROGRAM_FLASH_INDEX 0 +#define AP1xx_CONFIG_FLASH_INDEX 1 + +/* + * System Ace Stuff + */ +#define AP1000_SYSACE_REGBASE 0x28000000 + +#define SYSACE_STATREG0 0x04 // 7:0 +#define SYSACE_STATREG1 0x05 // 15:8 +#define SYSACE_STATREG2 0x06 // 23:16 +#define SYSACE_STATREG3 0x07 // 31:24 + +#define SYSACE_ERRREG0 0x08 // 7:0 +#define SYSACE_ERRREG1 0x09 // 15:8 +#define SYSACE_ERRREG2 0x0a // 23:16 +#define SYSACE_ERRREG3 0x0b // 31:24 + +#define SYSACE_CTRLREG0 0x18 // 7:0 +#define SYSACE_CTRLREG1 0x19 // 15:8 +#define SYSACE_CTRLREG2 0x1A // 23:16 +#define SYSACE_CTRLREG3 0x1B // 31:24 + +/* + * Software reconfig thing + */ +#define SW_BYTE_SECTOR_ADDR 0x24FE0000 +#define SW_BYTE_SECTOR_OFFSET 0x0001FFFF +#define SW_BYTE_SECTOR_SIZE 0x00020000 +#define SW_BYTE_MASK 0x00000003 + +#define DEFAULT_TEMP_ADDR 0x00100000 + +#define AP1000_CPLD_BASE 0x26000000 + +/* PowerSpan II Stuff */ +#define PSII_SYNC() asm("eieio") +#define PSPAN_BASEADDR 0x30000000 +#define EEPROM_DEFAULT { 0x01, /* Byte 0 - Long Load = 0x02, short = 01, use 0xff for try no load */ \ + 0x0,0x0,0x0, /* Bytes 1 - 3 Power span reserved */ \ + 0x0, /* Byte 4 - Powerspan reserved - start of short load */ \ + 0x0F, /* Byte 5 - Enable PCI 1 & 2 as Bus masters and Memory targets. */ \ + 0x0E, /* Byte 6 - PCI 1 Target image prefetch - on for image 0,1,2, off for i20 & 3. */ \ + 0x00, 0x00, /* Byte 7,8 - PCI-1 Subsystem ID - */ \ + 0x00, 0x00, /* Byte 9,10 - PCI-1 Subsystem Vendor Id - */ \ + 0x00, /* Byte 11 - No PCI interrupt generation on PCI-1 PCI-2 int A */ \ + 0x1F, /* Byte 12 - PCI-1 enable bridge registers, all target images */ \ + 0xBA, /* Byte 13 - Target 0 image 128 Meg(Ram), Target 1 image 64 Meg. (config Flash/CPLD )*/ \ + 0xA0, /* Byte 14 - Target 2 image 64 Meg(program Flash), target 3 64k. */ \ + 0x00, /* Byte 15 - Vital Product Data Disabled. */ \ + 0x88, /* Byte 16 - PCI arbiter config complete, all requests routed through PCI-1, Unlock PCI-1 */ \ + 0x40, /* Byte 17 - Interrupt direction control - PCI-1 Int A out, everything else in. */ \ + 0x00, /* Byte 18 - I2O disabled */ \ + 0x00, /* Byte 19 - PCI-2 Target image prefetch - off for all images. */ \ + 0x00,0x00, /* Bytes 20,21 - PCI 2 Subsystem Id */ \ + 0x00,0x00, /* Bytes 22,23 - PCI 2 Subsystem Vendor id */ \ + 0x0C, /* Byte 24 - PCI-2 BAR enables, target image 0, & 1 */ \ + 0xBB, /* Byte 25 - PCI-2 target 0 - 128 Meg(Ram), target 1 - 128 Meg (program/config flash) */ \ + 0x00, /* Byte 26 - PCI-2 target 2 & 3 unused. */ \ + 0x00,0x00,0x00,0x00,0x00, /* Bytes 27,28,29,30, 31 - Reserved */ \ + /* Long Load Information */ \ + 0x82,0x60, /* Bytes 32,33 - PCI-1 Device ID - Powerspan II */ \ + 0x10,0xE3, /* Bytes 24,35 - PCI-1 Vendor ID - Tundra */ \ + 0x06, /* Byte 36 - PCI-1 Class Base - Bridge device. */ \ + 0x80, /* Byte 37 - PCI-1 Class sub class - Other bridge. */ \ + 0x00, /* Byte 38 - PCI-1 Class programing interface - Other bridge */ \ + 0x01, /* Byte 39 - Power span revision 1. */ \ + 0x6E, /* Byte 40 - PB SI0 enabled, translation enabled, decode enabled, 64 Meg */ \ + 0x40, /* Byte 41 - PB SI0 memory command mode, PCI-1 dest */ \ + 0x22, /* Byte 42 - Prefetch discard after read, PCI-little endian conversion, 32 byte prefetch */ \ + 0x00,0x00, /* Bytes 43, 44 - Translation address for SI0, set to zero for now. */ \ + 0x0E, /* Byte 45 - Translation address (0) and PB bus master enables - all. */ \ + 0x2c,00,00, /* Bytes 46,47,48 - PB SI0 processor base address - 0x2C000000 */ \ + 0x30,00,00, /* Bytes 49,50,51 - PB Address for Powerspan registers - 0x30000000, big Endian */ \ + 0x82,0x60, /* Bytes 52, 53 - PCI-2 Device ID - Powerspan II */ \ + 0x10,0xE3, /* Bytes 54,55 - PCI 2 Vendor Id - Tundra */ \ + 0x06, /* Byte 56 - PCI-2 Class Base - Bridge device */ \ + 0x80, /* Byte 57 - PCI-2 Class sub class - Other Bridge. */ \ + 0x00, /* Byte 58 - PCI-2 class programming interface - Other bridge */ \ + 0x01, /* Byte 59 - PCI-2 class revision 1 */ \ + 0x00,0x00,0x00,0x00 }; /* Bytes 60,61, 62, 63 - Powerspan reserved */ + + +#define EEPROM_LENGTH 64 /* Long Load */ + +#define I2C_SENSOR_DEV 0x9 +#define I2C_SENSOR_CHIP_SEL 0x4 + +/* + * Board Functions + */ +void set_eat_machine_checks(int a_flag); +int get_eat_machine_checks(void); +unsigned int get_platform(void); +unsigned int get_device(void); +void* memcpyb(void * dest,const void *src,size_t count); +int process_bootflag(ulong bootflag); +void user_led_on(void); +void user_led_off(void); + +#endif /* __COMMON_H_ */ diff --git a/board/amirix/ap1000/config.mk b/board/amirix/ap1000/config.mk new file mode 100644 index 000000000..c09783a6a --- /dev/null +++ b/board/amirix/ap1000/config.mk @@ -0,0 +1,27 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 +# + +# Start at bottom of RAM, but at an aliased address so that it looks +# like it's not in RAM. This is a bit of voodoo to allow it to be +# run from RAM instead of Flash. +TEXT_BASE = 0x08000000 diff --git a/board/amirix/ap1000/flash.c b/board/amirix/ap1000/flash.c new file mode 100644 index 000000000..f07edf0e1 --- /dev/null +++ b/board/amirix/ap1000/flash.c @@ -0,0 +1,853 @@ +/** + * @file flash.c + */ + +/* + * (C) Copyright 2003 + * AMIRIX Systems Inc. + * + * Originated from ppcboot-2.0.0/board/esd/cpci440/strataflash.c + * + * (C) Copyright 2002 + * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.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 +#include + +#undef DEBUG_FLASH +/* + * This file implements a Common Flash Interface (CFI) driver for ppcboot. + * The width of the port and the width of the chips are determined at initialization. + * These widths are used to calculate the address for access CFI data structures. + * It has been tested on an Intel Strataflash implementation. + * + * References + * JEDEC Standard JESD68 - Common Flash Interface (CFI) + * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes + * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets + * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet + * + * TODO + * Use Primary Extended Query table (PRI) and Alternate Algorithm Query Table (ALT) to determine if protection is available + * Add support for other command sets Use the PRI and ALT to determine command set + * Verify erase and program timeouts. + */ + +#define FLASH_CMD_CFI 0x98 +#define FLASH_CMD_READ_ID 0x90 +#define FLASH_CMD_RESET 0xff +#define FLASH_CMD_BLOCK_ERASE 0x20 +#define FLASH_CMD_ERASE_CONFIRM 0xD0 +#define FLASH_CMD_WRITE 0x40 +#define FLASH_CMD_PROTECT 0x60 +#define FLASH_CMD_PROTECT_SET 0x01 +#define FLASH_CMD_PROTECT_CLEAR 0xD0 +#define FLASH_CMD_CLEAR_STATUS 0x50 +#define FLASH_CMD_WRITE_TO_BUFFER 0xE8 +#define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0 + +#define FLASH_STATUS_DONE 0x80 +#define FLASH_STATUS_ESS 0x40 +#define FLASH_STATUS_ECLBS 0x20 +#define FLASH_STATUS_PSLBS 0x10 +#define FLASH_STATUS_VPENS 0x08 +#define FLASH_STATUS_PSS 0x04 +#define FLASH_STATUS_DPS 0x02 +#define FLASH_STATUS_R 0x01 +#define FLASH_STATUS_PROTECT 0x01 + +#define FLASH_OFFSET_CFI 0x55 +#define FLASH_OFFSET_CFI_RESP 0x10 +#define FLASH_OFFSET_WTOUT 0x1F +#define FLASH_OFFSET_WBTOUT 0x20 +#define FLASH_OFFSET_ETOUT 0x21 +#define FLASH_OFFSET_CETOUT 0x22 +#define FLASH_OFFSET_WMAX_TOUT 0x23 +#define FLASH_OFFSET_WBMAX_TOUT 0x24 +#define FLASH_OFFSET_EMAX_TOUT 0x25 +#define FLASH_OFFSET_CEMAX_TOUT 0x26 +#define FLASH_OFFSET_SIZE 0x27 +#define FLASH_OFFSET_INTERFACE 0x28 +#define FLASH_OFFSET_BUFFER_SIZE 0x2A +#define FLASH_OFFSET_NUM_ERASE_REGIONS 0x2C +#define FLASH_OFFSET_ERASE_REGIONS 0x2D +#define FLASH_OFFSET_PROTECT 0x02 +#define FLASH_OFFSET_USER_PROTECTION 0x85 +#define FLASH_OFFSET_INTEL_PROTECTION 0x81 + + +#define FLASH_MAN_CFI 0x01000000 + + + + +typedef union { + unsigned char c; + unsigned short w; + unsigned long l; +} cfiword_t; + +typedef union { + unsigned char * cp; + unsigned short *wp; + unsigned long *lp; +} cfiptr_t; + +#define NUM_ERASE_REGIONS 4 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + + +/*----------------------------------------------------------------------- + * Functions + */ + + + +static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c); +static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf); +static void flash_write_cmd(flash_info_t * info, int sect, uchar offset, uchar cmd); +static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd); +static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd); +static int flash_detect_cfi(flash_info_t * info); +static ulong flash_get_size (ulong base, int banknum); +static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword); +static int flash_full_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt); +#ifdef CFG_FLASH_USE_BUFFER_WRITE +static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len); +#endif +/*----------------------------------------------------------------------- + * create an address based on the offset and the port width + */ +uchar * flash_make_addr(flash_info_t * info, int sect, int offset) +{ + return ((uchar *)(info->start[sect] + (offset * info->chipwidth))); +} +/*----------------------------------------------------------------------- + * read a character at a port width address + */ +uchar flash_read_uchar(flash_info_t * info, uchar offset) +{ + if (info->portwidth == FLASH_CFI_8BIT) { + volatile uchar *cp; + uchar c; + cp = flash_make_addr(info, 0, offset); + c = *cp; +#ifdef DEBUG_FLASH + printf("flash_read_uchar offset=%04x ptr=%08x c=%02x\n", + offset, (unsigned int)cp, c); +#endif + return (c); + + } else if (info->portwidth == FLASH_CFI_16BIT) { + volatile ushort *sp; + ushort s; + uchar c; + sp = (ushort*)flash_make_addr(info, 0, offset); + s = *sp; + c = (uchar)s; +#ifdef DEBUG_FLASH + printf("flash_read_uchar offset=%04x ptr=%08x s=%04x c=%02x\n", + offset, (unsigned int)sp, s, c); +#endif + return (c); + + } + + return 0; +} + +/*----------------------------------------------------------------------- + * read a short word by swapping for ppc format. + */ +ushort flash_read_ushort(flash_info_t * info, int sect, uchar offset) +{ + if (info->portwidth == FLASH_CFI_8BIT) { + volatile uchar *cp; + uchar c0, c1; + ushort s; + cp = flash_make_addr(info, 0, offset); + c1 = cp[2]; + c0 = cp[0]; + s = c1<<8 | c0; +#ifdef DEBUG_FLASH + printf("flash_read_ushort offset=%04x ptr=%08x c1=%02x c0=%02x s=%04x\n", + offset, (unsigned int)cp, c1, c0, s); +#endif + return (s); + + } else if (info->portwidth == FLASH_CFI_16BIT) { + volatile ushort *sp; + ushort s; + uchar c0, c1; + sp = (ushort*)flash_make_addr(info, 0, offset); + s = *sp; + c1 = (uchar)sp[1]; + c0 = (uchar)sp[0]; + s = c1<<8 | c0; +#ifdef DEBUG_FLASH + printf("flash_read_ushort offset=%04x ptr=%08x c1=%02x c0=%02x s=%04x\n", + offset, (unsigned int)sp, c1, c0, s); +#endif + return (s); + + } + + return 0; +} + +/*----------------------------------------------------------------------- + * read a long word by picking the least significant byte of each maiximum + * port size word. Swap for ppc format. + */ +ulong flash_read_long(flash_info_t * info, int sect, uchar offset) +{ + if (info->portwidth == FLASH_CFI_8BIT) { + volatile uchar *cp; + uchar c0, c1, c2, c3; + ulong l; + cp = flash_make_addr(info, 0, offset); + c3 = cp[6]; + c2 = cp[4]; + c1 = cp[2]; + c0 = cp[0]; + l = c3<<24 | c2<<16 | c1<<8 | c0; +#ifdef DEBUG_FLASH + printf("flash_read_long offset=%04x ptr=%08x c3=%02x c2=%02x c1=%02x c0=%02x l=%08x\n", + offset, (unsigned int)cp, c3, c2, c1, c0, l); +#endif + return (l); + + } else if (info->portwidth == FLASH_CFI_16BIT) { + volatile ushort *sp; + uchar c0, c1, c2, c3; + ulong l; + sp = (ushort*)flash_make_addr(info, 0, offset); + c3 = (uchar)sp[3]; + c2 = (uchar)sp[2]; + c1 = (uchar)sp[1]; + c0 = (uchar)sp[0]; + l = c3<<24 | c2<<16 | c1<<8 | c0; +#ifdef DEBUG_FLASH + printf("flash_read_long offset=%04x ptr=%08x c3=%02x c2=%02x c1=%02x c0=%02x l=%08x\n", + offset, (unsigned int)sp, c3, c2, c1, c0, l); +#endif + return (l); + + } + + return 0; +} + +/*----------------------------------------------------------------------- + */ +unsigned long flash_init (void) +{ + unsigned long size; + + size = 0; + + flash_info[0].flash_id = FLASH_UNKNOWN; + flash_info[0].portwidth = FLASH_CFI_16BIT; + flash_info[0].chipwidth = FLASH_CFI_16BIT; + size += flash_info[0].size = flash_get_size(CFG_PROGFLASH_BASE, 0); + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", 1, + flash_info[0].size, flash_info[0].size<<20); + }; + + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].portwidth = FLASH_CFI_8BIT; + flash_info[1].chipwidth = FLASH_CFI_16BIT; + size += flash_info[1].size = flash_get_size(CFG_CONFFLASH_BASE, 1); + if (flash_info[1].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", 2, + flash_info[1].size, flash_info[1].size<<20); + }; + + return (size); +} + +/*----------------------------------------------------------------------- + */ +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + int rcode = 0; + int prot; + int sect; + + if( info->flash_id != FLASH_MAN_CFI) { + printf ("Can't erase unknown flash type - aborted\n"); + return 1; + } + if ((s_first < 0) || (s_first > s_last)) { + printf ("- no sectors to erase\n"); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE); + flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM); + + if(flash_full_status_check(info, sect, info->erase_blk_tout, "erase")) { + rcode = 1; + } else + printf("."); + } + } + printf (" done\n"); + return rcode; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id != FLASH_MAN_CFI) { + printf ("missing or unknown FLASH type\n"); + return; + } + + printf("CFI conformant FLASH (x%d device in x%d mode)", + (info->chipwidth << 3 ), (info->portwidth << 3 )); + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + printf(" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", + info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf ("\n"); + printf (" %08lX%5s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong wp; + ulong cp; + int aln; + cfiword_t cword; + int i, rc; + + /* get lower aligned address */ + wp = (addr & ~(info->portwidth - 1)); + + /* handle unaligned start */ + if((aln = addr - wp) != 0) { + cword.l = 0; + cp = wp; + for(i=0;iportwidth) && (cnt > 0) ; i++) { + flash_add_byte(info, &cword, *src++); + cnt--; + cp++; + } + for(; (cnt == 0) && (i < info->portwidth); ++i, ++cp) + flash_add_byte(info, &cword, (*(uchar *)cp)); + if((rc = flash_write_cfiword(info, wp, cword)) != 0) + return rc; + wp = cp; + } + +#ifdef CFG_FLASH_USE_BUFFER_WRITE + while(cnt >= info->portwidth) { + i = info->buffer_size > cnt? cnt: info->buffer_size; + if((rc = flash_write_cfibuffer(info, wp, src,i)) != ERR_OK) + return rc; + wp += i; + src += i; + cnt -=i; + } +#else + /* handle the aligned part */ + while(cnt >= info->portwidth) { + cword.l = 0; + for(i = 0; i < info->portwidth; i++) { + flash_add_byte(info, &cword, *src++); + } + if((rc = flash_write_cfiword(info, wp, cword)) != 0) + return rc; + wp += info->portwidth; + cnt -= info->portwidth; + } +#endif /* CFG_FLASH_USE_BUFFER_WRITE */ + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + cword.l = 0; + for (i=0, cp=wp; (iportwidth) && (cnt>0); ++i, ++cp) { + flash_add_byte(info, &cword, *src++); + --cnt; + } + for (; iportwidth; ++i, ++cp) { + flash_add_byte(info, & cword, (*(uchar *)cp)); + } + + return flash_write_cfiword(info, wp, cword); +} + +/*----------------------------------------------------------------------- + */ +int flash_real_protect(flash_info_t *info, long sector, int prot) +{ + int retcode = 0; + + flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT); + if(prot) + flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET); + else + flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR); + + if((retcode = flash_full_status_check(info, sector, info->erase_blk_tout, + prot?"protect":"unprotect")) == 0) { + + info->protect[sector] = prot; + /* Intel's unprotect unprotects all locking */ + if(prot == 0) { + int i; + for(i = 0 ; isector_count; i++) { + if(info->protect[i]) + flash_real_protect(info, i, 1); + } + } + } + + return retcode; +} +/*----------------------------------------------------------------------- + * wait for XSR.7 to be set. Time out with an error if it does not. + * This routine does not set the flash to read-array mode. + */ +static int flash_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt) +{ + ulong start; + + /* Wait for command completion */ + start = get_timer (0); + while(!flash_isset(info, sector, 0, FLASH_STATUS_DONE)) { + if (get_timer(start) > info->erase_blk_tout) { + printf("Flash %s timeout at address %lx\n", prompt, info->start[sector]); + flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); + return ERR_TIMOUT; + } + } + return ERR_OK; +} +/*----------------------------------------------------------------------- + * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check. + * This routine sets the flash to read-array mode. + */ +static int flash_full_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt) +{ + int retcode; + retcode = flash_status_check(info, sector, tout, prompt); + if((retcode == ERR_OK) && !flash_isequal(info,sector, 0, FLASH_STATUS_DONE)) { + retcode = ERR_INVAL; + printf("Flash %s error at address %lx\n", prompt,info->start[sector]); + if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)){ + printf("Command Sequence Error.\n"); + } else if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS)){ + printf("Block Erase Error.\n"); + retcode = ERR_NOT_ERASED; + } else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) { + printf("Locking Error\n"); + } + if(flash_isset(info, sector, 0, FLASH_STATUS_DPS)){ + printf("Block locked.\n"); + retcode = ERR_PROTECTED; + } + if(flash_isset(info, sector, 0, FLASH_STATUS_VPENS)) + printf("Vpp Low Error.\n"); + } + flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); + return retcode; +} +/*----------------------------------------------------------------------- + */ +static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c) +{ + switch(info->portwidth) { + case FLASH_CFI_8BIT: + cword->c = c; + break; + case FLASH_CFI_16BIT: + cword->w = (cword->w << 8) | c; + break; + case FLASH_CFI_32BIT: + cword->l = (cword->l << 8) | c; + } +} + + +/*----------------------------------------------------------------------- + * make a proper sized command based on the port and chip widths + */ +static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf) +{ + //int i; + uchar *cp = (uchar *)cmdbuf; + // for(i=0; i< info->portwidth; i++) + // *cp++ = ((i+1) % info->chipwidth) ? '\0':cmd; + if (info->portwidth == FLASH_CFI_8BIT && info->chipwidth == FLASH_CFI_16BIT) { + cp[0] = cmd; + } else if (info->portwidth == FLASH_CFI_16BIT && info->chipwidth == FLASH_CFI_16BIT) { + cp[0] = '\0'; + cp[1] = cmd; + }; +} + +/* + * Write a proper sized command to the correct address + */ +static void flash_write_cmd(flash_info_t * info, int sect, uchar offset, uchar cmd) +{ + + volatile cfiptr_t addr; + cfiword_t cword; + addr.cp = flash_make_addr(info, sect, offset); + flash_make_cmd(info, cmd, &cword); + switch(info->portwidth) { + case FLASH_CFI_8BIT: + *addr.cp = cword.c; + break; + case FLASH_CFI_16BIT: + *addr.wp = cword.w; + break; + case FLASH_CFI_32BIT: + *addr.lp = cword.l; + break; + } +} + +/*----------------------------------------------------------------------- + */ +static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd) +{ + cfiptr_t cptr; + cfiword_t cword; + int retval; + cptr.cp = flash_make_addr(info, sect, offset); + flash_make_cmd(info, cmd, &cword); + switch(info->portwidth) { + case FLASH_CFI_8BIT: + retval = (cptr.cp[0] == cword.c); + break; + case FLASH_CFI_16BIT: + retval = (cptr.wp[0] == cword.w); + break; + case FLASH_CFI_32BIT: + retval = (cptr.lp[0] == cword.l); + break; + default: + retval = 0; + break; + } + return retval; +} +/*----------------------------------------------------------------------- + */ +static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd) +{ + cfiptr_t cptr; + cfiword_t cword; + int retval; + cptr.cp = flash_make_addr(info, sect, offset); + flash_make_cmd(info, cmd, &cword); + switch(info->portwidth) { + case FLASH_CFI_8BIT: + retval = ((cptr.cp[0] & cword.c) == cword.c); + break; + case FLASH_CFI_16BIT: + retval = ((cptr.wp[0] & cword.w) == cword.w); + break; + case FLASH_CFI_32BIT: + retval = ((cptr.lp[0] & cword.l) == cword.l); + break; + default: + retval = 0; + break; + } + return retval; +} + +/*----------------------------------------------------------------------- + * detect if flash is compatible with the Common Flash Interface (CFI) + * http://www.jedec.org/download/search/jesd68.pdf + * +*/ +static int flash_detect_cfi(flash_info_t * info) +{ + +#if 0 + for(info->portwidth=FLASH_CFI_8BIT; info->portwidth <= FLASH_CFI_32BIT; + info->portwidth <<= 1) { + for(info->chipwidth =FLASH_CFI_BY8; + info->chipwidth <= info->portwidth; + info->chipwidth <<= 1) { + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + flash_write_cmd(info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); + if(flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP,'Q') && + flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') && + flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) + return 1; + } + } +#endif + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + flash_write_cmd(info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); + if(flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP,'Q') && + flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') && + flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { + return 1; + } else { + return 0; + }; +} +/* + * The following code cannot be run from FLASH! + * + */ +static ulong flash_get_size (ulong base, int banknum) +{ + flash_info_t * info = &flash_info[banknum]; + int i, j; + int sect_cnt; + unsigned long sector; + unsigned long tmp; + int size_ratio; + uchar num_erase_regions; + int erase_region_size; + int erase_region_count; + + info->start[0] = base; + + if(flash_detect_cfi(info)){ +#ifdef DEBUG_FLASH + printf("portwidth=%d chipwidth=%d\n", info->portwidth, info->chipwidth); /* test-only */ +#endif + size_ratio = 1; // info->portwidth / info->chipwidth; + num_erase_regions = flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS); +#ifdef DEBUG_FLASH + printf("found %d erase regions\n", num_erase_regions); +#endif + sect_cnt = 0; + sector = base; + for(i = 0 ; i < num_erase_regions; i++) { + if(i > NUM_ERASE_REGIONS) { + printf("%d erase regions found, only %d used\n", + num_erase_regions, NUM_ERASE_REGIONS); + break; + } + tmp = flash_read_long(info, 0, FLASH_OFFSET_ERASE_REGIONS); + erase_region_count = (tmp & 0xffff) +1; + tmp >>= 16; + erase_region_size = (tmp & 0xffff)? ((tmp & 0xffff) * 256): 128; + for(j = 0; j< erase_region_count; j++) { + info->start[sect_cnt] = sector; + sector += (erase_region_size * size_ratio); + info->protect[sect_cnt] = flash_isset(info, sect_cnt, FLASH_OFFSET_PROTECT, FLASH_STATUS_PROTECT); + sect_cnt++; + } + } + + info->sector_count = sect_cnt; + /* multiply the size by the number of chips */ + info->size = (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) * size_ratio; + info->buffer_size = (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE)); + tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT); + info->erase_blk_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT))); + tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT); + info->buffer_write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT))); + tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT); + info->write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT)))/ 1000; + info->flash_id = FLASH_MAN_CFI; + } + + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + return(info->size); +} + + +/*----------------------------------------------------------------------- + */ +static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword) +{ + + cfiptr_t ctladdr; + cfiptr_t cptr; + int flag; + + ctladdr.cp = flash_make_addr(info, 0, 0); + cptr.cp = (uchar *)dest; + + + /* Check if Flash is (sufficiently) erased */ + switch(info->portwidth) { + case FLASH_CFI_8BIT: + flag = ((cptr.cp[0] & cword.c) == cword.c); + break; + case FLASH_CFI_16BIT: + flag = ((cptr.wp[0] & cword.w) == cword.w); + break; + case FLASH_CFI_32BIT: + flag = ((cptr.lp[0] & cword.l) == cword.l); + break; + default: + return 2; + } + if(!flag) + return 2; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE); + + switch(info->portwidth) { + case FLASH_CFI_8BIT: + cptr.cp[0] = cword.c; + break; + case FLASH_CFI_16BIT: + cptr.wp[0] = cword.w; + break; + case FLASH_CFI_32BIT: + cptr.lp[0] = cword.l; + break; + } + + /* re-enable interrupts if necessary */ + if(flag) + enable_interrupts(); + + return flash_full_status_check(info, 0, info->write_tout, "write"); +} + +#ifdef CFG_FLASH_USE_BUFFER_WRITE + +/* loop through the sectors from the highest address + * when the passed address is greater or equal to the sector address + * we have a match + */ +static int find_sector(flash_info_t *info, ulong addr) +{ + int sector; + for(sector = info->sector_count - 1; sector >= 0; sector--) { + if(addr >= info->start[sector]) + break; + } + return sector; +} + +static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len) +{ + + int sector; + int cnt; + int retcode; + volatile cfiptr_t src; + volatile cfiptr_t dst; + + src.cp = cp; + dst.cp = (uchar *)dest; + sector = find_sector(info, dest); + flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); + if((retcode = flash_status_check(info, sector, info->buffer_write_tout, + "write to buffer")) == ERR_OK) { + switch(info->portwidth) { + case FLASH_CFI_8BIT: + cnt = len; + break; + case FLASH_CFI_16BIT: + cnt = len >> 1; + break; + case FLASH_CFI_32BIT: + cnt = len >> 2; + break; + default: + return ERR_INVAL; + break; + } + flash_write_cmd(info, sector, 0, (uchar)cnt-1); + while(cnt-- > 0) { + switch(info->portwidth) { + case FLASH_CFI_8BIT: + *dst.cp++ = *src.cp++; + break; + case FLASH_CFI_16BIT: + *dst.wp++ = *src.wp++; + break; + case FLASH_CFI_32BIT: + *dst.lp++ = *src.lp++; + break; + default: + return ERR_INVAL; + break; + } + } + flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM); + retcode = flash_full_status_check(info, sector, info->buffer_write_tout, + "buffer write"); + } + flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); + return retcode; +} +#endif /* CFG_USE_FLASH_BUFFER_WRITE */ diff --git a/board/amirix/ap1000/init.S b/board/amirix/ap1000/init.S new file mode 100644 index 000000000..8c3a35783 --- /dev/null +++ b/board/amirix/ap1000/init.S @@ -0,0 +1,34 @@ +/* + * init.S: Stubs for ppcboot initialization + * + * Copyright 2002 Mind NV + * + * http://www.mind.be/ + * + * Author : Peter De Schrijver (p2@mind.be) + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire + * program is licensed under the GPL. + * + */ + +#include + +#include +#include + +#include +#include + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + blr + + .globl sdram_init +sdram_init: + blr diff --git a/board/amirix/ap1000/pci.c b/board/amirix/ap1000/pci.c new file mode 100644 index 000000000..34cd5872b --- /dev/null +++ b/board/amirix/ap1000/pci.c @@ -0,0 +1,346 @@ +/* + * (C) Copyright 2003 + * AMIRIX Systems Inc. + * + * 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 +#include +#include +#include + +#define PCI_MEM_82559ER_CSR_BASE 0x30200000 +#define PCI_IO_82559ER_CSR_BASE 0x40000200 + +/** AP1100 specific values */ +#define PSII_BASE 0x30000000 /**< PowerSpan II dual bridge local bus register address */ +#define PSII_CONFIG_ADDR 0x30000290 /**< PowerSpan II Configuration Cycle Address configuration register */ +#define PSII_CONFIG_DATA 0x30000294 /**< PowerSpan II Configuration Cycle Data register. */ +#define PSII_CONFIG_DEST_PCI2 0x01000000 /**< PowerSpan II configuration cycle destination selection, set for PCI2 bus */ +#define PSII_PCI_MEM_BASE 0x30200000 /**< Local Bus address for start of PCI memory space on PCI2 bus. */ +#define PSII_PCI_MEM_SIZE 0x1BE00000 /**< PCI Memory space about 510 Meg. */ +#define AP1000_SYS_MEM_START 0x00000000 /**< System memory starts at 0. */ +#define AP1000_SYS_MEM_SIZE 0x08000000 /**< System memory is 128 Meg. */ + +/* static int G_verbosity_level = 1; */ +#define G_verbosity_level 1 + +void write1(unsigned long addr, unsigned char val) { + volatile unsigned char* p = (volatile unsigned char*)addr; + + if(G_verbosity_level > 1) + printf("write1: addr=%08x val=%02x\n", (unsigned int)addr, val); + *p = val; + asm("eieio"); +} + +unsigned char read1(unsigned long addr) { + unsigned char val; + volatile unsigned char* p = (volatile unsigned char*)addr; + + if(G_verbosity_level > 1) + printf("read1: addr=%08x ", (unsigned int)addr); + val = *p; + asm("eieio"); + if(G_verbosity_level > 1) + printf("val=%08x\n", val); + return val; +} + +void write2(unsigned long addr, unsigned short val) { + volatile unsigned short* p = (volatile unsigned short*)addr; + + if(G_verbosity_level > 1) + printf("write2: addr=%08x val=%04x -> *p=%04x\n", (unsigned int)addr, val, + ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8)); + + *p = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8); + asm("eieio"); +} + +unsigned short read2(unsigned long addr) { + unsigned short val; + volatile unsigned short* p = (volatile unsigned short*)addr; + + if(G_verbosity_level > 1) + printf("read2: addr=%08x ", (unsigned int)addr); + val = *p; + val = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8); + asm("eieio"); + if(G_verbosity_level > 1) + printf("*p=%04x -> val=%04x\n", + ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8), val); + return val; +} + +void write4(unsigned long addr, unsigned long val) { + volatile unsigned long* p = (volatile unsigned long*)addr; + + if(G_verbosity_level > 1) + printf("write4: addr=%08x val=%08x -> *p=%08x\n", (unsigned int)addr, (unsigned int)val, + (unsigned int)(((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8))); + + *p = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8); + asm("eieio"); +} + +unsigned long read4(unsigned long addr) { + unsigned long val; + volatile unsigned long* p = (volatile unsigned long*)addr; + + if(G_verbosity_level > 1) + printf("read4: addr=%08x", (unsigned int)addr); + + val = *p; + val = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8); + asm("eieio"); + + if(G_verbosity_level > 1) + printf("*p=%04x -> val=%04x\n", + (unsigned int)(((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8)), (unsigned int)val); + return val; +} + +void write4be(unsigned long addr, unsigned long val) { + volatile unsigned long* p = (volatile unsigned long*)addr; + + if(G_verbosity_level > 1) + printf("write4: addr=%08x val=%08x\n", (unsigned int)addr, (unsigned int)val); + *p = val; + asm("eieio"); +} + +/** One byte configuration write on PSII. + * Currently fixes destination PCI bus to PCI2, onboard + * pci. + * @param hose PCI Host controller information. Ignored. + * @param dev Encoded PCI device/Bus and Function value. + * @param reg PCI Configuration register number. + * @param val Address of location for received byte. + * @return Always Zero. + */ +static int psII_read_config_byte( + struct pci_controller *hose, + pci_dev_t dev, + int reg, + u8 *val) +{ + write4be(PSII_CONFIG_ADDR, + PSII_CONFIG_DEST_PCI2 | /* Operate on PCI2 bus interface . */ + (PCI_BUS(dev) << 16) | + (PCI_DEV(dev) << 11) | + (PCI_FUNC(dev) << 8) | + ((reg & 0xFF) & ~3)); /* Configuation cycle type 0 */ + + *val = read1(PSII_CONFIG_DATA+(reg&0x03)); + return(0); +} + +/** One byte configuration write on PSII. + * Currently fixes destination bus to PCI2, onboard + * pci. + * @param hose PCI Host controller information. Ignored. + * @param dev Encoded PCI device/Bus and Function value. + * @param reg PCI Configuration register number. + * @param val Output byte. + * @return Always Zero. + */ +static int psII_write_config_byte( + struct pci_controller *hose, + pci_dev_t dev, + int reg, + u8 val) +{ + write4be(PSII_CONFIG_ADDR, + PSII_CONFIG_DEST_PCI2 | /* Operate on PCI2 bus interface . */ + (PCI_BUS(dev) << 16) | + (PCI_DEV(dev) << 11) | + (PCI_FUNC(dev) << 8) | + ((reg & 0xFF) & ~3)); /* Configuation cycle type 0 */ + + write1(PSII_CONFIG_DATA+(reg&0x03),(unsigned char )val); + + return(0); +} + +/** One word (16 bit) configuration read on PSII. + * Currently fixes destination PCI bus to PCI2, onboard + * pci. + * @param hose PCI Host controller information. Ignored. + * @param dev Encoded PCI device/Bus and Function value. + * @param reg PCI Configuration register number. + * @param val Address of location for received word. + * @return Always Zero. + */ +static int psII_read_config_word( + struct pci_controller *hose, + pci_dev_t dev, + int reg, + u16 *val) +{ + write4be(PSII_CONFIG_ADDR, + PSII_CONFIG_DEST_PCI2 | /* Operate on PCI2 bus interface . */ + (PCI_BUS(dev) << 16) | + (PCI_DEV(dev) << 11) | + (PCI_FUNC(dev) << 8) | + ((reg & 0xFF) & ~3)); /* Configuation cycle type 0 */ + + *val = read2(PSII_CONFIG_DATA+(reg&0x03)); + return(0); +} + +/** One word (16 bit) configuration write on PSII. + * Currently fixes destination bus to PCI2, onboard + * pci. + * @param hose PCI Host controller information. Ignored. + * @param dev Encoded PCI device/Bus and Function value. + * @param reg PCI Configuration register number. + * @param val Output word. + * @return Always Zero. + */ +static int psII_write_config_word( + struct pci_controller *hose, + pci_dev_t dev, + int reg, + u16 val) +{ + write4be(PSII_CONFIG_ADDR, + PSII_CONFIG_DEST_PCI2 | /* Operate on PCI2 bus interface . */ + (PCI_BUS(dev) << 16) | + (PCI_DEV(dev) << 11) | + (PCI_FUNC(dev) << 8) | + ((reg & 0xFF) & ~3)); /* Configuation cycle type 0 */ + + write2(PSII_CONFIG_DATA+(reg&0x03),(unsigned short )val); + + return(0); +} + +/** One DWord (32 bit) configuration read on PSII. + * Currently fixes destination PCI bus to PCI2, onboard + * pci. + * @param hose PCI Host controller information. Ignored. + * @param dev Encoded PCI device/Bus and Function value. + * @param reg PCI Configuration register number. + * @param val Address of location for received byte. + * @return Always Zero. + */ +static int psII_read_config_dword( + struct pci_controller *hose, + pci_dev_t dev, + int reg, + u32 *val) +{ + write4be(PSII_CONFIG_ADDR, + PSII_CONFIG_DEST_PCI2 | /* Operate on PCI2 bus interface . */ + (PCI_BUS(dev) << 16) | + (PCI_DEV(dev) << 11) | + (PCI_FUNC(dev) << 8) | + ((reg & 0xFF) & ~3)); /* Configuation cycle type 0 */ + + *val = read4(PSII_CONFIG_DATA); + return(0); +} + +/** One DWord (32 bit) configuration write on PSII. + * Currently fixes destination bus to PCI2, onboard + * pci. + * @param hose PCI Host controller information. Ignored. + * @param dev Encoded PCI device/Bus and Function value. + * @param reg PCI Configuration register number. + * @param val Output Dword. + * @return Always Zero. + */ +static int psII_write_config_dword( + struct pci_controller *hose, + pci_dev_t dev, + int reg, + u32 val) +{ + write4be(PSII_CONFIG_ADDR, + PSII_CONFIG_DEST_PCI2 | /* Operate on PCI2 bus interface . */ + (PCI_BUS(dev) << 16) | + (PCI_DEV(dev) << 11) | + (PCI_FUNC(dev) << 8) | + ((reg & 0xFF) & ~3)); /* Configuation cycle type 0 */ + + write4(PSII_CONFIG_DATA,(unsigned long)val); + + return(0); +} + + + +static struct pci_config_table ap1000_config_table[] = { +#ifdef CONFIG_AP1000 + {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_BUS(CFG_ETH_DEV_FN), PCI_DEV(CFG_ETH_DEV_FN), PCI_FUNC(CFG_ETH_DEV_FN), + pci_cfgfunc_config_device, + {CFG_ETH_IOBASE, CFG_ETH_MEMBASE, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, +#endif + { } +}; + + +static struct pci_controller psII_hose = { + config_table: ap1000_config_table, +}; + +void pci_init_board(void) +{ + struct pci_controller *hose = &psII_hose; + + /* + * Register the hose + */ + hose->first_busno = 0; + hose->last_busno = 0xff; + + + /* System memory space */ + pci_set_region(hose->regions + 0, + AP1000_SYS_MEM_START, AP1000_SYS_MEM_START, AP1000_SYS_MEM_SIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI Memory space */ + pci_set_region(hose->regions + 1, + PSII_PCI_MEM_BASE, PSII_PCI_MEM_BASE, PSII_PCI_MEM_SIZE, + PCI_REGION_MEM); + + /* No IO Memory space - for now */ + + pci_set_ops(hose, + psII_read_config_byte, + psII_read_config_word, + psII_read_config_dword, + psII_write_config_byte, + psII_write_config_word, + psII_write_config_dword); + + hose->region_count = 2; + + pci_register_hose(hose); + + hose->last_busno = pci_hose_scan(hose); +} diff --git a/board/amirix/ap1000/powerspan.c b/board/amirix/ap1000/powerspan.c new file mode 100644 index 000000000..fe395ccb8 --- /dev/null +++ b/board/amirix/ap1000/powerspan.c @@ -0,0 +1,712 @@ +/** + * @file powerspan.c Source file for PowerSpan II code. + */ + +/* + * (C) Copyright 2005 + * AMIRIX Systems Inc. + * + * 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 +#include +#include +#include "powerspan.h" +#define tolower(x) x +#include "ap1000.h" + +#ifdef INCLUDE_PCI + +/** Write one byte with byte swapping. + * @param addr [IN] the address to write to + * @param val [IN] the value to write + */ +void write1(unsigned long addr, unsigned char val) { + volatile unsigned char* p = (volatile unsigned char*)addr; +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("write1: addr=%08x val=%02x\n", addr, val); + } +#endif + *p = val; + PSII_SYNC(); +} + +/** Read one byte with byte swapping. + * @param addr [IN] the address to read from + * @return the value at addr + */ +unsigned char read1(unsigned long addr) { + unsigned char val; + volatile unsigned char* p = (volatile unsigned char*)addr; + + val = *p; + PSII_SYNC(); +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("read1: addr=%08x val=%02x\n", addr, val); + } +#endif + return val; +} + +/** Write one 2-byte word with byte swapping. + * @param addr [IN] the address to write to + * @param val [IN] the value to write + */ +void write2(unsigned long addr, unsigned short val) { + volatile unsigned short* p = (volatile unsigned short*)addr; + +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("write2: addr=%08x val=%04x -> *p=%04x\n", addr, val, + ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8)); + } +#endif + *p = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8); + PSII_SYNC(); +} + +/** Read one 2-byte word with byte swapping. + * @param addr [IN] the address to read from + * @return the value at addr + */ +unsigned short read2(unsigned long addr) { + unsigned short val; + volatile unsigned short* p = (volatile unsigned short*)addr; + + val = *p; + val = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8); + PSII_SYNC(); +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("read2: addr=%08x *p=%04x -> val=%04x\n", addr, *p, val); + } +#endif + return val; +} + +/** Write one 4-byte word with byte swapping. + * @param addr [IN] the address to write to + * @param val [IN] the value to write + */ +void write4(unsigned long addr, unsigned long val) { + volatile unsigned long* p = (volatile unsigned long*)addr; +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("write4: addr=%08x val=%08x -> *p=%08x\n", addr, val, + ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8)); + } +#endif + *p = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8); + PSII_SYNC(); +} + +/** Read one 4-byte word with byte swapping. + * @param addr [IN] the address to read from + * @return the value at addr + */ +unsigned long read4(unsigned long addr) { + unsigned long val; + volatile unsigned long* p = (volatile unsigned long*)addr; + + val = *p; + val = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | + ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8); + PSII_SYNC(); +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("read4: addr=%08x *p=%08x -> val=%08x\n", addr, *p, val); + } +#endif + return val; +} + +int PCIReadConfig(int bus, int dev, int fn, int reg, int width, unsigned long* val){ + unsigned int conAdrVal; + unsigned int conDataReg = REG_CONFIG_DATA; + unsigned int status; + int ret_val = 0; + + + /* DEST bit hardcoded to 1: local pci is PCI-2 */ + /* TYPE bit is hardcoded to 1: all config cycles are local */ + conAdrVal = (1 << 24) + | ((bus & 0xFF) << 16) + | ((dev & 0xFF) << 11) + | ((fn & 0x07) << 8) + | (reg & 0xFC); + + /* clear any pending master aborts */ + write4(REG_P1_CSR, CLEAR_MASTER_ABORT); + + /* Load the conAdrVal value first, then read from pb_conf_data */ + write4(REG_CONFIG_ADDRESS, conAdrVal); + PSII_SYNC(); + + + /* Note: documentation does not match the pspan library code */ + /* Note: *pData comes back as -1 if device is not present */ + switch (width){ + case 4:{ + *(unsigned int*)val = read4(conDataReg); + break; + } + case 2:{ + *(unsigned short*)val = read2(conDataReg); + break; + } + case 1:{ + *(unsigned char*)val = read1(conDataReg); + break; + } + default:{ + ret_val = ILLEGAL_REG_OFFSET; + break; + } + } + PSII_SYNC(); + + /* clear any pending master aborts */ + status = read4(REG_P1_CSR); + if(status & CLEAR_MASTER_ABORT){ + ret_val = NO_DEVICE_FOUND; + write4(REG_P1_CSR, CLEAR_MASTER_ABORT); + } + + return ret_val; +} + + +int PCIWriteConfig(int bus, int dev, int fn, int reg, int width, unsigned long val){ + unsigned int conAdrVal; + unsigned int conDataReg = REG_CONFIG_DATA; + unsigned int status; + int ret_val = 0; + + + /* DEST bit hardcoded to 1: local pci is PCI-2 */ + /* TYPE bit is hardcoded to 1: all config cycles are local */ + conAdrVal = (1 << 24) + | ((bus & 0xFF) << 16) + | ((dev & 0xFF) << 11) + | ((fn & 0x07) << 8) + | (reg & 0xFC); + + /* clear any pending master aborts */ + write4(REG_P1_CSR, CLEAR_MASTER_ABORT); + + /* Load the conAdrVal value first, then read from pb_conf_data */ + write4(REG_CONFIG_ADDRESS, conAdrVal); + PSII_SYNC(); + + + /* Note: documentation does not match the pspan library code */ + /* Note: *pData comes back as -1 if device is not present */ + switch (width){ + case 4:{ + write4(conDataReg, val); + break; + } + case 2:{ + write2(conDataReg, val); + break; + } + case 1:{ + write1(conDataReg, val); + break; + } + default:{ + ret_val = ILLEGAL_REG_OFFSET; + break; + } + } + PSII_SYNC(); + + /* clear any pending master aborts */ + status = read4(REG_P1_CSR); + if(status & CLEAR_MASTER_ABORT){ + ret_val = NO_DEVICE_FOUND; + write4(REG_P1_CSR, CLEAR_MASTER_ABORT); + } + + return ret_val; +} + + +int pci_read_config_byte(int bus, int dev, int fn, int reg, unsigned char* val){ + unsigned long read_val; + int ret_val; + + ret_val = PCIReadConfig(bus, dev, fn, reg, 1, &read_val); + *val = read_val & 0xFF; + + return ret_val; +} + +int pci_write_config_byte(int bus, int dev, int fn, int reg, unsigned char val){ + return PCIWriteConfig(bus, dev, fn, reg, 1, val); +} + +int pci_read_config_word(int bus, int dev, int fn, int reg, unsigned short* val){ + unsigned long read_val; + int ret_val; + + ret_val = PCIReadConfig(bus, dev, fn, reg, 2, &read_val); + *val = read_val & 0xFFFF; + + return ret_val; +} + +int pci_write_config_word(int bus, int dev, int fn, int reg, unsigned short val){ + return PCIWriteConfig(bus, dev, fn, reg, 2, val); +} + +int pci_read_config_dword(int bus, int dev, int fn, int reg, unsigned long* val){ + return PCIReadConfig(bus, dev, fn, reg, 4, val); +} + +int pci_write_config_dword(int bus, int dev, int fn, int reg, unsigned long val){ + return PCIWriteConfig(bus, dev, fn, reg, 4, val); +} + +#endif /* INCLUDE_PCI */ + +int I2CAccess(unsigned char theI2CAddress, unsigned char theDevCode, unsigned char theChipSel, unsigned char* theValue, int RWFlag){ + int ret_val = 0; + unsigned int reg_value; + + reg_value = PowerSpanRead(REG_I2C_CSR); + + if(reg_value & I2C_CSR_ACT){ + printf("Error: I2C busy\n"); + ret_val = I2C_BUSY; + } + else{ + reg_value = ((theI2CAddress & 0xFF) << 24) + | ((theDevCode & 0x0F) << 12) + | ((theChipSel & 0x07) << 9) + | I2C_CSR_ERR; + if(RWFlag == I2C_WRITE){ + reg_value |= I2C_CSR_RW | ((*theValue & 0xFF) << 16); + } + + PowerSpanWrite(REG_I2C_CSR, reg_value); + udelay(1); + + do{ + reg_value = PowerSpanRead(REG_I2C_CSR); + + if((reg_value & I2C_CSR_ACT) == 0){ + if(reg_value & I2C_CSR_ERR){ + ret_val = I2C_ERR; + } + else{ + *theValue = (reg_value & I2C_CSR_DATA) >> 16; + } + } + } while(reg_value & I2C_CSR_ACT); + } + + return ret_val; +} + +int EEPROMRead(unsigned char theI2CAddress, unsigned char* theValue){ + return I2CAccess(theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL, theValue, I2C_READ); +} + +int EEPROMWrite(unsigned char theI2CAddress, unsigned char theValue){ + return I2CAccess(theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL, &theValue, I2C_WRITE); +} + +int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ + char cmd; + int ret_val = 0; + unsigned int address = 0; + unsigned char value = 1; + unsigned char read_value; + int ii; + int error = 0; + unsigned char* mem_ptr; + unsigned char default_eeprom[] = EEPROM_DEFAULT; + + if(argc < 2){ + goto usage; + } + + cmd = argv[1][0]; + if(argc > 2){ + address = simple_strtoul(argv[2], NULL, 16); + if(argc > 3){ + value = simple_strtoul(argv[3], NULL, 16) & 0xFF; + } + } + + switch (cmd){ + case 'r':{ + if(address > 256){ + printf("Illegal Address\n"); + goto usage; + } + printf("@0x%x: ", address); + for(ii = 0;ii < value;ii++){ + if(EEPROMRead(address + ii, &read_value) != 0){ + printf("Read Error\n"); + } + else{ + printf("0x%02x ", read_value); + } + + if(((ii + 1) % 16) == 0){ + printf("\n"); + } + } + printf("\n"); + break; + } + case 'w':{ + if(address > 256){ + printf("Illegal Address\n"); + goto usage; + } + if(argc < 4){ + goto usage; + } + if(EEPROMWrite(address, value) != 0){ + printf("Write Error\n"); + } + break; + } + case 'g':{ + if(argc != 3){ + goto usage; + } + mem_ptr = (unsigned char*)address; + for(ii = 0;((ii < EEPROM_LENGTH) && (error == 0));ii++){ + if(EEPROMRead(ii, &read_value) != 0){ + printf("Read Error\n"); + error = 1; + } + else{ + *mem_ptr = read_value; + mem_ptr++; + } + } + break; + } + case 'p':{ + if(argc != 3){ + goto usage; + } + mem_ptr = (unsigned char*)address; + for(ii = 0;((ii < EEPROM_LENGTH) && (error == 0));ii++){ + if(EEPROMWrite(ii, *mem_ptr) != 0){ + printf("Write Error\n"); + error = 1; + } + + mem_ptr++; + } + break; + } + case 'd':{ + if(argc != 2){ + goto usage; + } + for(ii = 0;((ii < EEPROM_LENGTH) && (error == 0));ii++){ + if(EEPROMWrite(ii, default_eeprom[ii]) != 0){ + printf("Write Error\n"); + error = 1; + } + } + break; + } + default:{ + goto usage; + } + } + + goto done; + usage: + printf ("Usage:\n%s\n", cmdtp->help); + + done: + return ret_val; + +} + +U_BOOT_CMD( + eeprom, 4, 0, do_eeprom, + "eeprom - read/write/copy to/from the PowerSpan II eeprom\n", + "eeprom r OFF [NUM]\n" + " - read NUM words starting at OFF\n" + "eeprom w OFF VAL\n" + " - write word VAL at offset OFF\n" + "eeprom g ADD\n" + " - store contents of eeprom at address ADD\n" + "eeprom p ADD\n" + " - put data stored at address ADD into the eeprom\n" + "eeprom d\n" + " - return eeprom to default contents\n" +); + +unsigned int PowerSpanRead(unsigned int theOffset){ + volatile unsigned int* ptr = (volatile unsigned int*)(PSPAN_BASEADDR + theOffset); + unsigned int ret_val; + +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("PowerSpanRead: offset=%08x ", theOffset); + } +#endif + ret_val = *ptr; + PSII_SYNC(); + +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("value=%08x\n", ret_val); + } +#endif + + return ret_val; +} + +void PowerSpanWrite(unsigned int theOffset, unsigned int theValue){ + volatile unsigned int* ptr = (volatile unsigned int*)(PSPAN_BASEADDR + theOffset); +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("PowerSpanWrite: offset=%08x val=%02x\n", theOffset, theValue); + } +#endif + *ptr = theValue; + PSII_SYNC(); +} + +/** + * Sets the indicated bits in the indicated register. + * @param theOffset [IN] the register to access. + * @param theMask [IN] bits set in theMask will be set in the register. + */ +void PowerSpanSetBits(unsigned int theOffset, unsigned int theMask){ + volatile unsigned int* ptr = (volatile unsigned int*)(PSPAN_BASEADDR + theOffset); + unsigned int register_value; + +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("PowerSpanSetBits: offset=%08x mask=%02x\n", theOffset, theMask); + } +#endif + register_value = *ptr; + PSII_SYNC(); + + register_value |= theMask; + *ptr = register_value; + PSII_SYNC(); +} + +/** + * Clears the indicated bits in the indicated register. + * @param theOffset [IN] the register to access. + * @param theMask [IN] bits set in theMask will be cleared in the register. + */ +void PowerSpanClearBits(unsigned int theOffset, unsigned int theMask){ + volatile unsigned int* ptr = (volatile unsigned int*)(PSPAN_BASEADDR + theOffset); + unsigned int register_value; + +#ifdef VERBOSITY + if(gVerbosityLevel > 1){ + printf("PowerSpanClearBits: offset=%08x mask=%02x\n", theOffset, theMask); + } +#endif + register_value = *ptr; + PSII_SYNC(); + + register_value &= ~theMask; + *ptr = register_value; + PSII_SYNC(); +} + +/** + * Configures a slave image on the local bus, based on the parameters and some hardcoded system values. + * Slave Images are images that cause the PowerSpan II to be a master on the PCI bus. Thus, they + * are outgoing from the standpoint of the local bus. + * @param theImageIndex [IN] the PowerSpan II image to set (assumed to be 0-7). + * @param theBlockSize [IN] the block size of the image (as used by PowerSpan II: PB_SIx_CTL[BS]). + * @param theMemIOFlag [IN] if PX_TGT_USE_MEM_IO, this image will have the MEM_IO bit set. + * @param theEndianness [IN] the endian bits for the image (already shifted, use defines). + * @param theLocalBaseAddr [IN] the Local address for the image (assumed to be valid with provided block size). + * @param thePCIBaseAddr [IN] the PCI address for the image (assumed to be valid with provided block size). + */ +int SetSlaveImage(int theImageIndex, unsigned int theBlockSize, int theMemIOFlag, int theEndianness, unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr){ + unsigned int reg_offset = theImageIndex * PB_SLAVE_IMAGE_OFF; + unsigned int reg_value = 0; + + /* Make sure that the Slave Image is disabled */ + PowerSpanClearBits((REGS_PB_SLAVE_CSR + reg_offset), PB_SLAVE_CSR_IMG_EN); + + /* Setup the mask required for requested PB Slave Image configuration */ + reg_value = PB_SLAVE_CSR_TA_EN | theEndianness | (theBlockSize << 24); + if(theMemIOFlag == PB_SLAVE_USE_MEM_IO){ + reg_value |= PB_SLAVE_CSR_MEM_IO; + } + + /* hardcoding the following: + TA_EN = 1 + MD_EN = 0 + MODE = 0 + PRKEEP = 0 + RD_AMT = 0 + */ + PowerSpanWrite((REGS_PB_SLAVE_CSR + reg_offset), reg_value); + + /* these values are not checked by software */ + PowerSpanWrite((REGS_PB_SLAVE_BADDR + reg_offset), theLocalBaseAddr); + PowerSpanWrite((REGS_PB_SLAVE_TADDR + reg_offset), thePCIBaseAddr); + + /* Enable the Slave Image */ + PowerSpanSetBits((REGS_PB_SLAVE_CSR + reg_offset), PB_SLAVE_CSR_IMG_EN); + + return 0; +} + +/** + * Configures a target image on the local bus, based on the parameters and some hardcoded system values. + * Target Images are used when the PowerSpan II is acting as a target for an access. Thus, they + * are incoming from the standpoint of the local bus. + * In order to behave better on the host PCI bus, if thePCIBaseAddr is NULL (0x00000000), then the PCI + * base address will not be updated; makes sense given that the hosts own memory should be mapped to + * PCI address 0x00000000. + * @param theImageIndex [IN] the PowerSpan II image to set. + * @param theBlockSize [IN] the block size of the image (as used by PowerSpan II: Px_TIx_CTL[BS]). + * @param theMemIOFlag [IN] if PX_TGT_USE_MEM_IO, this image will have the MEM_IO bit set. + * @param theEndianness [IN] the endian bits for the image (already shifted, use defines). + * @param theLocalBaseAddr [IN] the Local address for the image (assumed to be valid with provided block size). + * @param thePCIBaseAddr [IN] the PCI address for the image (assumed to be valid with provided block size). + */ +int SetTargetImage(int theImageIndex, unsigned int theBlockSize, int theMemIOFlag, int theEndianness, unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr){ + unsigned int csr_reg_offset = theImageIndex * P1_TGT_IMAGE_OFF; + unsigned int pci_reg_offset = theImageIndex * P1_BST_OFF; + unsigned int reg_value = 0; + + /* Make sure that the Slave Image is disabled */ + PowerSpanClearBits((REGS_P1_TGT_CSR + csr_reg_offset), PB_SLAVE_CSR_IMG_EN); + + /* Setup the mask required for requested PB Slave Image configuration */ + reg_value = PX_TGT_CSR_TA_EN | PX_TGT_CSR_BAR_EN | (theBlockSize << 24) | PX_TGT_CSR_RTT_READ | PX_TGT_CSR_WTT_WFLUSH | theEndianness; + if(theMemIOFlag == PX_TGT_USE_MEM_IO){ + reg_value |= PX_TGT_MEM_IO; + } + + /* hardcoding the following: + TA_EN = 1 + BAR_EN = 1 + MD_EN = 0 + MODE = 0 + DEST = 0 + RTT = 01010 + GBL = 0 + CI = 0 + WTT = 00010 + PRKEEP = 0 + MRA = 0 + RD_AMT = 0 + */ + PowerSpanWrite((REGS_P1_TGT_CSR + csr_reg_offset), reg_value); + + PowerSpanWrite((REGS_P1_TGT_TADDR + csr_reg_offset), theLocalBaseAddr); + + if(thePCIBaseAddr != (unsigned int)NULL){ + PowerSpanWrite((REGS_P1_BST + pci_reg_offset), thePCIBaseAddr); + } + + /* Enable the Slave Image */ + PowerSpanSetBits((REGS_P1_TGT_CSR + csr_reg_offset), PB_SLAVE_CSR_IMG_EN); + + return 0; +} + +int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ + char cmd; + int ret_val = 1; + unsigned int image_index; + unsigned int block_size; + unsigned int mem_io; + unsigned int local_addr; + unsigned int pci_addr; + int endianness; + + if(argc != 8){ + goto usage; + } + + cmd = argv[1][0]; + image_index = simple_strtoul(argv[2], NULL, 16); + block_size = simple_strtoul(argv[3], NULL, 16); + mem_io = simple_strtoul(argv[4], NULL, 16); + endianness = argv[5][0]; + local_addr = simple_strtoul(argv[6], NULL, 16); + pci_addr = simple_strtoul(argv[7], NULL, 16); + + + switch (cmd){ + case 'i':{ + if(tolower(endianness) == 'b'){ + endianness = PX_TGT_CSR_BIG_END; + } + else if(tolower(endianness) == 'l'){ + endianness = PX_TGT_CSR_TRUE_LEND; + } + else{ + goto usage; + } + SetTargetImage(image_index, block_size, mem_io, endianness, local_addr, pci_addr); + break; + } + case 'o':{ + if(tolower(endianness) == 'b'){ + endianness = PB_SLAVE_CSR_BIG_END; + } + else if(tolower(endianness) == 'l'){ + endianness = PB_SLAVE_CSR_TRUE_LEND; + } + else{ + goto usage; + } + SetSlaveImage(image_index, block_size, mem_io, endianness, local_addr, pci_addr); + break; + } + default:{ + goto usage; + } + } + + goto done; + usage: + printf ("Usage:\n%s\n", cmdtp->help); + + done: + return ret_val; + +} + + + diff --git a/board/amirix/ap1000/powerspan.h b/board/amirix/ap1000/powerspan.h new file mode 100644 index 000000000..4e9a8c1bd --- /dev/null +++ b/board/amirix/ap1000/powerspan.h @@ -0,0 +1,170 @@ +/** + * @file powerspan.h Header file for PowerSpan II code. + */ + +/* + * (C) Copyright 2005 + * AMIRIX Systems Inc. + * + * 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 + */ + +#ifndef POWERSPAN_H +#define POWERSPAN_H + +#define CLEAR_MASTER_ABORT 0xdeadbeef +#define NO_DEVICE_FOUND -1 +#define ILLEGAL_REG_OFFSET -2 +#define I2C_BUSY -3 +#define I2C_ERR -4 + +#define REG_P1_CSR 0x004 +#define REGS_P1_BST 0x018 +#define REG_P1_ERR_CSR 0x150 +#define REG_P1_MISC_CSR 0x160 +#define REGS_P1_TGT_CSR 0x100 +#define REGS_P1_TGT_TADDR 0x104 +#define REGS_PB_SLAVE_CSR 0x200 +#define REGS_PB_SLAVE_TADDR 0x204 +#define REGS_PB_SLAVE_BADDR 0x208 +#define REG_CONFIG_ADDRESS 0x290 +#define REG_CONFIG_DATA 0x294 +#define REG_PB_ERR_CSR 0x2B0 +#define REG_PB_MISC_CSR 0x2C0 +#define REG_MISC_CSR 0x400 +#define REG_I2C_CSR 0x408 +#define REG_RESET_CSR 0x40C +#define REG_ISR0 0x410 +#define REG_ISR1 0x414 +#define REG_IER0 0x418 +#define REG_MBOX_MAP 0x420 +#define REG_HW_MAP 0x42C +#define REG_IDR 0x444 + +#define CSR_MEMORY_SPACE_ENABLE 0x00000002 +#define CSR_PCI_MASTER_ENABLE 0x00000004 + +#define P1_BST_OFF 0x04 + +#define PX_ERR_ERR_STATUS 0x01000000 + +#define PX_MISC_CSR_MAX_RETRY_MASK 0x00000F00 +#define PX_MISC_CSR_MAX_RETRY 0x00000F00 +#define PX_MISC_REG_BAR_ENABLE 0x00008000 +#define PB_MISC_TEA_ENABLE 0x00000010 +#define PB_MISC_MAC_TEA 0x00000040 + +#define P1_TGT_IMAGE_OFF 0x010 +#define PX_TGT_CSR_IMG_EN 0x80000000 +#define PX_TGT_CSR_TA_EN 0x40000000 +#define PX_TGT_CSR_BAR_EN 0x20000000 +#define PX_TGT_CSR_MD_EN 0x10000000 +#define PX_TGT_CSR_MODE 0x00800000 +#define PX_TGT_CSR_DEST 0x00400000 +#define PX_TGT_CSR_MEM_IO 0x00200000 +#define PX_TGT_CSR_GBL 0x00080000 +#define PX_TGT_CSR_CL 0x00040000 +#define PX_TGT_CSR_PRKEEP 0x00000080 + +#define PX_TGT_CSR_BS_MASK 0x0F000000 +#define PX_TGT_MEM_IO 0x00200000 +#define PX_TGT_CSR_RTT_MASK 0x001F0000 +#define PX_TGT_CSR_RTT_READ 0x000A0000 +#define PX_TGT_CSR_WTT_MASK 0x00001F00 +#define PX_TGT_CSR_WTT_WFLUSH 0x00000200 +#define PX_TGT_CSR_END_MASK 0x00000060 +#define PX_TGT_CSR_BIG_END 0x00000040 +#define PX_TGT_CSR_TRUE_LEND 0x00000060 +#define PX_TGT_CSR_RDAMT_MASK 0x00000007 + +#define PX_TGT_CSR_BS_64MB 0xa +#define PX_TGT_CSR_BS_16MB 0x8 + +#define PX_TGT_USE_MEM_IO 1 +#define PX_TGT_NOT_MEM_IO 0 + +#define PB_SLAVE_IMAGE_OFF 0x010 +#define PB_SLAVE_CSR_IMG_EN 0x80000000 +#define PB_SLAVE_CSR_TA_EN 0x40000000 +#define PB_SLAVE_CSR_MD_EN 0x20000000 +#define PB_SLAVE_CSR_MODE 0x00800000 +#define PB_SLAVE_CSR_DEST 0x00400000 +#define PB_SLAVE_CSR_MEM_IO 0x00200000 +#define PB_SLAVE_CSR_PRKEEP 0x00000080 + +#define PB_SLAVE_CSR_BS_MASK 0x1F000000 +#define PB_SLAVE_CSR_END_MASK 0x00000060 +#define PB_SLAVE_CSR_BIG_END 0x00000040 +#define PB_SLAVE_CSR_TRUE_LEND 0x00000060 +#define PB_SLAVE_CSR_RDAMT_MASK 0x00000007 + +#define PB_SLAVE_USE_MEM_IO 1 +#define PB_SLAVE_NOT_MEM_IO 0 + + +#define MISC_CSR_PCI1_LOCK 0x00000080 + +#define I2C_CSR_ADDR 0xFF000000 /* Specifies I2C Device Address to be Accessed */ +#define I2C_CSR_DATA 0x00FF0000 /* Specifies the Required Data for a Write */ +#define I2C_CSR_DEV_CODE 0x0000F000 /* Device Select. I2C 4-bit Device Code */ +#define I2C_CSR_CS 0x00000E00 /* Chip Select */ +#define I2C_CSR_RW 0x00000100 /* Read/Write */ +#define I2C_CSR_ACT 0x00000080 /* I2C Interface Active */ +#define I2C_CSR_ERR 0x00000040 /* Error */ + +#define I2C_EEPROM_DEV 0xa +#define I2C_EEPROM_CHIP_SEL 0 + +#define I2C_READ 0 +#define I2C_WRITE 1 + +#define RESET_CSR_EEPROM_LOAD 0x00000010 + +#define ISR_CLEAR_ALL 0xFFFFFFFF + +#define IER0_DMA_INTS_EN 0x0F000000 +#define IER0_PCI_1_EN 0x00400000 +#define IER0_HW_INTS_EN 0x003F0000 +#define IER0_MB_INTS_EN 0x000000FF +#define IER0_DEFAULT (IER0_DMA_INTS_EN | IER0_PCI_1_EN | IER0_HW_INTS_EN | IER0_MB_INTS_EN) + +#define MBOX_MAP_TO_INT4 0xCCCCCCCC + +#define HW_MAP_HW4_TO_INT4 0x000C0000 + +#define IDR_PCI_A_OUT 0x40000000 +#define IDR_MBOX_OUT 0x10000000 + + +int pci_read_config_byte(int bus, int dev, int fn, int reg, unsigned char* val); +int pci_write_config_byte(int bus, int dev, int fn, int reg, unsigned char val); +int pci_read_config_word(int bus, int dev, int fn, int reg, unsigned short* val); +int pci_write_config_word(int bus, int dev, int fn, int reg, unsigned short val); +int pci_read_config_dword(int bus, int dev, int fn, int reg, unsigned long* val); +int pci_write_config_dword(int bus, int dev, int fn, int reg, unsigned long val); + +unsigned int PowerSpanRead(unsigned int theOffset); +void PowerSpanWrite(unsigned int theOffset, unsigned int theValue); + +int I2CAccess(unsigned char theI2CAddress, unsigned char theDevCode, unsigned char theChipSel, unsigned char* theValue, int RWFlag); + +int PCIWriteConfig(int bus, int dev, int fn, int reg, int width, unsigned long val); +int PCIReadConfig(int bus, int dev, int fn, int reg, int width, unsigned long* val); + +int SetSlaveImage(int theImageIndex, unsigned int theBlockSize, int theMemIOFlag, int theEndianness, unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr); +int SetTargetImage(int theImageIndex, unsigned int theBlockSize, int theMemIOFlag, int theEndianness, unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr); + +#endif diff --git a/board/amirix/ap1000/serial.c b/board/amirix/ap1000/serial.c new file mode 100644 index 000000000..431e46961 --- /dev/null +++ b/board/amirix/ap1000/serial.c @@ -0,0 +1,128 @@ +/* + * (C) Copyright 2002 + * Peter De Schrijver (p2@mind.be), Mind Linux Solutions, NV. + * + * 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 +#include +#include +#include +#include + +#include + +#if 0 +#include "serial.h" +#endif + +const NS16550_t COM_PORTS[] = { (NS16550_t) CFG_NS16550_COM1, (NS16550_t) CFG_NS16550_COM2 }; + +#undef CFG_DUART_CHAN +#define CFG_DUART_CHAN gComPort +static int gComPort = 0; + +int +serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; + + (void)NS16550_init(COM_PORTS[0], clock_divisor); + gComPort = 0; + + return 0; + +} + +void +serial_putc(const char c) +{ + if (c == '\n'){ + NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r'); + } + + NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c); +} + +int +serial_getc(void) +{ + return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]); +} + +int +serial_tstc(void) +{ + return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]); +} + +void +serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + NS16550_reinit(COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit(COM_PORTS[1], clock_divisor); +#endif +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void +kgdb_serial_init(void) +{ +} + +void +putDebugChar (int c) +{ + serial_putc (c); +} + +void +putDebugStr (const char *str) +{ + serial_puts (str); +} + +int +getDebugChar (void) +{ + return serial_getc(); +} + +void +kgdb_interruptible (int yes) +{ + return; +} +#endif /* CFG_CMD_KGDB */ diff --git a/board/amirix/ap1000/u-boot.lds b/board/amirix/ap1000/u-boot.lds new file mode 100644 index 000000000..97e8290e4 --- /dev/null +++ b/board/amirix/ap1000/u-boot.lds @@ -0,0 +1,144 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/ppc4xx/start.o (.text) + board/amirix/ap1000/init.o (.text) + cpu/ppc4xx/kgdb.o (.text) + cpu/ppc4xx/traps.o (.text) + cpu/ppc4xx/interrupts.o (.text) + cpu/ppc4xx/serial.o (.text) + cpu/ppc4xx/cpu_init.o (.text) + cpu/ppc4xx/speed.o (.text) + common/dlmalloc.o (.text) + lib_generic/crc32.o (.text) + lib_ppc/extable.o (.text) + lib_generic/zlib.o (.text) + +/* . = env_offset;*/ +/* common/environment.o(.text)*/ + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index 469f97d6f..cbd7b2455 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -381,6 +381,13 @@ ulong get_OPB_freq (void) extern void get_sys_info (sys_info_t * sysInfo); extern ulong get_PCI_freq (void); +#elif defined(CONFIG_AP1000) +void get_sys_info (sys_info_t * sysInfo) { + sysInfo->freqProcessor = 240 * 1000 * 1000; + sysInfo->freqPLB = 80 * 1000 * 1000; + sysInfo->freqPCI = 33 * 1000 * 1000; +} + #elif defined(CONFIG_405) void get_sys_info (sys_info_t * sysInfo) { diff --git a/drivers/e1000.c b/drivers/e1000.c index cc50c2687..787134abf 100644 --- a/drivers/e1000.c +++ b/drivers/e1000.c @@ -112,6 +112,7 @@ static int e1000_detect_gig_phy(struct e1000_hw *hw); readl((a)->hw_addr + E1000_##reg + ((offset) << 2))) #define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);} +#ifndef CONFIG_AP1000 /* remove for warnings */ /****************************************************************************** * Raises the EEPROM's clock input. * @@ -478,6 +479,7 @@ e1000_validate_eeprom_checksum(struct eth_device *nic) return -E1000_ERR_EEPROM; } } +#endif /* #ifndef CONFIG_AP1000 */ /****************************************************************************** * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the @@ -488,6 +490,7 @@ e1000_validate_eeprom_checksum(struct eth_device *nic) static int e1000_read_mac_addr(struct eth_device *nic) { +#ifndef CONFIG_AP1000 struct e1000_hw *hw = nic->priv; uint16_t offset; uint16_t eeprom_data; @@ -509,6 +512,32 @@ e1000_read_mac_addr(struct eth_device *nic) /* Invert the last bit if this is the second device */ nic->enetaddr[5] += 1; } +#else + /* + * The AP1000's e1000 has no eeprom; the MAC address is stored in the + * environment variables. Currently this does not support the addition + * of a PMC e1000 card, which is certainly a possibility, so this should + * be updated to properly use the env variable only for the onboard e1000 + */ + + int ii; + char *s, *e; + + DEBUGFUNC(); + + s = getenv ("ethaddr"); + if (s == NULL){ + return -E1000_ERR_EEPROM; + } + else{ + for(ii = 0; ii < 6; ii++) { + nic->enetaddr[ii] = s ? simple_strtoul (s, &e, 16) : 0; + if (s){ + s = (*e) ? e + 1 : e; + } + } + } +#endif return 0; } @@ -876,6 +905,7 @@ e1000_setup_link(struct eth_device *nic) DEBUGFUNC(); +#ifndef CONFIG_AP1000 /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or @@ -888,6 +918,11 @@ e1000_setup_link(struct eth_device *nic) DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } +#else + /* we have to hardcode the proper value for our hardware. */ + /* this value is for the 82540EM pci card used for prototyping, and it works. */ + eeprom_data = 0xb220; +#endif if (hw->fc == e1000_fc_default) { if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) @@ -2950,12 +2985,14 @@ e1000_initialize(bd_t * bis) free(nic); return 0; } +#ifndef CONFIG_AP1000 if (e1000_validate_eeprom_checksum(nic) < 0) { printf("The EEPROM Checksum Is Not Valid\n"); free(hw); free(nic); return 0; } +#endif e1000_read_mac_addr(nic); E1000_WRITE_REG(hw, PBA, E1000_DEFAULT_PBA); diff --git a/include/configs/AP1000.h b/include/configs/AP1000.h new file mode 100644 index 000000000..d9c4b5bd6 --- /dev/null +++ b/include/configs/AP1000.h @@ -0,0 +1,255 @@ +/* + * AMIRIX.h: AMIRIX specific config options + * + * Author : Frank Smith (smith at amirix dot com) + * + * Derived from : other configuration header files in this tree + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire + * program is licensed under the GPL. + * + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#undef DEBUG + +#define CONFIG_405 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ + +#define CONFIG_AP1000 1 /* ...on an AP1000 board */ + +#define CONFIG_PCI 1 + +#define CFG_HUSH_PARSER 1 /* use "hush" command parser */ +#define CFG_PROMPT "0> " +#define CFG_PROMPT_HUSH_PS2 "> " + +#define CONFIG_COMMAND_EDIT 1 +#define CONFIG_COMMAND_HISTORY 1 +#define CONFIG_COMPLETE_ADDRESSES 1 + +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_FLASH_USE_BUFFER_WRITE + +#ifdef CFG_ENV_IS_IN_NVRAM +#undef CFG_ENV_IS_IN_FLASH +#else +#ifdef CFG_ENV_IS_IN_FLASH +#undef CFG_ENV_IS_IN_NVRAM +#endif +#endif + +#define CONFIG_BAUDRATE 57600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#define CONFIG_BOOTCOMMAND "" /* autoboot command */ + +/* Size (bytes) of interrupt driven serial port buffer. + * Set to 0 to use polling instead of interrupts. + * Setting to 0 will also disable RTS/CTS handshaking. + */ +#undef CONFIG_SERIAL_SOFTWARE_FIFO + +#define CONFIG_BOOTARGS "console=ttyS0,57600" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + + + +#define CONFIG_COMMANDS ( (CONFIG_CMD_DFL & \ + (~CFG_CMD_RTC) & ~(CFG_CMD_I2C)) | \ + CFG_CMD_IRQ | \ + CFG_CMD_PCI | \ + CFG_CMD_DHCP | \ + CFG_CMD_ASKENV | \ + CFG_CMD_ELF | \ + CFG_CMD_PING | \ + CFG_CMD_MVENV \ + ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SYS_CLK_FREQ 30000000 + +#define CONFIG_SPD_EEPROM 1 /* use SPD EEPROM for setup */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +/* usually: (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) */ +#define CFG_PBSIZE (CFG_CBSIZE+4+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_ALT_MEMTEST 1 +#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x01000000 /* 4 ... 16 MB in DRAM */ + +/* + * If CFG_EXT_SERIAL_CLOCK, then the UART divisor is 1. + * If CFG_405_UART_ERRATA_59, then UART divisor is 31. + * Otherwise, UART divisor is determined by CPU Clock and CFG_BASE_BAUD value. + * The Linux BASE_BAUD define should match this configuration. + * baseBaud = cpuClock/(uartDivisor*16) + * If CFG_405_UART_ERRATA_59 and 200MHz CPU clock, + * set Linux BASE_BAUD to 403200. + */ +#undef CFG_EXT_SERIAL_CLOCK /* external serial clock */ +#undef CFG_405_UART_ERRATA_59 /* 405GP/CR Rev. D silicon */ + +#define CFG_NS16550_CLK 40000000 +#define CFG_DUART_CHAN 0 +#define CFG_NS16550_COM1 (0x4C000000 + 0x1000) +#define CFG_NS16550_COM2 (0x4C800000 + 0x1000) +#define CFG_NS16550_REG_SIZE 4 +#define CFG_NS16550 1 +#define CFG_INIT_CHAN1 1 +#define CFG_INIT_CHAN2 0 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400} + +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0x20000000 +#define CFG_MONITOR_BASE TEXT_BASE +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 196 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_FLASH_CFI 1 +#define CFG_PROGFLASH_BASE CFG_FLASH_BASE +#define CFG_CONFFLASH_BASE 0x24000000 + +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_PROTECTION 1 /* use hardware protection */ + +/* BEG ENVIRONNEMENT FLASH */ +#ifdef CFG_ENV_IS_IN_FLASH +#define CFG_ENV_OFFSET 0x00040000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment Sector */ +#define CFG_ENV_SECT_SIZE 0x20000 /* see README - env sector total size */ +#endif +/* END ENVIRONNEMENT FLASH */ +/*----------------------------------------------------------------------- + * NVRAM organization + */ +#define CFG_NVRAM_BASE_ADDR 0xf0000000 /* NVRAM base address */ +#define CFG_NVRAM_SIZE 0x1ff8 /* NVRAM size */ + +#ifdef CFG_ENV_IS_IN_NVRAM +#define CFG_ENV_SIZE 0x1000 /* Size of Environment vars */ +#define CFG_ENV_ADDR \ + (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE) /* Env */ +#endif +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 16384 +#define CFG_CACHELINE_SIZE 32 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM CFG_FLASH_BASE /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0 /* FLASH bank #1 */ + + +/* Configuration Port location */ +#define CONFIG_PORT_ADDR 0xF0000500 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + +#define CFG_INIT_RAM_ADDR 0x400000 /* inside of SDRAM */ +#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Definitions for Serial Presence Detect EEPROM address + * (to get SDRAM settings) + */ +#define SPD_EEPROM_ADDRESS 0x50 + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 230400 /* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ +#endif + +/* JFFS2 stuff */ + +#define CFG_JFFS2_FIRST_BANK 0 +#define CFG_JFFS2_NUM_BANKS 1 +#define CFG_JFFS2_FIRST_SECTOR 1 + +#define CONFIG_NET_MULTI +#define CONFIG_E1000 + +#define CFG_ETH_DEV_FN 0x0800 +#define CFG_ETH_IOBASE 0x31000000 +#define CFG_ETH_MEMBASE 0x32000000 + +#endif /* __CONFIG_H */ diff --git a/net/eth.c b/net/eth.c index aa45b75a5..fe1edd13b 100644 --- a/net/eth.c +++ b/net/eth.c @@ -125,7 +125,7 @@ int eth_initialize(bd_t *bis) #ifdef CONFIG_DB64460 mv6446x_eth_initialize(bis); #endif -#if defined(CONFIG_4xx) && !defined(CONFIG_IOP480) +#if defined(CONFIG_4xx) && !defined(CONFIG_IOP480) && !defined(CONFIG_AP1000) ppc_4xx_eth_initialize(bis); #endif #ifdef CONFIG_INCA_IP_SWITCH