diff options
Diffstat (limited to 'board')
213 files changed, 34036 insertions, 1891 deletions
diff --git a/board/BuS/EB+MCF-EV123/EB+MCF-EV123.c b/board/BuS/EB+MCF-EV123/EB+MCF-EV123.c index f18313d..dcfd83e 100644 --- a/board/BuS/EB+MCF-EV123/EB+MCF-EV123.c +++ b/board/BuS/EB+MCF-EV123/EB+MCF-EV123.c @@ -50,13 +50,13 @@ long int initdram (int board_type) MCFSDRAMC_DACR0 = MCFSDRAMC_DACR_BASE(CFG_SDRAM_BASE0) | MCFSDRAMC_DACR_CASL(1) - | MCFSDRAMC_DACR_CBM(3) + | MCFSDRAMC_DACR_CBM(3) | MCFSDRAMC_DACR_PS_16); MCFSDRAMC_DMR0 = MCFSDRAMC_DMR_BAM_16M | MCFSDRAMC_DMR_V; - MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IP; + MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IP; *(unsigned short *)(CFG_SDRAM_BASE0) = 0xA5A5; MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_RE; @@ -70,10 +70,10 @@ long int initdram (int board_type) #ifdef CFG_SDRAM_BASE1 MCFSDRAMC_DACR1 = MCFSDRAMC_DACR_BASE(CFG_SDRAM_BASE1) | MCFSDRAMC_DACR_CASL(1) - | MCFSDRAMC_DACR_CBM(3) + | MCFSDRAMC_DACR_CBM(3) | MCFSDRAMC_DACR_PS_16; - MCFSDRAMC_DMR1 = MCFSDRAMC_DMR_BAM_16M + MCFSDRAMC_DMR1 = MCFSDRAMC_DMR_BAM_16M | MCFSDRAMC_DMR_V; MCFSDRAMC_DACR1 |= MCFSDRAMC_DACR_IP; @@ -82,7 +82,7 @@ long int initdram (int board_type) MCFSDRAMC_DACR1 |= MCFSDRAMC_DACR_RE; for (i=0; i < 2000; i++) asm(" nop"); - MCFSDRAMC_DACR1 |= MCFSDRAMC_DACR_IMRS; + MCFSDRAMC_DACR1 |= MCFSDRAMC_DACR_IMRS; *(unsigned int *)(CFG_SDRAM_BASE1 + 0x220) = 0xA5A5; size += CFG_SDRAM_SIZE1 * 1024 * 1024; #endif diff --git a/board/BuS/EB+MCF-EV123/VCxK.c b/board/BuS/EB+MCF-EV123/VCxK.c index 4938817..4b46b7c 100644 --- a/board/BuS/EB+MCF-EV123/VCxK.c +++ b/board/BuS/EB+MCF-EV123/VCxK.c @@ -66,7 +66,7 @@ int init_vcxk(void) return 1; } -void vcxk_loadimage(ulong source) +void vcxk_loadimage(ulong source) { int cnt; vcxk_acknowledge_wait(); diff --git a/board/BuS/EB+MCF-EV123/VCxK.h b/board/BuS/EB+MCF-EV123/VCxK.h index 74467ba..f591e5c 100644 --- a/board/BuS/EB+MCF-EV123/VCxK.h +++ b/board/BuS/EB+MCF-EV123/VCxK.h @@ -25,24 +25,24 @@ #define __VCXK_H_ extern int init_vcxk(void); -void vcxk_loadimage(ulong source); +void vcxk_loadimage(ulong source); #define VIDEO_ACKNOWLEDGE_PORT MCFGPTB_GPTPORT -#define VIDEO_ACKNOWLEDGE_DDR MCFGPTB_GPTDDR +#define VIDEO_ACKNOWLEDGE_DDR MCFGPTB_GPTDDR #define VIDEO_ACKNOWLEDGE_PIN 0x0001 -#define VIDEO_ENABLE_PORT MCFGPTB_GPTPORT -#define VIDEO_ENABLE_DDR MCFGPTB_GPTDDR +#define VIDEO_ENABLE_PORT MCFGPTB_GPTPORT +#define VIDEO_ENABLE_DDR MCFGPTB_GPTDDR #define VIDEO_ENABLE_PIN 0x0002 -#define VIDEO_REQUEST_PORT MCFGPTB_GPTPORT -#define VIDEO_REQUEST_DDR MCFGPTB_GPTDDR +#define VIDEO_REQUEST_PORT MCFGPTB_GPTPORT +#define VIDEO_REQUEST_DDR MCFGPTB_GPTDDR #define VIDEO_REQUEST_PIN 0x0004 #define VIDEO_Invert_CFG MCFGPIO_PEPAR #define VIDEO_Invert_IO MCFGPIO_PEPAR_PEPA2 -#define VIDEO_INVERT_PORT MCFGPIO_PORTE -#define VIDEO_INVERT_DDR MCFGPIO_DDRE +#define VIDEO_INVERT_PORT MCFGPIO_PORTE +#define VIDEO_INVERT_DDR MCFGPIO_DDRE #define VIDEO_INVERT_PIN MCFGPIO_PORT2 #endif diff --git a/board/BuS/EB+MCF-EV123/cfm_flash.c b/board/BuS/EB+MCF-EV123/cfm_flash.c index 6ecf0d1..b326384 100644 --- a/board/BuS/EB+MCF-EV123/cfm_flash.c +++ b/board/BuS/EB+MCF-EV123/cfm_flash.c @@ -60,7 +60,7 @@ void cfm_flash_init (flash_info_t * info) MCFCFM_MCR = 0; MCFCFM_CLKD = CFM_CLK; debug ("CFM Clock divider: %ld (%d Hz @ %ld Hz)\n",CFM_CLK,\ - CFG_CLK / (2* ((CFM_CLK & 0x3F)+1) * (1+((CFM_CLK & 0x40)>>6)*7)),\ + CFG_CLK / (2* ((CFM_CLK & 0x3F)+1) * (1+((CFM_CLK & 0x40)>>6)*7)),\ CFG_CLK); MCFCFM_SACC = 0; MCFCFM_DACC = 0; diff --git a/board/BuS/EB+MCF-EV123/flash.c b/board/BuS/EB+MCF-EV123/flash.c index ba76bef..5e2647d 100644 --- a/board/BuS/EB+MCF-EV123/flash.c +++ b/board/BuS/EB+MCF-EV123/flash.c @@ -256,7 +256,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) enable_interrupts (); if (cflag) - icache_enable (); + icache_enable (); return rc; } diff --git a/board/BuS/EB+MCF-EV123/u-boot.lds b/board/BuS/EB+MCF-EV123/u-boot.lds index d790018..ac53245 100644 --- a/board/BuS/EB+MCF-EV123/u-boot.lds +++ b/board/BuS/EB+MCF-EV123/u-boot.lds @@ -34,11 +34,11 @@ SECTIONS .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel.text : { *(.rel.text) } - .rela.text : { *(.rela.text) } + .rela.text : { *(.rela.text) } .rel.data : { *(.rel.data) } - .rela.data : { *(.rela.data) } - .rel.rodata : { *(.rel.rodata) } - .rela.rodata : { *(.rela.rodata) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.ctors : { *(.rel.ctors) } diff --git a/board/LEOX/elpt860/u-boot.lds b/board/LEOX/elpt860/u-boot.lds index b09fc33..214752d 100644 --- a/board/LEOX/elpt860/u-boot.lds +++ b/board/LEOX/elpt860/u-boot.lds @@ -43,11 +43,11 @@ SECTIONS .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel.text : { *(.rel.text) } - .rela.text : { *(.rela.text) } + .rela.text : { *(.rela.text) } .rel.data : { *(.rel.data) } - .rela.data : { *(.rela.data) } - .rel.rodata : { *(.rel.rodata) } - .rela.rodata : { *(.rela.rodata) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.ctors : { *(.rel.ctors) } diff --git a/board/LEOX/elpt860/u-boot.lds.debug b/board/LEOX/elpt860/u-boot.lds.debug index 6f5af91..17f99eb 100644 --- a/board/LEOX/elpt860/u-boot.lds.debug +++ b/board/LEOX/elpt860/u-boot.lds.debug @@ -43,11 +43,11 @@ SECTIONS .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel.text : { *(.rel.text) } - .rela.text : { *(.rela.text) } + .rela.text : { *(.rela.text) } .rel.data : { *(.rel.data) } - .rela.data : { *(.rela.data) } - .rel.rodata : { *(.rel.rodata) } - .rela.rodata : { *(.rela.rodata) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.ctors : { *(.rel.ctors) } diff --git a/board/MAI/AmigaOneG3SE/Makefile b/board/MAI/AmigaOneG3SE/Makefile index cb6ea26..fa28d3b 100644 --- a/board/MAI/AmigaOneG3SE/Makefile +++ b/board/MAI/AmigaOneG3SE/Makefile @@ -30,7 +30,7 @@ endif LIB = $(obj)lib$(BOARD).a COBJS = $(BOARD).o articiaS.o flash.o serial.o smbus.o articiaS_pci.o \ - via686.o i8259.o ../bios_emulator/x86interface.o \ + via686.o i8259.o ../bios_emulator/x86interface.o \ ../bios_emulator/bios.o ../bios_emulator/glue.o \ interrupts.o ps2kbd.o video.o usb_uhci.o enet.o \ ../menu/cmd_menu.o cmd_boota.o nvram.o diff --git a/board/MAI/AmigaOneG3SE/articiaS_pci.c b/board/MAI/AmigaOneG3SE/articiaS_pci.c index 480dae5..45b8195 100644 --- a/board/MAI/AmigaOneG3SE/articiaS_pci.c +++ b/board/MAI/AmigaOneG3SE/articiaS_pci.c @@ -368,11 +368,11 @@ void articiaS_pci_init (void) if (articiaS_init_vga() == -1) { /* If the VGA didn't init and we have stdout set to VGA, reset to serial */ -/* s = getenv("stdout"); */ -/* if (s && strcmp(s, "vga") == 0) */ -/* { */ -/* setenv("stdout", "serial"); */ -/* } */ +/* s = getenv("stdout"); */ +/* if (s && strcmp(s, "vga") == 0) */ +/* { */ +/* setenv("stdout", "serial"); */ +/* } */ } } pci_write_config_byte(PCI_BDF(0,1,0), PCI_INTERRUPT_LINE, 0xFF); diff --git a/board/MAI/AmigaOneG3SE/enet.c b/board/MAI/AmigaOneG3SE/enet.c index d4be889..ad2bcde 100644 --- a/board/MAI/AmigaOneG3SE/enet.c +++ b/board/MAI/AmigaOneG3SE/enet.c @@ -41,57 +41,57 @@ /* 3Com Commands, top 5 bits are command and bottom 11 bits are parameters */ -#define TotalReset (0<<11) -#define SelectWindow (1<<11) -#define StartCoax (2<<11) -#define RxDisable (3<<11) -#define RxEnable (4<<11) -#define RxReset (5<<11) -#define UpStall (6<<11) -#define UpUnstall (6<<11)+1 -#define DownStall (6<<11)+2 -#define DownUnstall (6<<11)+3 -#define RxDiscard (8<<11) -#define TxEnable (9<<11) -#define TxDisable (10<<11) -#define TxReset (11<<11) -#define FakeIntr (12<<11) -#define AckIntr (13<<11) -#define SetIntrEnb (14<<11) -#define SetStatusEnb (15<<11) -#define SetRxFilter (16<<11) -#define SetRxThreshold (17<<11) -#define SetTxThreshold (18<<11) -#define SetTxStart (19<<11) -#define StartDMAUp (20<<11) -#define StartDMADown (20<<11)+1 +#define TotalReset (0<<11) +#define SelectWindow (1<<11) +#define StartCoax (2<<11) +#define RxDisable (3<<11) +#define RxEnable (4<<11) +#define RxReset (5<<11) +#define UpStall (6<<11) +#define UpUnstall (6<<11)+1 +#define DownStall (6<<11)+2 +#define DownUnstall (6<<11)+3 +#define RxDiscard (8<<11) +#define TxEnable (9<<11) +#define TxDisable (10<<11) +#define TxReset (11<<11) +#define FakeIntr (12<<11) +#define AckIntr (13<<11) +#define SetIntrEnb (14<<11) +#define SetStatusEnb (15<<11) +#define SetRxFilter (16<<11) +#define SetRxThreshold (17<<11) +#define SetTxThreshold (18<<11) +#define SetTxStart (19<<11) +#define StartDMAUp (20<<11) +#define StartDMADown (20<<11)+1 #define StatsEnable (21<<11) #define StatsDisable (22<<11) -#define StopCoax (23<<11) -#define SetFilterBit (25<<11) +#define StopCoax (23<<11) +#define SetFilterBit (25<<11) /* The SetRxFilter command accepts the following classes */ -#define RxStation 1 +#define RxStation 1 #define RxMulticast 2 #define RxBroadcast 4 -#define RxProm 8 +#define RxProm 8 /* 3Com status word defnitions */ -#define IntLatch 0x0001 -#define HostError 0x0002 -#define TxComplete 0x0004 -#define TxAvailable 0x0008 -#define RxComplete 0x0010 -#define RxEarly 0x0020 -#define IntReq 0x0040 -#define StatsFull 0x0080 -#define DMADone (1<<8) -#define DownComplete (1<<9) -#define UpComplete (1<<10) -#define DMAInProgress (1<<11) /* DMA controller is still busy.*/ -#define CmdInProgress (1<<12) /* EL3_CMD is still busy.*/ +#define IntLatch 0x0001 +#define HostError 0x0002 +#define TxComplete 0x0004 +#define TxAvailable 0x0008 +#define RxComplete 0x0010 +#define RxEarly 0x0020 +#define IntReq 0x0040 +#define StatsFull 0x0080 +#define DMADone (1<<8) +#define DownComplete (1<<9) +#define UpComplete (1<<10) +#define DMAInProgress (1<<11) /* DMA controller is still busy.*/ +#define CmdInProgress (1<<12) /* EL3_CMD is still busy.*/ /* Polling Registers */ @@ -100,17 +100,17 @@ /* Register window 0 offets */ -#define Wn0EepromCmd 10 /* Window 0: EEPROM command register. */ -#define Wn0EepromData 12 /* Window 0: EEPROM results register. */ +#define Wn0EepromCmd 10 /* Window 0: EEPROM command register. */ +#define Wn0EepromData 12 /* Window 0: EEPROM results register. */ #define IntrStatus 0x0E /* Valid in all windows. */ /* Register window 0 EEPROM bits */ -#define EEPROM_Read 0x80 -#define EEPROM_WRITE 0x40 -#define EEPROM_ERASE 0xC0 -#define EEPROM_EWENB 0x30 /* Enable erasing/writing for 10 msec. */ -#define EEPROM_EWDIS 0x00 /* Disable EWENB before 10 msec timeout. */ +#define EEPROM_Read 0x80 +#define EEPROM_WRITE 0x40 +#define EEPROM_ERASE 0xC0 +#define EEPROM_EWENB 0x30 /* Enable erasing/writing for 10 msec. */ +#define EEPROM_EWDIS 0x00 /* Disable EWENB before 10 msec timeout. */ /* EEPROM locations. */ @@ -129,13 +129,13 @@ /* Register window 1 offsets, the window used in normal operation */ -#define TX_FIFO 0x10 -#define RX_FIFO 0x10 -#define RxErrors 0x14 -#define RxStatus 0x18 +#define TX_FIFO 0x10 +#define RX_FIFOa 0x10 +#define RxErrors 0x14 +#define RxStatus 0x18 #define Timer 0x1A -#define TxStatus 0x1B -#define TxFree 0x1C /* Remaining free bytes in Tx buffer. */ +#define TxStatus 0x1B +#define TxFree 0x1C /* Remaining free bytes in Tx buffer. */ /* Register Window 2 */ @@ -147,47 +147,47 @@ #define Wn3_MAC_Ctrl 6 #define Wn3_Options 8 -#define BFEXT(value, offset, bitcount) \ +#define BFEXT(value, offset, bitcount) \ ((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1)) #define BFINS(lhs, rhs, offset, bitcount) \ - (((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) | \ + (((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) | \ (((rhs) & ((1 << (bitcount)) - 1)) << (offset))) #define RAM_SIZE(v) BFEXT(v, 0, 3) -#define RAM_WIDTH(v) BFEXT(v, 3, 1) -#define RAM_SPEED(v) BFEXT(v, 4, 2) +#define RAM_WIDTH(v) BFEXT(v, 3, 1) +#define RAM_SPEED(v) BFEXT(v, 4, 2) #define ROM_SIZE(v) BFEXT(v, 6, 2) -#define RAM_SPLIT(v) BFEXT(v, 16, 2) +#define RAM_SPLIT(v) BFEXT(v, 16, 2) #define XCVR(v) BFEXT(v, 20, 4) -#define AUTOSELECT(v) BFEXT(v, 24, 1) +#define AUTOSELECT(v) BFEXT(v, 24, 1) /* Register Window 4: Xcvr/media bits */ -#define Wn4_FIFODiag 4 -#define Wn4_NetDiag 6 +#define Wn4_FIFODiag 4 +#define Wn4_NetDiag 6 #define Wn4_PhysicalMgmt 8 -#define Wn4_Media 10 +#define Wn4_Media 10 -#define Media_SQE 0x0008 /* Enable SQE error counting for AUI. */ -#define Media_10TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ -#define Media_Lnk 0x0080 /* Enable just link beat for 100TX/100FX. */ -#define Media_LnkBeat 0x0800 +#define Media_SQE 0x0008 /* Enable SQE error counting for AUI. */ +#define Media_10TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ +#define Media_Lnk 0x0080 /* Enable just link beat for 100TX/100FX. */ +#define Media_LnkBeat 0x0800 /* Register Window 7: Bus Master control */ -#define Wn7_MasterAddr 0 -#define Wn7_MasterLen 6 -#define Wn7_MasterStatus 12 +#define Wn7_MasterAddr 0 +#define Wn7_MasterLen 6 +#define Wn7_MasterStatus 12 /* Boomerang bus master control registers. */ -#define PktStatus 0x20 +#define PktStatus 0x20 #define DownListPtr 0x24 -#define FragAddr 0x28 -#define FragLen 0x2c +#define FragAddr 0x28 +#define FragLen 0x2c #define TxFreeThreshold 0x2f -#define UpPktStatus 0x30 +#define UpPktStatus 0x30 #define UpListPtr 0x38 /* The Rx and Tx descriptor lists. */ diff --git a/board/amcc/acadia/Makefile b/board/amcc/acadia/Makefile new file mode 100644 index 0000000..183f694 --- /dev/null +++ b/board/amcc/acadia/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2007 +# 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 cpr.o memory.o +SOBJS = + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +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/amcc/acadia/acadia.c b/board/amcc/acadia/acadia.c new file mode 100644 index 0000000..c8aaad2 --- /dev/null +++ b/board/amcc/acadia/acadia.c @@ -0,0 +1,152 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <asm/processor.h> + +extern void board_pll_init_f(void); + +/* Some specific Acadia Defines */ +#define CPLD_BASE 0x80000000 + +void liveoak_gpio_init(void) +{ + /* + * GPIO0 setup (select GPIO or alternate function) + */ + out32(GPIO0_OSRL, CFG_GPIO0_OSRL); + out32(GPIO0_OSRH, CFG_GPIO0_OSRH); /* output select */ + out32(GPIO0_ISR1L, CFG_GPIO0_ISR1L); + out32(GPIO0_ISR1H, CFG_GPIO0_ISR1H); /* input select */ + out32(GPIO0_TSRL, CFG_GPIO0_TSRL); + out32(GPIO0_TSRH, CFG_GPIO0_TSRH); /* three-state select */ + out32(GPIO0_TCR, CFG_GPIO0_TCR); /* enable output driver for outputs */ + + /* + * Ultra (405EZ) was nice enough to add another GPIO controller + */ + out32(GPIO1_OSRH, CFG_GPIO1_OSRH); /* output select */ + out32(GPIO1_OSRL, CFG_GPIO1_OSRL); + out32(GPIO1_ISR1H, CFG_GPIO1_ISR1H); /* input select */ + out32(GPIO1_ISR1L, CFG_GPIO1_ISR1L); + out32(GPIO1_TSRH, CFG_GPIO1_TSRH); /* three-state select */ + out32(GPIO1_TSRL, CFG_GPIO1_TSRL); + out32(GPIO1_TCR, CFG_GPIO1_TCR); /* enable output driver for outputs */ +} + +#if 0 /* test-only: not called at all??? */ +void ext_bus_cntlr_init(void) +{ +#if (defined(EBC_PB4AP) && defined(EBC_PB4CR) && !(CFG_INIT_DCACHE_CS == 4)) + mtebc(pb4ap, EBC_PB4AP); + mtebc(pb4cr, EBC_PB4CR); +#endif +} +#endif + +int board_early_init_f(void) +{ + unsigned int reg; + +#if 0 /* test-only */ + /* + * If CRAM memory and SPI/NAND boot, and if the CRAM memory is + * already initialized by the pre-loader then we can't reinitialize + * CPR registers, GPIO registers and EBC registers as this will + * have the effect of un-initializing CRAM. + */ + spr_reg = (volatile unsigned long) mfspr(SPRG7); + if (spr_reg != LOAK_CRAM) { /* != CRAM */ + board_pll_init_f(); + liveoak_gpio_init(); + ext_bus_cntlr_init(); + + mtebc(pb1ap, CFG_EBC_PB1AP); + mtebc(pb1cr, CFG_EBC_PB1CR); + + mtebc(pb2ap, CFG_EBC_PB2AP); + mtebc(pb2cr, CFG_EBC_PB2CR); + } +#else + board_pll_init_f(); + liveoak_gpio_init(); +/* ext_bus_cntlr_init(); */ +#endif + +#if 0 /* test-only (orig) */ + /* + * If we boot from NAND Flash, we are running in + * RAM, so disable the EBC_CS0 so that it goes back + * to the NOR Flash. It will be enabled later + * for the NAND Flash on EBC_CS1 + */ + mfsdr(sdrultra0, reg); + mtsdr(sdrultra0, reg & ~SDR_ULTRA0_CSNSEL0); +#endif +#if 0 /* test-only */ + /* configure for NAND */ + mfsdr(sdrultra0, reg); + reg &= ~SDR_ULTRA0_CSN_MASK; + reg |= SDR_ULTRA0_CSNSEL0 >> CFG_NAND_CS; + mtsdr(sdrultra0, reg & ~SDR_ULTRA0_CSNSEL0); +#endif + + /* USB Host core needs this bit set */ + mfsdr(sdrultra1, reg); + mtsdr(sdrultra1, reg | SDR_ULTRA1_LEDNENABLE); + + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr(uicer, 0x00000000); /* disable all ints */ + mtdcr(uiccr, 0x00000010); + mtdcr(uicpr, 0xFE7FFFF0); /* set int polarities */ + mtdcr(uictr, 0x00000010); /* set int trigger levels */ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + + return 0; +} + +int misc_init_f(void) +{ + /* Set EPLD to take PHY out of reset */ + out8(CPLD_BASE + 0x05, 0x00); + udelay(100000); + + return 0; +} + +/* + * Check Board Identity: + */ +int checkboard(void) +{ + char *s = getenv("serial#"); + + printf("Board: Acadia - AMCC PPC405EZ Evaluation Board"); + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} diff --git a/board/amcc/acadia/config.mk b/board/amcc/acadia/config.mk new file mode 100644 index 0000000..ce21374 --- /dev/null +++ b/board/amcc/acadia/config.mk @@ -0,0 +1,41 @@ +# +# (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 +# + +sinclude $(TOPDIR)/board/amcc/liveoak/config.tmp + +ifndef TEXT_BASE +TEXT_BASE = 0xFFFC0000 +endif + +ifeq ($(CONFIG_NAND_U_BOOT),y) +LDSCRIPT = $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds +endif + +ifeq ($(CONFIG_SPI_U_BOOT),y) +LDSCRIPT = $(TOPDIR)/board/$(BOARDDIR)/u-boot-spi.lds +PAD_TO = 0x00840000 +endif + +ifeq ($(debug),1) +PLATFORM_CPPFLAGS += -DDEBUG +endif diff --git a/board/amcc/acadia/cpr.c b/board/amcc/acadia/cpr.c new file mode 100644 index 0000000..23b9e12 --- /dev/null +++ b/board/amcc/acadia/cpr.c @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <asm/processor.h> +#include <ppc405.h> + +/* test-only: move into cpu directory!!! */ + +#if defined(PLLMR0_200_133_66) +void board_pll_init_f(void) +{ + /* + * set PLL clocks based on input sysclk is 33M + * + * ---------------------------------- + * | CLK | FREQ (MHz) | DIV RATIO | + * ---------------------------------- + * | CPU | 200.0 | 4 (0x02)| + * | PLB | 133.3 | 6 (0x06)| + * | OPB | 66.6 | 12 (0x0C)| + * | EBC | 66.6 | 12 (0x0C)| + * | SPI | 66.6 | 12 (0x0C)| + * | UART0 | 10.0 | 40 (0x28)| + * | UART1 | 10.0 | 40 (0x28)| + * | DAC | 2.0 | 200 (0xC8)| + * | ADC | 2.0 | 200 (0xC8)| + * | PWM | 100.0 | 4 (0x04)| + * | EMAC | 25.0 | 16 (0x10)| + * ----------------------------------- + */ + + /* Initialize PLL */ + mtcpr(cprpllc, 0x0000033c); + mtcpr(cprplld, 0x0c010200); + mtcpr(cprprimad, 0x04060c0c); + mtcpr(cprperd0, 0x000c0000); /* SPI clk div. eq. OPB clk div. */ + mtcpr(cprclkupd, 0x40000000); +} + +#elif defined(PLLMR0_266_160_80) + +void board_pll_init_f(void) +{ + /* + * set PLL clocks based on input sysclk is 33M + * + * ---------------------------------- + * | CLK | FREQ (MHz) | DIV RATIO | + * ---------------------------------- + * | CPU | 266.64 | 3 | + * | PLB | 159.98 | 5 (0x05)| + * | OPB | 79.99 | 10 (0x0A)| + * | EBC | 79.99 | 10 (0x0A)| + * | SPI | 79.99 | 10 (0x0A)| + * | UART0 | 28.57 | 7 (0x07)| + * | UART1 | 28.57 | 7 (0x07)| + * | DAC | 28.57 | 7 (0xA7)| + * | ADC | 4 | 50 (0x32)| + * | PWM | 28.57 | 7 (0x07)| + * | EMAC | 4 | 50 (0x32)| + * ----------------------------------- + */ + + /* Initialize PLL */ + mtcpr(cprpllc, 0x20000238); + mtcpr(cprplld, 0x03010400); + mtcpr(cprprimad, 0x03050a0a); + mtcpr(cprperc0, 0x00000000); + mtcpr(cprperd0, 0x070a0707); /* SPI clk div. eq. OPB clk div. */ + mtcpr(cprperd1, 0x07323200); + mtcpr(cprclkupd, 0x40000000); +} + +#elif defined(PLLMR0_333_166_83) + +void board_pll_init_f(void) +{ + /* + * set PLL clocks based on input sysclk is 33M + * + * ---------------------------------- + * | CLK | FREQ (MHz) | DIV RATIO | + * ---------------------------------- + * | CPU | 333.33 | 2 | + * | PLB | 166.66 | 4 (0x04)| + * | OPB | 83.33 | 8 (0x08)| + * | EBC | 83.33 | 8 (0x08)| + * | SPI | 83.33 | 8 (0x08)| + * | UART0 | 16.66 | 5 (0x05)| + * | UART1 | 16.66 | 5 (0x05)| + * | DAC | ???? | 166 (0xA6)| + * | ADC | ???? | 166 (0xA6)| + * | PWM | 41.66 | 3 (0x03)| + * | EMAC | ???? | 3 (0x03)| + * ----------------------------------- + */ + + /* Initialize PLL */ + mtcpr(cprpllc, 0x0000033C); + mtcpr(cprplld, 0x0a010000); + mtcpr(cprprimad, 0x02040808); + mtcpr(cprperd0, 0x02080505); /* SPI clk div. eq. OPB clk div. */ + mtcpr(cprperd1, 0xA6A60300); + mtcpr(cprclkupd, 0x40000000); +} + +#elif defined(PLLMR0_100_100_12) + +void board_pll_init_f(void) +{ + /* + * set PLL clocks based on input sysclk is 33M + * + * ---------------------- + * | CLK | FREQ (MHz) | + * ---------------------- + * | CPU | 100.00 | + * | PLB | 100.00 | + * | OPB | 12.00 | + * | EBC | 49.00 | + * ---------------------- + */ + + /* Initialize PLL */ + mtcpr(cprpllc, 0x000003BC); + mtcpr(cprplld, 0x06060600); + mtcpr(cprprimad, 0x02020004); + mtcpr(cprperd0, 0x04002828); /* SPI clk div. eq. OPB clk div. */ + mtcpr(cprperd1, 0xC8C81600); + mtcpr(cprclkupd, 0x40000000); +} +#endif /* CPU_<speed>_405EZ */ + +#if defined(CONFIG_NAND_SPL) || defined(CONFIG_SPI_SPL) +/* + * Get timebase clock frequency + */ +unsigned long get_tbclk (void) +{ + unsigned long cpr_plld; + unsigned long cpr_primad; + unsigned long primad_cpudv; + unsigned long pllFbkDiv; + unsigned long freqProcessor; + + /* + * Read PLL Mode registers + */ + mfcpr(cprplld, cpr_plld); + + /* + * Read CPR_PRIMAD register + */ + mfcpr(cprprimad, cpr_primad); + + /* + * Determine CPU clock frequency + */ + primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24); + if (primad_cpudv == 0) + primad_cpudv = 16; + + /* + * Determine FBK_DIV. + */ + pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24); + if (pllFbkDiv == 0) + pllFbkDiv = 256; + + freqProcessor = (CONFIG_SYS_CLK_FREQ * pllFbkDiv) / primad_cpudv; + + return (freqProcessor); +} +#endif /* defined(CONFIG_NAND_SPL) || defined(CONFIG_SPI_SPL) */ diff --git a/board/amcc/acadia/flash.c b/board/amcc/acadia/flash.c new file mode 100644 index 0000000..0626aba --- /dev/null +++ b/board/amcc/acadia/flash.c @@ -0,0 +1,1108 @@ +/* + * (C) Copyright 2004-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 Jun Gu <jung@artesyncp.com> + * Add support for Am29F016D and dynamic switch setting. + * + * 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 + */ + +/* + * Modified 4/5/2001 + * Wait for completion of each sector erase command issued + * 4/5/2001 + * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +#ifdef DEBUG +#define DEBUGF(x...) printf(x) +#else +#define DEBUGF(x...) +#endif /* DEBUG */ + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* + * Mark big flash bank (16 bit instead of 8 bit access) in address with bit 0 + */ +static unsigned long flash_addr_table[][CFG_MAX_FLASH_BANKS] = { + {0xffc00001}, /* 0:boot from big flash */ +}; + +/* + * include common flash code (for amcc boards) + */ +/*----------------------------------------------------------------------- + * Functions + */ +static int write_word(flash_info_t * info, ulong dest, ulong data); +#ifdef CFG_FLASH_2ND_16BIT_DEV +static int write_word_1(flash_info_t * info, ulong dest, ulong data); +static int write_word_2(flash_info_t * info, ulong dest, ulong data); +static int flash_erase_1(flash_info_t * info, int s_first, int s_last); +static int flash_erase_2(flash_info_t * info, int s_first, int s_last); +static ulong flash_get_size_1(vu_long * addr, flash_info_t * info); +static ulong flash_get_size_2(vu_long * addr, flash_info_t * info); +#endif + +void flash_print_info(flash_info_t * info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + if (info->flash_id == FLASH_UNKNOWN) { + printf("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: + printf("AMD "); + break; + case FLASH_MAN_STM: + printf("STM "); + break; + case FLASH_MAN_FUJ: + printf("FUJITSU "); + break; + case FLASH_MAN_SST: + printf("SST "); + break; + case FLASH_MAN_MX: + printf("MIXC "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + printf("AM29F040 (512 Kbit, uniform sector size)\n"); + break; + case FLASH_AM400B: + printf("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: + printf("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: + printf("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: + printf("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AMD016: + printf("AM29F016D (16 Mbit, uniform sector size)\n"); + break; + case FLASH_AM160B: + printf("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: + printf("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: + printf("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: + printf("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_AM033C: + printf("AM29LV033C (32 Mbit, top boot sector)\n"); + break; + case FLASH_SST800A: + printf("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + break; + case FLASH_SST160A: + printf("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + break; + case FLASH_STMW320DT: + printf ("M29W320DT (32 M, top sector)\n"); + break; + case FLASH_MXLV320T: + printf ("MXLV320T (32 Mbit, top sector)\n"); + break; + default: + printf("Unknown Chip Type\n"); + break; + } + + printf(" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf(" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count - 1)) + size = info->start[i + 1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k = 0; k < size; k++) { + if (*flash++ != 0xffffffff) { + erased = 0; + break; + } + } + + if ((i % 5) == 0) + printf("\n "); + printf(" %08lX%s%s", + info->start[i], + erased ? " E" : " ", info->protect[i] ? "RO " : " "); + } + printf("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ +#ifdef CFG_FLASH_2ND_16BIT_DEV +static ulong flash_get_size(vu_long * addr, flash_info_t * info) +{ + /* bit 0 used for big flash marking */ + if ((ulong)addr & 0x1) { + return flash_get_size_2((vu_long *)((ulong)addr & 0xfffffffe), info); + } else { + return flash_get_size_1(addr, info); + } +} + +static ulong flash_get_size_1(vu_long * addr, flash_info_t * info) +#else +static ulong flash_get_size(vu_long * addr, flash_info_t * info) +#endif +{ + short i; + CFG_FLASH_WORD_SIZE value; + ulong base = (ulong) addr; + volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) addr; + + DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr); + + /* Write auto select command: read Manufacturer ID */ + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00900090; + udelay(1000); + + value = addr2[0]; + DEBUGF("FLASH MANUFACT: %x\n", value); + + switch (value) { + case (CFG_FLASH_WORD_SIZE) AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (CFG_FLASH_WORD_SIZE) FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (CFG_FLASH_WORD_SIZE) SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + case (CFG_FLASH_WORD_SIZE) STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr2[1]; /* device ID */ + DEBUGF("\nFLASH DEVICEID: %x\n", value); + + switch (value) { + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + + case (CFG_FLASH_WORD_SIZE) AMD_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + + case (CFG_FLASH_WORD_SIZE) STM_ID_M29W040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + + case (CFG_FLASH_WORD_SIZE) AMD_ID_F016D: + info->flash_id += FLASH_AMD016; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV033C: + info->flash_id += FLASH_AMDLV033C; + info->sector_count = 64; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (CFG_FLASH_WORD_SIZE) AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + } + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMD016)) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = + base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]); + + /* For AMD29033C flash we need to resend the command of * + * reading flash protection for upper 8 Mb of flash */ + if (i == 32) { + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xAAAAAAAA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x55555555; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x90909090; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; + } + + /* issue bank reset to return to read mode */ + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00F000F0; + + return (info->size); +} + +static int wait_for_DQ7_1(flash_info_t * info, int sect) +{ + ulong start, now, last; + volatile CFG_FLASH_WORD_SIZE *addr = + (CFG_FLASH_WORD_SIZE *) (info->start[sect]); + + start = get_timer(0); + last = start; + while ((addr[0] & (CFG_FLASH_WORD_SIZE) 0x00800080) != + (CFG_FLASH_WORD_SIZE) 0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf("Timeout\n"); + return -1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc('.'); + last = now; + } + } + return 0; +} + +#ifdef CFG_FLASH_2ND_16BIT_DEV +int flash_erase(flash_info_t * info, int s_first, int s_last) +{ + if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_MXLV320T)) { + return flash_erase_2(info, s_first, s_last); + } else { + return flash_erase_1(info, s_first, s_last); + } +} + +static int flash_erase_1(flash_info_t * info, int s_first, int s_last) +#else +int flash_erase(flash_info_t * info, int s_first, int s_last) +#endif +{ + volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *) (info->start[0]); + volatile CFG_FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect; + int i; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf("- missing\n"); + } else { + printf("- no sectors to erase\n"); + } + return 1; + } + + if (info->flash_id == FLASH_UNKNOWN) { + printf("Can't erase unknown flash type - aborted\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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[sect]); + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00500050; /* block erase */ + for (i = 0; i < 50; i++) + udelay(1000); /* wait 1 ms */ + } else { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00300030; /* sector erase */ + } + l_sect = sect; + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + wait_for_DQ7_1(info, sect); + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay(1000); + + /* reset to read mode */ + addr = (CFG_FLASH_WORD_SIZE *) info->start[0]; + addr[0] = (CFG_FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */ + + printf(" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * 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 cp, wp, data; + int i, l, rc; + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < 4 && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < 4; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i = 0; i < 4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < 4; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +#ifdef CFG_FLASH_2ND_16BIT_DEV +static int write_word(flash_info_t * info, ulong dest, ulong data) +{ + if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_MXLV320T)) { + return write_word_2(info, dest, data); + } else { + return write_word_1(info, dest, data); + } +} + +static int write_word_1(flash_info_t * info, ulong dest, ulong data) +#else +static int write_word(flash_info_t * info, ulong dest, ulong data) +#endif +{ + volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[0]); + volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *) dest; + volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *) & data; + ulong start; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + + for (i = 0; i < 4 / sizeof(CFG_FLASH_WORD_SIZE); i++) { + int flag; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00A000A0; + + dest2[i] = data2[i]; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer(0); + while ((dest2[i] & (CFG_FLASH_WORD_SIZE) 0x00800080) != + (data2[i] & (CFG_FLASH_WORD_SIZE) 0x00800080)) { + + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + + return (0); +} + +#ifdef CFG_FLASH_2ND_16BIT_DEV + +#undef CFG_FLASH_WORD_SIZE +#define CFG_FLASH_WORD_SIZE unsigned short + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size_2(vu_long * addr, flash_info_t * info) +{ + short i; + int n; + CFG_FLASH_WORD_SIZE value; + ulong base = (ulong) addr; + volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) addr; + + DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr); + + /* issue bank reset to return to read mode */ + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00F000F0; + /* Write auto select command: read Manufacturer ID */ + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00900090; + udelay(1000); + + value = addr2[0]; + DEBUGF("FLASH MANUFACT: %x\n", value); + +#if 0 /* TODO: remove ifdef when Flash responds correctly */ + switch (value) { + case (CFG_FLASH_WORD_SIZE) AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (CFG_FLASH_WORD_SIZE) FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (CFG_FLASH_WORD_SIZE) SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + case (CFG_FLASH_WORD_SIZE) STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + case (CFG_FLASH_WORD_SIZE) MX_MANUFACT: + info->flash_id = FLASH_MAN_MX; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } +#endif /* TODO: remove ifdef when Flash responds correctly */ + + /* + * TODO: Start + * uncomment block above when Flash responds correctly. + * also remove the lines below: + */ + info->flash_id = FLASH_MAN_AMD; + DEBUGF("FLASH MANUFACT: FLASH_MAN_AMD\n"); + /* TODO: End */ + + value = addr2[1]; /* device ID */ + + DEBUGF("\nFLASH DEVICEID: %x\n", value); + +#if 0 /* TODO: remove ifdef when Flash responds correctly */ + switch (value) { + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)STM_ID_29W320DT: + info->flash_id += FLASH_STMW320DT; + info->sector_count = 67; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)MX_ID_LV320T: + info->flash_id += FLASH_MXLV320T; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + } +#endif /* TODO: remove ifdef when Flash responds correctly */ + + /* + * TODO: Start + * uncomment block above when Flash responds correctly. + * also remove the lines below: + */ + DEBUGF("\nFLASH DEVICEID: FLASH_AM320T\n"); + info->flash_id += FLASH_AM320T; + info->sector_count = 71; + info->size = 0x00400000; /* => 4 MB */ + /* TODO: End */ + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMD016)) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) { + /* set sector offsets for top boot block type */ + base += info->size; + i = info->sector_count; + /* 1 x 16k boot sector */ + base -= 16 << 10; + --i; + info->start[i] = base; + /* 2 x 8k boot sectors */ + for (n=0; n<2; ++n) { + base -= 8 << 10; + --i; + info->start[i] = base; + } + /* 1 x 32k boot sector */ + base -= 32 << 10; + --i; + info->start[i] = base; + + while (i > 0) { /* 64k regular sectors */ + base -= 64 << 10; + --i; + info->start[i] = base; + } + } else if ( ((info->flash_id & FLASH_TYPEMASK) == FLASH_MXLV320T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ) { + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00002000; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000a000; + info->start[i--] = base + info->size - 0x0000c000; + info->start[i--] = base + info->size - 0x0000e000; + info->start[i--] = base + info->size - 0x00010000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + else { + if (info->flash_id & FLASH_BTYPE){ + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = + base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address,(A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]); + + /* For AMD29033C flash we need to resend the command of * + * reading flash protection for upper 8 Mb of flash */ + if (i == 32) { + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xAAAAAAAA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x55555555; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x90909090; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; + } + + /* issue bank reset to return to read mode */ + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00F000F0; + + return (info->size); +} + +/* + * TODO: FIX: this wait loop sometimes fails: DQ7 indicates the erase command + * never was accepted (i.e. didn't start) - why???? + */ +static int wait_for_DQ7_2(flash_info_t * info, int sect) +{ + ulong start, now, last, counter = 0; + volatile CFG_FLASH_WORD_SIZE *addr = + (CFG_FLASH_WORD_SIZE *) (info->start[sect]); + + start = get_timer(0); + DEBUGF("DQ7_2: start = 0x%08lx\n", start); + last = start; + while ((addr[0] & (CFG_FLASH_WORD_SIZE) 0x00800080) != + (CFG_FLASH_WORD_SIZE) 0x00800080) { + DEBUGF("DQ7_2: start = 0x%08lx, now = 0x%08lx\n", start, now); + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf("Timeout\n"); + return -1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc('.'); + last = now; + } + udelay(1000000); /* 1 sec */ + putc('.'); + counter++; + if (counter > 5) { + return -1; + } + DEBUGF("DQ7_2: now = 0x%08lx, last = 0x%08lx\n", now, last); + } + return 0; +} + +static void wr_flash_cmd(ulong sector, ushort addr, CFG_FLASH_WORD_SIZE value) +{ + int fw_size; + + fw_size = sizeof(value); + switch (fw_size) + { + case 1: + out8((ulong)(sector + addr), value); + break; + case 2: + out16((ulong)(sector + (addr << 1)), value); + break; + default: + printf("flash_erase: error incorrect chip programing size.\n"); + } + return; +} + +static int flash_erase_2(flash_info_t * info, int s_first, int s_last) +{ + volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *) (info->start[0]); + volatile CFG_FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect, count = 0; + int i; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf("- missing\n"); + } else { + printf("- no sectors to erase\n"); + } + return 1; + } + + if (info->flash_id == FLASH_UNKNOWN) { + printf("Can't erase unknown flash type - aborted\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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first, count = 0; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[sect]); + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00500050; /* block erase */ + for (i = 0; i < 50; i++) + udelay(1000); /* wait 1 ms */ + } else { + /* + * TODO: fix code + */ + wr_flash_cmd((ulong)addr, 0, (CFG_FLASH_WORD_SIZE) 0x00F000F0); + wr_flash_cmd((ulong)addr, CFG_FLASH_ADDR0, (CFG_FLASH_WORD_SIZE) 0x00AA00AA); + wr_flash_cmd((ulong)addr, CFG_FLASH_ADDR1, (CFG_FLASH_WORD_SIZE) 0x00550055); + wr_flash_cmd((ulong)addr, CFG_FLASH_ADDR0, (CFG_FLASH_WORD_SIZE) 0x00800080); + wr_flash_cmd((ulong)addr, CFG_FLASH_ADDR0, (CFG_FLASH_WORD_SIZE) 0x00AA00AA); + wr_flash_cmd((ulong)addr, CFG_FLASH_ADDR1, (CFG_FLASH_WORD_SIZE) 0x00550055); + wr_flash_cmd((ulong)addr2, 0, (CFG_FLASH_WORD_SIZE) 0x00300030); + udelay(2000000); /* 2 sec */ + wr_flash_cmd((ulong)addr, 0, (CFG_FLASH_WORD_SIZE) 0x00F000F0); + +#if 0 + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[0] = (CFG_FLASH_WORD_SIZE) 0x00300030; /* sector erase */ +#endif + } + l_sect = sect; + printf(".."); + printf(".."); + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + wait_for_DQ7_2(info, sect); + count++; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay(1000); + + /* reset to read mode */ + addr = (CFG_FLASH_WORD_SIZE *) info->start[0]; + addr[0] = (CFG_FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */ + + printf(" done\n"); + + if (count > 0) { + return 0; + } else { + return 1; + } +} + +static int write_word_2(flash_info_t * info, ulong dest, ulong data) +{ + volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[0]); + volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *) dest; + volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *) & data; + ulong start; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + + for (i = 0; i < 4 / sizeof(CFG_FLASH_WORD_SIZE); i++) { + int flag; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00A000A0; + + dest2[i] = data2[i]; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer(0); + while ((dest2[i] & (CFG_FLASH_WORD_SIZE) 0x00800080) != + (data2[i] & (CFG_FLASH_WORD_SIZE) 0x00800080)) { + + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + + return (0); +} +#endif /* CFG_FLASH_2ND_16BIT_DEV */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size(vu_long * addr, flash_info_t * info); +static int write_word(flash_info_t * info, ulong dest, ulong data); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init(void) +{ + unsigned long total_b = 0; + unsigned long size_b[CFG_MAX_FLASH_BANKS]; + unsigned short index = 0; + int i; + + index = 0; + + DEBUGF("\n"); + DEBUGF("FLASH: Index: %d\n", index); + + /* Init: no FLASHes known */ + for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + flash_info[i].sector_count = -1; + flash_info[i].size = 0; + + /* check whether the address is 0 */ + if (flash_addr_table[index][i] == 0) { + continue; + } + + /* call flash_get_size() to initialize sector address */ + size_b[i] = flash_get_size((vu_long *) flash_addr_table[index][i], + &flash_info[i]); + flash_info[i].size = size_b[i]; + if (flash_info[i].flash_id == FLASH_UNKNOWN) { + printf("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", + i, size_b[i], size_b[i] << 20); + flash_info[i].sector_count = -1; + flash_info[i].size = 0; + } + + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[i]); +#if defined(CFG_ENV_IS_IN_FLASH) + (void)flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[i]); +#if defined(CFG_ENV_IS_IN_FLASH) && defined(CFG_ENV_ADDR_REDUND) + (void)flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR_REDUND, + CFG_ENV_ADDR_REDUND + CFG_ENV_SECT_SIZE - 1, + &flash_info[i]); +#endif +#endif + + total_b += flash_info[i].size; + } + + return total_b; +} diff --git a/board/amcc/acadia/memory.c b/board/amcc/acadia/memory.c new file mode 100644 index 0000000..a1b0155 --- /dev/null +++ b/board/amcc/acadia/memory.c @@ -0,0 +1,552 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <asm/processor.h> + +#define CRAM_BANK0_BASE 0x0 +#define CRAM_DIDR 0x00100000 +#define MICRON_MT45W8MW16BGX_CRAM_ID 0x1b431b43 +#define MICRON_MT45W8MW16BGX_CRAM_ID2 0x13431343 +#define MICRON_DIDR_VENDOR_ID 0x00030003 /* 00011b */ +#define CRAM_DIDR_VENDOR_ID_MASK 0x001f001f /* DIDR[4:0] */ +#define CRAM_DEVID_NOT_SUPPORTED 0x00000000 + +#define PSRAM_PASS 0x50415353 /* "PASS" */ +#define PSRAM_FAIL 0x4641494C /* "FAIL" */ + +static u32 is_cram_inited(void); +static u32 is_cram(void); +static long int cram_init(u32); +static void cram_bcr_write(u32); +void udelay (unsigned long); + +void sdram_init(void) +{ + volatile unsigned long spr_reg; + + /* + * If CRAM not initialized or CRAM looks initialized because this + * is after a warm reboot then set SPRG7 to indicate CRAM needs + * initialization. Note that CRAM is initialized by the SPI and + * NAND preloader. + */ + spr_reg = (volatile unsigned long) mfspr(SPRG6); + if ((is_cram_inited() != 1) || (spr_reg != LOAK_SPL)) { + mtspr(SPRG7, LOAK_NONE); /* "NONE" */ + } +#if 1 + /* + * When running the NAND SPL, the normal EBC configuration is not + * done, so We need to enable EPLD access on EBC_CS_2 and the memory + * on EBC_CS_3 + */ + + /* Enable CPLD - Needed for PSRAM Access */ + + + /* Init SDRAM by setting EBC Bank 3 for PSRAM */ + mtebc(pb1ap, CFG_EBC_PB1AP); + mtebc(pb1cr, CFG_EBC_PB1CR); + + mtebc(pb2ap, CFG_EBC_PB2AP); + mtebc(pb2cr, CFG_EBC_PB2CR); + + /* pre-boot loader code: we are in OCM */ + mtspr(SPRG6, LOAK_SPL); /* "SPL " */ + mtspr(SPRG7, LOAK_OCM); /* "OCM " */ +#endif + return; +} + +static void cram_bcr_write(u32 wr_val) +{ + u32 tmp_reg; + u32 val; + volatile u32 gpio_reg; + + /* # Program CRAM write */ + + /* + * set CRAM_CRE = 0x1 + * set wr_val = wr_val << 2 + */ + gpio_reg = in32(GPIO1_OR); + out32(GPIO1_OR, gpio_reg | 0x00000400); + wr_val = wr_val << 2; + /* wr_val = 0x1c048; */ + + /* + * # stop PLL clock before programming CRAM + * set EPLD0_MUX_CTL.OESPR3 = 1 + * delay 2 + */ + + /* + * # CS1 + * read 0x00200000 + * #shift 2 bit left before write + * set val = wr_val + 0x00200000 + * write dmem val 0 + * read 0x00200000 val + * print val/8x + */ + tmp_reg = in32(0x00200000); + val = wr_val + 0x00200000; + /* val = 0x0021c048; */ + out32(val, 0x0000); + udelay(100000); + val = in32(0x00200000); + + debug("CRAM VAL: %x for CS1 ", val); + + /* + * # CS2 + * read 0x02200000 + * #shift 2 bit left before write + * set val = wr_val + 0x02200000 + * write dmem val 0 + * read 0x02200000 val + * print val/8x + */ + tmp_reg = in32(0x02200000); + val = wr_val + 0x02200000; + /* val = 0x0221c048; */ + out32(val, 0x0000); + udelay(100000); + val = in32(0x02200000); + + debug("CRAM VAL: %x for CS2 ", val); + + /* + * # Start PLL clock before programming CRAM + * set EPLD0_MUX_CTL.OESPR3 = 0 + */ + + /* + * set CRAMCR = 0x1 + */ + gpio_reg = in32(GPIO1_OR); + out32(GPIO1_OR, gpio_reg | 0x00000400); + + /* + * # read CRAM config BCR ( bit19:18 = 10b ) + * #read 0x00200000 + * # 1001_1001_0001_1111 ( 991f ) => + * #10_0110_0100_0111_1100 => 2647c => 0022647c + * #0011_0010_0011_1110 (323e) + * # + */ + + /* + * set EPLD0_MUX_CTL.CRAMCR = 0x0 + */ + gpio_reg = in32(GPIO1_OR); + out32(GPIO1_OR, gpio_reg & 0xFFFFFBFF); + return; +} + +static u32 is_cram_inited() +{ + volatile unsigned long spr_reg; + + /* + * If CRAM is initialized already, then don't reinitialize it again. + * In the case of NAND boot and SPI boot, CRAM will already be + * initialized by the pre-loader + */ + spr_reg = (volatile unsigned long) mfspr(SPRG7); + if (spr_reg == LOAK_CRAM) { + return 1; + } else { + return 0; + } +} + +/****** + * return 0 if not CRAM + * return 1 if CRAM and it's already inited by preloader + * else return cram_id (CRAM Device Identification Register) + ******/ +static u32 is_cram(void) +{ + u32 gpio_TCR, gpio_OSRL, gpio_OR, gpio_ISR1L; + volatile u32 gpio_reg; + volatile u32 cram_id = 0; + + if (is_cram_inited() == 1) { + /* this is CRAM and it is already inited (by preloader) */ + cram_id = 1; + } else { + /* + * # CRAM CLOCK + * set GPIO0_TCR.G8 = 1 + * set GPIO0_OSRL.G8 = 0 + * set GPIO0_OR.G8 = 0 + */ + gpio_reg = in32(GPIO0_TCR); + gpio_TCR = gpio_reg; + out32(GPIO0_TCR, gpio_reg | 0x00800000); + gpio_reg = in32(GPIO0_OSRL); + gpio_OSRL = gpio_reg; + out32(GPIO0_OSRL, gpio_reg & 0xffffbfff); + gpio_reg = in32(GPIO0_OR); + gpio_OR = gpio_reg; + out32(GPIO0_OR, gpio_reg & 0xff7fffff); + + /* + * # CRAM Addreaa Valid + * set GPIO0_TCR.G10 = 1 + * set GPIO0_OSRL.G10 = 0 + * set GPIO0_OR.G10 = 0 + */ + gpio_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, gpio_reg | 0x00200000); + gpio_reg = in32(GPIO0_OSRL); + out32(GPIO0_OSRL, gpio_reg & 0xfffffbff); + gpio_reg = in32(GPIO0_OR); + out32(GPIO0_OR, gpio_reg & 0xffdfffff); + + /* + * # config input (EBC_WAIT) + * set GPIO0_ISR1L.G9 = 1 + * set GPIO0_TCR.G9 = 0 + */ + gpio_reg = in32(GPIO0_ISR1L); + gpio_ISR1L = gpio_reg; + out32(GPIO0_ISR1L, gpio_reg | 0x00001000); + gpio_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, gpio_reg & 0xffbfffff); + + /* + * Enable CRE to read Registers + * set GPIO0_TCR.21 = 1 + * set GPIO1_OR.21 = 1 + */ + gpio_reg = in32(GPIO1_TCR); + out32(GPIO1_TCR, gpio_reg | 0x00000400); + + gpio_reg = in32(GPIO1_OR); + out32(GPIO1_OR, gpio_reg | 0x00000400); + + /* Read Version ID */ + cram_id = (volatile u32) in32(CRAM_BANK0_BASE+CRAM_DIDR); + udelay(100000); + + asm volatile(" sync"); + asm volatile(" eieio"); + + debug("Cram ID: %X ", cram_id); + + switch (cram_id) { + case MICRON_MT45W8MW16BGX_CRAM_ID: + case MICRON_MT45W8MW16BGX_CRAM_ID2: + /* supported CRAM vendor/part */ + break; + case CRAM_DEVID_NOT_SUPPORTED: + default: + /* check for DIDR Vendor ID of Micron */ + if ((cram_id & CRAM_DIDR_VENDOR_ID_MASK) == + MICRON_DIDR_VENDOR_ID) + { + /* supported CRAM vendor */ + break; + } + /* this is not CRAM or not supported CRAM vendor/part */ + cram_id = 0; + /* + * reset the GPIO registers to the values that were + * there before this routine + */ + out32(GPIO0_TCR, gpio_TCR); + out32(GPIO0_OSRL, gpio_OSRL); + out32(GPIO0_OR, gpio_OR); + out32(GPIO0_ISR1L, gpio_ISR1L); + break; + } + } + + return cram_id; +} + +static long int cram_init(u32 already_inited) +{ + volatile u32 tmp_reg; + u32 cram_wr_val; + + if (already_inited == 0) return 0; + + /* + * If CRAM is initialized already, then don't reinitialize it again. + * In the case of NAND boot and SPI boot, CRAM will already be + * initialized by the pre-loader + */ + if (already_inited != 1) { + /* + * #o CRAM Card + * # - CRAMCRE @reg16 = 1; for CRAM to use + * # - CRAMCRE @reg16 = 0; for CRAM to program + * + * # enable CRAM SEL, move from setEPLD.cmd + * set EPLD0_MUX_CTL.OECRAM = 0 + * set EPLD0_MUX_CTL.CRAMCR = 1 + * set EPLD0_ETHRSTBOOT.SLCRAM = 0 + * #end + */ + + /* + * #1. EBC need to program READY, CLK, ADV for ASync mode + * # config output + */ + + /* + * # CRAM CLOCK + * set GPIO0_TCR.G8 = 1 + * set GPIO0_OSRL.G8 = 0 + * set GPIO0_OR.G8 = 0 + */ + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg | 0x00800000); + tmp_reg = in32(GPIO0_OSRL); + out32(GPIO0_OSRL, tmp_reg & 0xffffbfff); + tmp_reg = in32(GPIO0_OR); + out32(GPIO0_OR, tmp_reg & 0xff7fffff); + + /* + * # CRAM Addreaa Valid + * set GPIO0_TCR.G10 = 1 + * set GPIO0_OSRL.G10 = 0 + * set GPIO0_OR.G10 = 0 + */ + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg | 0x00200000); + tmp_reg = in32(GPIO0_OSRL); + out32(GPIO0_OSRL, tmp_reg & 0xfffffbff); + tmp_reg = in32(GPIO0_OR); + out32(GPIO0_OR, tmp_reg & 0xffdfffff); + + /* + * # config input (EBC_WAIT) + * set GPIO0_ISR1L.G9 = 1 + * set GPIO0_TCR.G9 = 0 + */ + tmp_reg = in32(GPIO0_ISR1L); + out32(GPIO0_ISR1L, tmp_reg | 0x00001000); + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg & 0xffbfffff); + + /* + * # config CS4 from GPIO + * set GPIO0_TCR.G0 = 1 + * set GPIO0_OSRL.G0 = 1 + */ + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg | 0x80000000); + tmp_reg = in32(GPIO0_OSRL); + out32(GPIO0_OSRL, tmp_reg | 0x40000000); + + /* + * #2. EBC in Async mode + * # set EBC0_PB1AP = 0x078f0ec0 + * set EBC0_PB1AP = 0x078f1ec0 + * set EBC0_PB2AP = 0x078f1ec0 + */ + mtebc(pb1ap, 0x078F1EC0); + mtebc(pb2ap, 0x078F1EC0); + + /* + * #set EBC0_PB1CR = 0x000bc000 + * #enable CS2 for CRAM + * set EBC0_PB2CR = 0x020bc000 + */ + mtebc(pb1cr, 0x000BC000); + mtebc(pb2cr, 0x020BC000); + + /* + * #3. set CRAM in Sync mode + * #exec cm_bcr_write.cmd { 0x701f } + * #3. set CRAM in Sync mode (full drv strength) + * exec cm_bcr_write.cmd { 0x701F } + */ + cram_wr_val = 0x7012; /* CRAM burst setting */ + cram_bcr_write(cram_wr_val); + + /* + * #4. EBC in Sync mode + * #set EBC0_PB1AP = 0x9f800fc0 + * #set EBC0_PB1AP = 0x900001c0 + * set EBC0_PB2AP = 0x9C0201c0 + * set EBC0_PB2AP = 0x9C0201c0 + */ + mtebc(pb1ap, 0x9C0201C0); + mtebc(pb2ap, 0x9C0201C0); + + /* + * #5. EBC need to program READY, CLK, ADV for Sync mode + * # config output + * set GPIO0_TCR.G8 = 1 + * set GPIO0_OSRL.G8 = 1 + * set GPIO0_TCR.G10 = 1 + * set GPIO0_OSRL.G10 = 1 + */ + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg | 0x00800000); + tmp_reg = in32(GPIO0_OSRL); + out32(GPIO0_OSRL, tmp_reg | 0x00004000); + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg | 0x00200000); + tmp_reg = in32(GPIO0_OSRL); + out32(GPIO0_OSRL, tmp_reg | 0x00000400); + + /* + * # config input + * set GPIO0_ISR1L.G9 = 1 + * set GPIO0_TCR.G9 = 0 + */ + tmp_reg = in32(GPIO0_ISR1L); + out32(GPIO0_ISR1L, tmp_reg | 0x00001000); + tmp_reg = in32(GPIO0_TCR); + out32(GPIO0_TCR, tmp_reg & 0xffbfffff); + + /* + * # config EBC to use RDY + * set SDR0_ULTRA0.EBCREN = 1 + */ + mfsdr(sdrultra0, tmp_reg); + mtsdr(sdrultra0, tmp_reg | 0x04000000); + + /* + * set EPLD0_MUX_CTL.OESPR3 = 0 + */ + mtspr(SPRG7, LOAK_CRAM); /* "CRAM" */ + } /* if (already_inited != 1) */ + + return (64 * 1024 * 1024); +} + +/****** + * return 0 if not PSRAM + * return 1 if is PSRAM + ******/ +static int is_psram(u32 addr) +{ + u32 test_pattern = 0xdeadbeef; + volatile u32 readback; + + if (addr == CFG_SDRAM_BASE) { + /* This is to temp enable OE for PSRAM */ + out16(EPLD_BASE+EPLD_MUXOE, 0x7f0f); + udelay(10000); + } + + out32(addr, test_pattern); + asm volatile(" sync"); + asm volatile(" eieio"); + + readback = (volatile u32) in32(addr); + asm volatile(" sync"); + asm volatile(" eieio"); + if (readback == test_pattern) { + return 1; + } else { + return 0; + } +} + +static long int psram_init(void) +{ + u32 readback; + long psramsize = 0; + int i; + + /* This is to temp enable OE for PSRAM */ + out16(EPLD_BASE+EPLD_MUXOE, 0x7f0f); + udelay(10000); + + /* + * PSRAM bank 1: read then write to address 0x00000000 + */ + for (i = 0; i < 100; i++) { + if (is_psram(CFG_SDRAM_BASE + (i*256)) == 1) { + readback = PSRAM_PASS; + } else { + readback = PSRAM_FAIL; + break; + } + } + if (readback == PSRAM_PASS) { + debug("psram_init(bank0): pass\n"); + psramsize = (16 * 1024 * 1024); + } else { + debug("psram_init(bank0): fail\n"); + return 0; + } + +#if 0 + /* + * PSRAM bank 1: read then write to address 0x01000000 + */ + for (i = 0; i < 100; i++) { + if (is_psram((1 << 24) + (i*256)) == 1) { + readback = PSRAM_PASS; + } else { + readback = PSRAM_FAIL; + break; + } + } + if (readback == PSRAM_PASS) { + debug("psram_init(bank1): pass\n"); + psramsize = psramsize + (16 * 1024 * 1024); + } +#endif + + mtspr(SPRG7, LOAK_PSRAM); /* "PSRA" - PSRAM */ + + return psramsize; +} + +long int initdram(int board_type) +{ + long int sram_size; + u32 cram_inited; + + /* Determine Attached Memory Expansion Card*/ + cram_inited = is_cram(); + if (cram_inited != 0) { /* CRAM */ + debug("CRAM Expansion Card attached\n"); + sram_size = cram_init(cram_inited); + } else if (is_psram(CFG_SDRAM_BASE+4) == 1) { /* PSRAM */ + debug("PSRAM Expansion Card attached\n"); + sram_size = psram_init(); + } else { /* no SRAM */ + debug("No Memory Card Attached!!\n"); + sram_size = 0; + } + + return sram_size; +} + +int testdram(void) +{ + return (0); +} diff --git a/board/amcc/acadia/u-boot.lds b/board/amcc/acadia/u-boot.lds new file mode 100644 index 0000000..be03092 --- /dev/null +++ b/board/amcc/acadia/u-boot.lds @@ -0,0 +1,150 @@ +/* + * (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 +{ + .resetvec 0xFFFFFFFC : + { + *(.resetvec) + } = 0xffff + + /* 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) + 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) + *(.eh_frame) + } + .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/board/amcc/ebony/init.S b/board/amcc/ebony/init.S index cc8f8b4..c86076e 100644 --- a/board/amcc/ebony/init.S +++ b/board/amcc/ebony/init.S @@ -22,53 +22,7 @@ #include <ppc_asm.tmpl> #include <config.h> - -/* General */ -#define TLB_VALID 0x00000200 - -/* Supported page sizes */ - -#define SZ_1K 0x00000000 -#define SZ_4K 0x00000010 -#define SZ_16K 0x00000020 -#define SZ_64K 0x00000030 -#define SZ_256K 0x00000040 -#define SZ_1M 0x00000050 -#define SZ_16M 0x00000070 -#define SZ_256M 0x00000090 - -/* Storage attributes */ -#define SA_W 0x00000800 /* Write-through */ -#define SA_I 0x00000400 /* Caching inhibited */ -#define SA_M 0x00000200 /* Memory coherence */ -#define SA_G 0x00000100 /* Guarded */ -#define SA_E 0x00000080 /* Endian */ - -/* Access control */ -#define AC_X 0x00000024 /* Execute */ -#define AC_W 0x00000012 /* Write */ -#define AC_R 0x00000009 /* Read */ - -/* Some handy macros */ - -#define EPN(e) ((e) & 0xfffffc00) -#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) -#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) -#define TLB2(a) ( (a)&0x00000fbf ) - -#define tlbtab_start\ - mflr r1 ;\ - bl 0f ; - -#define tlbtab_end\ - .long 0, 0, 0 ; \ -0: mflr r0 ; \ - mtlr r1 ; \ - blr ; - -#define tlbentry(epn,sz,rpn,erpn,attr)\ - .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) - +#include <asm-ppc/mmu.h> /************************************************************************** * TLB TABLE @@ -81,16 +35,23 @@ * *************************************************************************/ - .section .bootpg,"ax" - .globl tlbtab + .section .bootpg,"ax" + .globl tlbtab tlbtab: - tlbtab_start - tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) - tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X ) - tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X ) - tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I ) - tlbtab_end + tlbtab_start + + tlbentry(0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ + + tlbentry(CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X) + tlbentry(CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X) + tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I) + tlbtab_end diff --git a/board/amcc/katmai/Makefile b/board/amcc/katmai/Makefile new file mode 100644 index 0000000..d06a402 --- /dev/null +++ b/board/amcc/katmai/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2007 +# 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 = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o cmd_katmai.o +SOBJS = init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend *~ + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/amcc/katmai/cmd_katmai.c b/board/amcc/katmai/cmd_katmai.c new file mode 100644 index 0000000..684f6a5 --- /dev/null +++ b/board/amcc/katmai/cmd_katmai.c @@ -0,0 +1,267 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <command.h> +#include <i2c.h> +#include <asm/byteorder.h> + +static int do_bootstrap(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + uchar chip; + ulong data; + int nbytes; + extern char console_buffer[]; + + char sysClock[4]; + char cpuClock[4]; + char plbClock[4]; + char pcixClock[4]; + + if (argc < 3) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[2], "prom0") == 0) + chip = IIC0_BOOTPROM_ADDR; + else + chip = IIC0_ALT_BOOTPROM_ADDR; + + do { + printf("enter sys clock frequency 33 or 66 Mhz or quit to abort\n"); + nbytes = readline (" ? "); + + if (strcmp(console_buffer, "quit") == 0) + return 0; + + if ((strcmp(console_buffer, "33") != 0) & + (strcmp(console_buffer, "66") != 0)) + nbytes=0; + + strcpy(sysClock, console_buffer); + + } while (nbytes == 0); + + do { + if (strcmp(sysClock, "66") == 0) { + printf("enter cpu clock frequency 400, 533 Mhz or quit to abort\n"); + } else { +#ifdef CONFIG_STRESS + printf("enter cpu clock frequency 400, 500, 533, 667 Mhz or quit to abort\n"); +#else + printf("enter cpu clock frequency 400, 500, 533 Mhz or quit to abort\n"); +#endif + } + nbytes = readline (" ? "); + + if (strcmp(console_buffer, "quit") == 0) + return 0; + + if (strcmp(sysClock, "66") == 0) { + if ((strcmp(console_buffer, "400") != 0) & + (strcmp(console_buffer, "533") != 0) +#ifdef CONFIG_STRESS + & (strcmp(console_buffer, "667") != 0) +#endif + ) { + nbytes = 0; + } + } else { + if ((strcmp(console_buffer, "400") != 0) & + (strcmp(console_buffer, "500") != 0) & + (strcmp(console_buffer, "533") != 0) +#ifdef CONFIG_STRESS + & (strcmp(console_buffer, "667") != 0) +#endif + ) { + nbytes = 0; + } + } + + strcpy(cpuClock, console_buffer); + + } while (nbytes == 0); + + if (strcmp(cpuClock, "500") == 0) + strcpy(plbClock, "166"); + else if (strcmp(cpuClock, "533") == 0) + strcpy(plbClock, "133"); + else { + do { + if (strcmp(cpuClock, "400") == 0) + printf("enter plb clock frequency 100, 133 Mhz or quit to abort\n"); + +#ifdef CONFIG_STRESS + if (strcmp(cpuClock, "667") == 0) + printf("enter plb clock frequency 133, 166 Mhz or quit to abort\n"); + +#endif + nbytes = readline (" ? "); + + if (strcmp(console_buffer, "quit") == 0) + return 0; + + if (strcmp(cpuClock, "400") == 0) { + if ((strcmp(console_buffer, "100") != 0) & + (strcmp(console_buffer, "133") != 0)) + nbytes = 0; + } +#ifdef CONFIG_STRESS + if (strcmp(cpuClock, "667") == 0) { + if ((strcmp(console_buffer, "133") != 0) & + (strcmp(console_buffer, "166") != 0)) + nbytes = 0; + } +#endif + strcpy(plbClock, console_buffer); + + } while (nbytes == 0); + } + + do { + printf("enter Pci-X clock frequency 33, 66, 100 or 133 Mhz or quit to abort\n"); + nbytes = readline (" ? "); + + if (strcmp(console_buffer, "quit") == 0) + return 0; + + if ((strcmp(console_buffer, "33") != 0) & + (strcmp(console_buffer, "66") != 0) & + (strcmp(console_buffer, "100") != 0) & + (strcmp(console_buffer, "133") != 0)) { + nbytes = 0; + } + strcpy(pcixClock, console_buffer); + + } while (nbytes == 0); + + printf("\nsys clk = %sMhz\n", sysClock); + printf("cpu clk = %sMhz\n", cpuClock); + printf("plb clk = %sMhz\n", plbClock); + printf("Pci-X clk = %sMhz\n", pcixClock); + + do { + printf("\npress [y] to write I2C bootstrap \n"); + printf("or [n] to abort. \n"); + printf("Don't forget to set board switches \n"); + printf("according to your choice before re-starting \n"); + printf("(refer to 440spe_uboot_kit_um_1_01.pdf) \n"); + + nbytes = readline (" ? "); + if (strcmp(console_buffer, "n") == 0) + return 0; + + } while (nbytes == 0); + + if (strcmp(sysClock, "33") == 0) { + if ((strcmp(cpuClock, "400") == 0) & + (strcmp(plbClock, "100") == 0)) + data = 0x8678c206; + + if ((strcmp(cpuClock, "400") == 0) & + (strcmp(plbClock, "133") == 0)) + data = 0x8678c2c6; + + if ((strcmp(cpuClock, "500") == 0)) + data = 0x8778f2c6; + + if ((strcmp(cpuClock, "533") == 0)) + data = 0x87790252; + +#ifdef CONFIG_STRESS + if ((strcmp(cpuClock, "667") == 0) & + (strcmp(plbClock, "133") == 0)) + data = 0x87794256; + + if ((strcmp(cpuClock, "667") == 0) & + (strcmp(plbClock, "166") == 0)) + data = 0x87794206; + +#endif + } + if (strcmp(sysClock, "66") == 0) { + if ((strcmp(cpuClock, "400") == 0) & + (strcmp(plbClock, "100") == 0)) + data = 0x84706206; + + if ((strcmp(cpuClock, "400") == 0) & + (strcmp(plbClock, "133") == 0)) + data = 0x847062c6; + + if ((strcmp(cpuClock, "533") == 0)) + data = 0x85708206; + +#ifdef CONFIG_STRESS + if ((strcmp(cpuClock, "667") == 0) & + (strcmp(plbClock, "133") == 0)) + data = 0x8570a256; + + if ((strcmp(cpuClock, "667") == 0) & + (strcmp(plbClock, "166") == 0)) + data = 0x8570a206; + +#endif + } + +#ifdef DEBUG + printf(" pin strap0 to write in i2c = %x\n", data); +#endif /* DEBUG */ + + if (i2c_write(chip, 0, 1, (uchar *)&data, 4) != 0) + printf("Error writing strap0 in %s\n", argv[2]); + + if (strcmp(pcixClock, "33") == 0) + data = 0x00000701; + + if (strcmp(pcixClock, "66") == 0) + data = 0x00000601; + + if (strcmp(pcixClock, "100") == 0) + data = 0x00000501; + + if (strcmp(pcixClock, "133") == 0) + data = 0x00000401; + + if (strcmp(plbClock, "166") == 0) + data |= 0x05950000; + else + data |= 0x05A50000; + +#ifdef DEBUG + printf(" pin strap1 to write in i2c = %x\n", data); +#endif /* DEBUG */ + + udelay(1000); + if (i2c_write(chip, 4, 1, (uchar *)&data, 4) != 0) + printf("Error writing strap1 in %s\n", argv[2]); + + return 0; +} + +U_BOOT_CMD( + bootstrap, 3, 1, do_bootstrap, + "bootstrap - program the serial device strap\n", + "wrclk [prom0|prom1] - program the serial device strap\n" + ); diff --git a/board/amcc/katmai/config.mk b/board/amcc/katmai/config.mk new file mode 100644 index 0000000..115c1ae --- /dev/null +++ b/board/amcc/katmai/config.mk @@ -0,0 +1,38 @@ +# +# (C) Copyright 2006 +# 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 +# + +# +# AMCC 440SPe Evaluation (Katmai) board +# + +TEXT_BASE = 0xfffc0000 + +PLATFORM_CPPFLAGS += -DCONFIG_440=1 + +ifeq ($(debug),1) +PLATFORM_CPPFLAGS += -DDEBUG +endif + +ifeq ($(dbcr),1) +PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000 +endif diff --git a/board/amcc/katmai/init.S b/board/amcc/katmai/init.S new file mode 100644 index 0000000..6b024ee --- /dev/null +++ b/board/amcc/katmai/init.S @@ -0,0 +1,118 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 <ppc_asm.tmpl> +#include <config.h> +#include <asm-ppc/mmu.h> + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + * Pointer to the table is returned in r1 + * + *************************************************************************/ + + .section .bootpg,"ax" + +/************************************************************************** + * TLB table for revA + *************************************************************************/ + .globl tlbtabA +tlbtabA: + tlbtab_start + + /* + * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the + * speed up boot process. It is patched after relocation to enable SA_I + */ + tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ + + tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) + tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE_BASE, SZ_16K, 0x20000000, 0xC, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x40000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x80000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0xC0000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x50000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x90000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0xD0000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbtab_end + +/************************************************************************** + * TLB table for revB + * + * Notice: revB of the 440SPe chip is very strict about PLB real addresses + * and ranges to be mapped for config space: it seems to only work with + * d_nnnn_nnnn range (hangs the core upon config transaction attempts when + * set otherwise) while revA uses c_nnnn_nnnn. + *************************************************************************/ + .globl tlbtabB +tlbtabB: + tlbtab_start + + /* + * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the + * speed up boot process. It is patched after relocation to enable SA_I + */ + tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ + + tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) + + tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_ACE_BASE, SZ_1K, 0xE0000000, 4,AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x00100000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x20100000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0x40100000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x10000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x30000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0x50000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbtab_end diff --git a/board/amcc/katmai/katmai.c b/board/amcc/katmai/katmai.c new file mode 100644 index 0000000..fbf1a98 --- /dev/null +++ b/board/amcc/katmai/katmai.c @@ -0,0 +1,529 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> +#include <i2c.h> +#include <asm-ppc/io.h> + +#include "../cpu/ppc4xx/440spe_pcie.h" + +#undef PCIE_ENDPOINT +/* #define PCIE_ENDPOINT 1 */ + +int ppc440spe_init_pcie_rootport(int port); +void ppc440spe_setup_pcie(struct pci_controller *hose, int port); + +int board_early_init_f (void) +{ + unsigned long mfr; + + /*----------------------------------------------------------------------+ + * Interrupt controller setup for the Katmai 440SPe Evaluation board. + *-----------------------------------------------------------------------+ + *-----------------------------------------------------------------------+ + * Interrupt | Source | Pol. | Sensi.| Crit. | + *-----------+-----------------------------------+-------+-------+-------+ + * IRQ 00 | UART0 | High | Level | Non | + * IRQ 01 | UART1 | High | Level | Non | + * IRQ 02 | IIC0 | High | Level | Non | + * IRQ 03 | IIC1 | High | Level | Non | + * IRQ 04 | PCI0X0 MSG IN | High | Level | Non | + * IRQ 05 | PCI0X0 CMD Write | High | Level | Non | + * IRQ 06 | PCI0X0 Power Mgt | High | Level | Non | + * IRQ 07 | PCI0X0 VPD Access | Rising| Edge | Non | + * IRQ 08 | PCI0X0 MSI level 0 | High | Lvl/ed| Non | + * IRQ 09 | External IRQ 15 - (PCI-Express) | pgm H | Pgm | Non | + * IRQ 10 | UIC2 Non-critical Int. | NA | NA | Non | + * IRQ 11 | UIC2 Critical Interrupt | NA | NA | Crit | + * IRQ 12 | PCI Express MSI Level 0 | Rising| Edge | Non | + * IRQ 13 | PCI Express MSI Level 1 | Rising| Edge | Non | + * IRQ 14 | PCI Express MSI Level 2 | Rising| Edge | Non | + * IRQ 15 | PCI Express MSI Level 3 | Rising| Edge | Non | + * IRQ 16 | UIC3 Non-critical Int. | NA | NA | Non | + * IRQ 17 | UIC3 Critical Interrupt | NA | NA | Crit | + * IRQ 18 | External IRQ 14 - (PCI-Express) | Pgm | Pgm | Non | + * IRQ 19 | DMA Channel 0 FIFO Full | High | Level | Non | + * IRQ 20 | DMA Channel 0 Stat FIFO | High | Level | Non | + * IRQ 21 | DMA Channel 1 FIFO Full | High | Level | Non | + * IRQ 22 | DMA Channel 1 Stat FIFO | High | Level | Non | + * IRQ 23 | I2O Inbound Doorbell | High | Level | Non | + * IRQ 24 | Inbound Post List FIFO Not Empt | High | Level | Non | + * IRQ 25 | I2O Region 0 LL PLB Write | High | Level | Non | + * IRQ 26 | I2O Region 1 LL PLB Write | High | Level | Non | + * IRQ 27 | I2O Region 0 HB PLB Write | High | Level | Non | + * IRQ 28 | I2O Region 1 HB PLB Write | High | Level | Non | + * IRQ 29 | GPT Down Count Timer | Rising| Edge | Non | + * IRQ 30 | UIC1 Non-critical Int. | NA | NA | Non | + * IRQ 31 | UIC1 Critical Interrupt | NA | NA | Crit. | + *------------------------------------------------------------------------ + * IRQ 32 | Ext. IRQ 13 - (PCI-Express) |pgm (H)|pgm/Lvl| Non | + * IRQ 33 | MAL Serr | High | Level | Non | + * IRQ 34 | MAL Txde | High | Level | Non | + * IRQ 35 | MAL Rxde | High | Level | Non | + * IRQ 36 | DMC CE or DMC UE | High | Level | Non | + * IRQ 37 | EBC or UART2 | High |Lvl Edg| Non | + * IRQ 38 | MAL TX EOB | High | Level | Non | + * IRQ 39 | MAL RX EOB | High | Level | Non | + * IRQ 40 | PCIX0 MSI Level 1 | High |Lvl Edg| Non | + * IRQ 41 | PCIX0 MSI level 2 | High |Lvl Edg| Non | + * IRQ 42 | PCIX0 MSI level 3 | High |Lvl Edg| Non | + * IRQ 43 | L2 Cache | Risin | Edge | Non | + * IRQ 44 | GPT Compare Timer 0 | Risin | Edge | Non | + * IRQ 45 | GPT Compare Timer 1 | Risin | Edge | Non | + * IRQ 46 | GPT Compare Timer 2 | Risin | Edge | Non | + * IRQ 47 | GPT Compare Timer 3 | Risin | Edge | Non | + * IRQ 48 | GPT Compare Timer 4 | Risin | Edge | Non | + * IRQ 49 | Ext. IRQ 12 - PCI-X |pgm/Fal|pgm/Lvl| Non | + * IRQ 50 | Ext. IRQ 11 - |pgm (H)|pgm/Lvl| Non | + * IRQ 51 | Ext. IRQ 10 - |pgm (H)|pgm/Lvl| Non | + * IRQ 52 | Ext. IRQ 9 |pgm (H)|pgm/Lvl| Non | + * IRQ 53 | Ext. IRQ 8 |pgm (H)|pgm/Lvl| Non | + * IRQ 54 | DMA Error | High | Level | Non | + * IRQ 55 | DMA I2O Error | High | Level | Non | + * IRQ 56 | Serial ROM | High | Level | Non | + * IRQ 57 | PCIX0 Error | High | Edge | Non | + * IRQ 58 | Ext. IRQ 7- |pgm (H)|pgm/Lvl| Non | + * IRQ 59 | Ext. IRQ 6- |pgm (H)|pgm/Lvl| Non | + * IRQ 60 | EMAC0 Interrupt | High | Level | Non | + * IRQ 61 | EMAC0 Wake-up | High | Level | Non | + * IRQ 62 | Reserved | High | Level | Non | + * IRQ 63 | XOR | High | Level | Non | + *----------------------------------------------------------------------- + * IRQ 64 | PE0 AL | High | Level | Non | + * IRQ 65 | PE0 VPD Access | Risin | Edge | Non | + * IRQ 66 | PE0 Hot Reset Request | Risin | Edge | Non | + * IRQ 67 | PE0 Hot Reset Request | Falli | Edge | Non | + * IRQ 68 | PE0 TCR | High | Level | Non | + * IRQ 69 | PE0 BusMaster VCO | Falli | Edge | Non | + * IRQ 70 | PE0 DCR Error | High | Level | Non | + * IRQ 71 | Reserved | N/A | N/A | Non | + * IRQ 72 | PE1 AL | High | Level | Non | + * IRQ 73 | PE1 VPD Access | Risin | Edge | Non | + * IRQ 74 | PE1 Hot Reset Request | Risin | Edge | Non | + * IRQ 75 | PE1 Hot Reset Request | Falli | Edge | Non | + * IRQ 76 | PE1 TCR | High | Level | Non | + * IRQ 77 | PE1 BusMaster VCO | Falli | Edge | Non | + * IRQ 78 | PE1 DCR Error | High | Level | Non | + * IRQ 79 | Reserved | N/A | N/A | Non | + * IRQ 80 | PE2 AL | High | Level | Non | + * IRQ 81 | PE2 VPD Access | Risin | Edge | Non | + * IRQ 82 | PE2 Hot Reset Request | Risin | Edge | Non | + * IRQ 83 | PE2 Hot Reset Request | Falli | Edge | Non | + * IRQ 84 | PE2 TCR | High | Level | Non | + * IRQ 85 | PE2 BusMaster VCO | Falli | Edge | Non | + * IRQ 86 | PE2 DCR Error | High | Level | Non | + * IRQ 87 | Reserved | N/A | N/A | Non | + * IRQ 88 | External IRQ(5) | Progr | Progr | Non | + * IRQ 89 | External IRQ 4 - Ethernet | Progr | Progr | Non | + * IRQ 90 | External IRQ 3 - PCI-X | Progr | Progr | Non | + * IRQ 91 | External IRQ 2 - PCI-X | Progr | Progr | Non | + * IRQ 92 | External IRQ 1 - PCI-X | Progr | Progr | Non | + * IRQ 93 | External IRQ 0 - PCI-X | Progr | Progr | Non | + * IRQ 94 | Reserved | N/A | N/A | Non | + * IRQ 95 | Reserved | N/A | N/A | Non | + *----------------------------------------------------------------------- + * IRQ 96 | PE0 INTA | High | Level | Non | + * IRQ 97 | PE0 INTB | High | Level | Non | + * IRQ 98 | PE0 INTC | High | Level | Non | + * IRQ 99 | PE0 INTD | High | Level | Non | + * IRQ 100 | PE1 INTA | High | Level | Non | + * IRQ 101 | PE1 INTB | High | Level | Non | + * IRQ 102 | PE1 INTC | High | Level | Non | + * IRQ 103 | PE1 INTD | High | Level | Non | + * IRQ 104 | PE2 INTA | High | Level | Non | + * IRQ 105 | PE2 INTB | High | Level | Non | + * IRQ 106 | PE2 INTC | High | Level | Non | + * IRQ 107 | PE2 INTD | Risin | Edge | Non | + * IRQ 108 | PCI Express MSI Level 4 | Risin | Edge | Non | + * IRQ 109 | PCI Express MSI Level 5 | Risin | Edge | Non | + * IRQ 110 | PCI Express MSI Level 6 | Risin | Edge | Non | + * IRQ 111 | PCI Express MSI Level 7 | Risin | Edge | Non | + * IRQ 116 | PCI Express MSI Level 12 | Risin | Edge | Non | + * IRQ 112 | PCI Express MSI Level 8 | Risin | Edge | Non | + * IRQ 113 | PCI Express MSI Level 9 | Risin | Edge | Non | + * IRQ 114 | PCI Express MSI Level 10 | Risin | Edge | Non | + * IRQ 115 | PCI Express MSI Level 11 | Risin | Edge | Non | + * IRQ 117 | PCI Express MSI Level 13 | Risin | Edge | Non | + * IRQ 118 | PCI Express MSI Level 14 | Risin | Edge | Non | + * IRQ 119 | PCI Express MSI Level 15 | Risin | Edge | Non | + * IRQ 120 | PCI Express MSI Level 16 | Risin | Edge | Non | + * IRQ 121 | PCI Express MSI Level 17 | Risin | Edge | Non | + * IRQ 122 | PCI Express MSI Level 18 | Risin | Edge | Non | + * IRQ 123 | PCI Express MSI Level 19 | Risin | Edge | Non | + * IRQ 124 | PCI Express MSI Level 20 | Risin | Edge | Non | + * IRQ 125 | PCI Express MSI Level 21 | Risin | Edge | Non | + * IRQ 126 | PCI Express MSI Level 22 | Risin | Edge | Non | + * IRQ 127 | PCI Express MSI Level 23 | Risin | Edge | Non | + *-----------+-----------------------------------+-------+-------+-------+ */ + /*-------------------------------------------------------------------------+ + * Put UICs in PowerPC440SPemode. + * Initialise UIC registers. Clear all interrupts. Disable all interrupts. + * Set critical interrupt values. Set interrupt polarities. Set interrupt + * trigger levels. Make bit 0 High priority. Clear all interrupts again. + *------------------------------------------------------------------------*/ + mtdcr (uic3sr, 0xffffffff); /* Clear all interrupts */ + mtdcr (uic3er, 0x00000000); /* disable all interrupts */ + mtdcr (uic3cr, 0x00000000); /* Set Critical / Non Critical interrupts: */ + mtdcr (uic3pr, 0xffffffff); /* Set Interrupt Polarities*/ + mtdcr (uic3tr, 0x001fffff); /* Set Interrupt Trigger Levels */ + mtdcr (uic3vr, 0x00000001); /* Set Vect base=0,INT31 Highest priority */ + mtdcr (uic3sr, 0x00000000); /* clear all interrupts*/ + mtdcr (uic3sr, 0xffffffff); /* clear all interrupts*/ + + + mtdcr (uic2sr, 0xffffffff); /* Clear all interrupts */ + mtdcr (uic2er, 0x00000000); /* disable all interrupts*/ + mtdcr (uic2cr, 0x00000000); /* Set Critical / Non Critical interrupts*/ + mtdcr (uic2pr, 0xebebebff); /* Set Interrupt Polarities*/ + mtdcr (uic2tr, 0x74747400); /* Set Interrupt Trigger Levels */ + mtdcr (uic2vr, 0x00000001); /* Set Vect base=0,INT31 Highest priority */ + mtdcr (uic2sr, 0x00000000); /* clear all interrupts */ + mtdcr (uic2sr, 0xffffffff); /* clear all interrupts */ + + mtdcr (uic1sr, 0xffffffff); /* Clear all interrupts*/ + mtdcr (uic1er, 0x00000000); /* disable all interrupts*/ + mtdcr (uic1cr, 0x00000000); /* Set Critical / Non Critical interrupts*/ + mtdcr (uic1pr, 0xffffffff); /* Set Interrupt Polarities */ + mtdcr (uic1tr, 0x001f8040); /* Set Interrupt Trigger Levels*/ + mtdcr (uic1vr, 0x00000001); /* Set Vect base=0,INT31 Highest priority */ + mtdcr (uic1sr, 0x00000000); /* clear all interrupts*/ + mtdcr (uic1sr, 0xffffffff); /* clear all interrupts*/ + + mtdcr (uic0sr, 0xffffffff); /* Clear all interrupts */ + mtdcr (uic0er, 0x00000000); /* disable all interrupts excepted cascade to be checked */ + mtdcr (uic0cr, 0x00104001); /* Set Critical / Non Critical interrupts*/ + mtdcr (uic0pr, 0xffffffff); /* Set Interrupt Polarities*/ + mtdcr (uic0tr, 0x010f0004); /* Set Interrupt Trigger Levels */ + mtdcr (uic0vr, 0x00000001); /* Set Vect base=0,INT31 Highest priority */ + mtdcr (uic0sr, 0x00000000); /* clear all interrupts*/ + mtdcr (uic0sr, 0xffffffff); /* clear all interrupts*/ + +/* SDR0_MFR should be part of Ethernet init */ + mfsdr (sdr_mfr, mfr); + mfr &= ~SDR0_MFR_ECS_MASK; +/* mtsdr(sdr_mfr, mfr); */ + + mtsdr(SDR0_PFC0, CFG_PFC0); + + out32(GPIO0_OR, CFG_GPIO_OR); + out32(GPIO0_ODR, CFG_GPIO_ODR); + out32(GPIO0_TCR, CFG_GPIO_TCR); + + return 0; +} + +int checkboard (void) +{ + char *s = getenv("serial#"); + + printf("Board: Katmai - AMCC 440SPe Evaluation Board"); + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return 0; +} + +#if defined(CFG_DRAM_TEST) +int testdram (void) +{ + uint *pstart = (uint *) 0x00000000; + uint *pend = (uint *) 0x08000000; + uint *p; + + for (p = pstart; p < pend; p++) + *p = 0xaaaaaaaa; + + for (p = pstart; p < pend; p++) { + if (*p != 0xaaaaaaaa) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + + for (p = pstart; p < pend; p++) + *p = 0x55555555; + + for (p = pstart; p < pend; p++) { + if (*p != 0x55555555) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + return 0; +} +#endif + +/************************************************************************* + * pci_pre_init + * + * This routine is called just prior to registering the hose and gives + * the board the opportunity to check things. Returning a value of zero + * indicates that things are bad & PCI initialization should be aborted. + * + * Different boards may wish to customize the pci controller structure + * (add regions, override default access routines, etc) or perform + * certain pre-initialization actions. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) +int pci_pre_init(struct pci_controller * hose ) +{ + unsigned long strap; + + /*-------------------------------------------------------------------+ + * The katmai board is always configured as the host & requires the + * PCI arbiter to be enabled. + *-------------------------------------------------------------------*/ + mfsdr(sdr_sdstp1, strap); + if( (strap & SDR0_SDSTP1_PAE_MASK) == 0 ) { + printf("PCI: SDR0_STRP1[%08lX] - PCI Arbiter disabled.\n",strap); + return 0; + } + + return 1; +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ + +/************************************************************************* + * pci_target_init + * + * The bootstrap configuration provides default settings for the pci + * inbound map (PIM). But the bootstrap config choices are limited and + * may not be sufficient for a given board. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) +void pci_target_init(struct pci_controller * hose ) +{ + DECLARE_GLOBAL_DATA_PTR; + + /*-------------------------------------------------------------------+ + * Disable everything + *-------------------------------------------------------------------*/ + out32r( PCIX0_PIM0SA, 0 ); /* disable */ + out32r( PCIX0_PIM1SA, 0 ); /* disable */ + out32r( PCIX0_PIM2SA, 0 ); /* disable */ + out32r( PCIX0_EROMBA, 0 ); /* disable expansion rom */ + + /*-------------------------------------------------------------------+ + * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 + * strapping options to not support sizes such as 128/256 MB. + *-------------------------------------------------------------------*/ + out32r( PCIX0_PIM0LAL, CFG_SDRAM_BASE ); + out32r( PCIX0_PIM0LAH, 0 ); + out32r( PCIX0_PIM0SA, ~(gd->ram_size - 1) | 1 ); + out32r( PCIX0_BAR0, 0 ); + + /*-------------------------------------------------------------------+ + * Program the board's subsystem id/vendor id + *-------------------------------------------------------------------*/ + out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID ); + out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_DEVICEID ); + + out16r( PCIX0_CMD, in16r(PCIX0_CMD) | PCI_COMMAND_MEMORY ); +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ + +#if defined(CONFIG_PCI) +/************************************************************************* + * is_pci_host + * + * This routine is called to determine if a pci scan should be + * performed. With various hardware environments (especially cPCI and + * PPMC) it's insufficient to depend on the state of the arbiter enable + * bit in the strap register, or generic host/adapter assumptions. + * + * Rather than hard-code a bad assumption in the general 440 code, the + * 440 pci code requires the board to decide at runtime. + * + * Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * + ************************************************************************/ +int is_pci_host(struct pci_controller *hose) +{ + /* The katmai board is always configured as host. */ + return 1; +} + +int katmai_pcie_card_present(int port) +{ + u32 val; + + val = in32(GPIO0_IR); + switch (port) { + case 0: + return !(val & GPIO_VAL(CFG_GPIO_PCIE_PRESENT0)); + case 1: + return !(val & GPIO_VAL(CFG_GPIO_PCIE_PRESENT1)); + case 2: + return !(val & GPIO_VAL(CFG_GPIO_PCIE_PRESENT2)); + default: + return 0; + } +} + +static struct pci_controller pcie_hose[3] = {{0},{0},{0}}; + +void pcie_setup_hoses(void) +{ + struct pci_controller *hose; + int i, bus; + + /* + * assume we're called after the PCIX hose is initialized, which takes + * bus ID 0 and therefore start numbering PCIe's from 1. + */ + bus = 1; + for (i = 0; i <= 2; i++) { + /* Check for katmai card presence */ + if (!katmai_pcie_card_present(i)) + continue; + +#ifdef PCIE_ENDPOINT + if (ppc440spe_init_pcie_endport(i)) { +#else + if (ppc440spe_init_pcie_rootport(i)) { +#endif + printf("PCIE%d: initialization failed\n", i); + continue; + } + + hose = &pcie_hose[i]; + hose->first_busno = bus; + hose->last_busno = bus; + bus++; + + /* setup mem resource */ + pci_set_region(hose->regions + 0, + CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE, + CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE, + CFG_PCIE_MEMSIZE, + PCI_REGION_MEM + ); + hose->region_count = 1; + pci_register_hose(hose); + +#ifdef PCIE_ENDPOINT + ppc440spe_setup_pcie_endpoint(hose, i); + /* + * Reson for no scanning is endpoint can not generate + * upstream configuration accesses. + */ +#else + ppc440spe_setup_pcie_rootpoint(hose, i); + /* + * Config access can only go down stream + */ + hose->last_busno = pci_hose_scan(hose); +#endif + } +} +#endif /* defined(CONFIG_PCI) */ + +int misc_init_f (void) +{ + uint reg; +#if defined(CONFIG_STRESS) + uint i ; + uint disp; +#endif + + /* minimal init for PCIe */ +#if 0 /* test-only: test endpoint at some time, for now rootpoint only */ + /* pci express 0 Endpoint Mode */ + mfsdr(SDR0_PE0DLPSET, reg); + reg &= (~0x00400000); + mtsdr(SDR0_PE0DLPSET, reg); +#else + /* pci express 0 Rootpoint Mode */ + mfsdr(SDR0_PE0DLPSET, reg); + reg |= 0x00400000; + mtsdr(SDR0_PE0DLPSET, reg); +#endif + /* pci express 1 Rootpoint Mode */ + mfsdr(SDR0_PE1DLPSET, reg); + reg |= 0x00400000; + mtsdr(SDR0_PE1DLPSET, reg); + /* pci express 2 Rootpoint Mode */ + mfsdr(SDR0_PE2DLPSET, reg); + reg |= 0x00400000; + mtsdr(SDR0_PE2DLPSET, reg); + +#if defined(CONFIG_STRESS) + /* + * All this setting done by linux only needed by stress an charac. test + * procedure + * PCIe 1 Rootpoint PCIe2 Endpoint + * PCIe 0 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level + */ + for (i=0,disp=0; i<8; i++,disp+=3) { + mfsdr(SDR0_PE0HSSSET1L0+disp, reg); + reg |= 0x33000000; + mtsdr(SDR0_PE0HSSSET1L0+disp, reg); + } + + /*PCIe 1 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level */ + for (i=0,disp=0; i<4; i++,disp+=3) { + mfsdr(SDR0_PE1HSSSET1L0+disp, reg); + reg |= 0x33000000; + mtsdr(SDR0_PE1HSSSET1L0+disp, reg); + } + + /*PCIE 2 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level */ + for (i=0,disp=0; i<4; i++,disp+=3) { + mfsdr(SDR0_PE2HSSSET1L0+disp, reg); + reg |= 0x33000000; + mtsdr(SDR0_PE2HSSSET1L0+disp, reg); + } + + reg = 0x21242222; + mtsdr(SDR0_PE2UTLSET1, reg); + reg = 0x11000000; + mtsdr(SDR0_PE2UTLSET2, reg); + /* pci express 1 Endpoint Mode */ + reg = 0x00004000; + mtsdr(SDR0_PE2DLPSET, reg); + + mtsdr(SDR0_UART1, 0x2080005a); /* patch for TG */ +#endif + + return 0; +} + +#ifdef CONFIG_POST +/* + * Returns 1 if keys pressed to start the power-on long-running tests + * Called from board_init_f(). + */ +int post_hotkeys_pressed(void) +{ + return (ctrlc()); +} +#endif diff --git a/board/amcc/katmai/u-boot.lds b/board/amcc/katmai/u-boot.lds new file mode 100644 index 0000000..bf8fc5d --- /dev/null +++ b/board/amcc/katmai/u-boot.lds @@ -0,0 +1,141 @@ +/* + * (C) Copyright 2004 + * 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 +{ + .resetvec 0xFFFFFFFC : + { + *(.resetvec) + } = 0xffff + + .bootpg 0xFFFFF000 : + { + cpu/ppc4xx/start.o (.bootpg) + } = 0xffff + + /* 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 : + { + cpu/ppc4xx/start.o (.text) + board/amcc/katmai/init.o (.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .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/board/amcc/luan/init.S b/board/amcc/luan/init.S index 7830ebd..d5ee117 100644 --- a/board/amcc/luan/init.S +++ b/board/amcc/luan/init.S @@ -1,73 +1,31 @@ /* -* -* 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 -*/ + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 <ppc_asm.tmpl> #include <config.h> - -/* General */ -#define TLB_VALID 0x00000200 - -/* Supported page sizes */ - -#define SZ_1K 0x00000000 -#define SZ_4K 0x00000010 -#define SZ_16K 0x00000020 -#define SZ_64K 0x00000030 -#define SZ_256K 0x00000040 -#define SZ_1M 0x00000050 -#define SZ_16M 0x00000070 -#define SZ_256M 0x00000090 - -/* Storage attributes */ -#define SA_W 0x00000800 /* Write-through */ -#define SA_I 0x00000400 /* Caching inhibited */ -#define SA_M 0x00000200 /* Memory coherence */ -#define SA_G 0x00000100 /* Guarded */ -#define SA_E 0x00000080 /* Endian */ - -/* Access control */ -#define AC_X 0x00000024 /* Execute */ -#define AC_W 0x00000012 /* Write */ -#define AC_R 0x00000009 /* Read */ - -/* Some handy macros */ - -#define EPN(e) ((e) & 0xfffffc00) -#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) -#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) -#define TLB2(a) ( (a)&0x00000fbf ) - -#define tlbtab_start\ - mflr r1 ;\ - bl 0f ; - -#define tlbtab_end\ - .long 0, 0, 0 ; \ -0: mflr r0 ; \ - mtlr r1 ; \ - blr ; - -#define tlbentry(epn,sz,rpn,erpn,attr)\ - .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) - +#include <asm-ppc/mmu.h> /************************************************************************** * TLB TABLE @@ -80,53 +38,37 @@ * *************************************************************************/ - .section .bootpg,"ax" - .globl tlbtab + .section .bootpg,"ax" + .globl tlbtab tlbtab: - tlbtab_start - -#if (CFG_LARGE_FLASH == 0xffc00000) /* if booting from large flash */ - /* large flash */ - tlbentry( 0xffc00000, SZ_1M, 0xffc00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I|SA_W ) - tlbentry( 0xffd00000, SZ_1M, 0xffd00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I|SA_W ) - tlbentry( 0xffe00000, SZ_1M, 0xffe00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I|SA_W ) - tlbentry( 0xfff00000, SZ_1M, 0xfff00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I|SA_W ) - - tlbentry( 0xff800000, SZ_1M, 0xff800000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) - tlbentry( 0xff900000, SZ_1M, 0xff900000, 1, AC_R|AC_W|AC_X|SA_G|SA_I|SA_W ) -#else /* else booting from small flash */ - tlbentry( 0xffe00000, SZ_1M, 0xffe00000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) - tlbentry( 0xfff00000, SZ_1M, 0xfff00000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) - - tlbentry( 0xff800000, SZ_1M, 0xff800000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) - tlbentry( 0xff900000, SZ_1M, 0xff900000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) - tlbentry( 0xffa00000, SZ_1M, 0xffa00000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) - tlbentry( 0xffb00000, SZ_1M, 0xffb00000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) -#endif - - tlbentry( CFG_EPLD_BASE, SZ_256K, 0xff000000, 1, AC_R|AC_W|SA_G|SA_I ) - -#if (CFG_SRAM_BASE != 0) /* if SRAM up high and SDRAM at zero */ - tlbentry( 0x00000000, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( 0x10000000, SZ_256M, 0x10000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) -#elif (CFG_SMALL_FLASH == 0xff900000) /* else SRAM at 0 */ - tlbentry( 0x00000000, SZ_1M, 0xff800000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) -#elif (CFG_SMALL_FLASH == 0xfff00000) - tlbentry( 0x00000000, SZ_1M, 0xffe00000, 1, AC_R|AC_W|AC_X|SA_G/*|SA_I*/ ) -#else - #error DONT KNOW SRAM LOCATION -#endif - - /* internal ram (l2 cache) */ - tlbentry( CFG_ISRAM_BASE, SZ_256K, 0x80000000, 0, AC_R|AC_W|AC_X|SA_I ) - - /* peripherals at f0000000 */ - tlbentry( CFG_PERIPHERAL_BASE, SZ_4K, CFG_PERIPHERAL_BASE, 1, AC_R|AC_W|SA_G|SA_I ) - - /* PCI */ -#if (CONFIG_COMMANDS & CFG_CMD_PCI) - tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 9, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 9, AC_R|AC_W|SA_G|SA_I ) -#endif - tlbtab_end + tlbtab_start + + /* + * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the + * speed up boot process. It is patched after relocation to enable SA_I + */ + tlbentry(0xfff00000, SZ_1M, 0xfff00000, 1, AC_R|AC_W|AC_X|SA_G) + + tlbentry(0xffc00000, SZ_1M, 0xffc00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(0xffd00000, SZ_1M, 0xffd00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(0xffe00000, SZ_1M, 0xffe00000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(0xff900000, SZ_1M, 0xff900000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(CFG_EPLD_BASE, SZ_256K, 0xff000000, 1, AC_R|AC_W|SA_G|SA_I) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ + + /* internal ram (l2 cache) */ + tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x80000000, 0, AC_R|AC_W|AC_X|SA_I) + + /* peripherals at f0000000 */ + tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, CFG_PERIPHERAL_BASE, 1, AC_R|AC_W|SA_G|SA_I) + + /* PCI */ + tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 9, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 9, AC_R|AC_W|SA_G|SA_I) + tlbtab_end diff --git a/board/amcc/luan/luan.c b/board/amcc/luan/luan.c index 06a57f6..778aafc 100644 --- a/board/amcc/luan/luan.c +++ b/board/amcc/luan/luan.c @@ -106,105 +106,6 @@ int checkboard(void) /************************************************************************* - * long int fixed_sdram() - * - ************************************************************************/ -static long int fixed_sdram(void) -{ /* DDR2 init from BDI2000 script */ - mtdcr( 0x10, 0x00000021 ); /* MCIF0_MCOPT2 - zero DCEN bit */ - mtdcr( 0x11, 0x84000000 ); - mtdcr( 0x10, 0x00000020 ); /* MCIF0_MCOPT1 - no ECC, 64 bits, 4 banks, DDR2 */ - mtdcr( 0x11, 0x2D122000 ); - mtdcr( 0x10, 0x00000026 ); /* MCIF0_CODT - die termination on */ - mtdcr( 0x11, 0x00800026 ); - mtdcr( 0x10, 0x00000081 ); /* MCIF0_WRDTR - Write DQS Adv 90 + Fractional DQS Delay */ - mtdcr( 0x11, 0x82000800 ); - mtdcr( 0x10, 0x00000080 ); /* MCIF0_CLKTR - advance addr clock by 180 deg */ - mtdcr( 0x11, 0x80000000 ); - mtdcr( 0x10, 0x00000040 ); /* MCIF0_MB0CF - turn on CS0, N x 10 coll */ - mtdcr( 0x11, 0x00000201 ); - mtdcr( 0x10, 0x00000044 ); /* MCIF0_MB1CF - turn on CS0, N x 10 coll */ - mtdcr( 0x11, 0x00000201 ); - mtdcr( 0x10, 0x00000030 ); /* MCIF0_RTR - refresh every 7.8125uS */ - mtdcr( 0x11, 0x08200000 ); - mtdcr( 0x10, 0x00000085 ); /* MCIF0_SDTR1 - timing register 1 */ - mtdcr( 0x11, 0x80201000 ); - mtdcr( 0x10, 0x00000086 ); /* MCIF0_SDTR2 - timing register 2 */ - mtdcr( 0x11, 0x42103242 ); - mtdcr( 0x10, 0x00000087 ); /* MCIF0_SDTR3 - timing register 3 */ - mtdcr( 0x11, 0x0C100D14 ); - mtdcr( 0x10, 0x00000088 ); /* MCIF0_MMODE - CAS is 4 cycles */ - mtdcr( 0x11, 0x00000642 ); - mtdcr( 0x10, 0x00000089 ); /* MCIF0_MEMODE - diff DQS disabled */ - mtdcr( 0x11, 0x00000400 ); /* ODT term disabled */ - - mtdcr( 0x10, 0x00000050 ); /* MCIF0_INITPLR0 - NOP */ - mtdcr( 0x11, 0x81b80000 ); - mtdcr( 0x10, 0x00000051 ); /* MCIF0_INITPLR1 - PRE */ - mtdcr( 0x11, 0x82100400 ); - mtdcr( 0x10, 0x00000052 ); /* MCIF0_INITPLR2 - EMR2 */ - mtdcr( 0x11, 0x80820000 ); - mtdcr( 0x10, 0x00000053 ); /* MCIF0_INITPLR3 - EMR3 */ - mtdcr( 0x11, 0x80830000 ); - mtdcr( 0x10, 0x00000054 ); /* MCIF0_INITPLR4 - EMR DLL ENABLE */ - mtdcr( 0x11, 0x80810000 ); - mtdcr( 0x10, 0x00000055 ); /* MCIF0_INITPLR5 - MR DLL RESET */ - mtdcr( 0x11, 0x80800542 ); - mtdcr( 0x10, 0x00000056 ); /* MCIF0_INITPLR6 - PRE */ - mtdcr( 0x11, 0x82100400 ); - mtdcr( 0x10, 0x00000057 ); /* MCIF0_INITPLR7 - refresh */ - mtdcr( 0x11, 0x99080000 ); - mtdcr( 0x10, 0x00000058 ); /* MCIF0_INITPLR8 */ - mtdcr( 0x11, 0x99080000 ); - mtdcr( 0x10, 0x00000059 ); /* MCIF0_INITPLR9 */ - mtdcr( 0x11, 0x99080000 ); - mtdcr( 0x10, 0x0000005A ); /* MCIF0_INITPLR10 */ - mtdcr( 0x11, 0x99080000 ); - mtdcr( 0x10, 0x0000005B ); /* MCIF0_INITPLR11 - MR */ - mtdcr( 0x11, 0x80800442 ); - mtdcr( 0x10, 0x0000005C ); /* MCIF0_INITPLR12 - EMR OCD Default */ - mtdcr( 0x11, 0x80810380 ); - mtdcr( 0x10, 0x0000005D ); /* MCIF0_INITPLR13 - EMR OCD exit */ - mtdcr( 0x11, 0x80810000 ); - udelay( 10*1000 ); - - mtdcr( 0x10, 0x00000021 ); /* MCIF0_MCOPT2 - execute preloaded init */ - mtdcr( 0x11, 0x28000000 ); /* set DC_EN */ - udelay( 100*1000 ); - - mtdcr( 0x40, 0x0000F800 ); /* MQ0_B0BAS: base addr 00000000 / 256MB */ - mtdcr( 0x41, 0x1000F800 ); /* MQ0_B1BAS: base addr 10000000 / 256MB */ - - mtdcr( 0x10, 0x00000078 ); /* MCIF0_RDCC - auto set read stage */ - mtdcr( 0x11, 0x00000000 ); - mtdcr( 0x10, 0x00000070 ); /* MCIF0_RQDC - read DQS delay control */ - mtdcr( 0x11, 0x8000003A ); /* enabled, frac DQS delay */ - mtdcr( 0x10, 0x00000074 ); /* MCIF0_RFDC - two clock feedback delay */ - mtdcr( 0x11, 0x00000200 ); - - return 512 << 20; -} - - -/************************************************************************* - * long int initdram - * - ************************************************************************/ -long int initdram( int board_type ) -{ - long dram_size = 0; - -#if defined(CONFIG_SPD_EEPROM) - dram_size = spd_sdram (0); -#else - dram_size = fixed_sdram (); -#endif - - return dram_size; -} - - -/************************************************************************* * int testdram() * ************************************************************************/ diff --git a/board/amcc/luan/u-boot.lds b/board/amcc/luan/u-boot.lds index d122f49..72ce685 100644 --- a/board/amcc/luan/u-boot.lds +++ b/board/amcc/luan/u-boot.lds @@ -68,19 +68,6 @@ SECTIONS cpu/ppc4xx/start.o (.text) board/amcc/luan/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) diff --git a/board/amcc/ocotea/init.S b/board/amcc/ocotea/init.S index 7e0b132..d211c71 100644 --- a/board/amcc/ocotea/init.S +++ b/board/amcc/ocotea/init.S @@ -22,55 +22,7 @@ #include <ppc_asm.tmpl> #include <config.h> - -/* General */ -#define TLB_VALID 0x00000200 -#define _256M 0x10000000 - -/* Supported page sizes */ - -#define SZ_1K 0x00000000 -#define SZ_4K 0x00000010 -#define SZ_16K 0x00000020 -#define SZ_64K 0x00000030 -#define SZ_256K 0x00000040 -#define SZ_1M 0x00000050 -#define SZ_8M 0x00000060 -#define SZ_16M 0x00000070 -#define SZ_256M 0x00000090 - -/* Storage attributes */ -#define SA_W 0x00000800 /* Write-through */ -#define SA_I 0x00000400 /* Caching inhibited */ -#define SA_M 0x00000200 /* Memory coherence */ -#define SA_G 0x00000100 /* Guarded */ -#define SA_E 0x00000080 /* Endian */ - -/* Access control */ -#define AC_X 0x00000024 /* Execute */ -#define AC_W 0x00000012 /* Write */ -#define AC_R 0x00000009 /* Read */ - -/* Some handy macros */ - -#define EPN(e) ((e) & 0xfffffc00) -#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) -#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) -#define TLB2(a) ( (a)&0x00000fbf ) - -#define tlbtab_start\ - mflr r1 ;\ - bl 0f ; - -#define tlbtab_end\ - .long 0, 0, 0 ; \ -0: mflr r0 ; \ - mtlr r1 ; \ - blr ; - -#define tlbentry(epn,sz,rpn,erpn,attr)\ - .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) - +#include <asm-ppc/mmu.h> /************************************************************************** * TLB TABLE @@ -83,19 +35,23 @@ * *************************************************************************/ - .section .bootpg,"ax" - .globl tlbtab + .section .bootpg,"ax" + .globl tlbtab tlbtab: - tlbtab_start - tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X ) - tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X ) - tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_SDRAM_BASE + 0x10000000, SZ_256M, 0x10000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_SDRAM_BASE + 0x20000000, SZ_256M, 0x20000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I ) - tlbtab_end + tlbtab_start + + tlbentry(0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ + + tlbentry(CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X) + tlbentry(CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X) + tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I) + tlbtab_end diff --git a/board/amcc/sequoia/init.S b/board/amcc/sequoia/init.S index 3d4ac85..45bcd4b 100644 --- a/board/amcc/sequoia/init.S +++ b/board/amcc/sequoia/init.S @@ -90,7 +90,7 @@ tlbtab: /* * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the * speed up boot process. It is patched after relocation to enable SA_I - */ + */ #ifndef CONFIG_NAND_SPL tlbentry( CFG_BOOT_BASE_ADDR, SZ_256M, CFG_BOOT_BASE_ADDR, 1, AC_R|AC_W|AC_X|SA_G ) #else diff --git a/board/amcc/sequoia/sdram.c b/board/amcc/sequoia/sdram.c index 53f728d..f8b837e 100644 --- a/board/amcc/sequoia/sdram.c +++ b/board/amcc/sequoia/sdram.c @@ -1,5 +1,12 @@ /* * (C) Copyright 2006 + * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com + * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com + * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com + * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com + * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com + * + * (C) Copyright 2006-2007 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * This program is free software; you can redistribute it and/or @@ -18,10 +25,352 @@ * MA 02111-1307 USA */ +/* define DEBUG for debug output */ +#undef DEBUG + #include <common.h> #include <asm/processor.h> +#include <asm/io.h> #include <ppc440.h> +#include "sdram.h" + +#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) || \ + defined(CONFIG_DDR_DATA_EYE) +/*-----------------------------------------------------------------------------+ + * wait_for_dlllock. + +----------------------------------------------------------------------------*/ +static int wait_for_dlllock(void) +{ + unsigned long val; + int wait = 0; + + /* -----------------------------------------------------------+ + * Wait for the DCC master delay line to finish calibration + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_17); + val = DDR0_17_DLLLOCKREG_UNLOCKED; + + while (wait != 0xffff) { + val = mfdcr(ddrcfgd); + if ((val & DDR0_17_DLLLOCKREG_MASK) == DDR0_17_DLLLOCKREG_LOCKED) + /* dlllockreg bit on */ + return 0; + else + wait++; + } + debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val); + debug("Waiting for dlllockreg bit to raise\n"); + + return -1; +} +#endif + +#if defined(CONFIG_DDR_DATA_EYE) +/*-----------------------------------------------------------------------------+ + * wait_for_dram_init_complete. + +----------------------------------------------------------------------------*/ +int wait_for_dram_init_complete(void) +{ + unsigned long val; + int wait = 0; + + /* --------------------------------------------------------------+ + * Wait for 'DRAM initialization complete' bit in status register + * -------------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_00); + + while (wait != 0xffff) { + val = mfdcr(ddrcfgd); + if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6) + /* 'DRAM initialization complete' bit */ + return 0; + else + wait++; + } + + debug("DRAM initialization complete bit in status register did not rise\n"); + + return -1; +} + +#define NUM_TRIES 64 +#define NUM_READS 10 + +/*-----------------------------------------------------------------------------+ + * denali_core_search_data_eye. + +----------------------------------------------------------------------------*/ +void denali_core_search_data_eye(unsigned long memory_size) +{ + int k, j; + u32 val; + u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X; + u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0; + u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0; + u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0; + volatile u32 *ram_pointer; + u32 test[NUM_TRIES] = { + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 }; + + ram_pointer = (volatile u32 *)(CFG_SDRAM_BASE); + + for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) { + /*for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) {*/ + + /* -----------------------------------------------------------+ + * De-assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; + mtdcr(ddrcfgd, val); + + /* -----------------------------------------------------------+ + * Set 'wr_dqs_shift' + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_09); + val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) + | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); + mtdcr(ddrcfgd, val); + + /* -----------------------------------------------------------+ + * Set 'dqs_out_shift' = wr_dqs_shift + 32 + * ----------------------------------------------------------*/ + dqs_out_shift = wr_dqs_shift + 32; + mtdcr(ddrcfga, DDR0_22); + val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) + | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); + mtdcr(ddrcfgd, val); + + passing_cases = 0; + + for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64; dll_dqs_delay_X++) { + /*for (dll_dqs_delay_X=1; dll_dqs_delay_X<128; dll_dqs_delay_X++) {*/ + /* -----------------------------------------------------------+ + * Set 'dll_dqs_delay_X'. + * ----------------------------------------------------------*/ + /* dll_dqs_delay_0 */ + mtdcr(ddrcfga, DDR0_17); + val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) + | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + /* dll_dqs_delay_1 to dll_dqs_delay_4 */ + mtdcr(ddrcfga, DDR0_18); + val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) + | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + /* dll_dqs_delay_5 to dll_dqs_delay_8 */ + mtdcr(ddrcfga, DDR0_19); + val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) + | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + + ppcMsync(); + ppcMbar(); + + /* -----------------------------------------------------------+ + * Assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON; + mtdcr(ddrcfgd, val); + + ppcMsync(); + ppcMbar(); + + /* -----------------------------------------------------------+ + * Wait for the DCC master delay line to finish calibration + * ----------------------------------------------------------*/ + if (wait_for_dlllock() != 0) { + printf("dlllock did not occur !!!\n"); + printf("denali_core_search_data_eye!!!\n"); + printf("wr_dqs_shift = %d - dll_dqs_delay_X = %d\n", + wr_dqs_shift, dll_dqs_delay_X); + hang(); + } + ppcMsync(); + ppcMbar(); + + if (wait_for_dram_init_complete() != 0) { + printf("dram init complete did not occur !!!\n"); + printf("denali_core_search_data_eye!!!\n"); + printf("wr_dqs_shift = %d - dll_dqs_delay_X = %d\n", + wr_dqs_shift, dll_dqs_delay_X); + hang(); + } + udelay(100); /* wait 100us to ensure init is really completed !!! */ + + /* write values */ + for (j=0; j<NUM_TRIES; j++) { + ram_pointer[j] = test[j]; + + /* clear any cache at ram location */ + __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); + } + + /* read values back */ + for (j=0; j<NUM_TRIES; j++) { + for (k=0; k<NUM_READS; k++) { + /* clear any cache at ram location */ + __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); + + if (ram_pointer[j] != test[j]) + break; + } + + /* read error */ + if (k != NUM_READS) + break; + } + + /* See if the dll_dqs_delay_X value passed.*/ + if (j < NUM_TRIES) { + /* Failed */ + passing_cases = 0; + /* break; */ + } else { + /* Passed */ + if (passing_cases == 0) + dll_dqs_delay_X_sw_val = dll_dqs_delay_X; + passing_cases++; + if (passing_cases >= max_passing_cases) { + max_passing_cases = passing_cases; + wr_dqs_shift_with_max_passing_cases = wr_dqs_shift; + dll_dqs_delay_X_start_window = dll_dqs_delay_X_sw_val; + dll_dqs_delay_X_end_window = dll_dqs_delay_X; + } + } + + /* -----------------------------------------------------------+ + * De-assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; + mtdcr(ddrcfgd, val); + + } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */ + + } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */ + + /* -----------------------------------------------------------+ + * Largest passing window is now detected. + * ----------------------------------------------------------*/ + + /* Compute dll_dqs_delay_X value */ + dll_dqs_delay_X = (dll_dqs_delay_X_end_window + dll_dqs_delay_X_start_window) / 2; + wr_dqs_shift = wr_dqs_shift_with_max_passing_cases; + + debug("DQS calibration - Window detected:\n"); + debug("max_passing_cases = %d\n", max_passing_cases); + debug("wr_dqs_shift = %d\n", wr_dqs_shift); + debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X); + debug("dll_dqs_delay_X window = %d - %d\n", + dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window); + + /* -----------------------------------------------------------+ + * De-assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; + mtdcr(ddrcfgd, val); + + /* -----------------------------------------------------------+ + * Set 'wr_dqs_shift' + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_09); + val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) + | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); + mtdcr(ddrcfgd, val); + debug("DDR0_09=0x%08lx\n", val); + + /* -----------------------------------------------------------+ + * Set 'dqs_out_shift' = wr_dqs_shift + 32 + * ----------------------------------------------------------*/ + dqs_out_shift = wr_dqs_shift + 32; + mtdcr(ddrcfga, DDR0_22); + val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) + | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); + mtdcr(ddrcfgd, val); + debug("DDR0_22=0x%08lx\n", val); + + /* -----------------------------------------------------------+ + * Set 'dll_dqs_delay_X'. + * ----------------------------------------------------------*/ + /* dll_dqs_delay_0 */ + mtdcr(ddrcfga, DDR0_17); + val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) + | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + debug("DDR0_17=0x%08lx\n", val); + + /* dll_dqs_delay_1 to dll_dqs_delay_4 */ + mtdcr(ddrcfga, DDR0_18); + val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) + | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + debug("DDR0_18=0x%08lx\n", val); + + /* dll_dqs_delay_5 to dll_dqs_delay_8 */ + mtdcr(ddrcfga, DDR0_19); + val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) + | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + debug("DDR0_19=0x%08lx\n", val); + + /* -----------------------------------------------------------+ + * Assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON; + mtdcr(ddrcfgd, val); + + ppcMsync(); + ppcMbar(); + + /* -----------------------------------------------------------+ + * Wait for the DCC master delay line to finish calibration + * ----------------------------------------------------------*/ + if (wait_for_dlllock() != 0) { + printf("dlllock did not occur !!!\n"); + hang(); + } + ppcMsync(); + ppcMbar(); + + if (wait_for_dram_init_complete() != 0) { + printf("dram init complete did not occur !!!\n"); + hang(); + } + udelay(100); /* wait 100us to ensure init is really completed !!! */ +} +#endif /* CONFIG_DDR_DATA_EYE */ + /************************************************************************* * * initdram -- 440EPx's DDR controller is a DENALI Core @@ -30,18 +379,18 @@ long int initdram (int board_type) { #if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) - volatile ulong val; + ulong speed = get_bus_freq(0); mtsdram(DDR0_02, 0x00000000); mtsdram(DDR0_00, 0x0000190A); mtsdram(DDR0_01, 0x01000000); mtsdram(DDR0_03, 0x02030602); - mtsdram(DDR0_04, 0x13030300); - mtsdram(DDR0_05, 0x0202050E); - mtsdram(DDR0_06, 0x0104C823); + mtsdram(DDR0_04, 0x0A020200); + mtsdram(DDR0_05, 0x02020308); + mtsdram(DDR0_06, 0x0102C812); mtsdram(DDR0_07, 0x000D0100); - mtsdram(DDR0_08, 0x02360001); + mtsdram(DDR0_08, 0x02430001); mtsdram(DDR0_09, 0x00011D5F); mtsdram(DDR0_10, 0x00000300); mtsdram(DDR0_11, 0x0027C800); @@ -55,23 +404,27 @@ long int initdram (int board_type) mtsdram(DDR0_22, 0x00267F0B); mtsdram(DDR0_23, 0x00000000); mtsdram(DDR0_24, 0x01010002); - mtsdram(DDR0_26, 0x5B260181); + if (speed > 133333333) + mtsdram(DDR0_26, 0x5B26050C); + else + mtsdram(DDR0_26, 0x5B260408); mtsdram(DDR0_27, 0x0000682B); mtsdram(DDR0_28, 0x00000000); mtsdram(DDR0_31, 0x00000000); mtsdram(DDR0_42, 0x01000006); - mtsdram(DDR0_43, 0x050A0200); - mtsdram(DDR0_44, 0x00000005); + mtsdram(DDR0_43, 0x030A0200); + mtsdram(DDR0_44, 0x00000003); mtsdram(DDR0_02, 0x00000001); - /* - * Wait for DCC master delay line to finish calibration - */ - mfsdram(DDR0_17, val); - while (((val >> 8) & 0x000007f) == 0) { - mfsdram(DDR0_17, val); - } + wait_for_dlllock(); #endif /* #ifndef CONFIG_NAND_U_BOOT */ +#ifdef CONFIG_DDR_DATA_EYE + /* -----------------------------------------------------------+ + * Perform data eye search if requested. + * ----------------------------------------------------------*/ + denali_core_search_data_eye(CFG_MBYTES_SDRAM << 20); +#endif + return (CFG_MBYTES_SDRAM << 20); } diff --git a/board/amcc/sequoia/sdram.h b/board/amcc/sequoia/sdram.h new file mode 100644 index 0000000..7f847aa --- /dev/null +++ b/board/amcc/sequoia/sdram.h @@ -0,0 +1,505 @@ +/* + * (C) Copyright 2006 + * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com + * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com + * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com + * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com + * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _SPD_SDRAM_DENALI_H_ +#define _SPD_SDRAM_DENALI_H_ + +#define ppcMsync sync +#define ppcMbar eieio + +/* General definitions */ +#define MAX_SPD_BYTE 128 /* highest SPD byte # to read */ +#define DENALI_REG_NUMBER 45 /* 45 Regs in PPC440EPx Denali Core */ +#define SUPPORTED_DIMMS_NB 7 /* Number of supported DIMM modules types */ +#define SDRAM_NONE 0 /* No DIMM detected in Slot */ +#define MAXRANKS 2 /* 2 ranks maximum */ + +/* Supported PLB Frequencies */ +#define PLB_FREQ_133MHZ 133333333 +#define PLB_FREQ_152MHZ 152000000 +#define PLB_FREQ_160MHZ 160000000 +#define PLB_FREQ_166MHZ 166666666 + +/* Denali Core Registers */ +#define SDRAM_DCR_BASE 0x10 + +#define DDR_DCR_BASE 0x10 +#define ddrcfga (DDR_DCR_BASE+0x0) /* DDR configuration address reg */ +#define ddrcfgd (DDR_DCR_BASE+0x1) /* DDR configuration data reg */ + +/*-----------------------------------------------------------------------------+ + | Values for ddrcfga register - indirect addressing of these regs + +-----------------------------------------------------------------------------*/ + +#define DDR0_00 0x00 +#define DDR0_00_INT_ACK_MASK 0x7F000000 /* Write only */ +#define DDR0_00_INT_ACK_ALL 0x7F000000 +#define DDR0_00_INT_ACK_ENCODE(n) ((((unsigned long)(n))&0x7F)<<24) +#define DDR0_00_INT_ACK_DECODE(n) ((((unsigned long)(n))>>24)&0x7F) +/* Status */ +#define DDR0_00_INT_STATUS_MASK 0x00FF0000 /* Read only */ +/* Bit0. A single access outside the defined PHYSICAL memory space detected. */ +#define DDR0_00_INT_STATUS_BIT0 0x00010000 +/* Bit1. Multiple accesses outside the defined PHYSICAL memory space detected. */ +#define DDR0_00_INT_STATUS_BIT1 0x00020000 +/* Bit2. Single correctable ECC event detected */ +#define DDR0_00_INT_STATUS_BIT2 0x00040000 +/* Bit3. Multiple correctable ECC events detected. */ +#define DDR0_00_INT_STATUS_BIT3 0x00080000 +/* Bit4. Single uncorrectable ECC event detected. */ +#define DDR0_00_INT_STATUS_BIT4 0x00100000 +/* Bit5. Multiple uncorrectable ECC events detected. */ +#define DDR0_00_INT_STATUS_BIT5 0x00200000 +/* Bit6. DRAM initialization complete. */ +#define DDR0_00_INT_STATUS_BIT6 0x00400000 +/* Bit7. Logical OR of all lower bits. */ +#define DDR0_00_INT_STATUS_BIT7 0x00800000 + +#define DDR0_00_INT_STATUS_ENCODE(n) ((((unsigned long)(n))&0xFF)<<16) +#define DDR0_00_INT_STATUS_DECODE(n) ((((unsigned long)(n))>>16)&0xFF) +#define DDR0_00_DLL_INCREMENT_MASK 0x00007F00 +#define DDR0_00_DLL_INCREMENT_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_00_DLL_INCREMENT_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_00_DLL_START_POINT_MASK 0x0000007F +#define DDR0_00_DLL_START_POINT_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_00_DLL_START_POINT_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + + +#define DDR0_01 0x01 +#define DDR0_01_PLB0_DB_CS_LOWER_MASK 0x1F000000 +#define DDR0_01_PLB0_DB_CS_LOWER_ENCODE(n) ((((unsigned long)(n))&0x1F)<<24) +#define DDR0_01_PLB0_DB_CS_LOWER_DECODE(n) ((((unsigned long)(n))>>24)&0x1F) +#define DDR0_01_PLB0_DB_CS_UPPER_MASK 0x001F0000 +#define DDR0_01_PLB0_DB_CS_UPPER_ENCODE(n) ((((unsigned long)(n))&0x1F)<<16) +#define DDR0_01_PLB0_DB_CS_UPPER_DECODE(n) ((((unsigned long)(n))>>16)&0x1F) +#define DDR0_01_OUT_OF_RANGE_TYPE_MASK 0x00000700 /* Read only */ +#define DDR0_01_OUT_OF_RANGE_TYPE_ENCODE(n) ((((unsigned long)(n))&0x7)<<8) +#define DDR0_01_OUT_OF_RANGE_TYPE_DECODE(n) ((((unsigned long)(n))>>8)&0x7) +#define DDR0_01_INT_MASK_MASK 0x000000FF +#define DDR0_01_INT_MASK_ENCODE(n) ((((unsigned long)(n))&0xFF)<<0) +#define DDR0_01_INT_MASK_DECODE(n) ((((unsigned long)(n))>>0)&0xFF) +#define DDR0_01_INT_MASK_ALL_ON 0x000000FF +#define DDR0_01_INT_MASK_ALL_OFF 0x00000000 + +#define DDR0_02 0x02 +#define DDR0_02_MAX_CS_REG_MASK 0x02000000 /* Read only */ +#define DDR0_02_MAX_CS_REG_ENCODE(n) ((((unsigned long)(n))&0x2)<<24) +#define DDR0_02_MAX_CS_REG_DECODE(n) ((((unsigned long)(n))>>24)&0x2) +#define DDR0_02_MAX_COL_REG_MASK 0x000F0000 /* Read only */ +#define DDR0_02_MAX_COL_REG_ENCODE(n) ((((unsigned long)(n))&0xF)<<16) +#define DDR0_02_MAX_COL_REG_DECODE(n) ((((unsigned long)(n))>>16)&0xF) +#define DDR0_02_MAX_ROW_REG_MASK 0x00000F00 /* Read only */ +#define DDR0_02_MAX_ROW_REG_ENCODE(n) ((((unsigned long)(n))&0xF)<<8) +#define DDR0_02_MAX_ROW_REG_DECODE(n) ((((unsigned long)(n))>>8)&0xF) +#define DDR0_02_START_MASK 0x00000001 +#define DDR0_02_START_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_02_START_DECODE(n) ((((unsigned long)(n))>>0)&0x1) +#define DDR0_02_START_OFF 0x00000000 +#define DDR0_02_START_ON 0x00000001 + +#define DDR0_03 0x03 +#define DDR0_03_BSTLEN_MASK 0x07000000 +#define DDR0_03_BSTLEN_ENCODE(n) ((((unsigned long)(n))&0x7)<<24) +#define DDR0_03_BSTLEN_DECODE(n) ((((unsigned long)(n))>>24)&0x7) +#define DDR0_03_CASLAT_MASK 0x00070000 +#define DDR0_03_CASLAT_ENCODE(n) ((((unsigned long)(n))&0x7)<<16) +#define DDR0_03_CASLAT_DECODE(n) ((((unsigned long)(n))>>16)&0x7) +#define DDR0_03_CASLAT_LIN_MASK 0x00000F00 +#define DDR0_03_CASLAT_LIN_ENCODE(n) ((((unsigned long)(n))&0xF)<<8) +#define DDR0_03_CASLAT_LIN_DECODE(n) ((((unsigned long)(n))>>8)&0xF) +#define DDR0_03_INITAREF_MASK 0x0000000F +#define DDR0_03_INITAREF_ENCODE(n) ((((unsigned long)(n))&0xF)<<0) +#define DDR0_03_INITAREF_DECODE(n) ((((unsigned long)(n))>>0)&0xF) + +#define DDR0_04 0x04 +#define DDR0_04_TRC_MASK 0x1F000000 +#define DDR0_04_TRC_ENCODE(n) ((((unsigned long)(n))&0x1F)<<24) +#define DDR0_04_TRC_DECODE(n) ((((unsigned long)(n))>>24)&0x1F) +#define DDR0_04_TRRD_MASK 0x00070000 +#define DDR0_04_TRRD_ENCODE(n) ((((unsigned long)(n))&0x7)<<16) +#define DDR0_04_TRRD_DECODE(n) ((((unsigned long)(n))>>16)&0x7) +#define DDR0_04_TRTP_MASK 0x00000700 +#define DDR0_04_TRTP_ENCODE(n) ((((unsigned long)(n))&0x7)<<8) +#define DDR0_04_TRTP_DECODE(n) ((((unsigned long)(n))>>8)&0x7) + +#define DDR0_05 0x05 +#define DDR0_05_TMRD_MASK 0x1F000000 +#define DDR0_05_TMRD_ENCODE(n) ((((unsigned long)(n))&0x1F)<<24) +#define DDR0_05_TMRD_DECODE(n) ((((unsigned long)(n))>>24)&0x1F) +#define DDR0_05_TEMRS_MASK 0x00070000 +#define DDR0_05_TEMRS_ENCODE(n) ((((unsigned long)(n))&0x7)<<16) +#define DDR0_05_TEMRS_DECODE(n) ((((unsigned long)(n))>>16)&0x7) +#define DDR0_05_TRP_MASK 0x00000F00 +#define DDR0_05_TRP_ENCODE(n) ((((unsigned long)(n))&0xF)<<8) +#define DDR0_05_TRP_DECODE(n) ((((unsigned long)(n))>>8)&0xF) +#define DDR0_05_TRAS_MIN_MASK 0x000000FF +#define DDR0_05_TRAS_MIN_ENCODE(n) ((((unsigned long)(n))&0xFF)<<0) +#define DDR0_05_TRAS_MIN_DECODE(n) ((((unsigned long)(n))>>0)&0xFF) + +#define DDR0_06 0x06 +#define DDR0_06_WRITEINTERP_MASK 0x01000000 +#define DDR0_06_WRITEINTERP_ENCODE(n) ((((unsigned long)(n))&0x1)<<24) +#define DDR0_06_WRITEINTERP_DECODE(n) ((((unsigned long)(n))>>24)&0x1) +#define DDR0_06_TWTR_MASK 0x00070000 +#define DDR0_06_TWTR_ENCODE(n) ((((unsigned long)(n))&0x7)<<16) +#define DDR0_06_TWTR_DECODE(n) ((((unsigned long)(n))>>16)&0x7) +#define DDR0_06_TDLL_MASK 0x0000FF00 +#define DDR0_06_TDLL_ENCODE(n) ((((unsigned long)(n))&0xFF)<<8) +#define DDR0_06_TDLL_DECODE(n) ((((unsigned long)(n))>>8)&0xFF) +#define DDR0_06_TRFC_MASK 0x0000007F +#define DDR0_06_TRFC_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_06_TRFC_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + +#define DDR0_07 0x07 +#define DDR0_07_NO_CMD_INIT_MASK 0x01000000 +#define DDR0_07_NO_CMD_INIT_ENCODE(n) ((((unsigned long)(n))&0x1)<<24) +#define DDR0_07_NO_CMD_INIT_DECODE(n) ((((unsigned long)(n))>>24)&0x1) +#define DDR0_07_TFAW_MASK 0x001F0000 +#define DDR0_07_TFAW_ENCODE(n) ((((unsigned long)(n))&0x1F)<<16) +#define DDR0_07_TFAW_DECODE(n) ((((unsigned long)(n))>>16)&0x1F) +#define DDR0_07_AUTO_REFRESH_MODE_MASK 0x00000100 +#define DDR0_07_AUTO_REFRESH_MODE_ENCODE(n) ((((unsigned long)(n))&0x1)<<8) +#define DDR0_07_AUTO_REFRESH_MODE_DECODE(n) ((((unsigned long)(n))>>8)&0x1) +#define DDR0_07_AREFRESH_MASK 0x00000001 +#define DDR0_07_AREFRESH_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_07_AREFRESH_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_08 0x08 +#define DDR0_08_WRLAT_MASK 0x07000000 +#define DDR0_08_WRLAT_ENCODE(n) ((((unsigned long)(n))&0x7)<<24) +#define DDR0_08_WRLAT_DECODE(n) ((((unsigned long)(n))>>24)&0x7) +#define DDR0_08_TCPD_MASK 0x00FF0000 +#define DDR0_08_TCPD_ENCODE(n) ((((unsigned long)(n))&0xFF)<<16) +#define DDR0_08_TCPD_DECODE(n) ((((unsigned long)(n))>>16)&0xFF) +#define DDR0_08_DQS_N_EN_MASK 0x00000100 +#define DDR0_08_DQS_N_EN_ENCODE(n) ((((unsigned long)(n))&0x1)<<8) +#define DDR0_08_DQS_N_EN_DECODE(n) ((((unsigned long)(n))>>8)&0x1) +#define DDR0_08_DDRII_SDRAM_MODE_MASK 0x00000001 +#define DDR0_08_DDRII_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_08_DDRII_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_09 0x09 +#define DDR0_09_OCD_ADJUST_PDN_CS_0_MASK 0x1F000000 +#define DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(n) ((((unsigned long)(n))&0x1F)<<24) +#define DDR0_09_OCD_ADJUST_PDN_CS_0_DECODE(n) ((((unsigned long)(n))>>24)&0x1F) +#define DDR0_09_RTT_0_MASK 0x00030000 +#define DDR0_09_RTT_0_ENCODE(n) ((((unsigned long)(n))&0x3)<<16) +#define DDR0_09_RTT_0_DECODE(n) ((((unsigned long)(n))>>16)&0x3) +#define DDR0_09_WR_DQS_SHIFT_BYPASS_MASK 0x00007F00 +#define DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_09_WR_DQS_SHIFT_BYPASS_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_09_WR_DQS_SHIFT_MASK 0x0000007F +#define DDR0_09_WR_DQS_SHIFT_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_09_WR_DQS_SHIFT_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + +#define DDR0_10 0x0A +#define DDR0_10_WRITE_MODEREG_MASK 0x00010000 /* Write only */ +#define DDR0_10_WRITE_MODEREG_ENCODE(n) ((((unsigned long)(n))&0x1)<<16) +#define DDR0_10_WRITE_MODEREG_DECODE(n) ((((unsigned long)(n))>>16)&0x1) +#define DDR0_10_CS_MAP_MASK 0x00000300 +#define DDR0_10_CS_MAP_NO_MEM 0x00000000 +#define DDR0_10_CS_MAP_RANK0_INSTALLED 0x00000100 +#define DDR0_10_CS_MAP_RANK1_INSTALLED 0x00000200 +#define DDR0_10_CS_MAP_ENCODE(n) ((((unsigned long)(n))&0x3)<<8) +#define DDR0_10_CS_MAP_DECODE(n) ((((unsigned long)(n))>>8)&0x3) +#define DDR0_10_OCD_ADJUST_PUP_CS_0_MASK 0x0000001F +#define DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(n) ((((unsigned long)(n))&0x1F)<<0) +#define DDR0_10_OCD_ADJUST_PUP_CS_0_DECODE(n) ((((unsigned long)(n))>>0)&0x1F) + +#define DDR0_11 0x0B +#define DDR0_11_SREFRESH_MASK 0x01000000 +#define DDR0_11_SREFRESH_ENCODE(n) ((((unsigned long)(n))&0x1)<<24) +#define DDR0_11_SREFRESH_DECODE(n) ((((unsigned long)(n))>>24)&0x1F) +#define DDR0_11_TXSNR_MASK 0x00FF0000 +#define DDR0_11_TXSNR_ENCODE(n) ((((unsigned long)(n))&0xFF)<<16) +#define DDR0_11_TXSNR_DECODE(n) ((((unsigned long)(n))>>16)&0xFF) +#define DDR0_11_TXSR_MASK 0x0000FF00 +#define DDR0_11_TXSR_ENCODE(n) ((((unsigned long)(n))&0xFF)<<8) +#define DDR0_11_TXSR_DECODE(n) ((((unsigned long)(n))>>8)&0xFF) + +#define DDR0_12 0x0C +#define DDR0_12_TCKE_MASK 0x0000007 +#define DDR0_12_TCKE_ENCODE(n) ((((unsigned long)(n))&0x7)<<0) +#define DDR0_12_TCKE_DECODE(n) ((((unsigned long)(n))>>0)&0x7) + +#define DDR0_13 0x0D + +#define DDR0_14 0x0E +#define DDR0_14_DLL_BYPASS_MODE_MASK 0x01000000 +#define DDR0_14_DLL_BYPASS_MODE_ENCODE(n) ((((unsigned long)(n))&0x1)<<24) +#define DDR0_14_DLL_BYPASS_MODE_DECODE(n) ((((unsigned long)(n))>>24)&0x1) +#define DDR0_14_REDUC_MASK 0x00010000 +#define DDR0_14_REDUC_64BITS 0x00000000 +#define DDR0_14_REDUC_32BITS 0x00010000 +#define DDR0_14_REDUC_ENCODE(n) ((((unsigned long)(n))&0x1)<<16) +#define DDR0_14_REDUC_DECODE(n) ((((unsigned long)(n))>>16)&0x1) +#define DDR0_14_REG_DIMM_ENABLE_MASK 0x00000100 +#define DDR0_14_REG_DIMM_ENABLE_ENCODE(n) ((((unsigned long)(n))&0x1)<<8) +#define DDR0_14_REG_DIMM_ENABLE_DECODE(n) ((((unsigned long)(n))>>8)&0x1) + +#define DDR0_15 0x0F + +#define DDR0_16 0x10 + +#define DDR0_17 0x11 +#define DDR0_17_DLL_DQS_DELAY_0_MASK 0x7F000000 +#define DDR0_17_DLL_DQS_DELAY_0_ENCODE(n) ((((unsigned long)(n))&0x7F)<<24) +#define DDR0_17_DLL_DQS_DELAY_0_DECODE(n) ((((unsigned long)(n))>>24)&0x7F) +#define DDR0_17_DLLLOCKREG_MASK 0x00010000 /* Read only */ +#define DDR0_17_DLLLOCKREG_LOCKED 0x00010000 +#define DDR0_17_DLLLOCKREG_UNLOCKED 0x00000000 +#define DDR0_17_DLLLOCKREG_ENCODE(n) ((((unsigned long)(n))&0x1)<<16) +#define DDR0_17_DLLLOCKREG_DECODE(n) ((((unsigned long)(n))>>16)&0x1) +#define DDR0_17_DLL_LOCK_MASK 0x00007F00 /* Read only */ +#define DDR0_17_DLL_LOCK_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_17_DLL_LOCK_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) + +#define DDR0_18 0x12 +#define DDR0_18_DLL_DQS_DELAY_X_MASK 0x7F7F7F7F +#define DDR0_18_DLL_DQS_DELAY_4_MASK 0x7F000000 +#define DDR0_18_DLL_DQS_DELAY_4_ENCODE(n) ((((unsigned long)(n))&0x7F)<<24) +#define DDR0_18_DLL_DQS_DELAY_4_DECODE(n) ((((unsigned long)(n))>>24)&0x7F) +#define DDR0_18_DLL_DQS_DELAY_3_MASK 0x007F0000 +#define DDR0_18_DLL_DQS_DELAY_3_ENCODE(n) ((((unsigned long)(n))&0x7F)<<16) +#define DDR0_18_DLL_DQS_DELAY_3_DECODE(n) ((((unsigned long)(n))>>16)&0x7F) +#define DDR0_18_DLL_DQS_DELAY_2_MASK 0x00007F00 +#define DDR0_18_DLL_DQS_DELAY_2_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_18_DLL_DQS_DELAY_2_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_18_DLL_DQS_DELAY_1_MASK 0x0000007F +#define DDR0_18_DLL_DQS_DELAY_1_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_18_DLL_DQS_DELAY_1_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + +#define DDR0_19 0x13 +#define DDR0_19_DLL_DQS_DELAY_X_MASK 0x7F7F7F7F +#define DDR0_19_DLL_DQS_DELAY_8_MASK 0x7F000000 +#define DDR0_19_DLL_DQS_DELAY_8_ENCODE(n) ((((unsigned long)(n))&0x7F)<<24) +#define DDR0_19_DLL_DQS_DELAY_8_DECODE(n) ((((unsigned long)(n))>>24)&0x7F) +#define DDR0_19_DLL_DQS_DELAY_7_MASK 0x007F0000 +#define DDR0_19_DLL_DQS_DELAY_7_ENCODE(n) ((((unsigned long)(n))&0x7F)<<16) +#define DDR0_19_DLL_DQS_DELAY_7_DECODE(n) ((((unsigned long)(n))>>16)&0x7F) +#define DDR0_19_DLL_DQS_DELAY_6_MASK 0x00007F00 +#define DDR0_19_DLL_DQS_DELAY_6_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_19_DLL_DQS_DELAY_6_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_19_DLL_DQS_DELAY_5_MASK 0x0000007F +#define DDR0_19_DLL_DQS_DELAY_5_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_19_DLL_DQS_DELAY_5_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + +#define DDR0_20 0x14 +#define DDR0_20_DLL_DQS_BYPASS_3_MASK 0x7F000000 +#define DDR0_20_DLL_DQS_BYPASS_3_ENCODE(n) ((((unsigned long)(n))&0x7F)<<24) +#define DDR0_20_DLL_DQS_BYPASS_3_DECODE(n) ((((unsigned long)(n))>>24)&0x7F) +#define DDR0_20_DLL_DQS_BYPASS_2_MASK 0x007F0000 +#define DDR0_20_DLL_DQS_BYPASS_2_ENCODE(n) ((((unsigned long)(n))&0x7F)<<16) +#define DDR0_20_DLL_DQS_BYPASS_2_DECODE(n) ((((unsigned long)(n))>>16)&0x7F) +#define DDR0_20_DLL_DQS_BYPASS_1_MASK 0x00007F00 +#define DDR0_20_DLL_DQS_BYPASS_1_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_20_DLL_DQS_BYPASS_1_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_20_DLL_DQS_BYPASS_0_MASK 0x0000007F +#define DDR0_20_DLL_DQS_BYPASS_0_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_20_DLL_DQS_BYPASS_0_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + +#define DDR0_21 0x15 +#define DDR0_21_DLL_DQS_BYPASS_7_MASK 0x7F000000 +#define DDR0_21_DLL_DQS_BYPASS_7_ENCODE(n) ((((unsigned long)(n))&0x7F)<<24) +#define DDR0_21_DLL_DQS_BYPASS_7_DECODE(n) ((((unsigned long)(n))>>24)&0x7F) +#define DDR0_21_DLL_DQS_BYPASS_6_MASK 0x007F0000 +#define DDR0_21_DLL_DQS_BYPASS_6_ENCODE(n) ((((unsigned long)(n))&0x7F)<<16) +#define DDR0_21_DLL_DQS_BYPASS_6_DECODE(n) ((((unsigned long)(n))>>16)&0x7F) +#define DDR0_21_DLL_DQS_BYPASS_5_MASK 0x00007F00 +#define DDR0_21_DLL_DQS_BYPASS_5_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_21_DLL_DQS_BYPASS_5_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_21_DLL_DQS_BYPASS_4_MASK 0x0000007F +#define DDR0_21_DLL_DQS_BYPASS_4_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_21_DLL_DQS_BYPASS_4_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + +#define DDR0_22 0x16 +/* ECC */ +#define DDR0_22_CTRL_RAW_MASK 0x03000000 +#define DDR0_22_CTRL_RAW_ECC_DISABLE 0x00000000 /* ECC not being used */ +#define DDR0_22_CTRL_RAW_ECC_CHECK_ONLY 0x01000000 /* ECC checking is on, but no attempts to correct*/ +#define DDR0_22_CTRL_RAW_NO_ECC_RAM 0x02000000 /* No ECC RAM storage available */ +#define DDR0_22_CTRL_RAW_ECC_ENABLE 0x03000000 /* ECC checking and correcting on */ +#define DDR0_22_CTRL_RAW_ENCODE(n) ((((unsigned long)(n))&0x3)<<24) +#define DDR0_22_CTRL_RAW_DECODE(n) ((((unsigned long)(n))>>24)&0x3) + +#define DDR0_22_DQS_OUT_SHIFT_BYPASS_MASK 0x007F0000 +#define DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(n) ((((unsigned long)(n))&0x7F)<<16) +#define DDR0_22_DQS_OUT_SHIFT_BYPASS_DECODE(n) ((((unsigned long)(n))>>16)&0x7F) +#define DDR0_22_DQS_OUT_SHIFT_MASK 0x00007F00 +#define DDR0_22_DQS_OUT_SHIFT_ENCODE(n) ((((unsigned long)(n))&0x7F)<<8) +#define DDR0_22_DQS_OUT_SHIFT_DECODE(n) ((((unsigned long)(n))>>8)&0x7F) +#define DDR0_22_DLL_DQS_BYPASS_8_MASK 0x0000007F +#define DDR0_22_DLL_DQS_BYPASS_8_ENCODE(n) ((((unsigned long)(n))&0x7F)<<0) +#define DDR0_22_DLL_DQS_BYPASS_8_DECODE(n) ((((unsigned long)(n))>>0)&0x7F) + + +#define DDR0_23 0x17 +#define DDR0_23_ODT_RD_MAP_CS0_MASK 0x03000000 +#define DDR0_23_ODT_RD_MAP_CS0_ENCODE(n) ((((unsigned long)(n))&0x3)<<24) +#define DDR0_23_ODT_RD_MAP_CS0_DECODE(n) ((((unsigned long)(n))>>24)&0x3) +#define DDR0_23_ECC_C_SYND_MASK 0x00FF0000 /* Read only */ +#define DDR0_23_ECC_C_SYND_ENCODE(n) ((((unsigned long)(n))&0xFF)<<16) +#define DDR0_23_ECC_C_SYND_DECODE(n) ((((unsigned long)(n))>>16)&0xFF) +#define DDR0_23_ECC_U_SYND_MASK 0x0000FF00 /* Read only */ +#define DDR0_23_ECC_U_SYND_ENCODE(n) ((((unsigned long)(n))&0xFF)<<8) +#define DDR0_23_ECC_U_SYND_DECODE(n) ((((unsigned long)(n))>>8)&0xFF) +#define DDR0_23_FWC_MASK 0x00000001 /* Write only */ +#define DDR0_23_FWC_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_23_FWC_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_24 0x18 +#define DDR0_24_RTT_PAD_TERMINATION_MASK 0x03000000 +#define DDR0_24_RTT_PAD_TERMINATION_ENCODE(n) ((((unsigned long)(n))&0x3)<<24) +#define DDR0_24_RTT_PAD_TERMINATION_DECODE(n) ((((unsigned long)(n))>>24)&0x3) +#define DDR0_24_ODT_WR_MAP_CS1_MASK 0x00030000 +#define DDR0_24_ODT_WR_MAP_CS1_ENCODE(n) ((((unsigned long)(n))&0x3)<<16) +#define DDR0_24_ODT_WR_MAP_CS1_DECODE(n) ((((unsigned long)(n))>>16)&0x3) +#define DDR0_24_ODT_RD_MAP_CS1_MASK 0x00000300 +#define DDR0_24_ODT_RD_MAP_CS1_ENCODE(n) ((((unsigned long)(n))&0x3)<<8) +#define DDR0_24_ODT_RD_MAP_CS1_DECODE(n) ((((unsigned long)(n))>>8)&0x3) +#define DDR0_24_ODT_WR_MAP_CS0_MASK 0x00000003 +#define DDR0_24_ODT_WR_MAP_CS0_ENCODE(n) ((((unsigned long)(n))&0x3)<<0) +#define DDR0_24_ODT_WR_MAP_CS0_DECODE(n) ((((unsigned long)(n))>>0)&0x3) + +#define DDR0_25 0x19 +#define DDR0_25_VERSION_MASK 0xFFFF0000 /* Read only */ +#define DDR0_25_VERSION_ENCODE(n) ((((unsigned long)(n))&0xFFFF)<<16) +#define DDR0_25_VERSION_DECODE(n) ((((unsigned long)(n))>>16)&0xFFFF) +#define DDR0_25_OUT_OF_RANGE_LENGTH_MASK 0x000003FF /* Read only */ +#define DDR0_25_OUT_OF_RANGE_LENGTH_ENCODE(n) ((((unsigned long)(n))&0x3FF)<<0) +#define DDR0_25_OUT_OF_RANGE_LENGTH_DECODE(n) ((((unsigned long)(n))>>0)&0x3FF) + +#define DDR0_26 0x1A +#define DDR0_26_TRAS_MAX_MASK 0xFFFF0000 +#define DDR0_26_TRAS_MAX_ENCODE(n) ((((unsigned long)(n))&0xFFFF)<<16) +#define DDR0_26_TRAS_MAX_DECODE(n) ((((unsigned long)(n))>>16)&0xFFFF) +#define DDR0_26_TREF_MASK 0x00003FFF +#define DDR0_26_TREF_ENCODE(n) ((((unsigned long)(n))&0x3FF)<<0) +#define DDR0_26_TREF_DECODE(n) ((((unsigned long)(n))>>0)&0x3FF) + +#define DDR0_27 0x1B +#define DDR0_27_EMRS_DATA_MASK 0x3FFF0000 +#define DDR0_27_EMRS_DATA_ENCODE(n) ((((unsigned long)(n))&0x3FFF)<<16) +#define DDR0_27_EMRS_DATA_DECODE(n) ((((unsigned long)(n))>>16)&0x3FFF) +#define DDR0_27_TINIT_MASK 0x0000FFFF +#define DDR0_27_TINIT_ENCODE(n) ((((unsigned long)(n))&0xFFFF)<<0) +#define DDR0_27_TINIT_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFF) + +#define DDR0_28 0x1C +#define DDR0_28_EMRS3_DATA_MASK 0x3FFF0000 +#define DDR0_28_EMRS3_DATA_ENCODE(n) ((((unsigned long)(n))&0x3FFF)<<16) +#define DDR0_28_EMRS3_DATA_DECODE(n) ((((unsigned long)(n))>>16)&0x3FFF) +#define DDR0_28_EMRS2_DATA_MASK 0x00003FFF +#define DDR0_28_EMRS2_DATA_ENCODE(n) ((((unsigned long)(n))&0x3FFF)<<0) +#define DDR0_28_EMRS2_DATA_DECODE(n) ((((unsigned long)(n))>>0)&0x3FFF) + +#define DDR0_29 0x1D + +#define DDR0_30 0x1E + +#define DDR0_31 0x1F +#define DDR0_31_XOR_CHECK_BITS_MASK 0x0000FFFF +#define DDR0_31_XOR_CHECK_BITS_ENCODE(n) ((((unsigned long)(n))&0xFFFF)<<0) +#define DDR0_31_XOR_CHECK_BITS_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFF) + +#define DDR0_32 0x20 +#define DDR0_32_OUT_OF_RANGE_ADDR_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_32_OUT_OF_RANGE_ADDR_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_32_OUT_OF_RANGE_ADDR_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_33 0x21 +#define DDR0_33_OUT_OF_RANGE_ADDR_MASK 0x00000001 /* Read only */ +#define DDR0_33_OUT_OF_RANGE_ADDR_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_33_OUT_OF_RANGE_ADDR_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_34 0x22 +#define DDR0_34_ECC_U_ADDR_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_34_ECC_U_ADDR_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_34_ECC_U_ADDR_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_35 0x23 +#define DDR0_35_ECC_U_ADDR_MASK 0x00000001 /* Read only */ +#define DDR0_35_ECC_U_ADDR_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_35_ECC_U_ADDR_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_36 0x24 +#define DDR0_36_ECC_U_DATA_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_36_ECC_U_DATA_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_36_ECC_U_DATA_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_37 0x25 +#define DDR0_37_ECC_U_DATA_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_37_ECC_U_DATA_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_37_ECC_U_DATA_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_38 0x26 +#define DDR0_38_ECC_C_ADDR_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_38_ECC_C_ADDR_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_38_ECC_C_ADDR_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_39 0x27 +#define DDR0_39_ECC_C_ADDR_MASK 0x00000001 /* Read only */ +#define DDR0_39_ECC_C_ADDR_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_39_ECC_C_ADDR_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_40 0x28 +#define DDR0_40_ECC_C_DATA_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_40_ECC_C_DATA_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_40_ECC_C_DATA_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_41 0x29 +#define DDR0_41_ECC_C_DATA_MASK 0xFFFFFFFF /* Read only */ +#define DDR0_41_ECC_C_DATA_ENCODE(n) ((((unsigned long)(n))&0xFFFFFFFF)<<0) +#define DDR0_41_ECC_C_DATA_DECODE(n) ((((unsigned long)(n))>>0)&0xFFFFFFFF) + +#define DDR0_42 0x2A +#define DDR0_42_ADDR_PINS_MASK 0x07000000 +#define DDR0_42_ADDR_PINS_ENCODE(n) ((((unsigned long)(n))&0x7)<<24) +#define DDR0_42_ADDR_PINS_DECODE(n) ((((unsigned long)(n))>>24)&0x7) +#define DDR0_42_CASLAT_LIN_GATE_MASK 0x0000000F +#define DDR0_42_CASLAT_LIN_GATE_ENCODE(n) ((((unsigned long)(n))&0xF)<<0) +#define DDR0_42_CASLAT_LIN_GATE_DECODE(n) ((((unsigned long)(n))>>0)&0xF) + +#define DDR0_43 0x2B +#define DDR0_43_TWR_MASK 0x07000000 +#define DDR0_43_TWR_ENCODE(n) ((((unsigned long)(n))&0x7)<<24) +#define DDR0_43_TWR_DECODE(n) ((((unsigned long)(n))>>24)&0x7) +#define DDR0_43_APREBIT_MASK 0x000F0000 +#define DDR0_43_APREBIT_ENCODE(n) ((((unsigned long)(n))&0xF)<<16) +#define DDR0_43_APREBIT_DECODE(n) ((((unsigned long)(n))>>16)&0xF) +#define DDR0_43_COLUMN_SIZE_MASK 0x00000700 +#define DDR0_43_COLUMN_SIZE_ENCODE(n) ((((unsigned long)(n))&0x7)<<8) +#define DDR0_43_COLUMN_SIZE_DECODE(n) ((((unsigned long)(n))>>8)&0x7) +#define DDR0_43_EIGHT_BANK_MODE_MASK 0x00000001 +#define DDR0_43_EIGHT_BANK_MODE_8_BANKS 0x00000001 +#define DDR0_43_EIGHT_BANK_MODE_4_BANKS 0x00000000 +#define DDR0_43_EIGHT_BANK_MODE_ENCODE(n) ((((unsigned long)(n))&0x1)<<0) +#define DDR0_43_EIGHT_BANK_MODE_DECODE(n) ((((unsigned long)(n))>>0)&0x1) + +#define DDR0_44 0x2C +#define DDR0_44_TRCD_MASK 0x000000FF +#define DDR0_44_TRCD_ENCODE(n) ((((unsigned long)(n))&0xFF)<<0) +#define DDR0_44_TRCD_DECODE(n) ((((unsigned long)(n))>>0)&0xFF) + +#endif /* _SPD_SDRAM_DENALI_H_ */ diff --git a/board/amcc/sequoia/sequoia.c b/board/amcc/sequoia/sequoia.c index ccf6f0c..daaffe0 100644 --- a/board/amcc/sequoia/sequoia.c +++ b/board/amcc/sequoia/sequoia.c @@ -31,11 +31,13 @@ DECLARE_GLOBAL_DATA_PTR; extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ +ulong flash_get_size (ulong base, int banknum); + int board_early_init_f(void) { - unsigned long sdr0_cust0; - unsigned long sdr0_pfc1, sdr0_pfc2; - register uint reg; + u32 sdr0_cust0; + u32 sdr0_pfc1, sdr0_pfc2; + u32 reg; mtdcr(ebccfga, xbcfg); mtdcr(ebccfgd, 0xb8400000); @@ -140,6 +142,7 @@ int misc_init_r(void) { uint pbcr; int size_val = 0; + u32 reg; #ifdef CONFIG_440EPX unsigned long usb2d0cr = 0; unsigned long usb2phy0cr, usb2h0cr = 0; @@ -152,6 +155,11 @@ int misc_init_r(void) */ /* Re-do sizing to get full correct info */ + + /* adjust flash start and offset */ + gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize; + gd->bd->bi_flashoffset = 0; + #if defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) mtdcr(ebccfga, pb3cr); #else @@ -192,9 +200,10 @@ int misc_init_r(void) #endif mtdcr(ebccfgd, pbcr); - /* adjust flash start and offset */ - gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize; - gd->bd->bi_flashoffset = 0; + /* + * Re-check to get correct base address + */ + flash_get_size(gd->bd->bi_flashstart, 0); #ifdef CFG_ENV_IS_IN_FLASH /* Monitor protection ON by default */ @@ -327,18 +336,37 @@ int misc_init_r(void) } #endif /* CONFIG_440EPX */ + mfsdr(SDR0_SRST1, reg); /* enable security/kasumi engines */ + reg &= ~(SDR0_SRST1_CRYP0 | SDR0_SRST1_KASU0); + mtsdr(SDR0_SRST1, reg); + + /* + * Clear PLB4A0_ACR[WRP] + * This fix will make the MAL burst disabling patch for the Linux + * EMAC driver obsolete. + */ + reg = mfdcr(plb4_acr) & ~PLB4_ACR_WRP; + mtdcr(plb4_acr, reg); + return 0; } int checkboard(void) { char *s = getenv("serial#"); + u8 rev; + u8 val; #ifdef CONFIG_440EPX printf("Board: Sequoia - AMCC PPC440EPx Evaluation Board"); #else printf("Board: Rainier - AMCC PPC440GRx Evaluation Board"); #endif + + rev = *(u8 *)(CFG_CPLD + 0); + val = *(u8 *)(CFG_CPLD + 5) & 0x01; + printf(", Rev. %X, PCI=%d MHz", rev, val ? 66 : 33); + if (s != NULL) { puts(", serial# "); puts(s); diff --git a/board/amcc/yellowstone/Makefile b/board/amcc/taishan/Makefile index 261e5d4..462af00 100644 --- a/board/amcc/yellowstone/Makefile +++ b/board/amcc/taishan/Makefile @@ -1,5 +1,5 @@ # -# (C) Copyright 2002-2006 +# (C) Copyright 2007 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o +COBJS = $(BOARD).o lcd.o update.o showinfo.o SOBJS = init.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/amcc/taishan/config.mk b/board/amcc/taishan/config.mk new file mode 100644 index 0000000..4eefff2 --- /dev/null +++ b/board/amcc/taishan/config.mk @@ -0,0 +1,44 @@ +# +# (C) Copyright 2004 +# 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 +# + +# +# AMCC 440GX Reference Platform (Taishan) board +# + +#TEXT_BASE = 0xFFFE0000 + +ifeq ($(ramsym),1) +TEXT_BASE = 0x07FD0000 +else +TEXT_BASE = 0xFFFC0000 +endif + +PLATFORM_CPPFLAGS += -DCONFIG_440=1 + +ifeq ($(debug),1) +PLATFORM_CPPFLAGS += -DDEBUG +endif + +ifeq ($(dbcr),1) +PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000 +endif diff --git a/board/amcc/taishan/init.S b/board/amcc/taishan/init.S new file mode 100644 index 0000000..8db043b --- /dev/null +++ b/board/amcc/taishan/init.S @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <ppc_asm.tmpl> +#include <config.h> + +/* General */ +#define TLB_VALID 0x00000200 +#define _256M 0x10000000 + +/* Supported page sizes */ + +#define SZ_1K 0x00000000 +#define SZ_4K 0x00000010 +#define SZ_16K 0x00000020 +#define SZ_64K 0x00000030 +#define SZ_256K 0x00000040 +#define SZ_1M 0x00000050 +#define SZ_8M 0x00000060 +#define SZ_16M 0x00000070 +#define SZ_256M 0x00000090 + +/* Storage attributes */ +#define SA_W 0x00000800 /* Write-through */ +#define SA_I 0x00000400 /* Caching inhibited */ +#define SA_M 0x00000200 /* Memory coherence */ +#define SA_G 0x00000100 /* Guarded */ +#define SA_E 0x00000080 /* Endian */ + +/* Access control */ +#define AC_X 0x00000024 /* Execute */ +#define AC_W 0x00000012 /* Write */ +#define AC_R 0x00000009 /* Read */ + +/* Some handy macros */ + +#define EPN(e) ((e) & 0xfffffc00) +#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) +#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) +#define TLB2(a) ( (a)&0x00000fbf ) + +#define tlbtab_start\ + mflr r1 ;\ + bl 0f ; + +#define tlbtab_end\ + .long 0, 0, 0 ; \ +0: mflr r0 ; \ + mtlr r1 ; \ + blr ; + +#define tlbentry(epn,sz,rpn,erpn,attr)\ + .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + * Pointer to the table is returned in r1 + * + *************************************************************************/ + + .section .bootpg,"ax" + .globl tlbtab + +tlbtab: + tlbtab_start + tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) + tlbentry( CFG_ISRAM_BASE, SZ_256K, 0x80000000, 0, AC_R|AC_W|AC_X ) + tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I ) + tlbtab_end diff --git a/board/amcc/taishan/lcd.c b/board/amcc/taishan/lcd.c new file mode 100644 index 0000000..8d2dce3 --- /dev/null +++ b/board/amcc/taishan/lcd.c @@ -0,0 +1,380 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <config.h> +#include <common.h> +#include <command.h> +#include <i2c.h> +#include <miiphy.h> + +#ifdef CONFIG_TAISHAN + +#define LCD_DELAY_NORMAL_US 100 +#define LCD_DELAY_NORMAL_MS 2 +#define LCD_CMD_ADDR ((volatile char *)(CFG_EBC2_LCM_BASE)) +#define LCD_DATA_ADDR ((volatile char *)(CFG_EBC2_LCM_BASE+1)) +#define LCD_BLK_CTRL ((volatile char *)(CFG_EBC1_FPGA_BASE+0x2)) + +#define mdelay(t) ({unsigned long msec=(t); while (msec--) { udelay(1000);}}) + +static int g_lcd_init_b = 0; +static char *amcc_logo = " AMCC TAISHAN 440GX EvalBoard"; +static char addr_flag = 0x80; + +static void lcd_bl_ctrl(char val) +{ + char cpld_val; + + cpld_val = *LCD_BLK_CTRL; + *LCD_BLK_CTRL = val | cpld_val; +} + +static void lcd_putc(char val) +{ + int i = 100; + char addr; + + while (i--) { + if ((*LCD_CMD_ADDR & 0x80) != 0x80) { /*BF = 1 ? */ + udelay(LCD_DELAY_NORMAL_US); + break; + } + udelay(LCD_DELAY_NORMAL_US); + } + + if (*LCD_CMD_ADDR & 0x80) { + printf("LCD is busy\n"); + return; + } + + addr = *LCD_CMD_ADDR; + udelay(LCD_DELAY_NORMAL_US); + if ((addr != 0) && (addr % 0x10 == 0)) { + addr_flag ^= 0x40; + *LCD_CMD_ADDR = addr_flag; + } + + udelay(LCD_DELAY_NORMAL_US); + *LCD_DATA_ADDR = val; + udelay(LCD_DELAY_NORMAL_US); +} + +static void lcd_puts(char *s) +{ + char *p = s; + int i = 100; + + while (i--) { + if ((*LCD_CMD_ADDR & 0x80) != 0x80) { /*BF = 1 ? */ + udelay(LCD_DELAY_NORMAL_US); + break; + } + udelay(LCD_DELAY_NORMAL_US); + } + + if (*LCD_CMD_ADDR & 0x80) { + printf("LCD is busy\n"); + return; + } + + while (*p) + lcd_putc(*p++); +} + +static void lcd_put_logo(void) +{ + int i = 100; + char *p = amcc_logo; + + while (i--) { + if ((*LCD_CMD_ADDR & 0x80) != 0x80) { /*BF = 1 ? */ + udelay(LCD_DELAY_NORMAL_US); + break; + } + udelay(LCD_DELAY_NORMAL_US); + } + + if (*LCD_CMD_ADDR & 0x80) { + printf("LCD is busy\n"); + return; + } + + *LCD_CMD_ADDR = 0x80; + while (*p) + lcd_putc(*p++); +} + +int lcd_init(void) +{ + if (g_lcd_init_b == 0) { + puts("LCD: "); + mdelay(100); /* Waiting for the LCD initialize */ + + *LCD_CMD_ADDR = 0x38; /*set function:8-bit,2-line,5x7 font type */ + udelay(LCD_DELAY_NORMAL_US); + + *LCD_CMD_ADDR = 0x0f; /*set display on,cursor on,blink on */ + udelay(LCD_DELAY_NORMAL_US); + + *LCD_CMD_ADDR = 0x01; /*display clear */ + mdelay(LCD_DELAY_NORMAL_MS); + + *LCD_CMD_ADDR = 0x06; /*set entry */ + udelay(LCD_DELAY_NORMAL_US); + + lcd_bl_ctrl(0x02); + lcd_put_logo(); + + puts(" ready\n"); + g_lcd_init_b = 1; + } + + return 0; +} + +static int do_lcd_test(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + lcd_init(); + return 0; +} + +static int do_lcd_clear(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + *LCD_CMD_ADDR = 0x01; + mdelay(LCD_DELAY_NORMAL_MS); + return 0; +} +static int do_lcd_puts(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + if (argc < 2) { + printf("%s", cmdtp->usage); + return 1; + } + lcd_puts(argv[1]); + return 0; +} +static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + if (argc < 2) { + printf("%s", cmdtp->usage); + return 1; + } + lcd_putc((char)argv[1][0]); + return 0; +} +static int do_lcd_cur(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + ulong count; + ulong dir; + char cur_addr; + + if (argc < 3) { + printf("%s", cmdtp->usage); + return 1; + } + + count = simple_strtoul(argv[1], NULL, 16); + if (count > 31) { + printf("unable to shift > 0x20\n"); + count = 0; + } + + dir = simple_strtoul(argv[2], NULL, 16); + cur_addr = *LCD_CMD_ADDR; + udelay(LCD_DELAY_NORMAL_US); + if (dir == 0x0) { + if (addr_flag == 0x80) { + if (count >= (cur_addr & 0xf)) { + *LCD_CMD_ADDR = 0x80; + udelay(LCD_DELAY_NORMAL_US); + count = 0; + } + } else { + if (count >= ((cur_addr & 0x0f) + 0x0f)) { + *LCD_CMD_ADDR = 0x80; + addr_flag = 0x80; + udelay(LCD_DELAY_NORMAL_US); + count = 0x0; + } else if (count >= (cur_addr & 0xf)) { + count -= cur_addr & 0xf; + *LCD_CMD_ADDR = 0x80 | 0xf; + addr_flag = 0x80; + udelay(LCD_DELAY_NORMAL_US); + } + } + } else { + if (addr_flag == 0x80) { + if (count >= (0x1f - (cur_addr & 0xf))) { + count = 0x0; + addr_flag = 0xc0; + *LCD_CMD_ADDR = 0xc0 | 0xf; + udelay(LCD_DELAY_NORMAL_US); + } else if ((count + (cur_addr & 0xf)) >= 0x0f) { + count = count + (cur_addr & 0xf) - 0x0f; + addr_flag = 0xc0; + *LCD_CMD_ADDR = 0xc0; + udelay(LCD_DELAY_NORMAL_US); + } + } else if ((count + (cur_addr & 0xf)) >= 0x0f) { + count = 0x0; + *LCD_CMD_ADDR = 0xc0 | 0xf; + udelay(LCD_DELAY_NORMAL_US); + } + } + + while (count--) { + if (dir == 0) { + *LCD_CMD_ADDR = 0x10; + } else { + *LCD_CMD_ADDR = 0x14; + } + udelay(LCD_DELAY_NORMAL_US); + } + + return 0; +} + +U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd_test - lcd test display\n", NULL); +U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd_cls - lcd clear display\n", NULL); +U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts, + "lcd_puts - display string on lcd\n", + "<string> - <string> to be displayed\n"); +U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc, + "lcd_putc - display char on lcd\n", + "<char> - <char> to be displayed\n"); +U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur, + "lcd_cur - shift cursor on lcd\n", + "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n" + " <count> - 0~31\n" " <dir> - 0,backward; 1, forward\n"); + +#if 0 /* test-only */ +void set_phy_loopback_mode(void) +{ + char devemac2[32]; + char devemac3[32]; + + sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME); + sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME); + +#if 0 + unsigned short reg_short; + + miiphy_read(devemac2, 0x1, 1, ®_short); + if (reg_short & 0x04) { + /* + * printf("EMAC2 link up,do nothing\n"); + */ + } else { + udelay(1000); + miiphy_write(devemac2, 0x1, 0, 0x6000); + udelay(1000); + miiphy_read(devemac2, 0x1, 0, ®_short); + if (reg_short != 0x6000) { + printf + ("\nEMAC2 error set LOOPBACK mode error,reg2[0]=%x\n", + reg_short); + } + } + + miiphy_read(devemac3, 0x3, 1, ®_short); + if (reg_short & 0x04) { + /* + * printf("EMAC3 link up,do nothing\n"); + */ + } else { + udelay(1000); + miiphy_write(devemac3, 0x3, 0, 0x6000); + udelay(1000); + miiphy_read(devemac3, 0x3, 0, ®_short); + if (reg_short != 0x6000) { + printf + ("\nEMAC3 error set LOOPBACK mode error,reg2[0]=%x\n", + reg_short); + } + } +#else + /* Set PHY as LOOPBACK MODE, for Linux emac initializing */ + miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0, 0x6000); + udelay(1000); + miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0, 0x6000); + udelay(1000); +#endif /* 0 */ +} + +void set_phy_normal_mode(void) +{ + char devemac2[32]; + char devemac3[32]; + unsigned short reg_short; + + sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME); + sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME); + + /* Set phy of EMAC2 */ + miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x16, ®_short); + reg_short &= ~(0x7); + reg_short |= 0x6; /* RGMII DLL Delay */ + miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x16, reg_short); + + miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x17, ®_short); + reg_short &= ~(0x40); + miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x17, reg_short); + + miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x1c, 0x74f0); + + /* Set phy of EMAC3 */ + miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x16, ®_short); + reg_short &= ~(0x7); + reg_short |= 0x6; /* RGMII DLL Delay */ + miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x16, reg_short); + + miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x17, ®_short); + reg_short &= ~(0x40); + miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x17, reg_short); + + miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x1c, 0x74f0); +} +#endif /* 0 - test only */ + +static int do_led_test_off(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + volatile unsigned int *GpioOr = + (volatile unsigned int *)(CFG_PERIPHERAL_BASE + 0x700); + *GpioOr |= 0x00300000; + return 0; +} + +static int do_led_test_on(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + volatile unsigned int *GpioOr = + (volatile unsigned int *)(CFG_PERIPHERAL_BASE + 0x700); + *GpioOr &= ~0x00300000; + return 0; +} + +U_BOOT_CMD(ledon, 1, 1, do_led_test_on, + "ledon - led test light on\n", NULL); + +U_BOOT_CMD(ledoff, 1, 1, do_led_test_off, + "ledoff - led test light off\n", NULL); +#endif diff --git a/board/amcc/taishan/showinfo.c b/board/amcc/taishan/showinfo.c new file mode 100644 index 0000000..57b9d1c --- /dev/null +++ b/board/amcc/taishan/showinfo.c @@ -0,0 +1,236 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <config.h> +#include <common.h> +#include <command.h> +#include <asm/processor.h> +#include <pci.h> + +void show_reset_reg(void) +{ + unsigned long reg; + + /* read clock regsiter */ + printf("===== Display reset and initialize register Start =========\n"); + mfclk(clk_pllc,reg); + printf("cpr_pllc = %#010x\n",reg); + + mfclk(clk_plld,reg); + printf("cpr_plld = %#010x\n",reg); + + mfclk(clk_primad,reg); + printf("cpr_primad = %#010x\n",reg); + + mfclk(clk_primbd,reg); + printf("cpr_primbd = %#010x\n",reg); + + mfclk(clk_opbd,reg); + printf("cpr_opbd = %#010x\n",reg); + + mfclk(clk_perd,reg); + printf("cpr_perd = %#010x\n",reg); + + mfclk(clk_mald,reg); + printf("cpr_mald = %#010x\n",reg); + + /* read sdr register */ + mfsdr(sdr_ebc,reg); + printf("sdr_ebc = %#010x\n",reg); + + mfsdr(sdr_cp440,reg); + printf("sdr_cp440 = %#010x\n",reg); + + mfsdr(sdr_xcr,reg); + printf("sdr_xcr = %#010x\n",reg); + + mfsdr(sdr_xpllc,reg); + printf("sdr_xpllc = %#010x\n",reg); + + mfsdr(sdr_xplld,reg); + printf("sdr_xplld = %#010x\n",reg); + + mfsdr(sdr_pfc0,reg); + printf("sdr_pfc0 = %#010x\n",reg); + + mfsdr(sdr_pfc1,reg); + printf("sdr_pfc1 = %#010x\n",reg); + + mfsdr(sdr_cust0,reg); + printf("sdr_cust0 = %#010x\n",reg); + + mfsdr(sdr_cust1,reg); + printf("sdr_cust1 = %#010x\n",reg); + + mfsdr(sdr_uart0,reg); + printf("sdr_uart0 = %#010x\n",reg); + + mfsdr(sdr_uart1,reg); + printf("sdr_uart1 = %#010x\n",reg); + + printf("===== Display reset and initialize register End =========\n"); +} + +void show_xbridge_info(void) +{ + unsigned long reg; + + printf("PCI-X chip control registers\n"); + mfsdr(sdr_xcr, reg); + printf("sdr_xcr = %#010x\n", reg); + + mfsdr(sdr_xpllc, reg); + printf("sdr_xpllc = %#010x\n", reg); + + mfsdr(sdr_xplld, reg); + printf("sdr_xplld = %#010x\n", reg); + + printf("PCI-X Bridge Configure registers\n"); + printf("PCIX0_VENDID = %#06x\n", in16r(PCIX0_VENDID)); + printf("PCIX0_DEVID = %#06x\n", in16r(PCIX0_DEVID)); + printf("PCIX0_CMD = %#06x\n", in16r(PCIX0_CMD)); + printf("PCIX0_STATUS = %#06x\n", in16r(PCIX0_STATUS)); + printf("PCIX0_REVID = %#04x\n", in8(PCIX0_REVID)); + printf("PCIX0_CACHELS = %#04x\n", in8(PCIX0_CACHELS)); + printf("PCIX0_LATTIM = %#04x\n", in8(PCIX0_LATTIM)); + printf("PCIX0_HDTYPE = %#04x\n", in8(PCIX0_HDTYPE)); + printf("PCIX0_BIST = %#04x\n", in8(PCIX0_BIST)); + + printf("PCIX0_BAR0 = %#010x\n", in32r(PCIX0_BAR0)); + printf("PCIX0_BAR1 = %#010x\n", in32r(PCIX0_BAR1)); + printf("PCIX0_BAR2 = %#010x\n", in32r(PCIX0_BAR2)); + printf("PCIX0_BAR3 = %#010x\n", in32r(PCIX0_BAR3)); + printf("PCIX0_BAR4 = %#010x\n", in32r(PCIX0_BAR4)); + printf("PCIX0_BAR5 = %#010x\n", in32r(PCIX0_BAR5)); + + printf("PCIX0_CISPTR = %#010x\n", in32r(PCIX0_CISPTR)); + printf("PCIX0_SBSSYSVID = %#010x\n", in16r(PCIX0_SBSYSVID)); + printf("PCIX0_SBSSYSID = %#010x\n", in16r(PCIX0_SBSYSID)); + printf("PCIX0_EROMBA = %#010x\n", in32r(PCIX0_EROMBA)); + printf("PCIX0_CAP = %#04x\n", in8(PCIX0_CAP)); + printf("PCIX0_INTLN = %#04x\n", in8(PCIX0_INTLN)); + printf("PCIX0_INTPN = %#04x\n", in8(PCIX0_INTPN)); + printf("PCIX0_MINGNT = %#04x\n", in8(PCIX0_MINGNT)); + printf("PCIX0_MAXLTNCY = %#04x\n", in8(PCIX0_MAXLTNCY)); + + printf("PCIX0_BRDGOPT1 = %#010x\n", in32r(PCIX0_BRDGOPT1)); + printf("PCIX0_BRDGOPT2 = %#010x\n", in32r(PCIX0_BRDGOPT2)); + + printf("PCIX0_POM0LAL = %#010x\n", in32r(PCIX0_POM0LAL)); + printf("PCIX0_POM0LAH = %#010x\n", in32r(PCIX0_POM0LAH)); + printf("PCIX0_POM0SA = %#010x\n", in32r(PCIX0_POM0SA)); + printf("PCIX0_POM0PCILAL = %#010x\n", in32r(PCIX0_POM0PCIAL)); + printf("PCIX0_POM0PCILAH = %#010x\n", in32r(PCIX0_POM0PCIAH)); + printf("PCIX0_POM1LAL = %#010x\n", in32r(PCIX0_POM1LAL)); + printf("PCIX0_POM1LAH = %#010x\n", in32r(PCIX0_POM1LAH)); + printf("PCIX0_POM1SA = %#010x\n", in32r(PCIX0_POM1SA)); + printf("PCIX0_POM1PCILAL = %#010x\n", in32r(PCIX0_POM1PCIAL)); + printf("PCIX0_POM1PCILAH = %#010x\n", in32r(PCIX0_POM1PCIAH)); + printf("PCIX0_POM2SA = %#010x\n", in32r(PCIX0_POM2SA)); + + printf("PCIX0_PIM0SA = %#010x\n", in32r(PCIX0_PIM0SA)); + printf("PCIX0_PIM0LAL = %#010x\n", in32r(PCIX0_PIM0LAL)); + printf("PCIX0_PIM0LAH = %#010x\n", in32r(PCIX0_PIM0LAH)); + printf("PCIX0_PIM1SA = %#010x\n", in32r(PCIX0_PIM1SA)); + printf("PCIX0_PIM1LAL = %#010x\n", in32r(PCIX0_PIM1LAL)); + printf("PCIX0_PIM1LAH = %#010x\n", in32r(PCIX0_PIM1LAH)); + printf("PCIX0_PIM2SA = %#010x\n", in32r(PCIX0_PIM1SA)); + printf("PCIX0_PIM2LAL = %#010x\n", in32r(PCIX0_PIM1LAL)); + printf("PCIX0_PIM2LAH = %#010x\n", in32r(PCIX0_PIM1LAH)); + + printf("PCIX0_XSTS = %#010x\n", in32r(PCIX0_STS)); +} + +int do_show_xbridge_info(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + show_xbridge_info(); + return 0; +} + +U_BOOT_CMD(xbriinfo, 1, 1, do_show_xbridge_info, + "xbriinfo - Show PCIX bridge info\n", NULL); + +#define TAISHAN_PCI_DEV_ID0 0x800 +#define TAISHAN_PCI_DEV_ID1 0x1000 + +void show_pcix_device_info(void) +{ + int ii; + int dev; + u8 capp; + u8 xcapid; + u16 status; + u16 xcommand; + u32 xstatus; + + for (ii = 0; ii < 2; ii++) { + if (ii == 0) + dev = TAISHAN_PCI_DEV_ID0; + else + dev = TAISHAN_PCI_DEV_ID1; + + pci_read_config_word(dev, PCI_STATUS, &status); + if (status & PCI_STATUS_CAP_LIST) { + pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &capp); + + pci_read_config_byte(dev, (int)(capp), &xcapid); + if (xcapid == 0x07) { + pci_read_config_word(dev, (int)(capp + 2), + &xcommand); + pci_read_config_dword(dev, (int)(capp + 4), + &xstatus); + printf("BUS0 dev%d Xcommand=%#06x,Xstatus=%#010x\n", + (ii + 1), xcommand, xstatus); + } else { + printf("BUS0 dev%d PCI-X CAP ID error," + "CAP=%#04x,XCAPID=%#04x\n", + (ii + 1), capp, xcapid); + } + } else { + printf("BUS0 dev%d not found PCI_STATUS_CAP_LIST supporting\n", + ii + 1); + } + } + +} + +int do_show_pcix_device_info(cmd_tbl_t * cmdtp, int flag, int argc, + char *argv[]) +{ + show_pcix_device_info(); + return 0; +} + +U_BOOT_CMD(xdevinfo, 1, 1, do_show_pcix_device_info, + "xdevinfo - Show PCIX Device info\n", NULL); + +extern void show_reset_reg(void); + +int do_show_reset_reg_info(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + show_reset_reg(); + return 0; +} + +U_BOOT_CMD(resetinfo, 1, 1, do_show_reset_reg_info, + "resetinfo - Show Reset REG info\n", NULL); diff --git a/board/amcc/taishan/taishan.c b/board/amcc/taishan/taishan.c new file mode 100644 index 0000000..1a2e53b --- /dev/null +++ b/board/amcc/taishan/taishan.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2004 PaulReynolds@lhsolutions.com + * + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <asm/processor.h> +#include <spd_sdram.h> +#include <ppc4xx_enet.h> + +#ifdef CFG_INIT_SHOW_RESET_REG +void show_reset_reg(void); +#endif + +int lcd_init(void); + +int board_early_init_f (void) +{ + unsigned long reg; + volatile unsigned int *GpioOdr; + volatile unsigned int *GpioTcr; + volatile unsigned int *GpioOr; + + /*-------------------------------------------------------------------------+ + | Initialize EBC CONFIG + +-------------------------------------------------------------------------*/ + mtebc(xbcfg, EBC_CFG_LE_UNLOCK | + EBC_CFG_PTD_ENABLE | EBC_CFG_RTC_64PERCLK | + EBC_CFG_ATC_PREVIOUS | EBC_CFG_DTC_PREVIOUS | + EBC_CFG_CTC_PREVIOUS | EBC_CFG_EMC_DEFAULT | + EBC_CFG_PME_DISABLE | EBC_CFG_PR_32); + + /*-------------------------------------------------------------------------+ + | 64MB FLASH. Initialize bank 0 with default values. + +-------------------------------------------------------------------------*/ + mtebc(pb0ap, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(15) | + EBC_BXAP_BCE_DISABLE | + EBC_BXAP_CSN_ENCODE(1) | EBC_BXAP_OEN_ENCODE(1) | + EBC_BXAP_WBN_ENCODE(1) | EBC_BXAP_WBF_ENCODE(1) | + EBC_BXAP_TH_ENCODE(3) | EBC_BXAP_RE_DISABLED | + EBC_BXAP_BEM_WRITEONLY | + EBC_BXAP_PEN_DISABLED); + mtebc(pb0cr, EBC_BXCR_BAS_ENCODE(CFG_FLASH_BASE) | + EBC_BXCR_BS_64MB | EBC_BXCR_BU_RW|EBC_BXCR_BW_32BIT); + + /*-------------------------------------------------------------------------+ + | FPGA. Initialize bank 1 with default values. + +-------------------------------------------------------------------------*/ + mtebc(pb1ap, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(5) | + EBC_BXAP_BCE_DISABLE | + EBC_BXAP_CSN_ENCODE(1) | EBC_BXAP_OEN_ENCODE(1) | + EBC_BXAP_WBN_ENCODE(1) | EBC_BXAP_WBF_ENCODE(1) | + EBC_BXAP_TH_ENCODE(3) | EBC_BXAP_RE_DISABLED | + EBC_BXAP_BEM_WRITEONLY | + EBC_BXAP_PEN_DISABLED); + mtebc(pb1cr, EBC_BXCR_BAS_ENCODE(0x41000000) | + EBC_BXCR_BS_1MB | EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT); + + /*-------------------------------------------------------------------------+ + | LCM. Initialize bank 2 with default values. + +-------------------------------------------------------------------------*/ + mtebc(pb2ap, EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(64) | + EBC_BXAP_BCE_DISABLE | + EBC_BXAP_CSN_ENCODE(3) | EBC_BXAP_OEN_ENCODE(3) | + EBC_BXAP_WBN_ENCODE(3) | EBC_BXAP_WBF_ENCODE(3) | + EBC_BXAP_TH_ENCODE(7) | EBC_BXAP_RE_DISABLED | + EBC_BXAP_BEM_WRITEONLY | + EBC_BXAP_PEN_DISABLED); + mtebc(pb2cr, EBC_BXCR_BAS_ENCODE(0x42000000) | + EBC_BXCR_BS_1MB | EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT); + + /*-------------------------------------------------------------------------+ + | TMP. Initialize bank 3 with default values. + +-------------------------------------------------------------------------*/ + mtebc(pb3ap, EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(128) | + EBC_BXAP_BCE_DISABLE | + EBC_BXAP_CSN_ENCODE(3) | EBC_BXAP_OEN_ENCODE(3) | + EBC_BXAP_WBN_ENCODE(3) | EBC_BXAP_WBF_ENCODE(3) | + EBC_BXAP_TH_ENCODE(7) | EBC_BXAP_RE_DISABLED | + EBC_BXAP_BEM_WRITEONLY | + EBC_BXAP_PEN_DISABLED); + mtebc(pb3cr, EBC_BXCR_BAS_ENCODE(0x48000000) | + EBC_BXCR_BS_64MB | EBC_BXCR_BU_RW | EBC_BXCR_BW_32BIT); + + /*-------------------------------------------------------------------------+ + | Connector 4~7. Initialize bank 3~ 7 with default values. + +-------------------------------------------------------------------------*/ + mtebc(pb4ap,0); + mtebc(pb4cr,0); + mtebc(pb5ap,0); + mtebc(pb5cr,0); + mtebc(pb6ap,0); + mtebc(pb6cr,0); + mtebc(pb7ap,0); + mtebc(pb7cr,0); + + /*-------------------------------------------------------------------- + * Setup the interrupt controller polarities, triggers, etc. + *-------------------------------------------------------------------*/ + mtdcr (uic0sr, 0xffffffff); /* clear all */ + mtdcr (uic0er, 0x00000000); /* disable all */ + mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */ + mtdcr (uic0pr, 0xfffffe13); /* per ref-board manual */ + mtdcr (uic0tr, 0x01c00008); /* per ref-board manual */ + mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic0sr, 0xffffffff); /* clear all */ + + mtdcr (uic1sr, 0xffffffff); /* clear all */ + mtdcr (uic1er, 0x00000000); /* disable all */ + mtdcr (uic1cr, 0x00000000); /* all non-critical */ + mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */ + mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */ + mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic1sr, 0xffffffff); /* clear all */ + + mtdcr (uic2sr, 0xffffffff); /* clear all */ + mtdcr (uic2er, 0x00000000); /* disable all */ + mtdcr (uic2cr, 0x00000000); /* all non-critical */ + mtdcr (uic2pr, 0xffffffff); /* per ref-board manual */ + mtdcr (uic2tr, 0x00ff8c0f); /* per ref-board manual */ + mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic2sr, 0xffffffff); /* clear all */ + + mtdcr (uicb0sr, 0xfc000000); /* clear all */ + mtdcr (uicb0er, 0x00000000); /* disable all */ + mtdcr (uicb0cr, 0x00000000); /* all non-critical */ + mtdcr (uicb0pr, 0xfc000000); /* */ + mtdcr (uicb0tr, 0x00000000); /* */ + mtdcr (uicb0vr, 0x00000001); /* */ + + /* Enable two GPIO 10~11 and TraceA signal */ + mfsdr(sdr_pfc0,reg); + reg |= 0x00300000; + mtsdr(sdr_pfc0,reg); + + mfsdr(sdr_pfc1,reg); + reg |= 0x00100000; + mtsdr(sdr_pfc1,reg); + + /* Set GPIO 10 and 11 as output */ + GpioOdr = (volatile unsigned int*)(CFG_PERIPHERAL_BASE+0x718); + GpioTcr = (volatile unsigned int*)(CFG_PERIPHERAL_BASE+0x704); + GpioOr = (volatile unsigned int*)(CFG_PERIPHERAL_BASE+0x700); + + *GpioOdr &= ~(0x00300000); + *GpioTcr |= 0x00300000; + *GpioOr |= 0x00300000; + + return 0; +} + +int misc_init_r(void) +{ + lcd_init(); + + return 0; +} + +int checkboard (void) +{ + char *s = getenv ("serial#"); + + printf ("Board: Taishan - AMCC PPC440GX Evaluation Board"); + if (s != NULL) { + puts (", serial# "); + puts (s); + } + putc ('\n'); + +#ifdef CFG_INIT_SHOW_RESET_REG + show_reset_reg(); +#endif + + return (0); +} + +#if defined(CFG_DRAM_TEST) +int testdram (void) +{ + uint *pstart = (uint *) 0x04000000; + uint *pend = (uint *) 0x0fc00000; + uint *p; + + for (p = pstart; p < pend; p++) + *p = 0xaaaaaaaa; + + for (p = pstart; p < pend; p++) { + if (*p != 0xaaaaaaaa) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + + for (p = pstart; p < pend; p++) + *p = 0x55555555; + + for (p = pstart; p < pend; p++) { + if (*p != 0x55555555) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + return 0; +} +#endif + +/************************************************************************* + * pci_pre_init + * + * This routine is called just prior to registering the hose and gives + * the board the opportunity to check things. Returning a value of zero + * indicates that things are bad & PCI initialization should be aborted. + * + * Different boards may wish to customize the pci controller structure + * (add regions, override default access routines, etc) or perform + * certain pre-initialization actions. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) +int pci_pre_init(struct pci_controller * hose ) +{ + unsigned long strap; + + /*--------------------------------------------------------------------------+ + * The ocotea board is always configured as the host & requires the + * PCI arbiter to be enabled. + *--------------------------------------------------------------------------*/ + mfsdr(sdr_sdstp1, strap); + if( (strap & SDR0_SDSTP1_PAE_MASK) == 0 ){ + printf("PCI: SDR0_STRP1[%08lX] - PCI Arbiter disabled.\n",strap); + return 0; + } + + return 1; +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ + +/************************************************************************* + * pci_target_init + * + * The bootstrap configuration provides default settings for the pci + * inbound map (PIM). But the bootstrap config choices are limited and + * may not be sufficient for a given board. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) +void pci_target_init(struct pci_controller * hose ) +{ + DECLARE_GLOBAL_DATA_PTR; + + /*--------------------------------------------------------------------------+ + * Disable everything + *--------------------------------------------------------------------------*/ + out32r( PCIX0_PIM0SA, 0 ); /* disable */ + out32r( PCIX0_PIM1SA, 0 ); /* disable */ + out32r( PCIX0_PIM2SA, 0 ); /* disable */ + out32r( PCIX0_EROMBA, 0 ); /* disable expansion rom */ + + /*--------------------------------------------------------------------------+ + * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 strapping + * options to not support sizes such as 128/256 MB. + *--------------------------------------------------------------------------*/ + out32r( PCIX0_PIM0LAL, CFG_SDRAM_BASE ); + out32r( PCIX0_PIM0LAH, 0 ); + out32r( PCIX0_PIM0SA, ~(gd->ram_size - 1) | 1 ); + + out32r( PCIX0_BAR0, 0 ); + + /*--------------------------------------------------------------------------+ + * Program the board's subsystem id/vendor id + *--------------------------------------------------------------------------*/ + out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID ); + out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_DEVICEID ); + + out16r( PCIX0_CMD, in16r(PCIX0_CMD) | PCI_COMMAND_MEMORY ); +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ + +/************************************************************************* + * is_pci_host + * + * This routine is called to determine if a pci scan should be + * performed. With various hardware environments (especially cPCI and + * PPMC) it's insufficient to depend on the state of the arbiter enable + * bit in the strap register, or generic host/adapter assumptions. + * + * Rather than hard-code a bad assumption in the general 440 code, the + * 440 pci code requires the board to decide at runtime. + * + * Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * + ************************************************************************/ +#if defined(CONFIG_PCI) +int is_pci_host(struct pci_controller *hose) +{ + /* The ocotea board is always configured as host. */ + return(1); +} +#endif /* defined(CONFIG_PCI) */ + +#ifdef CONFIG_POST +/* + * Returns 1 if keys pressed to start the power-on long-running tests + * Called from board_init_f(). + */ +int post_hotkeys_pressed(void) +{ + return (ctrlc()); +} +#endif diff --git a/board/amcc/yellowstone/u-boot.lds b/board/amcc/taishan/u-boot.lds index a0ba44d..664716e 100644 --- a/board/amcc/yellowstone/u-boot.lds +++ b/board/amcc/taishan/u-boot.lds @@ -1,5 +1,5 @@ /* - * (C) Copyright 2002 + * (C) Copyright 2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -67,7 +67,7 @@ SECTIONS /* the sector layout of our flash chips! XXX FIXME XXX */ cpu/ppc4xx/start.o (.text) - board/amcc/yellowstone/init.o (.text) + board/amcc/taishan/init.o (.text) cpu/ppc4xx/kgdb.o (.text) cpu/ppc4xx/traps.o (.text) cpu/ppc4xx/interrupts.o (.text) diff --git a/board/amcc/taishan/update.c b/board/amcc/taishan/update.c new file mode 100644 index 0000000..ed2c196 --- /dev/null +++ b/board/amcc/taishan/update.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <config.h> +#include <common.h> +#include <command.h> +#include <asm/processor.h> +#include <i2c.h> + +#if defined(CONFIG_TAISHAN) + +const uchar bootstrap_buf[16] = { + 0x86, + 0x78, + 0xc1, + 0xa6, + 0x09, + 0x67, + 0x04, + 0x63, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +static int update_boot_eeprom(void) +{ + ulong len = 0x10; + uchar chip = CFG_BOOTSTRAP_IIC_ADDR; + uchar *pbuf = (uchar *)bootstrap_buf; + int ii, jj; + + for (ii = 0; ii < len; ii++) { + if (i2c_write(chip, ii, 1, &pbuf[ii], 1) != 0) { + printf("i2c_write failed\n"); + return -1; + } + + /* wait 10ms */ + for (jj = 0; jj < 10; jj++) + udelay(1000); + } + return 0; +} + +int do_update_boot_eeprom(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + return update_boot_eeprom(); +} + +U_BOOT_CMD(update_boot_eeprom, 1, 1, do_update_boot_eeprom, + "update_boot_eeprom - update bootstrap eeprom content\n", NULL); +#endif diff --git a/board/amcc/yellowstone/init.S b/board/amcc/yellowstone/init.S deleted file mode 100644 index 425ad08..0000000 --- a/board/amcc/yellowstone/init.S +++ /dev/null @@ -1,112 +0,0 @@ -/* -* -* 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 <ppc_asm.tmpl> -#include <config.h> - -/* General */ -#define TLB_VALID 0x00000200 - -/* Supported page sizes */ - -#define SZ_1K 0x00000000 -#define SZ_4K 0x00000010 -#define SZ_16K 0x00000020 -#define SZ_64K 0x00000030 -#define SZ_256K 0x00000040 -#define SZ_1M 0x00000050 -#define SZ_8M 0x00000060 -#define SZ_16M 0x00000070 -#define SZ_256M 0x00000090 - -/* Storage attributes */ -#define SA_W 0x00000800 /* Write-through */ -#define SA_I 0x00000400 /* Caching inhibited */ -#define SA_M 0x00000200 /* Memory coherence */ -#define SA_G 0x00000100 /* Guarded */ -#define SA_E 0x00000080 /* Endian */ - -/* Access control */ -#define AC_X 0x00000024 /* Execute */ -#define AC_W 0x00000012 /* Write */ -#define AC_R 0x00000009 /* Read */ - -/* Some handy macros */ - -#define EPN(e) ((e) & 0xfffffc00) -#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) -#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) -#define TLB2(a) ( (a)&0x00000fbf ) - -#define tlbtab_start\ - mflr r1 ;\ - bl 0f ; - -#define tlbtab_end\ - .long 0, 0, 0 ; \ -0: mflr r0 ; \ - mtlr r1 ; \ - blr ; - -#define tlbentry(epn,sz,rpn,erpn,attr)\ - .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) - - -/************************************************************************** - * TLB TABLE - * - * This table is used by the cpu boot code to setup the initial tlb - * entries. Rather than make broad assumptions in the cpu source tree, - * this table lets each board set things up however they like. - * - * Pointer to the table is returned in r1 - * - *************************************************************************/ - - .section .bootpg,"ax" - .globl tlbtab - -tlbtab: - tlbtab_start - - /* - * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the - * speed up boot process. It is patched after relocation to enable SA_I - */ - tlbentry( CFG_BOOT_BASE_ADDR, SZ_256M, CFG_BOOT_BASE_ADDR, 0, AC_R|AC_W|AC_X|SA_G/*|SA_I*/) - - /* TLB-entry for init-ram in dcache (SA_I must be turned off!) */ - tlbentry( CFG_INIT_RAM_ADDR, SZ_64K, CFG_INIT_RAM_ADDR, 0, AC_R|AC_W|AC_X|SA_G ) - - tlbentry( CFG_SDRAM_BASE, SZ_256M, CFG_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_PCI_BASE, SZ_256M, CFG_PCI_BASE, 0, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_NVRAM_BASE_ADDR, SZ_256M, CFG_NVRAM_BASE_ADDR, 0, AC_R|AC_W|AC_X|SA_W|SA_I ) - - /* PCI */ - tlbentry( CFG_PCI_MEMBASE, SZ_256M, CFG_PCI_MEMBASE, 0, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE1, SZ_256M, CFG_PCI_MEMBASE1, 0, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE2, SZ_256M, CFG_PCI_MEMBASE2, 0, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE3, SZ_256M, CFG_PCI_MEMBASE3, 0, AC_R|AC_W|SA_G|SA_I ) - - /* USB 2.0 Device */ - tlbentry( CFG_USB_DEVICE, SZ_1K, 0x50000000, 0, AC_R|AC_W|SA_G|SA_I ) - - tlbtab_end diff --git a/board/amcc/yellowstone/yellowstone.c b/board/amcc/yellowstone/yellowstone.c deleted file mode 100644 index 92dc9d4..0000000 --- a/board/amcc/yellowstone/yellowstone.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * - * 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 <common.h> -#include <ppc4xx.h> -#include <asm/processor.h> -#include <spd_sdram.h> - -DECLARE_GLOBAL_DATA_PTR; - -extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ - -int board_early_init_f(void) -{ - register uint reg; - - /*-------------------------------------------------------------------- - * Setup the external bus controller/chip selects - *-------------------------------------------------------------------*/ - mtdcr(ebccfga, xbcfg); - reg = mfdcr(ebccfgd); - mtdcr(ebccfgd, reg | 0x04000000); /* Set ATC */ - - mtebc(pb0ap, 0x03017300); /* FLASH/SRAM */ - mtebc(pb0cr, 0xfc0da000); /* BAS=0xfc0 64MB r/w 16-bit */ - - mtebc(pb1ap, 0x00000000); - mtebc(pb1cr, 0x00000000); - - mtebc(pb2ap, 0x04814500); - /*CPLD*/ mtebc(pb2cr, 0x80018000); /*BAS=0x800 1MB r/w 8-bit */ - - mtebc(pb3ap, 0x00000000); - mtebc(pb3cr, 0x00000000); - - mtebc(pb4ap, 0x00000000); - mtebc(pb4cr, 0x00000000); - - mtebc(pb5ap, 0x00000000); - mtebc(pb5cr, 0x00000000); - - /*-------------------------------------------------------------------- - * Setup the GPIO pins - *-------------------------------------------------------------------*/ - /*CPLD cs */ - /*setup Address lines for flash size 64Meg. */ - out32(GPIO0_OSRL, in32(GPIO0_OSRL) | 0x50010000); - out32(GPIO0_TSRL, in32(GPIO0_TSRL) | 0x50010000); - out32(GPIO0_ISR1L, in32(GPIO0_ISR1L) | 0x50000000); - - /*setup emac */ - out32(GPIO0_TCR, in32(GPIO0_TCR) | 0xC080); - out32(GPIO0_TSRL, in32(GPIO0_TSRL) | 0x40); - out32(GPIO0_ISR1L, in32(GPIO0_ISR1L) | 0x55); - out32(GPIO0_OSRH, in32(GPIO0_OSRH) | 0x50004000); - out32(GPIO0_ISR1H, in32(GPIO0_ISR1H) | 0x00440000); - - /*UART1 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) | 0x02000000); - out32(GPIO1_OSRL, in32(GPIO1_OSRL) | 0x00080000); - out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); - - /* external interrupts IRQ0...3 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000); - out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00); - out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); - -#if 0 /* test-only */ - /*setup USB 2.0 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) | 0xc0000000); - out32(GPIO1_OSRL, in32(GPIO1_OSRL) | 0x50000000); - out32(GPIO0_TCR, in32(GPIO0_TCR) | 0xf); - out32(GPIO0_OSRH, in32(GPIO0_OSRH) | 0xaa); - out32(GPIO0_ISR2H, in32(GPIO0_ISR2H) | 0x00000500); -#endif - - /*-------------------------------------------------------------------- - * Setup the interrupt controller polarities, triggers, etc. - *-------------------------------------------------------------------*/ - mtdcr(uic0sr, 0xffffffff); /* clear all */ - mtdcr(uic0er, 0x00000000); /* disable all */ - mtdcr(uic0cr, 0x00000009); /* ATI & UIC1 crit are critical */ - mtdcr(uic0pr, 0xfffffe13); /* per ref-board manual */ - mtdcr(uic0tr, 0x01c00008); /* per ref-board manual */ - mtdcr(uic0vr, 0x00000001); /* int31 highest, base=0x000 */ - mtdcr(uic0sr, 0xffffffff); /* clear all */ - - mtdcr(uic1sr, 0xffffffff); /* clear all */ - mtdcr(uic1er, 0x00000000); /* disable all */ - mtdcr(uic1cr, 0x00000000); /* all non-critical */ - mtdcr(uic1pr, 0xffffe0ff); /* per ref-board manual */ - mtdcr(uic1tr, 0x00ffc000); /* per ref-board manual */ - mtdcr(uic1vr, 0x00000001); /* int31 highest, base=0x000 */ - mtdcr(uic1sr, 0xffffffff); /* clear all */ - - /*-------------------------------------------------------------------- - * Setup other serial configuration - *-------------------------------------------------------------------*/ - mfsdr(sdr_pci0, reg); - mtsdr(sdr_pci0, 0x80000000 | reg); /* PCI arbiter enabled */ - mtsdr(sdr_pfc0, 0x00003e00); /* Pin function */ - mtsdr(sdr_pfc1, 0x00048000); /* Pin function: UART0 has 4 pins */ - - /*clear tmrclk divisor */ - *(unsigned char *)(CFG_BCSR_BASE | 0x04) = 0x00; - - /*enable ethernet */ - *(unsigned char *)(CFG_BCSR_BASE | 0x08) = 0xf0; - -#if 0 /* test-only */ - /*enable usb 1.1 fs device and remove usb 2.0 reset */ - *(unsigned char *)(CFG_BCSR_BASE | 0x09) = 0x00; -#endif - - /*get rid of flash write protect */ - *(unsigned char *)(CFG_BCSR_BASE | 0x07) = 0x00; - - return 0; -} - -int misc_init_r (void) -{ - uint pbcr; - int size_val = 0; - - /* Re-do sizing to get full correct info */ - mtdcr(ebccfga, pb0cr); - pbcr = mfdcr(ebccfgd); - switch (gd->bd->bi_flashsize) { - case 1 << 20: - size_val = 0; - break; - case 2 << 20: - size_val = 1; - break; - case 4 << 20: - size_val = 2; - break; - case 8 << 20: - size_val = 3; - break; - case 16 << 20: - size_val = 4; - break; - case 32 << 20: - size_val = 5; - break; - case 64 << 20: - size_val = 6; - break; - case 128 << 20: - size_val = 7; - break; - } - pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17); - mtdcr(ebccfga, pb0cr); - mtdcr(ebccfgd, pbcr); - - /* adjust flash start and offset */ - gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize; - gd->bd->bi_flashoffset = 0; - - /* Monitor protection ON by default */ - (void)flash_protect(FLAG_PROTECT_SET, - -CFG_MONITOR_LEN, - 0xffffffff, - &flash_info[0]); - - return 0; -} - -int checkboard(void) -{ - char *s = getenv("serial#"); - - printf("Board: Yellowstone - AMCC PPC440GR Evaluation Board"); - if (s != NULL) { - puts(", serial# "); - puts(s); - } - putc('\n'); - - return (0); -} - -/************************************************************************* - * sdram_init -- doesn't use serial presence detect. - * - * Assumes: 256 MB, ECC, non-registered - * PLB @ 133 MHz - * - ************************************************************************/ -#define NUM_TRIES 64 -#define NUM_READS 10 - -void sdram_tr1_set(int ram_address, int* tr1_value) -{ - int i; - int j, k; - volatile unsigned int* ram_pointer = (unsigned int*)ram_address; - int first_good = -1, last_bad = 0x1ff; - - unsigned long test[NUM_TRIES] = { - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 }; - - /* go through all possible SDRAM0_TR1[RDCT] values */ - for (i=0; i<=0x1ff; i++) { - /* set the current value for TR1 */ - mtsdram(mem_tr1, (0x80800800 | i)); - - /* write values */ - for (j=0; j<NUM_TRIES; j++) { - ram_pointer[j] = test[j]; - - /* clear any cache at ram location */ - __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); - } - - /* read values back */ - for (j=0; j<NUM_TRIES; j++) { - for (k=0; k<NUM_READS; k++) { - /* clear any cache at ram location */ - __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); - - if (ram_pointer[j] != test[j]) - break; - } - - /* read error */ - if (k != NUM_READS) { - break; - } - } - - /* we have a SDRAM0_TR1[RDCT] that is part of the window */ - if (j == NUM_TRIES) { - if (first_good == -1) - first_good = i; /* found beginning of window */ - } else { /* bad read */ - /* if we have not had a good read then don't care */ - if(first_good != -1) { - /* first failure after a good read */ - last_bad = i-1; - break; - } - } - } - - /* return the current value for TR1 */ - *tr1_value = (first_good + last_bad) / 2; -} - -void sdram_init(void) -{ - register uint reg; - int tr1_bank1, tr1_bank2; - - /*-------------------------------------------------------------------- - * Setup some default - *------------------------------------------------------------------*/ - mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */ - mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ - mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ - mtsdram(mem_clktr, 0x40000000); /* ?? */ - mtsdram(mem_wddctr, 0x40000000); /* ?? */ - - /*clear this first, if the DDR is enabled by a debugger - then you can not make changes. */ - mtsdram(mem_cfg0, 0x00000000); /* Disable EEC */ - - /*-------------------------------------------------------------------- - * Setup for board-specific specific mem - *------------------------------------------------------------------*/ - /* - * Following for CAS Latency = 2.5 @ 133 MHz PLB - */ - mtsdram(mem_b0cr, 0x000a4001); /* SDBA=0x000 128MB, Mode 3, enabled */ - mtsdram(mem_b1cr, 0x080a4001); /* SDBA=0x080 128MB, Mode 3, enabled */ - - mtsdram(mem_tr0, 0x410a4012); /* ?? */ - mtsdram(mem_rtr, 0x04080000); /* ?? */ - mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM */ - mtsdram(mem_cfg0, 0x30000000); /* Disable EEC */ - udelay(400); /* Delay 200 usecs (min) */ - - /*-------------------------------------------------------------------- - * Enable the controller, then wait for DCEN to complete - *------------------------------------------------------------------*/ - mtsdram(mem_cfg0, 0x80000000); /* Enable */ - - for (;;) { - mfsdram(mem_mcsts, reg); - if (reg & 0x80000000) - break; - } - - sdram_tr1_set(0x00000000, &tr1_bank1); - sdram_tr1_set(0x08000000, &tr1_bank2); - mtsdram(mem_tr1, (((tr1_bank1+tr1_bank2)/2) | 0x80800800) ); -} - -/************************************************************************* - * long int initdram - * - ************************************************************************/ -long int initdram(int board) -{ - sdram_init(); - return CFG_SDRAM_BANKS * (CFG_KBYTES_SDRAM * 1024); /* return bytes */ -} - -#if defined(CFG_DRAM_TEST) -int testdram(void) -{ - unsigned long *mem = (unsigned long *)0; - const unsigned long kend = (1024 / sizeof(unsigned long)); - unsigned long k, n; - - mtmsr(0); - - for (k = 0; k < CFG_KBYTES_SDRAM; - ++k, mem += (1024 / sizeof(unsigned long))) { - if ((k & 1023) == 0) { - printf("%3d MB\r", k / 1024); - } - - memset(mem, 0xaaaaaaaa, 1024); - for (n = 0; n < kend; ++n) { - if (mem[n] != 0xaaaaaaaa) { - printf("SDRAM test fails at: %08x\n", - (uint) & mem[n]); - return 1; - } - } - - memset(mem, 0x55555555, 1024); - for (n = 0; n < kend; ++n) { - if (mem[n] != 0x55555555) { - printf("SDRAM test fails at: %08x\n", - (uint) & mem[n]); - return 1; - } - } - } - printf("SDRAM test passes\n"); - return 0; -} -#endif - -/************************************************************************* - * pci_pre_init - * - * This routine is called just prior to registering the hose and gives - * the board the opportunity to check things. Returning a value of zero - * indicates that things are bad & PCI initialization should be aborted. - * - * Different boards may wish to customize the pci controller structure - * (add regions, override default access routines, etc) or perform - * certain pre-initialization actions. - * - ************************************************************************/ -#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) -int pci_pre_init(struct pci_controller *hose) -{ - unsigned long addr; - - /*-------------------------------------------------------------------------+ - | Set priority for all PLB3 devices to 0. - | Set PLB3 arbiter to fair mode. - +-------------------------------------------------------------------------*/ - mfsdr(sdr_amp1, addr); - mtsdr(sdr_amp1, (addr & 0x000000FF) | 0x0000FF00); - addr = mfdcr(plb3_acr); - mtdcr(plb3_acr, addr | 0x80000000); - - /*-------------------------------------------------------------------------+ - | Set priority for all PLB4 devices to 0. - +-------------------------------------------------------------------------*/ - mfsdr(sdr_amp0, addr); - mtsdr(sdr_amp0, (addr & 0x000000FF) | 0x0000FF00); - addr = mfdcr(plb4_acr) | 0xa0000000; /* Was 0x8---- */ - mtdcr(plb4_acr, addr); - - /*-------------------------------------------------------------------------+ - | Set Nebula PLB4 arbiter to fair mode. - +-------------------------------------------------------------------------*/ - /* Segment0 */ - addr = (mfdcr(plb0_acr) & ~plb0_acr_ppm_mask) | plb0_acr_ppm_fair; - addr = (addr & ~plb0_acr_hbu_mask) | plb0_acr_hbu_enabled; - addr = (addr & ~plb0_acr_rdp_mask) | plb0_acr_rdp_4deep; - addr = (addr & ~plb0_acr_wrp_mask) | plb0_acr_wrp_2deep; - mtdcr(plb0_acr, addr); - - /* Segment1 */ - addr = (mfdcr(plb1_acr) & ~plb1_acr_ppm_mask) | plb1_acr_ppm_fair; - addr = (addr & ~plb1_acr_hbu_mask) | plb1_acr_hbu_enabled; - addr = (addr & ~plb1_acr_rdp_mask) | plb1_acr_rdp_4deep; - addr = (addr & ~plb1_acr_wrp_mask) | plb1_acr_wrp_2deep; - mtdcr(plb1_acr, addr); - - return 1; -} -#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ - -/************************************************************************* - * pci_target_init - * - * The bootstrap configuration provides default settings for the pci - * inbound map (PIM). But the bootstrap config choices are limited and - * may not be sufficient for a given board. - * - ************************************************************************/ -#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) -void pci_target_init(struct pci_controller *hose) -{ - /*--------------------------------------------------------------------------+ - * Set up Direct MMIO registers - *--------------------------------------------------------------------------*/ - /*--------------------------------------------------------------------------+ - | PowerPC440 EP PCI Master configuration. - | Map one 1Gig range of PLB/processor addresses to PCI memory space. - | PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF - | Use byte reversed out routines to handle endianess. - | Make this region non-prefetchable. - +--------------------------------------------------------------------------*/ - out32r(PCIX0_PMM0MA, 0x00000000); /* PMM0 Mask/Attribute - disabled b4 setting */ - out32r(PCIX0_PMM0LA, CFG_PCI_MEMBASE); /* PMM0 Local Address */ - out32r(PCIX0_PMM0PCILA, CFG_PCI_MEMBASE); /* PMM0 PCI Low Address */ - out32r(PCIX0_PMM0PCIHA, 0x00000000); /* PMM0 PCI High Address */ - out32r(PCIX0_PMM0MA, 0xE0000001); /* 512M + No prefetching, and enable region */ - - out32r(PCIX0_PMM1MA, 0x00000000); /* PMM0 Mask/Attribute - disabled b4 setting */ - out32r(PCIX0_PMM1LA, CFG_PCI_MEMBASE2); /* PMM0 Local Address */ - out32r(PCIX0_PMM1PCILA, CFG_PCI_MEMBASE2); /* PMM0 PCI Low Address */ - out32r(PCIX0_PMM1PCIHA, 0x00000000); /* PMM0 PCI High Address */ - out32r(PCIX0_PMM1MA, 0xE0000001); /* 512M + No prefetching, and enable region */ - - out32r(PCIX0_PTM1MS, 0x00000001); /* Memory Size/Attribute */ - out32r(PCIX0_PTM1LA, 0); /* Local Addr. Reg */ - out32r(PCIX0_PTM2MS, 0); /* Memory Size/Attribute */ - out32r(PCIX0_PTM2LA, 0); /* Local Addr. Reg */ - - /*--------------------------------------------------------------------------+ - * Set up Configuration registers - *--------------------------------------------------------------------------*/ - - /* Program the board's subsystem id/vendor id */ - pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID, - CFG_PCI_SUBSYS_VENDORID); - pci_write_config_word(0, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_ID); - - /* Configure command register as bus master */ - pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER); - - /* 240nS PCI clock */ - pci_write_config_word(0, PCI_LATENCY_TIMER, 1); - - /* No error reporting */ - pci_write_config_word(0, PCI_ERREN, 0); - - pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101); - -} -#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ - -/************************************************************************* - * pci_master_init - * - ************************************************************************/ -#if defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) -void pci_master_init(struct pci_controller *hose) -{ - unsigned short temp_short; - - /*--------------------------------------------------------------------------+ - | Write the PowerPC440 EP PCI Configuration regs. - | Enable PowerPC440 EP to be a master on the PCI bus (PMM). - | Enable PowerPC440 EP to act as a PCI memory target (PTM). - +--------------------------------------------------------------------------*/ - pci_read_config_word(0, PCI_COMMAND, &temp_short); - pci_write_config_word(0, PCI_COMMAND, - temp_short | PCI_COMMAND_MASTER | - PCI_COMMAND_MEMORY); -} -#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) */ - -/************************************************************************* - * is_pci_host - * - * This routine is called to determine if a pci scan should be - * performed. With various hardware environments (especially cPCI and - * PPMC) it's insufficient to depend on the state of the arbiter enable - * bit in the strap register, or generic host/adapter assumptions. - * - * Rather than hard-code a bad assumption in the general 440 code, the - * 440 pci code requires the board to decide at runtime. - * - * Return 0 for adapter mode, non-zero for host (monarch) mode. - * - * - ************************************************************************/ -#if defined(CONFIG_PCI) -int is_pci_host(struct pci_controller *hose) -{ - /* Bamboo is always configured as host. */ - return (1); -} -#endif /* defined(CONFIG_PCI) */ - -/************************************************************************* - * hw_watchdog_reset - * - * This routine is called to reset (keep alive) the watchdog timer - * - ************************************************************************/ -#if defined(CONFIG_HW_WATCHDOG) -void hw_watchdog_reset(void) -{ - -} -#endif diff --git a/board/amcc/yosemite/yosemite.c b/board/amcc/yosemite/yosemite.c index 7f2e718..c2e12ba 100644 --- a/board/amcc/yosemite/yosemite.c +++ b/board/amcc/yosemite/yosemite.c @@ -39,24 +39,6 @@ int board_early_init_f(void) reg = mfdcr(ebccfgd); mtdcr(ebccfgd, reg | 0x04000000); /* Set ATC */ - mtebc(pb0ap, 0x03017300); /* FLASH/SRAM */ - mtebc(pb0cr, 0xfc0da000); /* BAS=0xfc0 64MB r/w 16-bit */ - - mtebc(pb1ap, 0x00000000); - mtebc(pb1cr, 0x00000000); - - mtebc(pb2ap, 0x04814500); - /*CPLD*/ mtebc(pb2cr, 0x80018000); /*BAS=0x800 1MB r/w 8-bit */ - - mtebc(pb3ap, 0x00000000); - mtebc(pb3cr, 0x00000000); - - mtebc(pb4ap, 0x00000000); - mtebc(pb4cr, 0x00000000); - - mtebc(pb5ap, 0x00000000); - mtebc(pb5cr, 0x00000000); - /*-------------------------------------------------------------------- * Setup the GPIO pins *-------------------------------------------------------------------*/ @@ -83,12 +65,14 @@ int board_early_init_f(void) out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); +#ifdef CONFIG_440EP /*setup USB 2.0 */ out32(GPIO1_TCR, in32(GPIO1_TCR) | 0xc0000000); out32(GPIO1_OSRL, in32(GPIO1_OSRL) | 0x50000000); out32(GPIO0_TCR, in32(GPIO0_TCR) | 0xf); out32(GPIO0_OSRH, in32(GPIO0_OSRH) | 0xaa); out32(GPIO0_ISR2H, in32(GPIO0_ISR2H) | 0x00000500); +#endif /*-------------------------------------------------------------------- * Setup the interrupt controller polarities, triggers, etc. @@ -123,8 +107,10 @@ int board_early_init_f(void) /*enable ethernet */ *(unsigned char *)(CFG_BCSR_BASE | 0x08) = 0xf0; +#ifdef CONFIG_440EP /*enable usb 1.1 fs device and remove usb 2.0 reset */ *(unsigned char *)(CFG_BCSR_BASE | 0x09) = 0x00; +#endif /*get rid of flash write protect */ *(unsigned char *)(CFG_BCSR_BASE | 0x07) = 0x00; @@ -186,8 +172,19 @@ int misc_init_r (void) int checkboard(void) { char *s = getenv("serial#"); + u8 rev; + u8 val; +#ifdef CONFIG_440EP printf("Board: Yosemite - AMCC PPC440EP Evaluation Board"); +#else + printf("Board: Yellowstone - AMCC PPC440GR Evaluation Board"); +#endif + + rev = *(u8 *)(CFG_CPLD + 0); + val = *(u8 *)(CFG_CPLD + 5) & 0x01; + printf(", Rev. %X, PCI=%d MHz", rev, val ? 66 : 33); + if (s != NULL) { puts(", serial# "); puts(s); @@ -548,3 +545,9 @@ void hw_watchdog_reset(void) } #endif + +void board_reset(void) +{ + /* give reset to BCSR */ + *(unsigned char *)(CFG_BCSR_BASE | 0x06) = 0x09; +} diff --git a/board/amcc/yucca/init.S b/board/amcc/yucca/init.S index c9eca68..c92dcf7 100644 --- a/board/amcc/yucca/init.S +++ b/board/amcc/yucca/init.S @@ -1,4 +1,7 @@ /* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com> * * See file CREDITS for list of people who contributed to this @@ -19,56 +22,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ -/* port to AMCC 440SPE evaluatioon board - SG April 12,2005 */ #include <ppc_asm.tmpl> #include <config.h> - -/* General */ -#define TLB_VALID 0x00000200 - -/* Supported page sizes */ - -#define SZ_1K 0x00000000 -#define SZ_4K 0x00000010 -#define SZ_16K 0x00000020 -#define SZ_64K 0x00000030 -#define SZ_256K 0x00000040 -#define SZ_1M 0x00000050 -#define SZ_16M 0x00000070 -#define SZ_256M 0x00000090 - -/* Storage attributes */ -#define SA_W 0x00000800 /* Write-through */ -#define SA_I 0x00000400 /* Caching inhibited */ -#define SA_M 0x00000200 /* Memory coherence */ -#define SA_G 0x00000100 /* Guarded */ -#define SA_E 0x00000080 /* Endian */ - -/* Access control */ -#define AC_X 0x00000024 /* Execute */ -#define AC_W 0x00000012 /* Write */ -#define AC_R 0x00000009 /* Read */ - -/* Some handy macros */ - -#define EPN(e) ((e) & 0xfffffc00) -#define TLB0(epn,sz) ((EPN((epn)) | (sz) | TLB_VALID )) -#define TLB1(rpn,erpn) (((rpn) & 0xfffffc00) | (erpn)) -#define TLB2(a) ((a) & 0x00000fbf) - -#define tlbtab_start\ - mflr r1 ;\ - bl 0f ; - -#define tlbtab_end\ - .long 0, 0, 0 ;\ -0: mflr r0 ;\ - mtlr r1 ;\ - blr ; - -#define tlbentry(epn,sz,rpn,erpn,attr)\ - .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) +#include <asm-ppc/mmu.h> /************************************************************************** * TLB TABLE @@ -89,12 +46,18 @@ .globl tlbtabA tlbtabA: tlbtab_start - tlbentry(0xfff00000, SZ_16M, 0xfff00000, 4, AC_R|AC_W|AC_X|SA_G) - tlbentry(CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry(CFG_SDRAM_BASE + 0x10000000, SZ_256M, 0x10000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry(CFG_SDRAM_BASE + 0x20000000, SZ_256M, 0x20000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry(CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) + /* + * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the + * speed up boot process. It is patched after relocation to enable SA_I + */ + tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) tlbentry(CFG_FPGA_BASE, SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I) @@ -126,12 +89,18 @@ tlbtabA: .globl tlbtabB tlbtabB: tlbtab_start - tlbentry(0xfff00000, SZ_16M, 0xfff00000, 4, AC_R|AC_W|AC_X|SA_G) - tlbentry(CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry(CFG_SDRAM_BASE + 0x10000000, SZ_256M, 0x10000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry(CFG_SDRAM_BASE + 0x20000000, SZ_256M, 0x20000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry(CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) + /* + * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the + * speed up boot process. It is patched after relocation to enable SA_I + */ + tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G) + + /* + * TLB entries for SDRAM are not needed on this platform. + * They are dynamically generated in the SPD DDR(2) detection + * routine. + */ tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) tlbentry(CFG_FPGA_BASE, SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I) diff --git a/board/amcc/yucca/yucca.c b/board/amcc/yucca/yucca.c index e9b34dd..90eaab1 100644 --- a/board/amcc/yucca/yucca.c +++ b/board/amcc/yucca/yucca.c @@ -44,8 +44,6 @@ int compare_to_true(char *str ); char *remove_l_w_space(char *in_str ); char *remove_t_w_space(char *in_str ); int get_console_port(void); -unsigned long ppcMfcpr(unsigned long cpr_reg); -unsigned long ppcMfsdr(unsigned long sdr_reg); int ppc440spe_init_pcie_rootport(int port); void ppc440spe_setup_pcie(struct pci_controller *hose, int port); @@ -221,7 +219,7 @@ int board_early_init_f (void) | +-------------------------------------------------------------------*/ /* Read Pin Strap Register in PPC440SP */ - sdr0_pinstp = ppcMfsdr(SDR0_PINSTP); + mfsdr(SDR0_PINSTP, sdr0_pinstp); bootstrap_settings = sdr0_pinstp & SDR0_PINSTP_BOOTSTRAP_MASK; switch (bootstrap_settings) { @@ -246,7 +244,7 @@ int board_early_init_f (void) * Boot Settings in IIC EEprom address 0x50 or 0x54 * Read Serial Device Strap Register1 in PPC440SPe */ - sdr0_sdstp1 = ppcMfsdr(SDR0_SDSTP1); + mfsdr(SDR0_SDSTP1, sdr0_sdstp1); boot_selection = sdr0_sdstp1 & SDR0_SDSTP1_ERPN_MASK; ebc_data_width = sdr0_sdstp1 & SDR0_SDSTP1_EBCW_MASK; @@ -564,277 +562,6 @@ int checkboard (void) return 0; } -static long int yucca_probe_for_dimms(void) -{ - int dimm_installed[MAXDIMMS]; - int dimm_num, result; - int dimms_found = 0; - uchar dimm_addr = IIC0_DIMM0_ADDR; - uchar dimm_spd_data[MAX_SPD_BYTES]; - - for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) { - /* check if there is a chip at the dimm address */ - switch (dimm_num) { - case 0: - dimm_addr = IIC0_DIMM0_ADDR; - break; - case 1: - dimm_addr = IIC0_DIMM1_ADDR; - break; - } - - result = i2c_probe(dimm_addr); - - memset(dimm_spd_data, 0, MAX_SPD_BYTES * sizeof(char)); - if (result == 0) { - /* read first byte of SPD data, if there is any data */ - result = i2c_read(dimm_addr, 0, 1, dimm_spd_data, 1); - - if (result == 0) { - result = dimm_spd_data[0]; - result = result > MAX_SPD_BYTES ? - MAX_SPD_BYTES : result; - result = i2c_read(dimm_addr, 0, 1, - dimm_spd_data, result); - } - } - - if ((result == 0) && - (dimm_spd_data[64] == MICRON_SPD_JEDEC_ID)) { - dimm_installed[dimm_num] = TRUE; - dimms_found++; - debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num); - } else { - dimm_installed[dimm_num] = FALSE; - debug("DIMM slot %d: Not populated or cannot sucessfully probe the DIMM\n", dimm_num); - } - } - - if (dimms_found == 0) { - printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n"); - hang(); - } - - if (dimm_installed[0] != TRUE) { - printf("\nERROR - DIMM slot 0 must be populated before DIMM slot 1.\n"); - printf(" Unsupported configuration. Move DIMM module from DIMM slot 1 to slot 0.\n\n"); - hang(); - } - - return dimms_found; -} - -/************************************************************************* - * init SDRAM controller with fixed value - * the initialization values are for 2x MICRON DDR2 - * PN: MT18HTF6472DY-53EB2 - * 512MB, DDR2, 533, CL4, ECC, REG - ************************************************************************/ -static long int fixed_sdram(void) -{ - long int yucca_dimms = 0; - - yucca_dimms = yucca_probe_for_dimms(); - - /* SDRAM0_MCOPT2 (0X21) Clear DCEN BIT */ - mtdcr( 0x10, 0x00000021 ); - mtdcr( 0x11, 0x84000000 ); - - /* SDRAM0_MCOPT1 (0X20) ECC OFF / 64 bits / 4 banks / DDR2 */ - mtdcr( 0x10, 0x00000020 ); - mtdcr( 0x11, 0x2D122000 ); - - /* SET MCIF0_CODT Die Termination On */ - mtdcr( 0x10, 0x00000026 ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x2A800021 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x02800021 ); - - /* On-Die Termination for Bank 0 */ - mtdcr( 0x10, 0x00000022 ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x18000000 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x06000000 ); - - /* On-Die Termination for Bank 1 */ - mtdcr( 0x10, 0x00000023 ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x18000000 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x01800000 ); - - /* On-Die Termination for Bank 2 */ - mtdcr( 0x10, 0x00000024 ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x01800000 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x00000000 ); - - /* On-Die Termination for Bank 3 */ - mtdcr( 0x10, 0x00000025 ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x01800000 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x00000000 ); - - /* Refresh Time register (0x30) Refresh every 7.8125uS */ - mtdcr( 0x10, 0x00000030 ); - mtdcr( 0x11, 0x08200000 ); - - /* SET MCIF0_MMODE CL 4 */ - mtdcr( 0x10, 0x00000088 ); - mtdcr( 0x11, 0x00000642 ); - - /* MCIF0_MEMODE */ - mtdcr( 0x10, 0x00000089 ); - mtdcr( 0x11, 0x00000004 ); - - /*SET MCIF0_MB0CF */ - mtdcr( 0x10, 0x00000040 ); - mtdcr( 0x11, 0x00000201 ); - - /* SET MCIF0_MB1CF */ - mtdcr( 0x10, 0x00000044 ); - mtdcr( 0x11, 0x00000201 ); - - /* SET MCIF0_MB2CF */ - mtdcr( 0x10, 0x00000048 ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x00000201 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x00000000 ); - - /* SET MCIF0_MB3CF */ - mtdcr( 0x10, 0x0000004c ); - if (yucca_dimms == 2) - mtdcr( 0x11, 0x00000201 ); - else if (yucca_dimms == 1) - mtdcr( 0x11, 0x00000000 ); - - /* SET MCIF0_INITPLR0 # NOP */ - mtdcr( 0x10, 0x00000050 ); - mtdcr( 0x11, 0xB5380000 ); - - /* SET MCIF0_INITPLR1 # PRE */ - mtdcr( 0x10, 0x00000051 ); - mtdcr( 0x11, 0x82100400 ); - - /* SET MCIF0_INITPLR2 # EMR2 */ - mtdcr( 0x10, 0x00000052 ); - mtdcr( 0x11, 0x80820000 ); - - /* SET MCIF0_INITPLR3 # EMR3 */ - mtdcr( 0x10, 0x00000053 ); - mtdcr( 0x11, 0x80830000 ); - - /* SET MCIF0_INITPLR4 # EMR DLL ENABLE */ - mtdcr( 0x10, 0x00000054 ); - mtdcr( 0x11, 0x80810000 ); - - /* SET MCIF0_INITPLR5 # MR DLL RESET */ - mtdcr( 0x10, 0x00000055 ); - mtdcr( 0x11, 0x80800542 ); - - /* SET MCIF0_INITPLR6 # PRE */ - mtdcr( 0x10, 0x00000056 ); - mtdcr( 0x11, 0x82100400 ); - - /* SET MCIF0_INITPLR7 # Refresh */ - mtdcr( 0x10, 0x00000057 ); - mtdcr( 0x11, 0x8A080000 ); - - /* SET MCIF0_INITPLR8 # Refresh */ - mtdcr( 0x10, 0x00000058 ); - mtdcr( 0x11, 0x8A080000 ); - - /* SET MCIF0_INITPLR9 # Refresh */ - mtdcr( 0x10, 0x00000059 ); - mtdcr( 0x11, 0x8A080000 ); - - /* SET MCIF0_INITPLR10 # Refresh */ - mtdcr( 0x10, 0x0000005A ); - mtdcr( 0x11, 0x8A080000 ); - - /* SET MCIF0_INITPLR11 # MR */ - mtdcr( 0x10, 0x0000005B ); - mtdcr( 0x11, 0x80800442 ); - - /* SET MCIF0_INITPLR12 # EMR OCD Default*/ - mtdcr( 0x10, 0x0000005C ); - mtdcr( 0x11, 0x80810380 ); - - /* SET MCIF0_INITPLR13 # EMR OCD Exit */ - mtdcr( 0x10, 0x0000005D ); - mtdcr( 0x11, 0x80810000 ); - - /* 0x80: Adv Addr clock by 180 deg */ - mtdcr( 0x10, 0x00000080 ); - mtdcr( 0x11, 0x80000000 ); - - /* 0x21: Exit self refresh, set DC_EN */ - mtdcr( 0x10, 0x00000021 ); - mtdcr( 0x11, 0x28000000 ); - - /* 0x81: Write DQS Adv 90 + Fractional DQS Delay */ - mtdcr( 0x10, 0x00000081 ); - mtdcr( 0x11, 0x80000800 ); - - /* MCIF0_SDTR1 */ - mtdcr( 0x10, 0x00000085 ); - mtdcr( 0x11, 0x80201000 ); - - /* MCIF0_SDTR2 */ - mtdcr( 0x10, 0x00000086 ); - mtdcr( 0x11, 0x42103242 ); - - /* MCIF0_SDTR3 */ - mtdcr( 0x10, 0x00000087 ); - mtdcr( 0x11, 0x0C100D14 ); - - /* SET MQ0_B0BAS base addr 00000000 / 256MB */ - mtdcr( 0x40, 0x0000F800 ); - - /* SET MQ0_B1BAS base addr 10000000 / 256MB */ - mtdcr( 0x41, 0x0400F800 ); - - /* SET MQ0_B2BAS base addr 20000000 / 256MB */ - if (yucca_dimms == 2) - mtdcr( 0x42, 0x0800F800 ); - else if (yucca_dimms == 1) - mtdcr( 0x42, 0x00000000 ); - - /* SET MQ0_B3BAS base addr 30000000 / 256MB */ - if (yucca_dimms == 2) - mtdcr( 0x43, 0x0C00F800 ); - else if (yucca_dimms == 1) - mtdcr( 0x43, 0x00000000 ); - - /* SDRAM_RQDC */ - mtdcr( 0x10, 0x00000070 ); - mtdcr( 0x11, 0x8000003F ); - - /* SDRAM_RDCC */ - mtdcr( 0x10, 0x00000078 ); - mtdcr( 0x11, 0x80000000 ); - - /* SDRAM_RFDC */ - mtdcr( 0x10, 0x00000074 ); - mtdcr( 0x11, 0x00000220 ); - - return (yucca_dimms * 512) << 20; -} - -long int initdram (int board_type) -{ - long dram_size = 0; - - dram_size = fixed_sdram(); - - return dram_size; -} - #if defined(CFG_DRAM_TEST) int testdram (void) { @@ -1267,42 +994,3 @@ int onboard_pci_arbiter_selected(int core_pci) #endif return (BOARD_OPTION_NOT_SELECTED); } - -/*---------------------------------------------------------------------------+ - | ppcMfcpr. - +---------------------------------------------------------------------------*/ -unsigned long ppcMfcpr(unsigned long cpr_reg) -{ - unsigned long msr; - unsigned long cpr_cfgaddr_temp; - unsigned long cpr_value; - - msr = (mfmsr () & ~(MSR_EE)); - cpr_cfgaddr_temp = mfdcr(CPR0_CFGADDR); - mtdcr(CPR0_CFGADDR, cpr_reg); - cpr_value = mfdcr(CPR0_CFGDATA); - mtdcr(CPR0_CFGADDR, cpr_cfgaddr_temp); - mtmsr(msr); - - return (cpr_value); -} - -/*----------------------------------------------------------------------------+ -| Indirect Access of the System DCR's (SDR) -| ppcMfsdr -+----------------------------------------------------------------------------*/ -unsigned long ppcMfsdr(unsigned long sdr_reg) -{ - unsigned long msr; - unsigned long sdr_cfgaddr_temp; - unsigned long sdr_value; - - msr = (mfmsr () & ~(MSR_EE)); - sdr_cfgaddr_temp = mfdcr(SDR0_CFGADDR); - mtdcr(SDR0_CFGADDR, sdr_reg); - sdr_value = mfdcr(SDR0_CFGDATA); - mtdcr(SDR0_CFGADDR, sdr_cfgaddr_temp); - mtmsr(msr); - - return (sdr_value); -} diff --git a/board/stamp/Makefile b/board/bf533-ezkit/Makefile index ee52007..4fe7d78 100644 --- a/board/stamp/Makefile +++ b/board/bf533-ezkit/Makefile @@ -1,7 +1,7 @@ # # U-boot - Makefile # -# Copyright (c) 2005 blackfin.uclinux.org +# Copyright (c) 2007 Analog Device Inc. # # (C) Copyright 2000-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -25,41 +25,28 @@ # MA 02111-1307 USA # -# -# (C) Copyright 2001-2006 -# 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 = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o stamp.o +COBJS := $(BOARD).o flash.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) SOBJS := $(addprefix $(obj),$(SOBJS)) -$(LIB): $(obj).depend $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) +$(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +u-boot.lds: u-boot.lds.S + $(CPP) $(CPPFLAGS) -P -Ubfin $^ > $@.tmp + mv -f $@.tmp $@ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend ######################################################################### diff --git a/board/ezkit533/ezkit533.c b/board/bf533-ezkit/bf533-ezkit.c index 8d6c8de..feaeb00 100644 --- a/board/ezkit533/ezkit533.c +++ b/board/bf533-ezkit/bf533-ezkit.c @@ -30,24 +30,28 @@ #include "psd4256.h" #endif -DECLARE_GLOBAL_DATA_PTR; - int checkboard(void) { +#if (BFIN_CPU == ADSP_BF531) + printf("CPU: ADSP BF531 Rev.: 0.%d\n", *pCHIPID >> 28); +#elif (BFIN_CPU == ADSP_BF532) + printf("CPU: ADSP BF532 Rev.: 0.%d\n", *pCHIPID >> 28); +#else printf("CPU: ADSP BF533 Rev.: 0.%d\n", *pCHIPID >> 28); +#endif printf("Board: ADI BF533 EZ-Kit Lite board\n"); printf(" Support: http://blackfin.uclinux.org/\n"); - printf(" Richard Klingler <richard@uclinux.net>\n"); return 0; } long int initdram(int board_type) { + DECLARE_GLOBAL_DATA_PTR; #ifdef DEBUG int brate; char *tmp = getenv("baudrate"); brate = simple_strtoul(tmp, NULL, 16); - printf("Serial Port initialized with Baud rate = %x\n",brate); + printf("Serial Port initialized with Baud rate = %x\n", brate); printf("SDRAM attributes:\n"); printf("tRCD %d SCLK Cycles,tRP %d SCLK Cycles,tRAS %d SCLK Cycles" "tWR %d SCLK Cycles,CAS Latency %d SCLK cycles \n", @@ -64,9 +68,13 @@ long int initdram(int board_type) /* miscellaneous platform dependent initialisations */ int misc_init_r(void) { - /* Set direction bits for Video en/decoder reset as output */ - *(volatile unsigned char *)(CFG_FLASH1_BASE + PSD_PORTA_DIR) = PSDA_VDEC_RST | PSDA_VENC_RST; - /* Deactivate Video en/decoder reset lines */ - *(volatile unsigned char *)(CFG_FLASH1_BASE + PSD_PORTA_DOUT) = PSDA_VDEC_RST | PSDA_VENC_RST; + /* Set direction bits for Video en/decoder reset as output */ + *(volatile unsigned char *)(CFG_FLASH1_BASE + PSD_PORTA_DIR) = + PSDA_VDEC_RST | PSDA_VENC_RST; + /* Deactivate Video en/decoder reset lines */ + *(volatile unsigned char *)(CFG_FLASH1_BASE + PSD_PORTA_DOUT) = + PSDA_VDEC_RST | PSDA_VENC_RST; + + return 0; } #endif diff --git a/board/bf533-ezkit/config.mk b/board/bf533-ezkit/config.mk new file mode 100644 index 0000000..f39be5f --- /dev/null +++ b/board/bf533-ezkit/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2001 +# 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 +# +# TEXT_BASE should be defined as the MAX_SDRAM Address - 256k bytes +# 256k is defined as CFG_MONITOR_LEN in ./include/configs/<board>.h +TEXT_BASE = 0x01FC0000 diff --git a/board/ezkit533/flash-defines.h b/board/bf533-ezkit/flash-defines.h index 8f9dff5..e211918 100644 --- a/board/ezkit533/flash-defines.h +++ b/board/bf533-ezkit/flash-defines.h @@ -52,17 +52,13 @@ #define CFG_FLASH0_BASE 0x20000000 #define RESET_VAL 0xF0 - -asm("#define FLASH_START_L 0x0000"); -asm("#define FLASH_START_H 0x2000"); - flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; int get_codes(void); int poll_toggle_bit(long lOffset); void reset_flash(void); int erase_flash(void); -int erase_block_flash(int,unsigned long); +int erase_block_flash(int, unsigned long); void unlock_flash(long lOffset); int write_data(long lStart, long lCount, long lStride, int *pnData); int FillData(long lStart, long lCount, long lStride, int *pnData); diff --git a/board/ezkit533/flash.c b/board/bf533-ezkit/flash.c index b0a0796..067a260 100644 --- a/board/ezkit533/flash.c +++ b/board/bf533-ezkit/flash.c @@ -26,6 +26,7 @@ * MA 02111-1307 USA */ +#include <asm/io.h> #include "flash-defines.h" void flash_reset(void) @@ -33,14 +34,13 @@ void flash_reset(void) reset_flash(); } -unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, - int bank_flag) +unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, int bank_flag) { int id = 0, i = 0; static int FlagDev = 1; id = get_codes(); - if(FlagDev) { + if (FlagDev) { #ifdef DEBUG printf("Device ID of the Flash is %x\n", id); #endif @@ -100,10 +100,11 @@ unsigned long flash_init(void) if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) { printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", - size_b0, size_b0 >> 20); + size_b0, size_b0 >> 20); } - (void)flash_protect(FLAG_PROTECT_SET,CFG_FLASH0_BASE,(flash_info[0].start[2] - 1),&flash_info[0]); + (void)flash_protect(FLAG_PROTECT_SET, CFG_FLASH0_BASE, + (flash_info[0].start[2] - 1), &flash_info[0]); return (size_b0 + size_b1 + size_b2); } @@ -122,15 +123,14 @@ void flash_print_info(flash_info_t * info) printf("ST Microelectronics "); break; default: - printf("Unknown Vendor "); + printf("Unknown Vendor: (0x%08X) ", info->flash_id); break; } for (i = 0; i < info->sector_count; ++i) { if ((i % 5) == 0) printf("\n "); printf(" %08lX%s", - info->start[i], - info->protect[i] ? " (RO)" : " "); + info->start[i], info->protect[i] ? " (RO)" : " "); } printf("\n"); return; @@ -138,8 +138,8 @@ void flash_print_info(flash_info_t * info) int flash_erase(flash_info_t * info, int s_first, int s_last) { - int cnt = 0,i; - int prot,sect; + int cnt = 0, i; + int prot, sect; prot = 0; for (sect = s_first; sect <= s_last; ++sect) { @@ -148,15 +148,16 @@ int flash_erase(flash_info_t * info, int s_first, int s_last) } if (prot) - printf ("- Warning: %d protected sectors will not be erased!\n", prot); + printf("- Warning: %d protected sectors will not be erased!\n", + prot); else - printf ("\n"); + printf("\n"); cnt = s_last - s_first + 1; if (cnt == FLASH_TOT_SECT) { printf("Erasing flash, Please Wait \n"); - if(erase_flash() < 0) { + if (erase_flash() < 0) { printf("Erasing flash failed \n"); return FLASH_FAIL; } @@ -164,7 +165,7 @@ int flash_erase(flash_info_t * info, int s_first, int s_last) printf("Erasing Flash locations, Please Wait\n"); for (i = s_first; i <= s_last; i++) { if (info->protect[i] == 0) { /* not protected */ - if(erase_block_flash(i, info->start[i]) < 0) { + if (erase_block_flash(i, info->start[i]) < 0) { printf("Error Sector erasing \n"); return FLASH_FAIL; } @@ -178,13 +179,12 @@ int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt) { int ret; - ret = write_data(addr, cnt, 1, (int *) src); - if(ret == FLASH_FAIL) + ret = write_data(addr, cnt, 1, (int *)src); + if (ret == FLASH_FAIL) return ERR_NOT_ERASED; return FLASH_SUCCESS; } - int write_data(long lStart, long lCount, long lStride, int *pnData) { long i = 0; @@ -198,20 +198,23 @@ int write_data(long lStart, long lCount, long lStride, int *pnData) for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) { for (iShift = 0, j = 0; (j < iNumWords); - j++, ulOffset += (lStride * 2)) { + j++, ulOffset += (lStride * 2)) { if ((ulOffset >= INVALIDLOCNSTART) - && (ulOffset < INVALIDLOCNEND)) { - printf("Invalid locations, Try writing to another location \n"); + && (ulOffset < INVALIDLOCNEND)) { + printf + ("Invalid locations, Try writing to another location \n"); return FLASH_FAIL; } get_sector_number(ulOffset, &nSector); - read_flash(ulOffset,&d); - if(d != 0xffff) { - printf("Flash not erased at offset 0x%x Please erase to reprogram \n",ulOffset); + read_flash(ulOffset, &d); + if (d != 0xffff) { + printf + ("Flash not erased at offset 0x%x Please erase to reprogram \n", + ulOffset); return FLASH_FAIL; } unlock_flash(ulOffset); - if(write_flash(ulOffset, (pnData[i] >> iShift)) < 0) { + if (write_flash(ulOffset, (pnData[i] >> iShift)) < 0) { printf("Error programming the flash \n"); return FLASH_FAIL; } @@ -220,17 +223,18 @@ int write_data(long lStart, long lCount, long lStride, int *pnData) } if (nLeftover > 0) { if ((ulOffset >= INVALIDLOCNSTART) - && (ulOffset < INVALIDLOCNEND)) - return FLASH_FAIL; + && (ulOffset < INVALIDLOCNEND)) + return FLASH_FAIL; get_sector_number(ulOffset, &nSector); - read_flash(ulOffset,&d); - if(d != 0xffff) { - printf("Flash already programmed. Please erase to reprogram \n"); - printf("uloffset = 0x%x \t d = 0x%x\n",ulOffset,d); + read_flash(ulOffset, &d); + if (d != 0xffff) { + printf + ("Flash already programmed. Please erase to reprogram \n"); + printf("uloffset = 0x%x \t d = 0x%x\n", ulOffset, d); return FLASH_FAIL; } unlock_flash(ulOffset); - if(write_flash(ulOffset, pnData[i]) < 0) { + if (write_flash(ulOffset, pnData[i]) < 0) { printf("Error programming the flash \n"); return FLASH_FAIL; } @@ -252,8 +256,8 @@ int read_data(long ulStart, long lCount, long lStride, int *pnData) for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) { for (iShift = 0, j = 0; j < iNumWords; j += 2) { if ((ulOffset >= INVALIDLOCNSTART) - && (ulOffset < INVALIDLOCNEND)) - return FLASH_FAIL; + && (ulOffset < INVALIDLOCNEND)) + return FLASH_FAIL; get_sector_number(ulOffset, &nSector); read_flash(ulOffset, &nLow); @@ -265,8 +269,8 @@ int read_data(long ulStart, long lCount, long lStride, int *pnData) } if (nLeftover > 0) { if ((ulOffset >= INVALIDLOCNSTART) - && (ulOffset < INVALIDLOCNEND)) - return FLASH_FAIL; + && (ulOffset < INVALIDLOCNEND)) + return FLASH_FAIL; get_sector_number(ulOffset, &nSector); read_flash(ulOffset, &pnData[i]); @@ -279,10 +283,10 @@ int write_flash(long nOffset, int nValue) long addr; addr = (CFG_FLASH_BASE + nOffset); - asm("ssync;"); - *(unsigned volatile short *) addr = nValue; - asm("ssync;"); - if(poll_toggle_bit(nOffset) < 0) + sync(); + *(unsigned volatile short *)addr = nValue; + sync(); + if (poll_toggle_bit(nOffset) < 0) return FLASH_FAIL; return FLASH_SUCCESS; } @@ -294,29 +298,30 @@ int read_flash(long nOffset, int *pnValue) if (nOffset != 0x2) reset_flash(); - asm("ssync;"); - nValue = *(volatile unsigned short *) addr; - asm("ssync;"); + sync(); + nValue = *(volatile unsigned short *)addr; + sync(); *pnValue = nValue; return TRUE; } int poll_toggle_bit(long lOffset) { - unsigned int u1,u2; + unsigned int u1, u2; unsigned long timeout = 0xFFFFFFFF; - volatile unsigned long *FB = (volatile unsigned long *)(0x20000000 + lOffset); - while(1) { - if(timeout < 0) + volatile unsigned long *FB = + (volatile unsigned long *)(0x20000000 + lOffset); + while (1) { + if (timeout < 0) break; u1 = *(volatile unsigned short *)FB; u2 = *(volatile unsigned short *)FB; - if((u1 & 0x0040) == (u2 & 0x0040)) + if ((u1 & 0x0040) == (u2 & 0x0040)) return FLASH_SUCCESS; - if((u2 & 0x0020) == 0x0000) + if ((u2 & 0x0020) == 0x0000) continue; u1 = *(volatile unsigned short *)FB; - if((u2 & 0x0040) == (u1 & 0x0040)) + if ((u2 & 0x0040) == (u1 & 0x0040)) return FLASH_SUCCESS; else { reset_flash(); @@ -325,7 +330,8 @@ int poll_toggle_bit(long lOffset) timeout--; } printf("Time out occured \n"); - if(timeout <0) return FLASH_FAIL; + if (timeout < 0) + return FLASH_FAIL; } void reset_flash(void) @@ -344,7 +350,7 @@ int erase_flash(void) write_flash(WRITESEQ5, WRITEDATA5); write_flash(WRITESEQ6, WRITEDATA6); - if(poll_toggle_bit(0x0000) < 0) + if (poll_toggle_bit(0x0000) < 0) return FLASH_FAIL; write_flash(SecFlashAOff + WRITESEQ1, WRITEDATA1); @@ -354,7 +360,7 @@ int erase_flash(void) write_flash(SecFlashAOff + WRITESEQ5, WRITEDATA5); write_flash(SecFlashAOff + WRITESEQ6, WRITEDATA6); - if(poll_toggle_bit(SecFlashASec1Off) < 0) + if (poll_toggle_bit(SecFlashASec1Off) < 0) return FLASH_FAIL; write_flash(PriFlashBOff + WRITESEQ1, WRITEDATA1); @@ -364,7 +370,7 @@ int erase_flash(void) write_flash(PriFlashBOff + WRITESEQ5, WRITEDATA5); write_flash(PriFlashBOff + WRITESEQ6, WRITEDATA6); - if(poll_toggle_bit(PriFlashBOff) <0) + if (poll_toggle_bit(PriFlashBOff) < 0) return FLASH_FAIL; write_flash(SecFlashBOff + WRITESEQ1, WRITEDATA1); @@ -374,7 +380,7 @@ int erase_flash(void) write_flash(SecFlashBOff + WRITESEQ5, WRITEDATA5); write_flash(SecFlashBOff + WRITESEQ6, WRITEDATA6); - if(poll_toggle_bit(SecFlashBOff) < 0) + if (poll_toggle_bit(SecFlashBOff) < 0) return FLASH_FAIL; return FLASH_SUCCESS; @@ -397,7 +403,7 @@ int erase_block_flash(int nBlock, unsigned long address) write_flash(ulSectorOff, BlockEraseVal); - if(poll_toggle_bit(ulSectorOff) < 0) + if (poll_toggle_bit(ulSectorOff) < 0) return FLASH_FAIL; return FLASH_SUCCESS; @@ -435,34 +441,34 @@ void get_sector_number(long ulOffset, int *pnSector) if (ulOffset >= SecFlashAOff) { if ((ulOffset < SecFlashASec1Off) - && (ulOffset < SecFlashASec2Off)) { - nSector = SECT32; + && (ulOffset < SecFlashASec2Off)) { + nSector = SECT32; } else if ((ulOffset >= SecFlashASec2Off) - && (ulOffset < SecFlashASec3Off)) { - nSector = SECT33; + && (ulOffset < SecFlashASec3Off)) { + nSector = SECT33; } else if ((ulOffset >= SecFlashASec3Off) - && (ulOffset < SecFlashASec4Off)) { - nSector = SECT34; + && (ulOffset < SecFlashASec4Off)) { + nSector = SECT34; } else if ((ulOffset >= SecFlashASec4Off) - && (ulOffset < SecFlashAEndOff)) { - nSector = SECT35; + && (ulOffset < SecFlashAEndOff)) { + nSector = SECT35; } } else if (ulOffset >= SecFlashBOff) { if ((ulOffset < SecFlashBSec1Off) - && (ulOffset < SecFlashBSec2Off)) { - nSector = SECT36; + && (ulOffset < SecFlashBSec2Off)) { + nSector = SECT36; } if ((ulOffset < SecFlashBSec2Off) - && (ulOffset < SecFlashBSec3Off)) { - nSector = SECT37; + && (ulOffset < SecFlashBSec3Off)) { + nSector = SECT37; } if ((ulOffset < SecFlashBSec3Off) - && (ulOffset < SecFlashBSec4Off)) { - nSector = SECT38; + && (ulOffset < SecFlashBSec4Off)) { + nSector = SECT38; } if ((ulOffset < SecFlashBSec4Off) - && (ulOffset < SecFlashBEndOff)) { - nSector = SECT39; + && (ulOffset < SecFlashBEndOff)) { + nSector = SECT39; } } else if ((ulOffset >= PriFlashAOff) && (ulOffset < SecFlashAOff)) { nSector = ulOffset & 0xffff0000; diff --git a/board/ezkit533/psd4256.h b/board/bf533-ezkit/psd4256.h index 01f6566..9776516 100644 --- a/board/ezkit533/psd4256.h +++ b/board/bf533-ezkit/psd4256.h @@ -49,19 +49,19 @@ * Flash A Port A Bit definitions */ -#define PSDA_PPICLK1 0x20 /* PPI Clock select bit 1 */ -#define PSDA_PPICLK0 0x10 /* PPI Clock select bit 0 */ -#define PSDA_VDEC_RST 0x08 /* Video decoder reset, 0 = RESET */ -#define PSDA_VENC_RST 0x04 /* Video encoder reset, 0 = RESET */ -#define PSDA_CODEC_RST 0x01 /* Codec reset, 0 = RESET */ +#define PSDA_PPICLK1 0x20 /* PPI Clock select bit 1 */ +#define PSDA_PPICLK0 0x10 /* PPI Clock select bit 0 */ +#define PSDA_VDEC_RST 0x08 /* Video decoder reset, 0 = RESET */ +#define PSDA_VENC_RST 0x04 /* Video encoder reset, 0 = RESET */ +#define PSDA_CODEC_RST 0x01 /* Codec reset, 0 = RESET */ /* * Flash A Port B Bit definitions */ -#define PSDA_LED9 0x20 /* LED 9, 1 = LED ON */ -#define PSDA_LED8 0x10 /* LED 8, 1 = LED ON */ -#define PSDA_LED7 0x08 /* LED 7, 1 = LED ON */ -#define PSDA_LED6 0x04 /* LED 6, 1 = LED ON */ -#define PSDA_LED5 0x02 /* LED 5, 1 = LED ON */ -#define PSDA_LED4 0x01 /* LED 4, 1 = LED ON */ +#define PSDA_LED9 0x20 /* LED 9, 1 = LED ON */ +#define PSDA_LED8 0x10 /* LED 8, 1 = LED ON */ +#define PSDA_LED7 0x08 /* LED 7, 1 = LED ON */ +#define PSDA_LED6 0x04 /* LED 6, 1 = LED ON */ +#define PSDA_LED5 0x02 /* LED 5, 1 = LED ON */ +#define PSDA_LED4 0x01 /* LED 4, 1 = LED ON */ diff --git a/board/ezkit533/u-boot.lds b/board/bf533-ezkit/u-boot.lds.S index 10203ff..9742e02 100644 --- a/board/ezkit533/u-boot.lds +++ b/board/bf533-ezkit/u-boot.lds.S @@ -1,7 +1,7 @@ /* - * U-boot - u-boot.lds + * U-boot - u-boot.lds.S * - * Copyright (c) 2005 blackfin.uclinux.org + * Copyright (c) 2005-2007 Analog Device Inc. * * (C) Copyright 2000-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -25,6 +25,8 @@ * MA 02111-1307 USA */ +#include <config.h> + OUTPUT_ARCH(bfin) SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); /* Do we need any of these for elf? @@ -55,6 +57,7 @@ SECTIONS .rela.plt : { *(.rela.plt) } .init : { *(.init) } .plt : { *(.plt) } + . = CFG_MONITOR_BASE; .text : { /* WARNING - the following is hand-optimized to fit within */ @@ -68,10 +71,11 @@ SECTIONS cpu/bf533/interrupt.o (.text) cpu/bf533/serial.o (.text) common/dlmalloc.o (.text) - lib_generic/vsprintf.o (.text) +/* lib_blackfin/bf533_string.o (.text) */ +/* lib_generic/vsprintf.o (.text) */ lib_generic/crc32.o (.text) lib_generic/zlib.o (.text) - board/ezkit533/ezkit533.o (.text) + board/bf533-ezkit/bf533-ezkit.o (.text) . = DEFINED(env_offset) ? env_offset : .; common/environment.o (.text) @@ -119,9 +123,9 @@ SECTIONS _edata = .; PROVIDE (edata = .); - __u_boot_cmd_start = .; + ___u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } - __u_boot_cmd_end = .; + ___u_boot_cmd_end = .; __start___ex_table = .; diff --git a/board/bf533-stamp/Makefile b/board/bf533-stamp/Makefile new file mode 100644 index 0000000..8223d59 --- /dev/null +++ b/board/bf533-stamp/Makefile @@ -0,0 +1,58 @@ +# +# U-boot - Makefile +# +# Copyright (c) 2007 Analog Device Inc. +# +# (C) Copyright 2000-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o spi.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +u-boot.lds: u-boot.lds.S + $(CPP) $(CPPFLAGS) -P -Ubfin $^ > $@.tmp + mv -f $@.tmp $@ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/stamp/stamp.c b/board/bf533-stamp/bf533-stamp.c index 7e3af20..2f6e751 100644 --- a/board/stamp/stamp.c +++ b/board/bf533-stamp/bf533-stamp.c @@ -27,9 +27,8 @@ #include <common.h> #include <asm/mem_init.h> -#include "stamp.h" - -DECLARE_GLOBAL_DATA_PTR; +#include <asm/io.h> +#include "bf533-stamp.h" #define STATUS_LED_OFF 0 #define STATUS_LED_ON 1 @@ -40,42 +39,45 @@ DECLARE_GLOBAL_DATA_PTR; # define SHOW_BOOT_PROGRESS(arg) #endif -int checkboard (void) +int checkboard(void) { - printf ("CPU: ADSP BF533 Rev.: 0.%d\n", *pCHIPID >> 28); - printf ("Board: ADI BF533 Stamp board\n"); - printf (" Support: http://blackfin.uclinux.org/\n"); - printf (" Richard Klingler <richard@uclinux.net>\n"); +#if (BFIN_CPU == ADSP_BF531) + printf("CPU: ADSP BF531 Rev.: 0.%d\n", *pCHIPID >> 28); +#elif (BFIN_CPU == ADSP_BF532) + printf("CPU: ADSP BF532 Rev.: 0.%d\n", *pCHIPID >> 28); +#else + printf("CPU: ADSP BF533 Rev.: 0.%d\n", *pCHIPID >> 28); +#endif + printf("Board: ADI BF533 Stamp board\n"); + printf(" Support: http://blackfin.uclinux.org/\n"); return 0; } -long int initdram (int board_type) +long int initdram(int board_type) { + DECLARE_GLOBAL_DATA_PTR; #ifdef DEBUG - printf ("SDRAM attributes:\n"); - printf (" tRCD:%d Cycles; tRP:%d Cycles; tRAS:%d Cycles; tWR:%d Cycles; " - "CAS Latency:%d cycles\n", - (SDRAM_tRCD >> 15), - (SDRAM_tRP >> 11), - (SDRAM_tRAS >> 6), - (SDRAM_tWR >> 19), - (SDRAM_CL >> 2)); - printf ("SDRAM Begin: 0x%x\n", CFG_SDRAM_BASE); - printf ("Bank size = %d MB\n", 128); + printf("SDRAM attributes:\n"); + printf + (" tRCD:%d Cycles; tRP:%d Cycles; tRAS:%d Cycles; tWR:%d Cycles; " + "CAS Latency:%d cycles\n", (SDRAM_tRCD >> 15), (SDRAM_tRP >> 11), + (SDRAM_tRAS >> 6), (SDRAM_tWR >> 19), (SDRAM_CL >> 2)); + printf("SDRAM Begin: 0x%x\n", CFG_SDRAM_BASE); + printf("Bank size = %d MB\n", 128); #endif gd->bd->bi_memstart = CFG_SDRAM_BASE; gd->bd->bi_memsize = CFG_MAX_RAM_SIZE; return (gd->bd->bi_memsize); } -void swap_to (int device_id) +void swap_to(int device_id) { if (device_id == ETHERNET) { *pFIO_DIR = PF0; - asm ("ssync;"); + sync(); *pFIO_FLAG_S = PF0; - asm ("ssync;"); + sync(); } else if (device_id == FLASH) { *pFIO_DIR = (PF4 | PF3 | PF2 | PF1 | PF0); *pFIO_FLAG_S = (PF4 | PF3 | PF2); @@ -85,9 +87,9 @@ void swap_to (int device_id) *pFIO_EDGE = (PF8 | PF7 | PF6 | PF5); *pFIO_INEN = (PF8 | PF7 | PF6 | PF5); *pFIO_FLAG_D = (PF4 | PF3 | PF2); - asm ("ssync;"); + sync(); } else { - printf ("Unknown bank to switch\n"); + printf("Unknown bank to switch\n"); } return; @@ -95,7 +97,7 @@ void swap_to (int device_id) #if defined(CONFIG_MISC_INIT_R) /* miscellaneous platform dependent initialisations */ -int misc_init_r (void) +int misc_init_r(void) { int i; int cf_stat = 0; @@ -104,7 +106,7 @@ int misc_init_r (void) *pFIO_EDGE = FIO_EDGE_CF_BITS; *pFIO_POLAR = FIO_POLAR_CF_BITS; for (i = 0; i < 0x300; i++) - asm ("nop;"); + asm("nop;"); if ((*pFIO_FLAG_S) & CF_STAT_BITS) { cf_stat = 0; @@ -115,37 +117,36 @@ int misc_init_r (void) *pFIO_EDGE = FIO_EDGE_BITS; *pFIO_POLAR = FIO_POLAR_BITS; - if (cf_stat) { - printf ("Booting from COMPACT flash\n"); + printf("Booting from COMPACT flash\n"); /* Set cycle time for CF */ - *(volatile unsigned long *) ambctl1 = CF_AMBCTL1VAL; + *(volatile unsigned long *)ambctl1 = CF_AMBCTL1VAL; for (i = 0; i < 0x1000; i++) - asm ("nop;"); + asm("nop;"); for (i = 0; i < 0x1000; i++) - asm ("nop;"); + asm("nop;"); for (i = 0; i < 0x1000; i++) - asm ("nop;"); + asm("nop;"); - serial_setbrg (); - ide_init (); + serial_setbrg(); + ide_init(); - setenv ("bootargs", ""); - setenv ("bootcmd", - "fatload ide 0:1 0x1000000 uImage-stamp;bootm 0x1000000;bootm 0x20100000"); + setenv("bootargs", ""); + setenv("bootcmd", + "fatload ide 0:1 0x1000000 uImage-stamp;bootm 0x1000000;bootm 0x20100000"); } else { - printf ("Booting from FLASH\n"); + printf("Booting from FLASH\n"); } - return 1; + return 0; } #endif #ifdef CONFIG_STAMP_CF -void cf_outb (unsigned char val, volatile unsigned char *addr) +void cf_outb(unsigned char val, volatile unsigned char *addr) { /* * Set PF1 PF0 respectively to 0 1 to divert address @@ -153,70 +154,70 @@ void cf_outb (unsigned char val, volatile unsigned char *addr) */ *pFIO_FLAG_S = CF_PF0; *pFIO_FLAG_C = CF_PF1; - asm ("ssync;"); + sync(); *(addr) = val; - asm ("ssync;"); + sync(); /* Setback PF1 PF0 to 0 0 to address external * memory banks */ - *(volatile unsigned short *) pFIO_FLAG_C = CF_PF1_PF0; - asm ("ssync;"); + *(volatile unsigned short *)pFIO_FLAG_C = CF_PF1_PF0; + sync(); } -unsigned char cf_inb (volatile unsigned char *addr) +unsigned char cf_inb(volatile unsigned char *addr) { volatile unsigned char c; *pFIO_FLAG_S = CF_PF0; *pFIO_FLAG_C = CF_PF1; - asm ("ssync;"); + sync(); c = *(addr); - asm ("ssync;"); + sync(); *pFIO_FLAG_C = CF_PF1_PF0; - asm ("ssync;"); + sync(); return c; } -void cf_insw (unsigned short *sect_buf, unsigned short *addr, int words) +void cf_insw(unsigned short *sect_buf, unsigned short *addr, int words) { int i; *pFIO_FLAG_S = CF_PF0; *pFIO_FLAG_C = CF_PF1; - asm ("ssync;"); + sync(); for (i = 0; i < words; i++) { *(sect_buf + i) = *(addr); - asm ("ssync;"); + sync(); } *pFIO_FLAG_C = CF_PF1_PF0; - asm ("ssync;"); + sync(); } -void cf_outsw (unsigned short *addr, unsigned short *sect_buf, int words) +void cf_outsw(unsigned short *addr, unsigned short *sect_buf, int words) { int i; *pFIO_FLAG_S = CF_PF0; *pFIO_FLAG_C = CF_PF1; - asm ("ssync;"); + sync(); for (i = 0; i < words; i++) { *(addr) = *(sect_buf + i); - asm ("ssync;"); + sync(); } *pFIO_FLAG_C = CF_PF1_PF0; - asm ("ssync;"); + sync(); } #endif -void stamp_led_set (int LED1, int LED2, int LED3) +void stamp_led_set(int LED1, int LED2, int LED3) { *pFIO_INEN &= ~(PF2 | PF3 | PF4); *pFIO_DIR |= (PF2 | PF3 | PF4); @@ -233,31 +234,31 @@ void stamp_led_set (int LED1, int LED2, int LED3) *pFIO_FLAG_S = PF4; else *pFIO_FLAG_C = PF4; - asm ("ssync;"); + sync(); } -void show_boot_progress (int status) +void show_boot_progress(int status) { switch (status) { case 1: - stamp_led_set (STATUS_LED_OFF, STATUS_LED_OFF, STATUS_LED_ON); + stamp_led_set(STATUS_LED_OFF, STATUS_LED_OFF, STATUS_LED_ON); break; case 2: - stamp_led_set (STATUS_LED_OFF, STATUS_LED_ON, STATUS_LED_OFF); + stamp_led_set(STATUS_LED_OFF, STATUS_LED_ON, STATUS_LED_OFF); break; case 3: - stamp_led_set (STATUS_LED_OFF, STATUS_LED_ON, STATUS_LED_ON); + stamp_led_set(STATUS_LED_OFF, STATUS_LED_ON, STATUS_LED_ON); break; case 4: - stamp_led_set (STATUS_LED_ON, STATUS_LED_OFF, STATUS_LED_OFF); + stamp_led_set(STATUS_LED_ON, STATUS_LED_OFF, STATUS_LED_OFF); break; case 5: case 6: - stamp_led_set (STATUS_LED_ON, STATUS_LED_OFF, STATUS_LED_ON); + stamp_led_set(STATUS_LED_ON, STATUS_LED_OFF, STATUS_LED_ON); break; case 7: case 8: - stamp_led_set (STATUS_LED_ON, STATUS_LED_ON, STATUS_LED_OFF); + stamp_led_set(STATUS_LED_ON, STATUS_LED_ON, STATUS_LED_OFF); break; case 9: case 10: @@ -266,11 +267,10 @@ void show_boot_progress (int status) case 13: case 14: case 15: - stamp_led_set (STATUS_LED_OFF, STATUS_LED_OFF, - STATUS_LED_OFF); + stamp_led_set(STATUS_LED_OFF, STATUS_LED_OFF, STATUS_LED_OFF); break; default: - stamp_led_set (STATUS_LED_ON, STATUS_LED_ON, STATUS_LED_ON); + stamp_led_set(STATUS_LED_ON, STATUS_LED_ON, STATUS_LED_ON); break; } } diff --git a/board/stamp/stamp.h b/board/bf533-stamp/bf533-stamp.h index 7bc33b4..b2b51aa 100644 --- a/board/stamp/stamp.h +++ b/board/bf533-stamp/bf533-stamp.h @@ -36,7 +36,6 @@ extern volatile unsigned long *amgctl; extern unsigned long pll_div_fact; extern void serial_setbrg(void); -extern void pll_set(int vco, int crystal_frq, int pll_div); /* Definitions used in Compact Flash Boot support */ #define FIO_EDGE_CF_BITS 0x0000 diff --git a/board/bf533-stamp/config.mk b/board/bf533-stamp/config.mk new file mode 100644 index 0000000..113438b --- /dev/null +++ b/board/bf533-stamp/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2001 +# 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 +# +# TEXT_BASE should be defined as the MAX_SDRAM Address - 256k bytes +# 256k is defined as CFG_MONITOR_LEN in ./include/configs/<board>.h +TEXT_BASE = 0x07FC0000 diff --git a/board/bf533-stamp/spi.c b/board/bf533-stamp/spi.c new file mode 100644 index 0000000..d30750f --- /dev/null +++ b/board/bf533-stamp/spi.c @@ -0,0 +1,473 @@ +/**************************************************************************** + * SPI flash driver for M25P64 + ****************************************************************************/ +#include <common.h> +#include <linux/ctype.h> +#include <asm/io.h> + +#if defined(CONFIG_SPI) + + /*Application definitions */ + +#define NUM_SECTORS 128 /* number of sectors */ +#define SECTOR_SIZE 0x10000 +#define NOP_NUM 1000 + +#define COMMON_SPI_SETTINGS (SPE|MSTR|CPHA|CPOL) /*Settings to the SPI_CTL */ +#define TIMOD01 (0x01) /*stes the SPI to work with core instructions */ + + /*Flash commands */ +#define SPI_WREN (0x06) /*Set Write Enable Latch */ +#define SPI_WRDI (0x04) /*Reset Write Enable Latch */ +#define SPI_RDSR (0x05) /*Read Status Register */ +#define SPI_WRSR (0x01) /*Write Status Register */ +#define SPI_READ (0x03) /*Read data from memory */ +#define SPI_PP (0x02) /*Program Data into memory */ +#define SPI_SE (0xD8) /*Erase one sector in memory */ +#define SPI_BE (0xC7) /*Erase all memory */ +#define WIP (0x1) /*Check the write in progress bit of the SPI status register */ +#define WEL (0x2) /*Check the write enable bit of the SPI status register */ + +#define TIMEOUT 350000000 + +typedef enum { + NO_ERR, + POLL_TIMEOUT, + INVALID_SECTOR, + INVALID_BLOCK, +} ERROR_CODE; + +void spi_init_f(void); +void spi_init_r(void); +ssize_t spi_read(uchar *, int, uchar *, int); +ssize_t spi_write(uchar *, int, uchar *, int); + +char ReadStatusRegister(void); +void Wait_For_SPIF(void); +void SetupSPI(const int spi_setting); +void SPI_OFF(void); +void SendSingleCommand(const int iCommand); + +ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector); +ERROR_CODE EraseBlock(int nBlock); +ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData); +ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData); +ERROR_CODE Wait_For_Status(char Statusbit); +ERROR_CODE Wait_For_WEL(void); + +/* ------------------- + * Variables + * ------------------- */ + +/* ************************************************************************** + * + * Function: spi_init_f + * + * Description: Init SPI-Controller (ROM part) + * + * return: --- + * + * *********************************************************************** */ +void spi_init_f(void) +{ +} + +/* ************************************************************************** + * + * Function: spi_init_r + * + * Description: Init SPI-Controller (RAM part) - + * The malloc engine is ready and we can move our buffers to + * normal RAM + * + * return: --- + * + * *********************************************************************** */ +void spi_init_r(void) +{ + return; +} + +/**************************************************************************** + * Function: spi_write + **************************************************************************** */ +ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len) +{ + unsigned long offset; + int start_block, end_block; + int start_byte, end_byte; + ERROR_CODE result = NO_ERR; + uchar temp[SECTOR_SIZE]; + int i, num; + + offset = addr[0] << 16 | addr[1] << 8 | addr[2]; + /* Get the start block number */ + result = GetSectorNumber(offset, &start_block); + if (result == INVALID_SECTOR) { + printf("Invalid sector! "); + return 0; + } + /* Get the end block number */ + result = GetSectorNumber(offset + len - 1, &end_block); + if (result == INVALID_SECTOR) { + printf("Invalid sector! "); + return 0; + } + + for (num = start_block; num <= end_block; num++) { + ReadData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp); + start_byte = num * SECTOR_SIZE; + end_byte = (num + 1) * SECTOR_SIZE - 1; + if (start_byte < offset) + start_byte = offset; + if (end_byte > (offset + len)) + end_byte = (offset + len - 1); + for (i = start_byte; i <= end_byte; i++) + temp[i - num * SECTOR_SIZE] = buffer[i - offset]; + EraseBlock(num); + result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp); + if (result != NO_ERR) + return 0; + printf("."); + } + return len; +} + +/**************************************************************************** + * Function: spi_read + **************************************************************************** */ +ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len) +{ + unsigned long offset; + offset = addr[0] << 16 | addr[1] << 8 | addr[2]; + ReadData(offset, len, (int *)buffer); + return len; +} + +void SendSingleCommand(const int iCommand) +{ + unsigned short dummy; + + /*turns on the SPI in single write mode */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + + /*sends the actual command to the SPI TX register */ + *pSPI_TDBR = iCommand; + sync(); + + /*The SPI status register will be polled to check the SPIF bit */ + Wait_For_SPIF(); + + dummy = *pSPI_RDBR; + + /*The SPI will be turned off */ + SPI_OFF(); + +} + +void SetupSPI(const int spi_setting) +{ + + if (icache_status() || dcache_status()) + udelay(CONFIG_CCLK_HZ / 50000000); + /*sets up the PF2 to be the slave select of the SPI */ + *pSPI_FLG = 0xFB04; + *pSPI_BAUD = CONFIG_SPI_BAUD; + *pSPI_CTL = spi_setting; + sync(); +} + +void SPI_OFF(void) +{ + + *pSPI_CTL = 0x0400; /* disable SPI */ + *pSPI_FLG = 0; + *pSPI_BAUD = 0; + sync(); + udelay(CONFIG_CCLK_HZ / 50000000); + +} + +void Wait_For_SPIF(void) +{ + unsigned short dummyread; + while ((*pSPI_STAT & TXS)) ; + while (!(*pSPI_STAT & SPIF)) ; + while (!(*pSPI_STAT & RXS)) ; + dummyread = *pSPI_RDBR; /* Read dummy to empty the receive register */ + +} + +ERROR_CODE Wait_For_WEL(void) +{ + int i; + char status_register = 0; + ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */ + + for (i = 0; i < TIMEOUT; i++) { + status_register = ReadStatusRegister(); + if ((status_register & WEL)) { + ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */ + break; + } + ErrorCode = POLL_TIMEOUT; /* Time out error */ + }; + + return ErrorCode; +} + +ERROR_CODE Wait_For_Status(char Statusbit) +{ + int i; + char status_register = 0xFF; + ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */ + + for (i = 0; i < TIMEOUT; i++) { + status_register = ReadStatusRegister(); + if (!(status_register & Statusbit)) { + ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */ + break; + } + ErrorCode = POLL_TIMEOUT; /* Time out error */ + }; + + return ErrorCode; +} + +char ReadStatusRegister(void) +{ + char status_register = 0; + + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turn on the SPI */ + + *pSPI_TDBR = SPI_RDSR; /* send instruction to read status register */ + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + *pSPI_TDBR = 0; /*send dummy to receive the status register */ + sync(); + Wait_For_SPIF(); /*wait until the data has been sent */ + status_register = *pSPI_RDBR; /*read the status register */ + + SPI_OFF(); /* Turn off the SPI */ + + return status_register; +} + +ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector) +{ + int nSector = 0; + ERROR_CODE ErrorCode = NO_ERR; + + if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) { + ErrorCode = INVALID_SECTOR; + return ErrorCode; + } + + nSector = (int)ulOffset / 0x10000; + *pnSector = nSector; + + /* ok */ + return ErrorCode; +} + +ERROR_CODE EraseBlock(int nBlock) +{ + unsigned long ulSectorOff = 0x0, ShiftValue; + ERROR_CODE ErrorCode = NO_ERR; + + /* if the block is invalid just return */ + if ((nBlock < 0) || (nBlock > NUM_SECTORS)) { + ErrorCode = INVALID_BLOCK; /* tells us if there was an error erasing flash */ + return ErrorCode; + } + /* figure out the offset of the block in flash */ + if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) { + ulSectorOff = (nBlock * SECTOR_SIZE); + + } else { + ErrorCode = INVALID_BLOCK; /* tells us if there was an error erasing flash */ + return ErrorCode; + } + + /* A write enable instruction must previously have been executed */ + SendSingleCommand(SPI_WREN); + + /*The status register will be polled to check the write enable latch "WREN" */ + ErrorCode = Wait_For_WEL(); + + if (POLL_TIMEOUT == ErrorCode) { + printf("SPI Erase block error\n"); + return ErrorCode; + } else + /*Turn on the SPI to send single commands */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + + /* Send the erase block command to the flash followed by the 24 address */ + /* to point to the start of a sector. */ + *pSPI_TDBR = SPI_SE; + sync(); + Wait_For_SPIF(); + ShiftValue = (ulSectorOff >> 16); /* Send the highest byte of the 24 bit address at first */ + *pSPI_TDBR = ShiftValue; + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + ShiftValue = (ulSectorOff >> 8); /* Send the middle byte of the 24 bit address at second */ + *pSPI_TDBR = ShiftValue; + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + *pSPI_TDBR = ulSectorOff; /* Send the lowest byte of the 24 bit address finally */ + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + + /*Turns off the SPI */ + SPI_OFF(); + + /* Poll the status register to check the Write in Progress bit */ + /* Sector erase takes time */ + ErrorCode = Wait_For_Status(WIP); + + /* block erase should be complete */ + return ErrorCode; +} + +/***************************************************************************** +* ERROR_CODE ReadData() +* +* Read a value from flash for verify purpose +* +* Inputs: unsigned long ulStart - holds the SPI start address +* int pnData - pointer to store value read from flash +* long lCount - number of elements to read +***************************************************************************** */ +ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData) +{ + unsigned long ShiftValue; + char *cnData; + int i; + + cnData = (char *)pnData; /* Pointer cast to be able to increment byte wise */ + + /* Start SPI interface */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + + *pSPI_TDBR = SPI_READ; /* Send the read command to SPI device */ + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + ShiftValue = (ulStart >> 16); /* Send the highest byte of the 24 bit address at first */ + *pSPI_TDBR = ShiftValue; /* Send the byte to the SPI device */ + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + ShiftValue = (ulStart >> 8); /* Send the middle byte of the 24 bit address at second */ + *pSPI_TDBR = ShiftValue; /* Send the byte to the SPI device */ + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + *pSPI_TDBR = ulStart; /* Send the lowest byte of the 24 bit address finally */ + sync(); + Wait_For_SPIF(); /* Wait until the instruction has been sent */ + + /* After the SPI device address has been placed on the MOSI pin the data can be */ + /* received on the MISO pin. */ + for (i = 0; i < lCount; i++) { + *pSPI_TDBR = 0; /*send dummy */ + sync(); + while (!(*pSPI_STAT & RXS)) ; + *cnData++ = *pSPI_RDBR; /*read */ + + if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0)) + printf("."); + } + + SPI_OFF(); /* Turn off the SPI */ + + return NO_ERR; +} + +ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount, + int *iDataSource, long *lWriteCount) +{ + + unsigned long ulWAddr; + long lWTransferCount = 0; + int i; + char iData; + char *temp = (char *)iDataSource; + ERROR_CODE ErrorCode = NO_ERR; /* tells us if there was an error erasing flash */ + + /* First, a Write Enable Command must be sent to the SPI. */ + SendSingleCommand(SPI_WREN); + + /* Second, the SPI Status Register will be tested whether the */ + /* Write Enable Bit has been set. */ + ErrorCode = Wait_For_WEL(); + if (POLL_TIMEOUT == ErrorCode) { + printf("SPI Write Time Out\n"); + return ErrorCode; + } else + /* Third, the 24 bit address will be shifted out the SPI MOSI bytewise. */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turns the SPI on */ + *pSPI_TDBR = SPI_PP; + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + ulWAddr = (ulStartAddr >> 16); + *pSPI_TDBR = ulWAddr; + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + ulWAddr = (ulStartAddr >> 8); + *pSPI_TDBR = ulWAddr; + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + ulWAddr = ulStartAddr; + *pSPI_TDBR = ulWAddr; + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + /* Fourth, maximum number of 256 bytes will be taken from the Buffer */ + /* and sent to the SPI device. */ + for (i = 0; (i < lTransferCount) && (i < 256); i++, lWTransferCount++) { + iData = *temp; + *pSPI_TDBR = iData; + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + temp++; + } + + SPI_OFF(); /* Turns the SPI off */ + + /* Sixth, the SPI Write in Progress Bit must be toggled to ensure the */ + /* programming is done before start of next transfer. */ + ErrorCode = Wait_For_Status(WIP); + + if (POLL_TIMEOUT == ErrorCode) { + printf("SPI Program Time out!\n"); + return ErrorCode; + } else + + *lWriteCount = lWTransferCount; + + return ErrorCode; +} + +ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData) +{ + + unsigned long ulWStart = ulStart; + long lWCount = lCount, lWriteCount; + long *pnWriteCount = &lWriteCount; + + ERROR_CODE ErrorCode = NO_ERR; + + while (lWCount != 0) { + ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount); + + /* After each function call of WriteFlash the counter must be adjusted */ + lWCount -= *pnWriteCount; + + /* Also, both address pointers must be recalculated. */ + ulWStart += *pnWriteCount; + pnData += *pnWriteCount / 4; + } + + /* return the appropriate error code */ + return ErrorCode; +} + +#endif /* CONFIG_SPI */ diff --git a/board/stamp/u-boot.lds b/board/bf533-stamp/u-boot.lds.S index 9a22e50..03ef72b 100644 --- a/board/stamp/u-boot.lds +++ b/board/bf533-stamp/u-boot.lds.S @@ -1,7 +1,7 @@ /* - * U-boot - u-boot.lds + * U-boot - u-boot.lds.S * - * Copyright (c) 2005 blackfin.uclinux.org + * Copyright (c) 2005-2007 Analog Device Inc. * * (C) Copyright 2000-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -25,6 +25,8 @@ * MA 02111-1307 USA */ +#include <config.h> + OUTPUT_ARCH(bfin) SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); /* Do we need any of these for elf? @@ -55,6 +57,7 @@ SECTIONS .rela.plt : { *(.rela.plt) } .init : { *(.init) } .plt : { *(.plt) } + . = CFG_MONITOR_BASE; .text : { /* WARNING - the following is hand-optimized to fit within */ @@ -68,9 +71,11 @@ SECTIONS cpu/bf533/interrupt.o (.text) cpu/bf533/serial.o (.text) common/dlmalloc.o (.text) - lib_generic/vsprintf.o (.text) +/* lib_blackfin/bf533_string.o (.text) */ +/* lib_generic/vsprintf.o (.text) */ lib_generic/crc32.o (.text) - lib_generic/zlib.o (.text) +/* lib_generic/zlib.o (.text) */ +/* board/stamp/stamp.o (.text) */ . = DEFINED(env_offset) ? env_offset : .; common/environment.o (.text) @@ -118,9 +123,9 @@ SECTIONS _edata = .; PROVIDE (edata = .); - __u_boot_cmd_start = .; + ___u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } - __u_boot_cmd_end = .; + ___u_boot_cmd_end = .; __start___ex_table = .; diff --git a/board/bf537-stamp/Makefile b/board/bf537-stamp/Makefile new file mode 100644 index 0000000..e488844 --- /dev/null +++ b/board/bf537-stamp/Makefile @@ -0,0 +1,58 @@ +# +# U-boot - Makefile +# +# Copyright (c) 2005-2007 Analog Device Inc. +# +# (C) Copyright 2000-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o flash.o ether_bf537.o post-memory.o stm_m25p64.o cmd_bf537led.o nand.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +u-boot.lds: u-boot.lds.S + $(CPP) $(CPPFLAGS) -P -Ubfin $^ > $@.tmp + mv -f $@.tmp $@ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/bf537-stamp/bf537-stamp.c b/board/bf537-stamp/bf537-stamp.c new file mode 100644 index 0000000..cc4e998 --- /dev/null +++ b/board/bf537-stamp/bf537-stamp.c @@ -0,0 +1,437 @@ +/* + * U-boot - BF537.c + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * (C) Copyright 2000-2004 + * 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 <common.h> +#include <config.h> +#include <command.h> +#include <asm/blackfin.h> +#include <asm/io.h> +#include "ether_bf537.h" + +#define POST_WORD_ADDR 0xFF903FFC + +/* + * the bootldr command loads an address, checks to see if there + * is a Boot stream that the on-chip BOOTROM can understand, + * and loads it via the BOOTROM Callback. It is possible + * to also add booting from SPI, or TWI, but this function does + * not currently support that. + */ +int do_bootldr(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr, entry; + ulong *data; + + /* Get the address */ + if (argc < 2) { + addr = load_addr; + } else { + addr = simple_strtoul(argv[1], NULL, 16); + } + + /* Check if it is a LDR file */ + data = (ulong *) addr; + if (*data == 0xFF800060 || *data == 0xFF800040 || *data == 0xFF800020) { + /* We want to boot from FLASH or SDRAM */ + entry = _BOOTROM_BOOT_DXE_FLASH; + printf("## Booting ldr image at 0x%08lx ...\n", addr); + if (icache_status()) + icache_disable(); + if (dcache_status()) + dcache_disable(); + + __asm__("R7=%[a];\n" "P0=%[b];\n" "JUMP (P0);\n": + :[a] "d"(addr),[b] "a"(entry) + :"R7", "P0"); + + } else { + printf("## No ldr image at address 0x%08lx\n", addr); + } + + return 0; +} + +U_BOOT_CMD(bootldr, 2, 0, do_bootldr, + "bootldr - boot ldr image from memory\n", + "[addr]\n - boot ldr image stored in memory\n"); + +int checkboard(void) +{ +#if (BFIN_CPU == ADSP_BF534) + printf("CPU: ADSP BF534 Rev.: 0.%d\n", *pCHIPID >> 28); +#elif (BFIN_CPU == ADSP_BF536) + printf("CPU: ADSP BF536 Rev.: 0.%d\n", *pCHIPID >> 28); +#else + printf("CPU: ADSP BF537 Rev.: 0.%d\n", *pCHIPID >> 28); +#endif + printf("Board: ADI BF537 stamp board\n"); + printf(" Support: http://blackfin.uclinux.org/\n"); + return 0; +} + +#if defined(CONFIG_BFIN_IDE) + +void cf_outb(unsigned char val, volatile unsigned char *addr) +{ + *(addr) = val; + sync(); +} + +unsigned char cf_inb(volatile unsigned char *addr) +{ + volatile unsigned char c; + + c = *(addr); + sync(); + + return c; +} + +void cf_insw(unsigned short *sect_buf, unsigned short *addr, int words) +{ + int i; + + for (i = 0; i < words; i++) + *(sect_buf + i) = *(addr); + sync(); +} + +void cf_outsw(unsigned short *addr, unsigned short *sect_buf, int words) +{ + int i; + + for (i = 0; i < words; i++) + *(addr) = *(sect_buf + i); + sync(); +} +#endif /* CONFIG_BFIN_IDE */ + +long int initdram(int board_type) +{ + DECLARE_GLOBAL_DATA_PTR; +#ifdef DEBUG + int brate; + char *tmp = getenv("baudrate"); + brate = simple_strtoul(tmp, NULL, 16); + printf("Serial Port initialized with Baud rate = %x\n", brate); + printf("SDRAM attributes:\n"); + printf("tRCD %d SCLK Cycles,tRP %d SCLK Cycles,tRAS %d SCLK Cycles" + "tWR %d SCLK Cycles,CAS Latency %d SCLK cycles \n", + 3, 3, 6, 2, 3); + printf("SDRAM Begin: 0x%x\n", CFG_SDRAM_BASE); + printf("Bank size = %d MB\n", CFG_MAX_RAM_SIZE >> 20); +#endif + gd->bd->bi_memstart = CFG_SDRAM_BASE; + gd->bd->bi_memsize = CFG_MAX_RAM_SIZE; + return CFG_MAX_RAM_SIZE; +} + +#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent initialisations */ +int misc_init_r(void) +{ +#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT) + char nid[32]; + unsigned char *pMACaddr = (unsigned char *)0x203F0000; + u8 SrcAddr[6] = { 0x02, 0x80, 0xAD, 0x20, 0x31, 0xB8 }; + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + /* The 0xFF check here is to make sure we don't use the address + * in flash if it's simply been erased (aka all 0xFF values) */ + if (getenv("ethaddr") == NULL && is_valid_ether_addr(pMACaddr)) { + sprintf(nid, "%02x:%02x:%02x:%02x:%02x:%02x", + pMACaddr[0], pMACaddr[1], + pMACaddr[2], pMACaddr[3], pMACaddr[4], pMACaddr[5]); + setenv("ethaddr", nid); + } + if (getenv("ethaddr")) { + SetupMacAddr(SrcAddr); + } +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ +#endif /* BFIN_BOOT_MODE == BF537_BYPASS_BOOT */ + +#if defined(CONFIG_BFIN_IDE) +#if defined(CONFIG_BFIN_TRUE_IDE) + /* Enable ATASEL when in True IDE mode */ + printf("Using CF True IDE Mode\n"); + cf_outb(0, (unsigned char *)CONFIG_CF_ATASEL_ENA); + udelay(1000); +#elif defined(CONFIG_BFIN_CF_IDE) + /* Disable ATASEL when we're in Common Memory Mode */ + printf("Using CF Common Memory Mode\n"); + cf_outb(0, (unsigned char *)CONFIG_CF_ATASEL_DIS); + udelay(1000); +#elif defined(CONFIG_BFIN_HDD_IDE) + printf("Using HDD IDE Mode\n"); +#endif + ide_init(); +#endif /* CONFIG_BFIN_IDE */ + return 0; +} +#endif /* CONFIG_MISC_INIT_R */ + +#ifdef CONFIG_POST +#if (BFIN_BOOT_MODE != BF537_BYPASS_BOOT) +/* Using sw10-PF5 as the hotkey */ +int post_hotkeys_pressed(void) +{ + return 0; +} +#else +/* Using sw10-PF5 as the hotkey */ +int post_hotkeys_pressed(void) +{ + int delay = 3; + int i; + unsigned short value; + + *pPORTF_FER &= ~PF5; + *pPORTFIO_DIR &= ~PF5; + *pPORTFIO_INEN |= PF5; + + printf("########Press SW10 to enter Memory POST########: %2d ", delay); + while (delay--) { + for (i = 0; i < 100; i++) { + value = *pPORTFIO & PF5; + if (value != 0) { + break; + } + udelay(10000); + } + printf("\b\b\b%2d ", delay); + } + printf("\b\b\b 0"); + printf("\n"); + if (value == 0) + return 0; + else { + printf("Hotkey has been pressed, Enter POST . . . . . .\n"); + return 1; + } +} +#endif +#endif + +#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) +void post_word_store(ulong a) +{ + volatile ulong *save_addr = (volatile ulong *)POST_WORD_ADDR; + *save_addr = a; +} + +ulong post_word_load(void) +{ + volatile ulong *save_addr = (volatile ulong *)POST_WORD_ADDR; + return *save_addr; +} +#endif + +#ifdef CONFIG_POST +int uart_post_test(int flags) +{ + return 0; +} + +#define BLOCK_SIZE 0x10000 +#define VERIFY_ADDR 0x2000000 +extern int erase_block_flash(int); +extern int write_data(long lStart, long lCount, uchar * pnData); +int flash_post_test(int flags) +{ + unsigned short *pbuf, *temp; + int offset, n, i; + int value = 0; + int result = 0; + printf("\n"); + pbuf = (unsigned short *)VERIFY_ADDR; + temp = pbuf; + for (n = FLASH_START_POST_BLOCK; n < FLASH_END_POST_BLOCK; n++) { + offset = (n - 7) * BLOCK_SIZE; + printf("--------Erase block:%2d..", n); + erase_block_flash(n); + printf("OK\r"); + printf("--------Program block:%2d...", n); + write_data(CFG_FLASH_BASE + offset, BLOCK_SIZE, pbuf); + printf("OK\r"); + printf("--------Verify block:%2d...", n); + for (i = 0; i < BLOCK_SIZE; i += 2) { + if (*(unsigned short *)(CFG_FLASH_BASE + offset + i) != + *temp++) { + value = 1; + result = 1; + } + } + if (value) + printf("failed\n"); + else + printf("OK %3d%%\r", + (int)( + (n + 1 - + FLASH_START_POST_BLOCK) * + 100 / (FLASH_END_POST_BLOCK - + FLASH_START_POST_BLOCK))); + + temp = pbuf; + value = 0; + } + printf("\n"); + if (result) + return -1; + else + return 0; +} + +/**************************************************** + * LED1 ---- PF6 LED2 ---- PF7 * + * LED3 ---- PF8 LED4 ---- PF9 * + * LED5 ---- PF10 LED6 ---- PF11 * + ****************************************************/ +int led_post_test(int flags) +{ + *pPORTF_FER &= ~(PF6 | PF7 | PF8 | PF9 | PF10 | PF11); + *pPORTFIO_DIR |= PF6 | PF7 | PF8 | PF9 | PF10 | PF11; + *pPORTFIO_INEN &= ~(PF6 | PF7 | PF8 | PF9 | PF10 | PF11); + *pPORTFIO &= ~(PF6 | PF7 | PF8 | PF9 | PF10 | PF11); + udelay(1000000); + printf("LED1 on"); + *pPORTFIO |= PF6; + udelay(1000000); + printf("\b\b\b\b\b\b\b"); + printf("LED2 on"); + *pPORTFIO |= PF7; + udelay(1000000); + printf("\b\b\b\b\b\b\b"); + printf("LED3 on"); + *pPORTFIO |= PF8; + udelay(1000000); + printf("\b\b\b\b\b\b\b"); + printf("LED4 on"); + *pPORTFIO |= PF9; + udelay(1000000); + printf("\b\b\b\b\b\b\b"); + printf("LED5 on"); + *pPORTFIO |= PF10; + udelay(1000000); + printf("\b\b\b\b\b\b\b"); + printf("lED6 on"); + *pPORTFIO |= PF11; + printf("\b\b\b\b\b\b\b "); + return 0; +} + +/************************************************ + * SW10 ---- PF5 SW11 ---- PF4 * + * SW12 ---- PF3 SW13 ---- PF2 * + ************************************************/ +int button_post_test(int flags) +{ + int i, delay = 5; + unsigned short value = 0; + int result = 0; + + *pPORTF_FER &= ~(PF5 | PF4 | PF3 | PF2); + *pPORTFIO_DIR &= ~(PF5 | PF4 | PF3 | PF2); + *pPORTFIO_INEN |= (PF5 | PF4 | PF3 | PF2); + + printf("\n--------Press SW10: %2d ", delay); + while (delay--) { + for (i = 0; i < 100; i++) { + value = *pPORTFIO & PF5; + if (value != 0) { + break; + } + udelay(10000); + } + printf("\b\b\b%2d ", delay); + } + if (value != 0) + printf("\b\bOK"); + else { + result = -1; + printf("\b\bfailed"); + } + + delay = 5; + printf("\n--------Press SW11: %2d ", delay); + while (delay--) { + for (i = 0; i < 100; i++) { + value = *pPORTFIO & PF4; + if (value != 0) { + break; + } + udelay(10000); + } + printf("\b\b\b%2d ", delay); + } + if (value != 0) + printf("\b\bOK"); + else { + result = -1; + printf("\b\bfailed"); + } + + delay = 5; + printf("\n--------Press SW12: %2d ", delay); + while (delay--) { + for (i = 0; i < 100; i++) { + value = *pPORTFIO & PF3; + if (value != 0) { + break; + } + udelay(10000); + } + printf("\b\b\b%2d ", delay); + } + if (value != 0) + printf("\b\bOK"); + else { + result = -1; + printf("\b\bfailed"); + } + + delay = 5; + printf("\n--------Press SW13: %2d ", delay); + while (delay--) { + for (i = 0; i < 100; i++) { + value = *pPORTFIO & PF2; + if (value != 0) { + break; + } + udelay(10000); + } + printf("\b\b\b%2d ", delay); + } + if (value != 0) + printf("\b\bOK"); + else { + result = -1; + printf("\b\bfailed"); + } + printf("\n"); + return result; +} +#endif diff --git a/board/bf537-stamp/cmd_bf537led.c b/board/bf537-stamp/cmd_bf537led.c new file mode 100644 index 0000000..fa650f2 --- /dev/null +++ b/board/bf537-stamp/cmd_bf537led.c @@ -0,0 +1,201 @@ +/* + * U-boot - cmd_bf537led.c + * + * Copyright (C) 2006 Aaron Gage, Ocean Optics 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 <common.h> +#include <config.h> +#include <command.h> +#include <asm/blackfin.h> +#include <asm-blackfin/string.h> +#ifdef CONFIG_BF537_STAMP_LEDCMD + +/* Define the command usage in a reusable way */ +#define USAGE_LONG \ + "led <number> <action>\n" \ + " <number> - Index (0-5) of LED to change, or \"all\"\n" \ + " <action> - Must be one of:\n" \ + " on off toggle\n" + +/* Number of LEDs supported by the board */ +#define NUMBER_LEDS 6 +/* The BF537 stamp has 6 LEDs. This mask indicates that all should be lit. */ +#define LED_ALL_MASK 0x003F + +void show_cmd_usage(void); +void set_led_state(int index, int state); +void configure_GPIO_to_output(int index); + +/* Map of LEDs according to their GPIO ports. This can be rearranged or + * otherwise changed to account for different GPIO configurations. + */ +int led_ports[] = { PF6, PF7, PF8, PF9, PF10, PF11 }; + +#define ACTION_TOGGLE -1 +#define ACTION_OFF 0 +#define ACTION_ON 1 + +#define LED_STATE_OFF 0 +#define LED_STATE_ON 1 + +/* This is a trivial atoi implementation since we don't have one available */ +int atoi(char *string) +{ + int length; + int retval = 0; + int i; + int sign = 1; + + length = strlen(string); + for (i = 0; i < length; i++) { + if (0 == i && string[0] == '-') { + sign = -1; + continue; + } + if (string[i] > '9' || string[i] < '0') { + break; + } + retval *= 10; + retval += string[i] - '0'; + } + retval *= sign; + return retval; +} + +int do_bf537led(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + int led_mask = 0; + int led_current_state = 0; + int action = ACTION_OFF; + int temp; + + if (3 != argc) { + /* Not enough arguments, so just show usage information */ + show_cmd_usage(); + return 1; + } + + if (strcmp(argv[1], "all") == 0) { + led_mask = LED_ALL_MASK; + } else { + temp = atoi(argv[1]); + if (temp < 0 || temp >= NUMBER_LEDS) { + printf("Invalid LED number [%s]\n", argv[1]); + show_cmd_usage(); + return 2; + } + led_mask |= (1 << temp); + } + + if (strcmp(argv[2], "off") == 0) { + action = ACTION_OFF; + } else if (strcmp(argv[2], "on") == 0) { + action = ACTION_ON; + } else if (strcmp(argv[2], "toggle") == 0) { + action = ACTION_TOGGLE; + } else { + printf("Invalid action [%s]\n", argv[2]); + show_cmd_usage(); + return 3; + } + + for (temp = 0; temp < NUMBER_LEDS; temp++) { + if ((led_mask & (1 << temp)) > 0) { + /* + * It is possible that the user has wired one of PF6-PF11 to + * something other than an LED, so this will only change a pin + * to output if the user has indicated a state change. This may + * happen a lot, but this way is safer than just setting all pins + * to output. + */ + configure_GPIO_to_output(temp); + + led_current_state = + ((*pPORTFIO & led_ports[temp]) > + 0) ? LED_STATE_ON : LED_STATE_OFF; + /* + printf("LED state for index %d (%x) is %d\n", temp, led_ports[temp], + led_current_state); + printf("*pPORTFIO is %x\n", *pPORTFIO); + */ + if (ACTION_ON == action + || (ACTION_TOGGLE == action + && 0 == led_current_state)) { + printf("Turning LED %d on\n", temp); + set_led_state(temp, LED_STATE_ON); + } else { + printf("Turning LED %d off\n", temp); + set_led_state(temp, LED_STATE_OFF); + } + } + } + + return 0; +} + +/* + * The GPIO pins that go to the LEDs on the BF537 stamp must be configured + * as output. This function simply configures them that way. This could + * be done to all of the GPIO lines at once, but if a user is using a + * custom board, this will try to be nice and only change the GPIO lines + * that the user specifically names. + */ +void configure_GPIO_to_output(int index) +{ + int port; + + port = led_ports[index]; + + /* Clear the Port F Function Enable Register */ + *pPORTF_FER &= ~port; + /* Set the Port F I/O direction register */ + *pPORTFIO_DIR |= port; + /* Clear the Port F I/O Input Enable Register */ + *pPORTFIO_INEN &= ~port; +} + +/* Enforce the given state on the GPIO line for the indicated LED */ +void set_led_state(int index, int state) +{ + int port; + + port = led_ports[index]; + + if (LED_STATE_OFF == state) { + /* Clear the bit to turn off the LED */ + *pPORTFIO &= ~port; + } else { + /* Set the bit to turn on the LED */ + *pPORTFIO |= port; + } +} + +/* Display usage information */ +void show_cmd_usage() +{ + printf("Usage:\n%s", USAGE_LONG); +} + +/* Register information for u-boot to find this command */ +U_BOOT_CMD(led, 3, 1, do_bf537led, + "led- Control BF537 stamp LEDs\n", USAGE_LONG); + +#endif diff --git a/board/bf537-stamp/config.mk b/board/bf537-stamp/config.mk new file mode 100644 index 0000000..a623c3d --- /dev/null +++ b/board/bf537-stamp/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2001 +# 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 +# +# TEXT_BASE should be defined as the MAX_SDRAM Address - 256k bytes +# 256k is defined as CFG_MONITOR_LEN in ./include/configs/<board>.h +TEXT_BASE = 0x03FC0000 diff --git a/board/bf537-stamp/ether_bf537.c b/board/bf537-stamp/ether_bf537.c new file mode 100644 index 0000000..f00837a --- /dev/null +++ b/board/bf537-stamp/ether_bf537.c @@ -0,0 +1,545 @@ +/* + * ADI Blackfin 537 MAC Ethernet + * + * Copyright (c) 2005 Analog Device, 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 <common.h> +#include <config.h> +#include <asm/blackfin.h> +#include <net.h> +#include <command.h> +#include <malloc.h> +#include "ether_bf537.h" + +#ifdef CONFIG_POST +#include <post.h> +#endif + +#undef DEBUG_ETHERNET + +#ifdef DEBUG_ETHERNET +#define DEBUGF(fmt,args...) printf(fmt,##args) +#else +#define DEBUGF(fmt,args...) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +#define RXBUF_BASE_ADDR 0xFF900000 +#define TXBUF_BASE_ADDR 0xFF800000 +#define TX_BUF_CNT 1 + +#define TOUT_LOOP 1000000 + +ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT]; +ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX]; +static u16 txIdx; /* index of the current RX buffer */ +static u16 rxIdx; /* index of the current TX buffer */ + +u8 SrcAddr[6]; +u16 PHYregs[NO_PHY_REGS]; /* u16 PHYADDR; */ + +/* DMAx_CONFIG values at DMA Restart */ +const ADI_DMA_CONFIG_REG rxdmacfg = { 1, 1, 2, 0, 0, 0, 0, 5, 7 }; + +#if 0 + rxdmacfg.b_DMA_EN = 1; /* enabled */ + rxdmacfg.b_WNR = 1; /* write to memory */ + rxdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */ + rxdmacfg.b_DMA2D = 0; /* N/A */ + rxdmacfg.b_RESTART= 0; /* N/A */ + rxdmacfg.b_DI_SEL = 0; /* N/A */ + rxdmacfg.b_DI_EN = 0; /* no interrupt */ + rxdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */ + rxdmacfg.b_FLOW = 7; /* large desc flow */ +#endif + +const ADI_DMA_CONFIG_REG txdmacfg = { 1, 0, 2, 0, 0, 0, 0, 5, 7 }; + +#if 0 + txdmacfg.b_DMA_EN = 1; /* enabled */ + txdmacfg.b_WNR = 0; /* read from memory */ + txdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */ + txdmacfg.b_DMA2D = 0; /* N/A */ + txdmacfg.b_RESTART= 0; /* N/A */ + txdmacfg.b_DI_SEL = 0; /* N/A */ + txdmacfg.b_DI_EN = 0; /* no interrupt */ + txdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */ + txdmacfg.b_FLOW = 7; /* large desc flow */ +#endif + +ADI_ETHER_BUFFER *SetupRxBuffer(int no); +ADI_ETHER_BUFFER *SetupTxBuffer(int no); + +static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd); +static void bfin_EMAC_halt(struct eth_device *dev); +static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, + int length); +static int bfin_EMAC_recv(struct eth_device *dev); + +int bfin_EMAC_initialize(bd_t * bis) +{ + struct eth_device *dev; + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (dev == NULL) + hang(); + + memset(dev, 0, sizeof(*dev)); + sprintf(dev->name, "BF537 ETHERNET"); + + dev->iobase = 0; + dev->priv = 0; + dev->init = bfin_EMAC_init; + dev->halt = bfin_EMAC_halt; + dev->send = bfin_EMAC_send; + dev->recv = bfin_EMAC_recv; + + eth_register(dev); + + return 1; +} + +static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, + int length) +{ + int i; + int result = 0; + unsigned int *buf; + buf = (unsigned int *)packet; + + if (length <= 0) { + printf("Ethernet: bad packet size: %d\n", length); + goto out; + } + + if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) { + printf("Ethernet: tx DMA error\n"); + goto out; + } + + for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) { + if (i > TOUT_LOOP) { + puts("Ethernet: tx time out\n"); + goto out; + } + } + txbuf[txIdx]->FrmData->NoBytes = length; + memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length); + txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData; + *pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0]; + *pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg); + *pEMAC_OPMODE |= TE; + + for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) { + if (i > TOUT_LOOP) { + puts("Ethernet: tx error\n"); + goto out; + } + } + result = txbuf[txIdx]->StatusWord; + txbuf[txIdx]->StatusWord = 0; + if ((txIdx + 1) >= TX_BUF_CNT) + txIdx = 0; + else + txIdx++; + out: + DEBUGF("BFIN EMAC send: length = %d\n", length); + return result; +} + +static int bfin_EMAC_recv(struct eth_device *dev) +{ + int length = 0; + + for (;;) { + if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) { + length = -1; + break; + } + if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) { + printf("Ethernet: rx dma overrun\n"); + break; + } + if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) { + printf("Ethernet: rx error\n"); + break; + } + length = rxbuf[rxIdx]->StatusWord & 0x000007FF; + if (length <= 4) { + printf("Ethernet: bad frame\n"); + break; + } + NetRxPackets[rxIdx] = + (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest); + NetReceive(NetRxPackets[rxIdx], length - 4); + *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR; + rxbuf[rxIdx]->StatusWord = 0x00000000; + if ((rxIdx + 1) >= PKTBUFSRX) + rxIdx = 0; + else + rxIdx++; + } + + return length; +} + +/************************************************************** + * + * Ethernet Initialization Routine + * + *************************************************************/ + +static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd) +{ + u32 opmode; + int dat; + int i; + DEBUGF("Eth_init: ......\n"); + + txIdx = 0; + rxIdx = 0; + +/* Initialize System Register */ + if (SetupSystemRegs(&dat) < 0) + return -1; + +/* Initialize EMAC address */ + SetupMacAddr(SrcAddr); + +/* Initialize TX and RX buffer */ + for (i = 0; i < PKTBUFSRX; i++) { + rxbuf[i] = SetupRxBuffer(i); + if (i > 0) { + rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR = + &(rxbuf[i]->Dma[0]); + if (i == (PKTBUFSRX - 1)) + rxbuf[i]->Dma[1].NEXT_DESC_PTR = + &(rxbuf[0]->Dma[0]); + } + } + for (i = 0; i < TX_BUF_CNT; i++) { + txbuf[i] = SetupTxBuffer(i); + if (i > 0) { + txbuf[i - 1]->Dma[1].NEXT_DESC_PTR = + &(txbuf[i]->Dma[0]); + if (i == (TX_BUF_CNT - 1)) + txbuf[i]->Dma[1].NEXT_DESC_PTR = + &(txbuf[0]->Dma[0]); + } + } + + /* Set RX DMA */ + *pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0]; + *pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG); + + /* Wait MII done */ + PollMdcDone(); + + /* We enable only RX here */ + /* ASTP : Enable Automatic Pad Stripping + PR : Promiscuous Mode for test + PSF : Receive frames with total length less than 64 bytes. + FDMODE : Full Duplex Mode + LB : Internal Loopback for test + RE : Receiver Enable */ + if (dat == FDMODE) + opmode = ASTP | FDMODE | PSF; + else + opmode = ASTP | PSF; + opmode |= RE; +#ifdef CONFIG_BFIN_MAC_RMII + opmode |= TE | RMII; +#endif + /* Turn on the EMAC */ + *pEMAC_OPMODE = opmode; + return 0; +} + +static void bfin_EMAC_halt(struct eth_device *dev) +{ + DEBUGF("Eth_halt: ......\n"); + /* Turn off the EMAC */ + *pEMAC_OPMODE = 0x00000000; + /* Turn off the EMAC RX DMA */ + *pDMA1_CONFIG = 0x0000; + *pDMA2_CONFIG = 0x0000; + +} + +void SetupMacAddr(u8 * MACaddr) +{ + char *tmp, *end; + int i; + /* this depends on a little-endian machine */ + tmp = getenv("ethaddr"); + if (tmp) { + for (i = 0; i < 6; i++) { + MACaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end + 1 : end; + } + +#ifndef CONFIG_NETCONSOLE + printf("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", + MACaddr[0], MACaddr[1], + MACaddr[2], MACaddr[3], MACaddr[4], MACaddr[5]); +#endif + *pEMAC_ADDRLO = MACaddr[0] | MACaddr[1] << 8 | + MACaddr[2] << 16 | MACaddr[3] << 24; + *pEMAC_ADDRHI = MACaddr[4] | MACaddr[5] << 8; + } +} + +void PollMdcDone(void) +{ + /* poll the STABUSY bit */ + while (*pEMAC_STAADD & STABUSY) ; +} + +void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data) +{ + PollMdcDone(); + + *pEMAC_STADAT = Data; + + *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) | + STAOP | STAIE | STABUSY; +} + +/********************************************************************************* + * Read an off-chip register in a PHY through the MDC/MDIO port * + *********************************************************************************/ +u16 RdPHYReg(u16 PHYAddr, u16 RegAddr) +{ + u16 Data; + + PollMdcDone(); + + *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) | + STAIE | STABUSY; + + PollMdcDone(); + + Data = (u16) * pEMAC_STADAT; + + PHYregs[RegAddr] = Data; /* save shadow copy */ + + return Data; +} + +void SoftResetPHY(void) +{ + u16 phydat; + /* set the reset bit */ + WrPHYReg(PHYADDR, PHY_MODECTL, PHY_RESET); + /* and clear it again */ + WrPHYReg(PHYADDR, PHY_MODECTL, 0x0000); + do { + /* poll until reset is complete */ + phydat = RdPHYReg(PHYADDR, PHY_MODECTL); + } while ((phydat & PHY_RESET) != 0); +} + +int SetupSystemRegs(int *opmode) +{ + u16 sysctl, phydat; + int count = 0; + /* Enable PHY output */ + *pVR_CTL |= PHYCLKOE; + /* MDC = 2.5 MHz */ + sysctl = SET_MDCDIV(24); + /* Odd word alignment for Receive Frame DMA word */ + /* Configure checksum support and rcve frame word alignment */ + sysctl |= RXDWA | RXCKS; + *pEMAC_SYSCTL = sysctl; + /* auto negotiation on */ + /* full duplex */ + /* 100 Mbps */ + phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET; + WrPHYReg(PHYADDR, PHY_MODECTL, phydat); + do { + udelay(1000); + phydat = RdPHYReg(PHYADDR, PHY_MODESTAT); + if (count > 3000) { + printf + ("Link is down, please check your network connection\n"); + return -1; + } + count++; + } while (!(phydat & 0x0004)); + + phydat = RdPHYReg(PHYADDR, PHY_ANLPAR); + + if ((phydat & 0x0100) || (phydat & 0x0040)) + *opmode = FDMODE; + else + *opmode = 0; + + *pEMAC_MMC_CTL = RSTC | CROLL; + + /* Initialize the TX DMA channel registers */ + *pDMA2_X_COUNT = 0; + *pDMA2_X_MODIFY = 4; + *pDMA2_Y_COUNT = 0; + *pDMA2_Y_MODIFY = 0; + + /* Initialize the RX DMA channel registers */ + *pDMA1_X_COUNT = 0; + *pDMA1_X_MODIFY = 4; + *pDMA1_Y_COUNT = 0; + *pDMA1_Y_MODIFY = 0; + return 0; +} + +ADI_ETHER_BUFFER *SetupRxBuffer(int no) +{ + ADI_ETHER_FRAME_BUFFER *frmbuf; + ADI_ETHER_BUFFER *buf; + int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */ + int total_size = nobytes_buffer + RECV_BUFSIZE; + + buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size); + frmbuf = + (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size + + nobytes_buffer); + + memset(buf, 0x00, nobytes_buffer); + buf->FrmData = frmbuf; + memset(frmbuf, 0xfe, RECV_BUFSIZE); + + /* set up first desc to point to receive frame buffer */ + buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); + buf->Dma[0].START_ADDR = (u32) buf->FrmData; + buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[0].CONFIG.b_WNR = 1; /* Write to memory */ + buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */ + buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */ + + /* set up second desc to point to status word */ + buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); + buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum; + buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */ + buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */ + buf->Dma[1].CONFIG.b_NDSIZE = 5; /* must be 0 when FLOW is 0 */ + buf->Dma[1].CONFIG.b_FLOW = 7; /* stop */ + + return buf; +} + +ADI_ETHER_BUFFER *SetupTxBuffer(int no) +{ + ADI_ETHER_FRAME_BUFFER *frmbuf; + ADI_ETHER_BUFFER *buf; + int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */ + int total_size = nobytes_buffer + RECV_BUFSIZE; + + buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size); + frmbuf = + (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size + + nobytes_buffer); + + memset(buf, 0x00, nobytes_buffer); + buf->FrmData = frmbuf; + memset(frmbuf, 0x00, RECV_BUFSIZE); + + /* set up first desc to point to receive frame buffer */ + buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); + buf->Dma[0].START_ADDR = (u32) buf->FrmData; + buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[0].CONFIG.b_WNR = 0; /* Read to memory */ + buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */ + buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */ + + /* set up second desc to point to status word */ + buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); + buf->Dma[1].START_ADDR = (u32) & buf->StatusWord; + buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */ + buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */ + buf->Dma[1].CONFIG.b_NDSIZE = 0; /* must be 0 when FLOW is 0 */ + buf->Dma[1].CONFIG.b_FLOW = 0; /* stop */ + + return buf; +} + +#if defined(CONFIG_POST) && defined(CFG_POST_ETHER) +int ether_post_test(int flags) +{ + uchar buf[64]; + int i, value = 0; + int length; + + printf("\n--------"); + bfin_EMAC_init(NULL, NULL); + /* construct the package */ + buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF); + buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8); + buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16); + buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24); + buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF); + buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8); + buf[12] = 0x08; /* Type: ARP */ + buf[13] = 0x06; + buf[14] = 0x00; /* Hardware type: Ethernet */ + buf[15] = 0x01; + buf[16] = 0x08; /* Protocal type: IP */ + buf[17] = 0x00; + buf[18] = 0x06; /* Hardware size */ + buf[19] = 0x04; /* Protocol size */ + buf[20] = 0x00; /* Opcode: request */ + buf[21] = 0x01; + + for (i = 0; i < 42; i++) + buf[i + 22] = i; + printf("--------Send 64 bytes......\n"); + bfin_EMAC_send(NULL, (volatile void *)buf, 64); + for (i = 0; i < 100; i++) { + udelay(10000); + if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) { + value = 1; + break; + } + } + if (value == 0) { + printf("--------EMAC can't receive any data\n"); + eth_halt(); + return -1; + } + length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4; + for (i = 0; i < length; i++) { + if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) { + printf("--------EMAC receive error data!\n"); + eth_halt(); + return -1; + } + } + printf("--------receive %d bytes, matched\n", length); + bfin_EMAC_halt(NULL); + return 0; +} +#endif +#endif /* CFG_CMD_NET */ diff --git a/board/bf537-stamp/ether_bf537.h b/board/bf537-stamp/ether_bf537.h new file mode 100644 index 0000000..64240ba --- /dev/null +++ b/board/bf537-stamp/ether_bf537.h @@ -0,0 +1,110 @@ +#define PHYADDR 0x01 +#define NO_PHY_REGS 0x20 + +#define DEFAULT_PHY_PHYID1 0x0007 +#define DEFAULT_PHY_PHYID2 0xC0A3 +#define PHY_MODECTL 0x00 +#define PHY_MODESTAT 0x01 +#define PHY_PHYID1 0x02 +#define PHY_PHYID2 0x03 +#define PHY_ANAR 0x04 +#define PHY_ANLPAR 0x05 +#define PHY_ANER 0x06 + +#define PHY_RESET 0x8000 +#define PHY_ANEG_EN 0x1000 +#define PHY_DUPLEX 0x0100 +#define PHY_SPD_SET 0x2000 + +#define RECV_BUFSIZE (0x614) + +typedef volatile u32 reg32; +typedef volatile u16 reg16; + +typedef struct ADI_DMA_CONFIG_REG { + u16 b_DMA_EN:1; /* 0 Enabled */ + u16 b_WNR:1; /* 1 Direction */ + u16 b_WDSIZE:2; /* 2:3 Transfer word size */ + u16 b_DMA2D:1; /* 4 DMA mode */ + u16 b_RESTART:1; /* 5 Retain FIFO */ + u16 b_DI_SEL:1; /* 6 Data interrupt timing select */ + u16 b_DI_EN:1; /* 7 Data interrupt enabled */ + u16 b_NDSIZE:4; /* 8:11 Flex descriptor size */ + u16 b_FLOW:3; /* 12:14Flow */ +} ADI_DMA_CONFIG_REG; + +typedef struct adi_ether_frame_buffer { + u16 NoBytes; /* the no. of following bytes */ + u8 Dest[6]; /* destination MAC address */ + u8 Srce[6]; /* source MAC address */ + u16 LTfield; /* length/type field */ + u8 Data[0]; /* payload bytes */ +} ADI_ETHER_FRAME_BUFFER; +/* 16 bytes/struct */ + +typedef struct dma_descriptor { + struct dma_descriptor *NEXT_DESC_PTR; + u32 START_ADDR; + ADI_DMA_CONFIG_REG CONFIG; +} DMA_DESCRIPTOR; +/* 10 bytes/struct in 12 bytes */ + +typedef struct adi_ether_buffer { + DMA_DESCRIPTOR Dma[2]; /* first for the frame, second for the status */ + ADI_ETHER_FRAME_BUFFER *FrmData;/* pointer to data */ + struct adi_ether_buffer *pNext; /* next buffer */ + struct adi_ether_buffer *pPrev; /* prev buffer */ + u16 IPHdrChksum; /* the IP header checksum */ + u16 IPPayloadChksum; /* the IP header and payload checksum */ + volatile u32 StatusWord; /* the frame status word */ +} ADI_ETHER_BUFFER; +/* 40 bytes/struct in 44 bytes */ + +void SetupMacAddr(u8 * MACaddr); + +void PollMdcDone(void); +void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data); +u16 RdPHYReg(u16 PHYAddr, u16 RegAddr); +void SoftResetPHY(void); +void DumpPHYRegs(void); + +int SetupSystemRegs(int *opmode); + +/** + * is_zero_ether_addr - Determine if give Ethernet address is all zeros. + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is all zeroes. + */ +static inline int is_zero_ether_addr(const u8 * addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +/** + * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is a multicast address. + * By definition the broadcast address is also a multicast address. + */ +static inline int is_multicast_ether_addr(const u8 * addr) +{ + return (0x01 & addr[0]); +} + +/** + * is_valid_ether_addr - Determine if the given Ethernet address is valid + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not + * a multicast address, and is not FF:FF:FF:FF:FF:FF. + * + * Return true if the address is valid. + */ +static inline int is_valid_ether_addr(const u8 * addr) +{ + /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to + * explicitly check for it here. */ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} diff --git a/board/bf537-stamp/flash-defines.h b/board/bf537-stamp/flash-defines.h new file mode 100644 index 0000000..f19e171 --- /dev/null +++ b/board/bf537-stamp/flash-defines.h @@ -0,0 +1,123 @@ +/* + * U-boot - flash-defines.h + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * (C) Copyright 2000-2004 + * 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 + */ + +#ifndef __FLASHDEFINES_H__ +#define __FLASHDEFINES_H__ + +#include <common.h> + +#define V_ULONG(a) (*(volatile unsigned long *)( a )) +#define V_BYTE(a) (*(volatile unsigned char *)( a )) +#define TRUE 0x1 +#define FALSE 0x0 +#define BUFFER_SIZE 0x80000 +#define NO_COMMAND 0 +#define GET_CODES 1 +#define RESET 2 +#define WRITE 3 +#define FILL 4 +#define ERASE_ALL 5 +#define ERASE_SECT 6 +#define READ 7 +#define GET_SECTNUM 8 +#define FLASH_START_L 0x0000 +#define FLASH_START_H 0x2000 +#define FLASH_MAN_ST 2 +#define RESET_VAL 0xF0 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +int get_codes(void); +int poll_toggle_bit(long lOffset); +void reset_flash(void); +int erase_flash(void); +int erase_block_flash(int); +void unlock_flash(long lOffset); +int write_data(long lStart, long lCount, uchar * pnData); +int read_flash(long nOffset, int *pnValue); +int write_flash(long nOffset, int nValue); +void get_sector_number(long lOffset, int *pnSector); +int GetSectorProtectionStatus(flash_info_t * info, int nSector); +int GetOffset(int nBlock); +int AFP_NumSectors = 71; +long AFP_SectorSize2 = 0x10000; +int AFP_SectorSize1 = 0x2000; + +#define NUM_SECTORS 71 + +#define WRITESEQ1 0x0AAA +#define WRITESEQ2 0x0554 +#define WRITESEQ3 0x0AAA +#define WRITESEQ4 0x0AAA +#define WRITESEQ5 0x0554 +#define WRITESEQ6 0x0AAA +#define WRITEDATA1 0xaa +#define WRITEDATA2 0x55 +#define WRITEDATA3 0x80 +#define WRITEDATA4 0xaa +#define WRITEDATA5 0x55 +#define WRITEDATA6 0x10 +#define PriFlashABegin 0 +#define SecFlashABegin 8 +#define SecFlashBBegin 36 +#define PriFlashAOff 0x0 +#define PriFlashBOff 0x100000 +#define SecFlashAOff 0x10000 +#define SecFlashBOff 0x280000 +#define INVALIDLOCNSTART 0x20270000 +#define INVALIDLOCNEND 0x20280000 +#define BlockEraseVal 0x30 +#define UNLOCKDATA1 0xaa +#define UNLOCKDATA2 0x55 +#define UNLOCKDATA3 0xa0 +#define GETCODEDATA1 0xaa +#define GETCODEDATA2 0x55 +#define GETCODEDATA3 0x90 +#define SecFlashASec1Off 0x200000 +#define SecFlashASec2Off 0x204000 +#define SecFlashASec3Off 0x206000 +#define SecFlashASec4Off 0x208000 +#define SecFlashAEndOff 0x210000 +#define SecFlashBSec1Off 0x280000 +#define SecFlashBSec2Off 0x284000 +#define SecFlashBSec3Off 0x286000 +#define SecFlashBSec4Off 0x288000 +#define SecFlashBEndOff 0x290000 + +#define SECT32 32 +#define SECT33 33 +#define SECT34 34 +#define SECT35 35 +#define SECT36 36 +#define SECT37 37 +#define SECT38 38 +#define SECT39 39 + +#define FLASH_SUCCESS 0 +#define FLASH_FAIL -1 + +#endif diff --git a/board/bf537-stamp/flash.c b/board/bf537-stamp/flash.c new file mode 100644 index 0000000..42dcf06 --- /dev/null +++ b/board/bf537-stamp/flash.c @@ -0,0 +1,403 @@ +/* + * U-boot - flash.c Flash driver for PSD4256GV + * + * Copyright (c) 2005 blackfin.uclinux.org + * This file is based on BF533EzFlash.c originally written by Analog Devices, Inc. + * + * (C) Copyright 2000-2004 + * 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 <malloc.h> +#include <config.h> +#include <asm/io.h> +#include "flash-defines.h" + +void flash_reset(void) +{ + reset_flash(); +} + +unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, int bank_flag) +{ + int id = 0, i = 0; + static int FlagDev = 1; + + id = get_codes(); + if (FlagDev) { + FlagDev = 0; + } + info->flash_id = id; + switch (bank_flag) { + case 0: + for (i = PriFlashABegin; i < SecFlashABegin; i++) + info->start[i] = (baseaddr + (i * AFP_SectorSize1)); + for (i = SecFlashABegin; i < NUM_SECTORS; i++) + info->start[i] = + (baseaddr + SecFlashAOff + + ((i - SecFlashABegin) * AFP_SectorSize2)); + info->size = 0x400000; + info->sector_count = NUM_SECTORS; + break; + case 1: + info->start[0] = baseaddr + SecFlashASec1Off; + info->start[1] = baseaddr + SecFlashASec2Off; + info->start[2] = baseaddr + SecFlashASec3Off; + info->start[3] = baseaddr + SecFlashASec4Off; + info->size = 0x10000; + info->sector_count = 4; + break; + case 2: + info->start[0] = baseaddr + SecFlashBSec1Off; + info->start[1] = baseaddr + SecFlashBSec2Off; + info->start[2] = baseaddr + SecFlashBSec3Off; + info->start[3] = baseaddr + SecFlashBSec4Off; + info->size = 0x10000; + info->sector_count = 4; + break; + } + return (info->size); +} + +unsigned long flash_init(void) +{ + unsigned long size_b; + int i; + + size_b = 0; + for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + size_b = flash_get_size(CFG_FLASH_BASE, &flash_info[0], 0); + + if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b == 0) { + printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b, size_b >> 20); + } + + /* flash_protect (int flag, ulong from, ulong to, flash_info_t *info) */ + (void)flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE, + (flash_info[0].start[2] - 1), &flash_info[0]); +#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT) + (void)flash_protect(FLAG_PROTECT_SET, 0x203F0000, 0x203FFFFF, + &flash_info[0]); +#endif + + return (size_b); +} + +void flash_print_info(flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id) { + case (STM_ID_29W320EB & 0xFFFF): + case (STM_ID_29W320DB & 0xFFFF): + printf("ST Microelectronics "); + break; + default: + printf("Unknown Vendor: (0x%08X) ", info->flash_id); + break; + } + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + printf(" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf("\n"); + return; +} + +int flash_erase(flash_info_t * info, int s_first, int s_last) +{ + int cnt = 0, i; + int prot, sect; + + 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"); + + cnt = s_last - s_first + 1; + +#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT) + printf("Erasing Flash locations, Please Wait\n"); + for (i = s_first; i <= s_last; i++) { + if (info->protect[i] == 0) { /* not protected */ + if (erase_block_flash(i) < 0) { + printf("Error Sector erasing \n"); + return FLASH_FAIL; + } + } + } +#elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT) + if (cnt == FLASH_TOT_SECT) { + printf("Erasing flash, Please Wait \n"); + if (erase_flash() < 0) { + printf("Erasing flash failed \n"); + return FLASH_FAIL; + } + } else { + printf("Erasing Flash locations, Please Wait\n"); + for (i = s_first; i <= s_last; i++) { + if (info->protect[i] == 0) { /* not protected */ + if (erase_block_flash(i) < 0) { + printf("Error Sector erasing \n"); + return FLASH_FAIL; + } + } + } + } +#endif + printf("\n"); + return FLASH_SUCCESS; +} + +int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + int d; + if (addr % 2) { + read_flash(addr - 1 - CFG_FLASH_BASE, &d); + d = (int)((d & 0x00FF) | (*src++ << 8)); + write_data(addr - 1, 2, (uchar *) & d); + write_data(addr + 1, cnt - 1, src); + } else + write_data(addr, cnt, src); + return FLASH_SUCCESS; +} + +int write_data(long lStart, long lCount, uchar * pnData) +{ + long i = 0; + unsigned long ulOffset = lStart - CFG_FLASH_BASE; + int d; + int nSector = 0; + int flag = 0; + + if (lCount % 2) { + flag = 1; + lCount = lCount - 1; + } + + for (i = 0; i < lCount - 1; i += 2, ulOffset += 2) { + get_sector_number(ulOffset, &nSector); + read_flash(ulOffset, &d); + if (d != 0xffff) { + printf + ("Flash not erased at offset 0x%x Please erase to reprogram \n", + ulOffset); + return FLASH_FAIL; + } + unlock_flash(ulOffset); + d = (int)(pnData[i] | pnData[i + 1] << 8); + write_flash(ulOffset, d); + if (poll_toggle_bit(ulOffset) < 0) { + printf("Error programming the flash \n"); + return FLASH_FAIL; + } + if ((i > 0) && (!(i % AFP_SectorSize2))) + printf("."); + } + if (flag) { + get_sector_number(ulOffset, &nSector); + read_flash(ulOffset, &d); + if (d != 0xffff) { + printf + ("Flash not erased at offset 0x%x Please erase to reprogram \n", + ulOffset); + return FLASH_FAIL; + } + unlock_flash(ulOffset); + d = (int)(pnData[i] | (d & 0xFF00)); + write_flash(ulOffset, d); + if (poll_toggle_bit(ulOffset) < 0) { + printf("Error programming the flash \n"); + return FLASH_FAIL; + } + } + return FLASH_SUCCESS; +} + +int write_flash(long nOffset, int nValue) +{ + long addr; + + addr = (CFG_FLASH_BASE + nOffset); + *(unsigned volatile short *)addr = nValue; + sync(); +#if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT) + if (icache_status()) + udelay(CONFIG_CCLK_HZ / 1000000); +#endif + return FLASH_SUCCESS; +} + +int read_flash(long nOffset, int *pnValue) +{ + unsigned short *pFlashAddr = + (unsigned short *)(CFG_FLASH_BASE + nOffset); + + *pnValue = *pFlashAddr; + + return TRUE; +} + +int poll_toggle_bit(long lOffset) +{ + unsigned int u1, u2; + volatile unsigned long *FB = + (volatile unsigned long *)(CFG_FLASH_BASE + lOffset); + while (1) { + u1 = *(volatile unsigned short *)FB; + u2 = *(volatile unsigned short *)FB; + u1 ^= u2; + if (!(u1 & 0x0040)) + break; + if (!(u2 & 0x0020)) + continue; + else { + u1 = *(volatile unsigned short *)FB; + u2 = *(volatile unsigned short *)FB; + u1 ^= u2; + if (!(u1 & 0x0040)) + break; + else { + reset_flash(); + return FLASH_FAIL; + } + } + } + return FLASH_SUCCESS; +} + +void reset_flash(void) +{ + write_flash(WRITESEQ1, RESET_VAL); + /* Wait for 10 micro seconds */ + udelay(10); +} + +int erase_flash(void) +{ + write_flash(WRITESEQ1, WRITEDATA1); + write_flash(WRITESEQ2, WRITEDATA2); + write_flash(WRITESEQ3, WRITEDATA3); + write_flash(WRITESEQ4, WRITEDATA4); + write_flash(WRITESEQ5, WRITEDATA5); + write_flash(WRITESEQ6, WRITEDATA6); + + if (poll_toggle_bit(0x0000) < 0) + return FLASH_FAIL; + + return FLASH_SUCCESS; +} + +int erase_block_flash(int nBlock) +{ + long ulSectorOff = 0x0; + + if ((nBlock < 0) || (nBlock > AFP_NumSectors)) + return FALSE; + + /* figure out the offset of the block in flash */ + if ((nBlock >= 0) && (nBlock < SecFlashABegin)) + ulSectorOff = nBlock * AFP_SectorSize1; + + else if ((nBlock >= SecFlashABegin) && (nBlock < NUM_SECTORS)) + ulSectorOff = + SecFlashAOff + (nBlock - SecFlashABegin) * AFP_SectorSize2; + /* no such sector */ + else + return FLASH_FAIL; + + write_flash((WRITESEQ1 | ulSectorOff), WRITEDATA1); + write_flash((WRITESEQ2 | ulSectorOff), WRITEDATA2); + write_flash((WRITESEQ3 | ulSectorOff), WRITEDATA3); + write_flash((WRITESEQ4 | ulSectorOff), WRITEDATA4); + write_flash((WRITESEQ5 | ulSectorOff), WRITEDATA5); + + write_flash(ulSectorOff, BlockEraseVal); + + if (poll_toggle_bit(ulSectorOff) < 0) + return FLASH_FAIL; + printf("."); + + return FLASH_SUCCESS; +} + +void unlock_flash(long ulOffset) +{ + unsigned long ulOffsetAddr = ulOffset; + ulOffsetAddr &= 0xFFFF0000; + + write_flash((WRITESEQ1 | ulOffsetAddr), UNLOCKDATA1); + write_flash((WRITESEQ2 | ulOffsetAddr), UNLOCKDATA2); + write_flash((WRITESEQ3 | ulOffsetAddr), UNLOCKDATA3); +} + +int get_codes() +{ + int dev_id = 0; + + write_flash(WRITESEQ1, GETCODEDATA1); + write_flash(WRITESEQ2, GETCODEDATA2); + write_flash(WRITESEQ3, GETCODEDATA3); + + read_flash(0x0402, &dev_id); + dev_id &= 0x0000FFFF; + + reset_flash(); + + return dev_id; +} + +void get_sector_number(long ulOffset, int *pnSector) +{ + int nSector = 0; + long lMainEnd = 0x400000; + long lBootEnd = 0x10000; + + /* sector numbers for the FLASH A boot sectors */ + if (ulOffset < lBootEnd) { + nSector = (int)ulOffset / AFP_SectorSize1; + } + /* sector numbers for the FLASH B boot sectors */ + else if ((ulOffset >= lBootEnd) && (ulOffset < lMainEnd)) { + nSector = ((ulOffset / (AFP_SectorSize2)) + 7); + } + /* if it is a valid sector, set it */ + if ((nSector >= 0) && (nSector < AFP_NumSectors)) + *pnSector = nSector; + +} diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c new file mode 100644 index 0000000..4d6e776 --- /dev/null +++ b/board/bf537-stamp/nand.c @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2006 Aubrey.Li, aubrey.li@analog.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 <common.h> +#include <asm/io.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <nand.h> + +#define CONCAT(a,b,c,d) a ## b ## c ## d +#define PORT(a,b) CONCAT(pPORT,a,b,) + +#ifndef CONFIG_NAND_GPIO_PORT +#define CONFIG_NAND_GPIO_PORT F +#endif + +/* + * hardware specific access to control-lines + */ +static void bfin_hwcontrol(struct mtd_info *mtd, int cmd) +{ + register struct nand_chip *this = mtd->priv; + + switch (cmd) { + + case NAND_CTL_SETCLE: + this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_CLE; + break; + case NAND_CTL_CLRCLE: + this->IO_ADDR_W = CFG_NAND_BASE; + break; + + case NAND_CTL_SETALE: + this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE; + break; + case NAND_CTL_CLRALE: + this->IO_ADDR_W = CFG_NAND_BASE; + break; + case NAND_CTL_SETNCE: + case NAND_CTL_CLRNCE: + break; + } + + this->IO_ADDR_R = this->IO_ADDR_W; + + /* Drain the writebuffer */ + sync(); +} + +int bfin_device_ready(struct mtd_info *mtd) +{ + int ret = (*PORT(CONFIG_NAND_GPIO_PORT, IO) & BFIN_NAND_READY) ? 1 : 0; + sync(); + return ret; +} + +/* + * Board-specific NAND initialization. The following members of the + * argument are board-specific (per include/linux/mtd/nand.h): + * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device + * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device + * - hwcontrol: hardwarespecific function for accesing control-lines + * - dev_ready: hardwarespecific function for accesing device ready/busy line + * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must + * only be provided if a hardware ECC is available + * - eccmode: mode of ecc, see defines + * - chip_delay: chip dependent delay for transfering data from array to + * read regs (tR) + * - options: various chip options. They can partly be set to inform + * nand_scan about special functionality. See the defines for further + * explanation + * Members with a "?" were not set in the merged testing-NAND branch, + * so they are not set here either. + */ +void board_nand_init(struct nand_chip *nand) +{ + *PORT(CONFIG_NAND_GPIO_PORT, _FER) &= ~BFIN_NAND_READY; + *PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY; + *PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY; + + nand->hwcontrol = bfin_hwcontrol; + nand->eccmode = NAND_ECC_SOFT; + nand->dev_ready = bfin_device_ready; + nand->chip_delay = 30; +} +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ diff --git a/board/bf537-stamp/post-memory.c b/board/bf537-stamp/post-memory.c new file mode 100644 index 0000000..6039350 --- /dev/null +++ b/board/bf537-stamp/post-memory.c @@ -0,0 +1,322 @@ +#include <common.h> +#include <asm/io.h> + +#ifdef CONFIG_POST + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CFG_POST_MEMORY +#define CLKIN 25000000 +#define PATTERN1 0x5A5A5A5A +#define PATTERN2 0xAAAAAAAA + +#define CCLK_NUM 4 +#define SCLK_NUM 3 + +void post_out_buff(char *buff); +int post_key_pressed(void); +void post_init_pll(int mult, int div); +int post_init_sdram(int sclk); +void post_init_uart(int sclk); + +const int pll[CCLK_NUM][SCLK_NUM][2] = { + {{20, 4}, {20, 5}, {20, 10}}, /* CCLK = 500M */ + {{16, 4}, {16, 5}, {16, 8}}, /* CCLK = 400M */ + {{8, 2}, {8, 4}, {8, 5}}, /* CCLK = 200M */ + {{4, 1}, {4, 2}, {4, 4}} /* CCLK = 100M */ +}; +const char *const log[CCLK_NUM][SCLK_NUM] = { + {"CCLK-500Mhz SCLK-125Mhz: Writing...\0", + "CCLK-500Mhz SCLK-100Mhz: Writing...\0", + "CCLK-500Mhz SCLK- 50Mhz: Writing...\0",}, + {"CCLK-400Mhz SCLK-100Mhz: Writing...\0", + "CCLK-400Mhz SCLK- 80Mhz: Writing...\0", + "CCLK-400Mhz SCLK- 50Mhz: Writing...\0",}, + {"CCLK-200Mhz SCLK-100Mhz: Writing...\0", + "CCLK-200Mhz SCLK- 50Mhz: Writing...\0", + "CCLK-200Mhz SCLK- 40Mhz: Writing...\0",}, + {"CCLK-100Mhz SCLK-100Mhz: Writing...\0", + "CCLK-100Mhz SCLK- 50Mhz: Writing...\0", + "CCLK-100Mhz SCLK- 25Mhz: Writing...\0",}, +}; + +int memory_post_test(int flags) +{ + int addr; + int m, n; + int sclk, sclk_temp; + int ret = 1; + + sclk_temp = CLKIN / 1000000; + sclk_temp = sclk_temp * CONFIG_VCO_MULT; + for (sclk = 0; sclk_temp > 0; sclk++) + sclk_temp -= CONFIG_SCLK_DIV; + sclk = sclk * 1000000; + post_init_uart(sclk); + if (post_key_pressed() == 0) + return 0; + + for (m = 0; m < CCLK_NUM; m++) { + for (n = 0; n < SCLK_NUM; n++) { + /* Calculate the sclk */ + sclk_temp = CLKIN / 1000000; + sclk_temp = sclk_temp * pll[m][n][0]; + for (sclk = 0; sclk_temp > 0; sclk++) + sclk_temp -= pll[m][n][1]; + sclk = sclk * 1000000; + + post_init_pll(pll[m][n][0], pll[m][n][1]); + post_init_sdram(sclk); + post_init_uart(sclk); + post_out_buff("\n\r\0"); + post_out_buff(log[m][n]); + for (addr = 0x0; addr < CFG_MAX_RAM_SIZE; addr += 4) + *(unsigned long *)addr = PATTERN1; + post_out_buff("Reading...\0"); + for (addr = 0x0; addr < CFG_MAX_RAM_SIZE; addr += 4) { + if ((*(unsigned long *)addr) != PATTERN1) { + post_out_buff("Error\n\r\0"); + ret = 0; + } + } + post_out_buff("OK\n\r\0"); + } + } + if (ret) + post_out_buff("memory POST passed\n\r\0"); + else + post_out_buff("memory POST failed\n\r\0"); + + post_out_buff("\n\r\n\r\0"); + return 1; +} + +void post_init_uart(int sclk) +{ + int divisor; + + for (divisor = 0; sclk > 0; divisor++) + sclk -= 57600 * 16; + + *pPORTF_FER = 0x000F; + *pPORTH_FER = 0xFFFF; + + *pUART_GCTL = 0x00; + *pUART_LCR = 0x83; + sync(); + *pUART_DLL = (divisor & 0xFF); + sync(); + *pUART_DLH = ((divisor >> 8) & 0xFF); + sync(); + *pUART_LCR = 0x03; + sync(); + *pUART_GCTL = 0x01; + sync(); +} + +void post_out_buff(char *buff) +{ + + int i = 0; + for (i = 0; i < 0x80000; i++) ; + i = 0; + while ((buff[i] != '\0') && (i != 100)) { + while (!(*pUART_LSR & 0x20)) ; + *pUART_THR = buff[i]; + sync(); + i++; + } + for (i = 0; i < 0x80000; i++) ; +} + +/* Using sw10-PF5 as the hotkey */ +#define KEY_LOOP 0x80000 +#define KEY_DELAY 0x80 +int post_key_pressed(void) +{ + int i, n; + unsigned short value; + + *pPORTF_FER &= ~PF5; + *pPORTFIO_DIR &= ~PF5; + *pPORTFIO_INEN |= PF5; + sync(); + + post_out_buff("########Press SW10 to enter Memory POST########: 3\0"); + for (i = 0; i < KEY_LOOP; i++) { + value = *pPORTFIO & PF5; + if (*pUART0_RBR == 0x0D) { + value = 0; + goto key_pressed; + } + if (value != 0) { + goto key_pressed; + } + for (n = 0; n < KEY_DELAY; n++) + asm("nop"); + } + post_out_buff("\b2\0"); + + for (i = 0; i < KEY_LOOP; i++) { + value = *pPORTFIO & PF5; + if (*pUART0_RBR == 0x0D) { + value = 0; + goto key_pressed; + } + if (value != 0) { + goto key_pressed; + } + for (n = 0; n < KEY_DELAY; n++) + asm("nop"); + } + post_out_buff("\b1\0"); + + for (i = 0; i < KEY_LOOP; i++) { + value = *pPORTFIO & PF5; + if (*pUART0_RBR == 0x0D) { + value = 0; + goto key_pressed; + } + if (value != 0) { + goto key_pressed; + } + for (n = 0; n < KEY_DELAY; n++) + asm("nop"); + } + key_pressed: + post_out_buff("\b0"); + post_out_buff("\n\r\0"); + if (value == 0) + return 0; + post_out_buff("Hotkey has been pressed, Enter POST . . . . . .\n\r\0"); + return 1; +} + +void post_init_pll(int mult, int div) +{ + + *pSIC_IWR = 0x01; + *pPLL_CTL = (mult << 9); + *pPLL_DIV = div; + asm("CLI R2;"); + asm("IDLE;"); + asm("STI R2;"); + while (!(*pPLL_STAT & 0x20)) ; +} + +int post_init_sdram(int sclk) +{ + int SDRAM_tRP, SDRAM_tRP_num, SDRAM_tRAS, SDRAM_tRAS_num, SDRAM_tRCD, + SDRAM_tWR; + int SDRAM_Tref, SDRAM_NRA, SDRAM_CL, SDRAM_SIZE, SDRAM_WIDTH, + mem_SDGCTL, mem_SDBCTL, mem_SDRRC; + + if ((sclk > 119402985)) { + SDRAM_tRP = TRP_2; + SDRAM_tRP_num = 2; + SDRAM_tRAS = TRAS_7; + SDRAM_tRAS_num = 7; + SDRAM_tRCD = TRCD_2; + SDRAM_tWR = TWR_2; + } else if ((sclk > 104477612) && (sclk <= 119402985)) { + SDRAM_tRP = TRP_2; + SDRAM_tRP_num = 2; + SDRAM_tRAS = TRAS_6; + SDRAM_tRAS_num = 6; + SDRAM_tRCD = TRCD_2; + SDRAM_tWR = TWR_2; + } else if ((sclk > 89552239) && (sclk <= 104477612)) { + SDRAM_tRP = TRP_2; + SDRAM_tRP_num = 2; + SDRAM_tRAS = TRAS_5; + SDRAM_tRAS_num = 5; + SDRAM_tRCD = TRCD_2; + SDRAM_tWR = TWR_2; + } else if ((sclk > 74626866) && (sclk <= 89552239)) { + SDRAM_tRP = TRP_2; + SDRAM_tRP_num = 2; + SDRAM_tRAS = TRAS_4; + SDRAM_tRAS_num = 4; + SDRAM_tRCD = TRCD_2; + SDRAM_tWR = TWR_2; + } else if ((sclk > 66666667) && (sclk <= 74626866)) { + SDRAM_tRP = TRP_2; + SDRAM_tRP_num = 2; + SDRAM_tRAS = TRAS_3; + SDRAM_tRAS_num = 3; + SDRAM_tRCD = TRCD_2; + SDRAM_tWR = TWR_2; + } else if ((sclk > 59701493) && (sclk <= 66666667)) { + SDRAM_tRP = TRP_1; + SDRAM_tRP_num = 1; + SDRAM_tRAS = TRAS_4; + SDRAM_tRAS_num = 4; + SDRAM_tRCD = TRCD_1; + SDRAM_tWR = TWR_2; + } else if ((sclk > 44776119) && (sclk <= 59701493)) { + SDRAM_tRP = TRP_1; + SDRAM_tRP_num = 1; + SDRAM_tRAS = TRAS_3; + SDRAM_tRAS_num = 3; + SDRAM_tRCD = TRCD_1; + SDRAM_tWR = TWR_2; + } else if ((sclk > 29850746) && (sclk <= 44776119)) { + SDRAM_tRP = TRP_1; + SDRAM_tRP_num = 1; + SDRAM_tRAS = TRAS_2; + SDRAM_tRAS_num = 2; + SDRAM_tRCD = TRCD_1; + SDRAM_tWR = TWR_2; + } else if (sclk <= 29850746) { + SDRAM_tRP = TRP_1; + SDRAM_tRP_num = 1; + SDRAM_tRAS = TRAS_1; + SDRAM_tRAS_num = 1; + SDRAM_tRCD = TRCD_1; + SDRAM_tWR = TWR_2; + } else { + SDRAM_tRP = TRP_1; + SDRAM_tRP_num = 1; + SDRAM_tRAS = TRAS_1; + SDRAM_tRAS_num = 1; + SDRAM_tRCD = TRCD_1; + SDRAM_tWR = TWR_2; + } + /*SDRAM INFORMATION: */ + SDRAM_Tref = 64; /* Refresh period in milliseconds */ + SDRAM_NRA = 4096; /* Number of row addresses in SDRAM */ + SDRAM_CL = CL_3; /* 2 */ + + SDRAM_SIZE = EBSZ_64; + SDRAM_WIDTH = EBCAW_10; + + mem_SDBCTL = SDRAM_WIDTH | SDRAM_SIZE | EBE; + + /* Equation from section 17 (p17-46) of BF533 HRM */ + mem_SDRRC = + (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - + (SDRAM_tRAS_num + SDRAM_tRP_num); + + /* Enable SCLK Out */ + mem_SDGCTL = + (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR + | PSS); + + sync(); + + *pEBIU_SDGCTL |= 0x1000000; + /* Set the SDRAM Refresh Rate control register based on SSCLK value */ + *pEBIU_SDRRC = mem_SDRRC; + + /* SDRAM Memory Bank Control Register */ + *pEBIU_SDBCTL = mem_SDBCTL; + + /* SDRAM Memory Global Control Register */ + *pEBIU_SDGCTL = mem_SDGCTL; + sync(); + return mem_SDRRC; +} + +#endif /* CONFIG_POST & CFG_POST_MEMORY */ +#endif /* CONFIG_POST */ diff --git a/board/bf537-stamp/stm_m25p64.c b/board/bf537-stamp/stm_m25p64.c new file mode 100644 index 0000000..7077e85 --- /dev/null +++ b/board/bf537-stamp/stm_m25p64.c @@ -0,0 +1,515 @@ +/**************************************************************************** + * SPI flash driver for M25P64 + ****************************************************************************/ +#include <common.h> +#include <linux/ctype.h> +#include <asm/io.h> + +#if defined(CONFIG_SPI) + +/* Application definitions */ + +#define NUM_SECTORS 128 /* number of sectors */ +#define SECTOR_SIZE 0x10000 +#define NOP_NUM 1000 + +#define COMMON_SPI_SETTINGS (SPE|MSTR|CPHA|CPOL) /* Settings to the SPI_CTL */ +#define TIMOD01 (0x01) /* stes the SPI to work with core instructions */ + +/* Flash commands */ +#define SPI_WREN (0x06) /*Set Write Enable Latch */ +#define SPI_WRDI (0x04) /*Reset Write Enable Latch */ +#define SPI_RDSR (0x05) /*Read Status Register */ +#define SPI_WRSR (0x01) /*Write Status Register */ +#define SPI_READ (0x03) /*Read data from memory */ +#define SPI_FAST_READ (0x0B) /*Read data from memory */ +#define SPI_PP (0x02) /*Program Data into memory */ +#define SPI_SE (0xD8) /*Erase one sector in memory */ +#define SPI_BE (0xC7) /*Erase all memory */ +#define WIP (0x1) /*Check the write in progress bit of the SPI status register */ +#define WEL (0x2) /*Check the write enable bit of the SPI status register */ + +#define TIMEOUT 350000000 + +typedef enum { + NO_ERR, + POLL_TIMEOUT, + INVALID_SECTOR, + INVALID_BLOCK, +} ERROR_CODE; + +void spi_init_f(void); +void spi_init_r(void); +ssize_t spi_read(uchar *, int, uchar *, int); +ssize_t spi_write(uchar *, int, uchar *, int); + +char ReadStatusRegister(void); +void Wait_For_SPIF(void); +void SetupSPI(const int spi_setting); +void SPI_OFF(void); +void SendSingleCommand(const int iCommand); + +ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector); +ERROR_CODE EraseBlock(int nBlock); +ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData); +ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData); +ERROR_CODE Wait_For_Status(char Statusbit); +ERROR_CODE Wait_For_WEL(void); + +/* + * Function: spi_init_f + * Description: Init SPI-Controller (ROM part) + * return: --- + */ +void spi_init_f(void) +{ +} + +/* + * Function: spi_init_r + * Description: Init SPI-Controller (RAM part) - + * The malloc engine is ready and we can move our buffers to + * normal RAM + * return: --- + */ +void spi_init_r(void) +{ + return; +} + +/* + * Function: spi_write + */ +ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len) +{ + unsigned long offset; + int start_block, end_block; + int start_byte, end_byte; + ERROR_CODE result = NO_ERR; + uchar temp[SECTOR_SIZE]; + int i, num; + + offset = addr[0] << 16 | addr[1] << 8 | addr[2]; + /* Get the start block number */ + result = GetSectorNumber(offset, &start_block); + if (result == INVALID_SECTOR) { + printf("Invalid sector! "); + return 0; + } + /* Get the end block number */ + result = GetSectorNumber(offset + len - 1, &end_block); + if (result == INVALID_SECTOR) { + printf("Invalid sector! "); + return 0; + } + + for (num = start_block; num <= end_block; num++) { + ReadData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp); + start_byte = num * SECTOR_SIZE; + end_byte = (num + 1) * SECTOR_SIZE - 1; + if (start_byte < offset) + start_byte = offset; + if (end_byte > (offset + len)) + end_byte = (offset + len - 1); + for (i = start_byte; i <= end_byte; i++) + temp[i - num * SECTOR_SIZE] = buffer[i - offset]; + EraseBlock(num); + result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp); + if (result != NO_ERR) + return 0; + printf("."); + } + return len; +} + +/* + * Function: spi_read + */ +ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len) +{ + unsigned long offset; + offset = addr[0] << 16 | addr[1] << 8 | addr[2]; + ReadData(offset, len, (int *)buffer); + return len; +} + +void SendSingleCommand(const int iCommand) +{ + unsigned short dummy; + + /* turns on the SPI in single write mode */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + + /* sends the actual command to the SPI TX register */ + *pSPI_TDBR = iCommand; + sync(); + + /* The SPI status register will be polled to check the SPIF bit */ + Wait_For_SPIF(); + + dummy = *pSPI_RDBR; + + /* The SPI will be turned off */ + SPI_OFF(); + +} + +void SetupSPI(const int spi_setting) +{ + + if (icache_status() || dcache_status()) + udelay(CONFIG_CCLK_HZ / 50000000); + /*sets up the PF10 to be the slave select of the SPI */ + *pPORTF_FER |= (PF10 | PF11 | PF12 | PF13); + *pSPI_FLG = 0xFF02; + *pSPI_BAUD = CONFIG_SPI_BAUD; + *pSPI_CTL = spi_setting; + sync(); + + *pSPI_FLG = 0xFD02; + sync(); +} + +void SPI_OFF(void) +{ + + *pSPI_CTL = 0x0400; /* disable SPI */ + *pSPI_FLG = 0; + *pSPI_BAUD = 0; + sync(); + udelay(CONFIG_CCLK_HZ / 50000000); + +} + +void Wait_For_SPIF(void) +{ + unsigned short dummyread; + while ((*pSPI_STAT & TXS)) ; + while (!(*pSPI_STAT & SPIF)) ; + while (!(*pSPI_STAT & RXS)) ; + /* Read dummy to empty the receive register */ + dummyread = *pSPI_RDBR; +} + +ERROR_CODE Wait_For_WEL(void) +{ + int i; + char status_register = 0; + ERROR_CODE ErrorCode = NO_ERR; + + for (i = 0; i < TIMEOUT; i++) { + status_register = ReadStatusRegister(); + if ((status_register & WEL)) { + ErrorCode = NO_ERR; + break; + } + ErrorCode = POLL_TIMEOUT; /* Time out error */ + }; + + return ErrorCode; +} + +ERROR_CODE Wait_For_Status(char Statusbit) +{ + int i; + char status_register = 0xFF; + ERROR_CODE ErrorCode = NO_ERR; + + for (i = 0; i < TIMEOUT; i++) { + status_register = ReadStatusRegister(); + if (!(status_register & Statusbit)) { + ErrorCode = NO_ERR; + break; + } + ErrorCode = POLL_TIMEOUT; /* Time out error */ + }; + + return ErrorCode; +} + +char ReadStatusRegister(void) +{ + char status_register = 0; + + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turn on the SPI */ + + *pSPI_TDBR = SPI_RDSR; /* send instruction to read status register */ + sync(); + Wait_For_SPIF(); /*wait until the instruction has been sent */ + *pSPI_TDBR = 0; /*send dummy to receive the status register */ + sync(); + Wait_For_SPIF(); /*wait until the data has been sent */ + status_register = *pSPI_RDBR; /*read the status register */ + + SPI_OFF(); /* Turn off the SPI */ + + return status_register; +} + +ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector) +{ + int nSector = 0; + ERROR_CODE ErrorCode = NO_ERR; + + if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) { + ErrorCode = INVALID_SECTOR; + return ErrorCode; + } + + nSector = (int)ulOffset / 0x10000; + *pnSector = nSector; + + return ErrorCode; +} + +ERROR_CODE EraseBlock(int nBlock) +{ + unsigned long ulSectorOff = 0x0, ShiftValue; + ERROR_CODE ErrorCode = NO_ERR; + + /* if the block is invalid just return */ + if ((nBlock < 0) || (nBlock > NUM_SECTORS)) { + ErrorCode = INVALID_BLOCK; + return ErrorCode; + } + /* figure out the offset of the block in flash */ + if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) { + ulSectorOff = (nBlock * SECTOR_SIZE); + + } else { + ErrorCode = INVALID_BLOCK; + return ErrorCode; + } + + /* A write enable instruction must previously have been executed */ + SendSingleCommand(SPI_WREN); + + /* The status register will be polled to check the write enable latch "WREN" */ + ErrorCode = Wait_For_WEL(); + + if (POLL_TIMEOUT == ErrorCode) { + printf("SPI Erase block error\n"); + return ErrorCode; + } else + + /* Turn on the SPI to send single commands */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + + /* + * Send the erase block command to the flash followed by the 24 address + * to point to the start of a sector + */ + *pSPI_TDBR = SPI_SE; + sync(); + Wait_For_SPIF(); + /* Send the highest byte of the 24 bit address at first */ + ShiftValue = (ulSectorOff >> 16); + *pSPI_TDBR = ShiftValue; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + /* Send the middle byte of the 24 bit address at second */ + ShiftValue = (ulSectorOff >> 8); + *pSPI_TDBR = ShiftValue; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + /* Send the lowest byte of the 24 bit address finally */ + *pSPI_TDBR = ulSectorOff; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + + /* Turns off the SPI */ + SPI_OFF(); + + /* Poll the status register to check the Write in Progress bit */ + /* Sector erase takes time */ + ErrorCode = Wait_For_Status(WIP); + + /* block erase should be complete */ + return ErrorCode; +} + +/* + * ERROR_CODE ReadData() + * Read a value from flash for verify purpose + * Inputs: unsigned long ulStart - holds the SPI start address + * int pnData - pointer to store value read from flash + * long lCount - number of elements to read + */ +ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData) +{ + unsigned long ShiftValue; + char *cnData; + int i; + + /* Pointer cast to be able to increment byte wise */ + + cnData = (char *)pnData; + /* Start SPI interface */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + +#ifdef CONFIG_SPI_FLASH_FAST_READ + /* Send the read command to SPI device */ + *pSPI_TDBR = SPI_FAST_READ; +#else + /* Send the read command to SPI device */ + *pSPI_TDBR = SPI_READ; +#endif + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + /* Send the highest byte of the 24 bit address at first */ + ShiftValue = (ulStart >> 16); + /* Send the byte to the SPI device */ + *pSPI_TDBR = ShiftValue; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + /* Send the middle byte of the 24 bit address at second */ + ShiftValue = (ulStart >> 8); + /* Send the byte to the SPI device */ + *pSPI_TDBR = ShiftValue; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + /* Send the lowest byte of the 24 bit address finally */ + *pSPI_TDBR = ulStart; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); + +#ifdef CONFIG_SPI_FLASH_FAST_READ + /* Send dummy for FAST_READ */ + *pSPI_TDBR = 0; + sync(); + /* Wait until the instruction has been sent */ + Wait_For_SPIF(); +#endif + + /* After the SPI device address has been placed on the MOSI pin the data can be */ + /* received on the MISO pin. */ + for (i = 0; i < lCount; i++) { + *pSPI_TDBR = 0; + sync(); + while (!(*pSPI_STAT & RXS)) ; + *cnData++ = *pSPI_RDBR; + + if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0)) + printf("."); + } + + /* Turn off the SPI */ + SPI_OFF(); + + return NO_ERR; +} + +ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount, + int *iDataSource, long *lWriteCount) +{ + + unsigned long ulWAddr; + long lWTransferCount = 0; + int i; + char iData; + char *temp = (char *)iDataSource; + ERROR_CODE ErrorCode = NO_ERR; + + /* First, a Write Enable Command must be sent to the SPI. */ + SendSingleCommand(SPI_WREN); + + /* + * Second, the SPI Status Register will be tested whether the + * Write Enable Bit has been set + */ + ErrorCode = Wait_For_WEL(); + if (POLL_TIMEOUT == ErrorCode) { + printf("SPI Write Time Out\n"); + return ErrorCode; + } else + /* Third, the 24 bit address will be shifted out + * the SPI MOSI bytewise. + * Turns the SPI on + */ + SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); + *pSPI_TDBR = SPI_PP; + sync(); + /*wait until the instruction has been sent */ + Wait_For_SPIF(); + ulWAddr = (ulStartAddr >> 16); + *pSPI_TDBR = ulWAddr; + sync(); + /*wait until the instruction has been sent */ + Wait_For_SPIF(); + ulWAddr = (ulStartAddr >> 8); + *pSPI_TDBR = ulWAddr; + sync(); + /*wait until the instruction has been sent */ + Wait_For_SPIF(); + ulWAddr = ulStartAddr; + *pSPI_TDBR = ulWAddr; + sync(); + /*wait until the instruction has been sent */ + Wait_For_SPIF(); + /* + * Fourth, maximum number of 256 bytes will be taken from the Buffer + * and sent to the SPI device. + */ + for (i = 0; (i < lTransferCount) && (i < 256); i++, lWTransferCount++) { + iData = *temp; + *pSPI_TDBR = iData; + sync(); + /*wait until the instruction has been sent */ + Wait_For_SPIF(); + temp++; + } + + /* Turns the SPI off */ + SPI_OFF(); + + /* + * Sixth, the SPI Write in Progress Bit must be toggled to ensure the + * programming is done before start of next transfer + */ + ErrorCode = Wait_For_Status(WIP); + + if (POLL_TIMEOUT == ErrorCode) { + printf("SPI Program Time out!\n"); + return ErrorCode; + } else + + *lWriteCount = lWTransferCount; + + return ErrorCode; +} + +ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData) +{ + + unsigned long ulWStart = ulStart; + long lWCount = lCount, lWriteCount; + long *pnWriteCount = &lWriteCount; + + ERROR_CODE ErrorCode = NO_ERR; + + while (lWCount != 0) { + ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount); + + /* + * After each function call of WriteFlash the counter + * must be adjusted + */ + lWCount -= *pnWriteCount; + + /* Also, both address pointers must be recalculated. */ + ulWStart += *pnWriteCount; + pnData += *pnWriteCount / 4; + } + + /* return the appropriate error code */ + return ErrorCode; +} + +#endif /* CONFIG_SPI */ diff --git a/board/bf537-stamp/u-boot.lds.S b/board/bf537-stamp/u-boot.lds.S new file mode 100644 index 0000000..3fb2d0c --- /dev/null +++ b/board/bf537-stamp/u-boot.lds.S @@ -0,0 +1,190 @@ +/* + * U-boot - u-boot.lds.S + * + * Copyright (c) 2005-2007 Analog Device Inc. + * + * (C) Copyright 2000-2004 + * 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 <config.h> + +OUTPUT_ARCH(bfin) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +MEMORY + { + ram : ORIGIN = (CFG_MONITOR_BASE), LENGTH = (256 * 1024) + l1_code : ORIGIN = 0xFFA00000, LENGTH = 0xC000 + l1_data : ORIGIN = 0xFF900000, LENGTH = 0x4000 + } + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; /*0x1000;*/ + .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) } + . = CFG_MONITOR_BASE; + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector before the environment sector. If it throws */ + /* an error during compilation remove an object here to get */ + /* it linked after the configuration sector. */ + + cpu/bf537/start.o (.text) + cpu/bf537/start1.o (.text) + cpu/bf537/traps.o (.text) + cpu/bf537/interrupt.o (.text) + cpu/bf537/serial.o (.text) + common/dlmalloc.o (.text) +/* lib_blackfin/bf533_string.o (.text) */ +/* lib_generic/vsprintf.o (.text) */ + lib_generic/crc32.o (.text) +/* lib_generic/zlib.o (.text) */ +/* board/bf537-stamp/bf537-stamp.o (.text) */ + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .text) + *(.fixup) + *(.got1) + } > ram + _etext = .; + PROVIDE (etext = .); + .text_l1 : + { + . = ALIGN(4) ; + _text_l1 = .; + PROVIDE (text_l1 = .); + board/bf537-stamp/post-memory.o (.text) + . = ALIGN(4) ; + _etext_l1 = .; + PROVIDE (etext_l1 = .); + } > l1_code AT > ram + + .rodata : + { + . = ALIGN(4); + *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .rodata) + *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .rodata1) + *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .rodata.str1.4) + *(.eh_frame) + . = ALIGN(4); + } > ram + + . = ALIGN(4); + _erodata = .; + PROVIDE (erodata = .); + .rodata_l1 : + { + . = ALIGN(4) ; + _rodata_l1 = .; + PROVIDE (rodata_l1 = .); + board/bf537-stamp/post-memory.o (.rodata) + board/bf537-stamp/post-memory.o (.rodata1) + board/bf537-stamp/post-memory.o (.rodata.str1.4) + . = ALIGN(4) ; + _erodata_l1 = .; + PROVIDE(erodata_l1 = .); + } > l1_data AT > ram + + .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 + } > ram + _edata = .; + PROVIDE (edata = .); + + ___u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } > ram + ___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 : + { + __bss_start = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } > ram + _end = . ; + PROVIDE (end = .); +} diff --git a/board/bf561-ezkit/Makefile b/board/bf561-ezkit/Makefile new file mode 100644 index 0000000..a3c2e5b --- /dev/null +++ b/board/bf561-ezkit/Makefile @@ -0,0 +1,58 @@ +# +# U-boot - Makefile +# +# Copyright (c) 2005-2007 Analog Device Inc. +# +# (C) Copyright 2000-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +u-boot.lds: u-boot.lds.S + $(CPP) $(CPPFLAGS) -P -Ubfin $^ > $@.tmp + mv -f $@.tmp $@ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/bf561-ezkit/bf561-ezkit.c b/board/bf561-ezkit/bf561-ezkit.c new file mode 100644 index 0000000..71281c0 --- /dev/null +++ b/board/bf561-ezkit/bf561-ezkit.c @@ -0,0 +1,73 @@ +/* + * U-boot - ezkit561.c + * + * Copyright (c) 2005 Bas Vermeulen <bas@buyways.nl> + * Copyright (c) 2005 blackfin.uclinux.org + * + * (C) Copyright 2000-2004 + * 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 <common.h> +#include <asm/io.h> + +int checkboard(void) +{ + printf("CPU: ADSP BF561\n"); + printf("Board: ADI BF561 EZ-Kit Lite board\n"); + printf(" Support: http://blackfin.uclinux.org/\n"); + return 0; +} + +long int initdram(int board_type) +{ + DECLARE_GLOBAL_DATA_PTR; +#ifdef DEBUG + int brate; + char *tmp = getenv("baudrate"); + brate = simple_strtoul(tmp, NULL, 16); + printf("Serial Port initialized with Baud rate = %x\n", brate); + printf("SDRAM attributes:\n"); + printf("tRCD %d SCLK Cycles,tRP %d SCLK Cycles,tRAS %d SCLK Cycles" + "tWR %d SCLK Cycles,CAS Latency %d SCLK cycles \n", + 3, 3, 6, 2, 3); + printf("SDRAM Begin: 0x%x\n", CFG_SDRAM_BASE); + printf("Bank size = %d MB\n", CFG_MAX_RAM_SIZE >> 20); +#endif + gd->bd->bi_memstart = CFG_SDRAM_BASE; + gd->bd->bi_memsize = CFG_MAX_RAM_SIZE; + return CFG_MAX_RAM_SIZE; +} + +#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent initialisations */ +int misc_init_r(void) +{ + /* Keep PF12 low to be able to drive the USB-LAN Extender */ + *pFIO0_DIR = 0x0000; + *pFIO0_FLAG_C = 0x1000; /* Clear PF12 */ + sync(); + *pFIO0_POLAR = 0x0000; + sync(); + + return 0; +} +#endif diff --git a/board/bf561-ezkit/config.mk b/board/bf561-ezkit/config.mk new file mode 100644 index 0000000..a623c3d --- /dev/null +++ b/board/bf561-ezkit/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2001 +# 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 +# +# TEXT_BASE should be defined as the MAX_SDRAM Address - 256k bytes +# 256k is defined as CFG_MONITOR_LEN in ./include/configs/<board>.h +TEXT_BASE = 0x03FC0000 diff --git a/board/bf561-ezkit/u-boot.lds.S b/board/bf561-ezkit/u-boot.lds.S new file mode 100644 index 0000000..84df5fc --- /dev/null +++ b/board/bf561-ezkit/u-boot.lds.S @@ -0,0 +1,153 @@ +/* + * U-boot - u-boot.lds.S + * + * Copyright (c) 2005-2007 Analog Device Inc. + * + * (C) Copyright 2000-2004 + * 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 <config.h> + +OUTPUT_ARCH(bfin) +OUTPUT_ARCH(bfin) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/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) } + . = CFG_MONITOR_BASE; + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector before the environment sector. If it throws */ + /* an error during compilation remove an object here to get */ + /* it linked after the configuration sector. */ + + cpu/bf561/start.o (.text) + cpu/bf561/start1.o (.text) + cpu/bf561/traps.o (.text) + cpu/bf561/interrupt.o (.text) + cpu/bf561/serial.o (.text) + common/dlmalloc.o (.text) +/* lib_blackfin/bf533_string.o (.text) */ +/* lib_generic/vsprintf.o (.text) */ + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + board/bf561-ezkit/bf561-ezkit.o (.text) + + . = DEFINED(env_offset) ? 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/board/cray/L1/L1.c b/board/cray/L1/L1.c index a7114eb..a0fac7f 100644 --- a/board/cray/L1/L1.c +++ b/board/cray/L1/L1.c @@ -23,7 +23,7 @@ #include <common.h> #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h> #include <command.h> #include <rtc.h> #include <post.h> diff --git a/board/dave/PPChameleonEVB/nand.c b/board/dave/PPChameleonEVB/nand.c index 40a827c..f5c3dd9 100644 --- a/board/dave/PPChameleonEVB/nand.c +++ b/board/dave/PPChameleonEVB/nand.c @@ -105,7 +105,7 @@ static int ppchameleonevb_device_ready(struct mtd_info *mtdinfo) * Members with a "?" were not set in the merged testing-NAND branch, * so they are not set here either. */ -void board_nand_init(struct nand_chip *nand) +int board_nand_init(struct nand_chip *nand) { nand->hwcontrol = ppchameleonevb_hwcontrol; @@ -113,5 +113,6 @@ void board_nand_init(struct nand_chip *nand) nand->eccmode = NAND_ECC_SOFT; nand->chip_delay = NAND_BIG_DELAY_US; nand->options = NAND_SAMSUNG_LP_OPTIONS; + return 0; } #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ diff --git a/board/delta/nand.c b/board/delta/nand.c index fe648fc..d170938 100644 --- a/board/delta/nand.c +++ b/board/delta/nand.c @@ -448,7 +448,7 @@ static void dfc_gpio_init(void) * Members with a "?" were not set in the merged testing-NAND branch, * so they are not set here either. */ -void board_nand_init(struct nand_chip *nand) +int board_nand_init(struct nand_chip *nand) { unsigned long tCH, tCS, tWH, tWP, tRH, tRP, tRP_high, tR, tWHR, tAR; @@ -576,6 +576,7 @@ void board_nand_init(struct nand_chip *nand) nand->cmdfunc = dfc_cmdfunc; nand->autooob = &delta_oob; nand->badblock_pattern = &delta_bbt_descr; + return 0; } #else diff --git a/board/emk/top5200/top5200.c b/board/emk/top5200/top5200.c index 12acc57..d741e6b 100644 --- a/board/emk/top5200/top5200.c +++ b/board/emk/top5200/top5200.c @@ -190,7 +190,7 @@ void init_ide_reset (void) { debug ("init_ide_reset\n"); - /* Configure PSC1_4 as GPIO output for ATA reset */ + /* Configure PSC1_4 as GPIO output for ATA reset */ *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4; *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC1_4; } diff --git a/board/esd/common/auto_update.c b/board/esd/common/auto_update.c index 5cd3423..001fd68 100644 --- a/board/esd/common/auto_update.c +++ b/board/esd/common/auto_update.c @@ -33,6 +33,7 @@ #include <asm/byteorder.h> #include <linux/mtd/nand_legacy.h> #include <fat.h> +#include <part.h> #include "auto_update.h" @@ -71,8 +72,6 @@ extern int transfer_pic(unsigned char, unsigned char *, int, int); extern int flash_sect_erase(ulong, ulong); extern int flash_sect_protect (int, ulong, ulong); extern int flash_write (char *, ulong, ulong); -/* change char* to void* to shutup the compiler */ -extern block_dev_desc_t *get_dev (char*, int); #if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY) /* references to names in cmd_nand.c */ diff --git a/board/esd/cpci5200/cpci5200.c b/board/esd/cpci5200/cpci5200.c index f14331b..a925b84 100644 --- a/board/esd/cpci5200/cpci5200.c +++ b/board/esd/cpci5200/cpci5200.c @@ -191,8 +191,7 @@ static struct pci_controller hose; extern void pci_mpc5xxx_init(struct pci_controller *); -void pci_init_board(void - ) { +void pci_init_board(void) { pci_mpc5xxx_init(&hose); } #endif diff --git a/board/esd/cpci750/cpci750.c b/board/esd/cpci750/cpci750.c index dbed597..17e3568 100644 --- a/board/esd/cpci750/cpci750.c +++ b/board/esd/cpci750/cpci750.c @@ -29,6 +29,7 @@ */ #include <common.h> +#include <command.h> #include <74xx_7xx.h> #include "../../Marvell/include/memory.h" #include "../../Marvell/include/pci.h" @@ -365,12 +366,12 @@ int misc_init_r () dcache_lock (); #endif if (flash_info[3].size < CFG_FLASH_INCREMENT) { - unsigned int flash_offset; + unsigned int flash_offset; unsigned int l; flash_offset = CFG_FLASH_INCREMENT - flash_info[3].size; for (l = 0; l < CFG_MAX_FLASH_SECT; l++) { - if (flash_info[3].start[l] != 0) { + if (flash_info[3].start[l] != 0) { flash_info[3].start[l] += flash_offset; } } @@ -502,7 +503,7 @@ static void move64 (unsigned long long *src, unsigned long long *dest) { asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ "stfd 0, 0(4)" /* *dest = fpr0 */ - : : : "fr0"); /* Clobbers fr0 */ + : : : "fr0"); /* Clobbers fr0 */ return; } @@ -580,9 +581,9 @@ int mem_test_data (void) move64 (&(pattern[i]), pmem); move64 (pmem, &temp64); - /* hi = (temp64>>32) & 0xffffffff; */ - /* lo = temp64 & 0xffffffff; */ - /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ + /* hi = (temp64>>32) & 0xffffffff; */ + /* lo = temp64 & 0xffffffff; */ + /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ hi = (pattern[i] >> 32) & 0xffffffff; lo = pattern[i] & 0xffffffff; @@ -855,11 +856,11 @@ int testdram (void) } #endif /* CFG_DRAM_TEST */ -/* ronen - the below functions are used by the bootm function */ +/* ronen - the below functions are used by the bootm function */ /* - we map the base register to fbe00000 (same mapping as in the LSP) */ /* - we turn off the RX gig dmas - to prevent the dma from overunning */ -/* the kernel data areas. */ -/* - we diable and invalidate the icache and dcache. */ +/* the kernel data areas. */ +/* - we diable and invalidate the icache and dcache. */ void my_remap_gt_regs_bootm (u32 cur_loc, u32 new_loc) { u32 temp; @@ -899,3 +900,22 @@ void board_prebootm_init () flush_data_cache (); dcache_disable (); } + + +int do_show_cfg(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + unsigned int reset_sample_low; + unsigned int reset_sample_high; + + GT_REG_READ(0x3c4, &reset_sample_low); + GT_REG_READ(0x3d4, &reset_sample_high); + printf("Reset configuration 0x%08x 0x%08x\n", reset_sample_low, reset_sample_high); + + return(0); +} + +U_BOOT_CMD( + show_cfg, 1, 1, do_show_cfg, + "show_cfg- Show Marvell strapping register\n", + "Show Marvell strapping register (ResetSampleLow ResetSampleHigh)\n" + ); diff --git a/board/esd/cpci750/sdram_init.c b/board/esd/cpci750/sdram_init.c index 6bdfc1d..c094755 100644 --- a/board/esd/cpci750/sdram_init.c +++ b/board/esd/cpci750/sdram_init.c @@ -1504,6 +1504,8 @@ int setup_sdram (AUX_MEM_DIMM_INFO * info) /* for (i = info->slot * 2; i < ((info->slot * 2) + info->banks); i++) */ { + int l, l1; + i = info->slot; DP (printf ("\n*** Running a MRS cycle for bank %d ***\n", i)); @@ -1511,20 +1513,39 @@ int setup_sdram (AUX_MEM_DIMM_INFO * info) /* map the bank */ memory_map_bank (i, 0, GB / 4); #if 1 /* test only */ - /* set SDRAM mode */ /* To_do check it */ + + tmp = GTREGREAD (SDRAM_MODE); + GT_REG_WRITE (EXTENDED_DRAM_MODE, 0x0); + GT_REG_WRITE (SDRAM_OPERATION, 0x4); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418 after SDRAM_MODE: Module still busy ... please wait... ***\n")); + } + + GT_REG_WRITE (SDRAM_MODE, tmp | 0x80); GT_REG_WRITE (SDRAM_OPERATION, 0x3); - check = GTREGREAD (SDRAM_OPERATION); - DP (printf - ("\n*** SDRAM_OPERATION 1418 (0 = Normal Operation) = %08lx ***\n", - check)); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418 after SDRAM_MODE: Module still busy ... please wait... ***\n")); + } + l1 = 0; + for (l=0;l<200;l++) + l1 += GTREGREAD (SDRAM_OPERATION); + GT_REG_WRITE (SDRAM_MODE, tmp); + GT_REG_WRITE (SDRAM_OPERATION, 0x3); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418 after SDRAM_MODE: Module still busy ... please wait... ***\n")); + } /* switch back to normal operation mode */ - GT_REG_WRITE (SDRAM_OPERATION, 0); - check = GTREGREAD (SDRAM_OPERATION); - DP (printf - ("\n*** SDRAM_OPERATION 1418 (0 = Normal Operation) = %08lx ***\n", - check)); + GT_REG_WRITE (SDRAM_OPERATION, 0x5); + while (GTREGREAD (SDRAM_OPERATION) != 0) { + DP (printf + ("\n*** SDRAM_OPERATION 1418 after SDRAM_MODE: Module still busy ... please wait... ***\n")); + } + #endif /* test only */ /* unmap the bank */ memory_map_bank (i, 0, 0); diff --git a/board/esd/du405/du405.c b/board/esd/du405/du405.c index a019ce4..6943213 100644 --- a/board/esd/du405/du405.c +++ b/board/esd/du405/du405.c @@ -25,7 +25,7 @@ #include "du405.h" #include <asm/processor.h> #include <ppc4xx.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h> #include <command.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/board/esd/mecp5200/Makefile b/board/esd/mecp5200/Makefile new file mode 100644 index 0000000..45efdb0 --- /dev/null +++ b/board/esd/mecp5200/Makefile @@ -0,0 +1,51 @@ + +# +# (C) Copyright 2003-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/esd/mecp5200/config.mk b/board/esd/mecp5200/config.mk new file mode 100644 index 0000000..07b5de1 --- /dev/null +++ b/board/esd/mecp5200/config.mk @@ -0,0 +1,44 @@ +# +# (C) Copyright 2003 +# 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 +# + +# +# IceCube board: +# +# Valid values for TEXT_BASE are: +# +# 0xFFF00000 boot high (standard configuration) +# 0xFF000000 boot low for 16 MiB boards +# 0xFF800000 boot low for 8 MiB boards +# 0x00100000 boot from RAM (for testing only) +# + +sinclude $(TOPDIR)/board/$(BOARDDIR)/config.tmp + +ifndef TEXT_BASE +## Standard: boot high +TEXT_BASE = 0xFFF00000 +## For testing: boot from RAM +# TEXT_BASE = 0x00100000 +endif + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/esd/mecp5200/mecp5200.c b/board/esd/mecp5200/mecp5200.c new file mode 100644 index 0000000..c4b91e9 --- /dev/null +++ b/board/esd/mecp5200/mecp5200.c @@ -0,0 +1,261 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2004 + * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.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 + */ + +/* + * pf5200.c - main board support/init for the esd pf5200. + */ + +#include <common.h> +#include <mpc5xxx.h> +#include <pci.h> +#include <command.h> + +#include "mt46v16m16-75.h" + +void init_power_switch(void); + +static void sdram_start(int hi_addr) +{ + long hi_addr_bit = hi_addr ? 0x01000000 : 0; + + /* unlock mode register */ + *(vu_long *) MPC5XXX_SDRAM_CTRL = + SDRAM_CONTROL | 0x80000000 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* precharge all banks */ + *(vu_long *) MPC5XXX_SDRAM_CTRL = + SDRAM_CONTROL | 0x80000002 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* set mode register: extended mode */ + *(vu_long *) MPC5XXX_SDRAM_MODE = SDRAM_EMODE; + __asm__ volatile ("sync"); + + /* set mode register: reset DLL */ + *(vu_long *) MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000; + __asm__ volatile ("sync"); + + /* precharge all banks */ + *(vu_long *) MPC5XXX_SDRAM_CTRL = + SDRAM_CONTROL | 0x80000002 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* auto refresh */ + *(vu_long *) MPC5XXX_SDRAM_CTRL = + SDRAM_CONTROL | 0x80000004 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* set mode register */ + *(vu_long *) MPC5XXX_SDRAM_MODE = SDRAM_MODE; + __asm__ volatile ("sync"); + + /* normal operation */ + *(vu_long *) MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit; + __asm__ volatile ("sync"); +} + +/* + * ATTENTION: Although partially referenced initdram does NOT make real use + * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE + * is something else than 0x00000000. + */ + +long int initdram(int board_type) +{ + ulong dramsize = 0; + ulong test1, test2; + + /* setup SDRAM chip selects */ + *(vu_long *) MPC5XXX_SDRAM_CS0CFG = 0x0000001e; /* 2G at 0x0 */ + *(vu_long *) MPC5XXX_SDRAM_CS1CFG = 0x80000000; /* disabled */ + __asm__ volatile ("sync"); + + /* setup config registers */ + *(vu_long *) MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1; + *(vu_long *) MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2; + __asm__ volatile ("sync"); + + /* set tap delay */ + *(vu_long *) MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY; + __asm__ volatile ("sync"); + + /* find RAM size using SDRAM CS0 only */ + sdram_start(0); + test1 = get_ram_size(CFG_SDRAM_BASE, 0x80000000); + sdram_start(1); + test2 = get_ram_size(CFG_SDRAM_BASE, 0x80000000); + + if (test1 > test2) { + sdram_start(0); + dramsize = test1; + } else { + dramsize = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize < (1 << 20)) + dramsize = 0; + + /* set SDRAM CS0 size according to the amount of RAM found */ + if (dramsize > 0) { + *(vu_long *) MPC5XXX_SDRAM_CS0CFG = + 0x13 + __builtin_ffs(dramsize >> 20) - 1; + /* let SDRAM CS1 start right after CS0 */ + *(vu_long *) MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001e; /* 2G */ + } else { +#if 0 + *(vu_long *) MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */ + /* let SDRAM CS1 start right after CS0 */ + *(vu_long *) MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001e; /* 2G */ +#else + *(vu_long *) MPC5XXX_SDRAM_CS0CFG = + 0x13 + __builtin_ffs(0x08000000 >> 20) - 1; + /* let SDRAM CS1 start right after CS0 */ + *(vu_long *) MPC5XXX_SDRAM_CS1CFG = 0x08000000 + 0x0000001e; /* 2G */ +#endif + } + +#if 0 + /* find RAM size using SDRAM CS1 only */ + sdram_start(0); + get_ram_size((ulong *) (CFG_SDRAM_BASE + dramsize), 0x80000000); + sdram_start(1); + get_ram_size((ulong *) (CFG_SDRAM_BASE + dramsize), 0x80000000); + sdram_start(0); +#endif + /* set SDRAM CS1 size according to the amount of RAM found */ + + *(vu_long *) MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */ + + init_power_switch(); + return (dramsize); +} + +int checkboard(void) +{ + puts("Board: esd CPX CPU5200 (mecp5200)\n"); + return 0; +} + +void flash_preinit(void) +{ + /* + * Now, when we are in RAM, enable flash write + * access for detection process. + * Note that CS_BOOT cannot be cleared when + * executing in flash. + */ + *(vu_long *) MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ +} + +void flash_afterinit(ulong size) +{ + if (size == CFG_FLASH_SIZE) { + /* adjust mapping */ + *(vu_long *) MPC5XXX_BOOTCS_START = + *(vu_long *) MPC5XXX_CS0_START = + START_REG(CFG_BOOTCS_START | size); + *(vu_long *) MPC5XXX_BOOTCS_STOP = + *(vu_long *) MPC5XXX_CS0_STOP = + STOP_REG(CFG_BOOTCS_START | size, size); + } +} + +#ifdef CONFIG_PCI +static struct pci_controller hose; + +extern void pci_mpc5xxx_init(struct pci_controller *); + +void pci_init_board(void) +{ + pci_mpc5xxx_init(&hose); +} +#endif + +#if defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) + +#define GPIO_PSC1_4 0x01000000UL + +void init_ide_reset(void) +{ + debug("init_ide_reset\n"); + + /* Configure PSC1_4 as GPIO output for ATA reset */ + *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4; + *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC1_4; +} + +void ide_set_reset(int idereset) +{ + debug("ide_reset(%d)\n", idereset); + + if (idereset) + *(vu_long *) MPC5XXX_WU_GPIO_DATA_O &= ~GPIO_PSC1_4; + else + *(vu_long *) MPC5XXX_WU_GPIO_DATA_O |= GPIO_PSC1_4; +} +#endif /* defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) */ + +#define MPC5XXX_SIMPLEIO_GPIO_ENABLE (MPC5XXX_GPIO + 0x0004) +#define MPC5XXX_SIMPLEIO_GPIO_DIR (MPC5XXX_GPIO + 0x000C) +#define MPC5XXX_SIMPLEIO_GPIO_DATA_OUTPUT (MPC5XXX_GPIO + 0x0010) +#define MPC5XXX_SIMPLEIO_GPIO_DATA_INPUT (MPC5XXX_GPIO + 0x0014) + +#define MPC5XXX_INTERRUPT_GPIO_ENABLE (MPC5XXX_GPIO + 0x0020) +#define MPC5XXX_INTERRUPT_GPIO_DIR (MPC5XXX_GPIO + 0x0028) +#define MPC5XXX_INTERRUPT_GPIO_DATA_OUTPUT (MPC5XXX_GPIO + 0x002C) +#define MPC5XXX_INTERRUPT_GPIO_STATUS (MPC5XXX_GPIO + 0x003C) + +#define GPIO_WU6 0x40000000UL +#define GPIO_USB0 0x00010000UL +#define GPIO_USB9 0x08000000UL +#define GPIO_USB9S 0x00080000UL + +void init_power_switch(void) +{ + debug("init_power_switch\n"); + + /* Configure GPIO_WU6 as GPIO output for ATA reset */ + *(vu_long *) MPC5XXX_WU_GPIO_DATA_O |= GPIO_WU6; + *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_WU6; + *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_WU6; + __asm__ volatile ("sync"); + + *(vu_long *) MPC5XXX_SIMPLEIO_GPIO_DATA_OUTPUT &= ~GPIO_USB0; + *(vu_long *) MPC5XXX_SIMPLEIO_GPIO_ENABLE |= GPIO_USB0; + *(vu_long *) MPC5XXX_SIMPLEIO_GPIO_DIR |= GPIO_USB0; + __asm__ volatile ("sync"); + + *(vu_long *) MPC5XXX_INTERRUPT_GPIO_DATA_OUTPUT &= ~GPIO_USB9; + *(vu_long *) MPC5XXX_INTERRUPT_GPIO_ENABLE &= ~GPIO_USB9; + __asm__ volatile ("sync"); + + if ((*(vu_long *) MPC5XXX_INTERRUPT_GPIO_STATUS & GPIO_USB9S) == 0) { + *(vu_long *) MPC5XXX_SIMPLEIO_GPIO_DATA_OUTPUT |= GPIO_USB0; + __asm__ volatile ("sync"); + } +} diff --git a/board/esd/mecp5200/mt46v16m16-75.h b/board/esd/mecp5200/mt46v16m16-75.h new file mode 100644 index 0000000..22d0a55 --- /dev/null +++ b/board/esd/mecp5200/mt46v16m16-75.h @@ -0,0 +1,37 @@ +/* + * (C) Copyright 2004 + * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.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 + */ + +#define SDRAM_DDR 1 /* is DDR */ + +#if defined(CONFIG_MPC5200) +/* Settings for XLB = 132 MHz */ +#define SDRAM_MODE 0x018D0000 +#define SDRAM_EMODE 0x40090000 +#define SDRAM_CONTROL 0x705f0f00 +#define SDRAM_CONFIG1 0x73722930 +#define SDRAM_CONFIG2 0x47770000 +#define SDRAM_TAPDELAY 0x10000000 + +#else +#error CONFIG_MPC5200 not defined +#endif diff --git a/board/esd/mecp5200/u-boot.lds b/board/esd/mecp5200/u-boot.lds new file mode 100644 index 0000000..d999dd1 --- /dev/null +++ b/board/esd/mecp5200/u-boot.lds @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2003 + * 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 : + { + cpu/mpc5xxx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/esd/pf5200/pf5200.c b/board/esd/pf5200/pf5200.c index 1f30d45..77e164b 100644 --- a/board/esd/pf5200/pf5200.c +++ b/board/esd/pf5200/pf5200.c @@ -191,8 +191,7 @@ static struct pci_controller hose; extern void pci_mpc5xxx_init(struct pci_controller *); -void pci_init_board(void - ) { +void pci_init_board(void) { pci_mpc5xxx_init(&hose); } #endif diff --git a/board/esd/plu405/plu405.c b/board/esd/plu405/plu405.c index 37b92fb..59171f8 100644 --- a/board/esd/plu405/plu405.c +++ b/board/esd/plu405/plu405.c @@ -215,12 +215,6 @@ int checkboard (void) } putc ('\n'); - - /* - * Disable sleep mode in LXT971 - */ - lxt971_no_sleep(); - return 0; } @@ -292,3 +286,14 @@ void board_auto_update_show(int au_active) } } #endif + +void reset_phy(void) +{ +#ifdef CONFIG_LXT971_NO_SLEEP + + /* + * Disable sleep mode in LXT971 + */ + lxt971_no_sleep(); +#endif +} diff --git a/board/hmi1001/hmi1001.c b/board/hmi1001/hmi1001.c index 237e863..9fa0e74 100644 --- a/board/hmi1001/hmi1001.c +++ b/board/hmi1001/hmi1001.c @@ -103,9 +103,9 @@ long int initdram (int board_type) /* find RAM size using SDRAM CS0 only */ sdram_start(0); - test1 = get_ram_size((ulong *)CFG_SDRAM_BASE, 0x20000000); + test1 = get_ram_size((long *)CFG_SDRAM_BASE, 0x20000000); sdram_start(1); - test2 = get_ram_size((ulong *)CFG_SDRAM_BASE, 0x20000000); + test2 = get_ram_size((long *)CFG_SDRAM_BASE, 0x20000000); if (test1 > test2) { sdram_start(0); dramsize = test1; @@ -179,7 +179,7 @@ struct kbd_data_t* get_keys (struct kbd_data_t *kbd_data) return kbd_data; } -static int compare_magic (const struct kbd_data_t *kbd_data, uchar *str) +static int compare_magic (const struct kbd_data_t *kbd_data, char *str) { char s1 = str[0]; char s2; @@ -222,11 +222,11 @@ static int compare_magic (const struct kbd_data_t *kbd_data, uchar *str) return 0; } -static uchar *key_match (const struct kbd_data_t *kbd_data) +static char *key_match (const struct kbd_data_t *kbd_data) { - uchar magic[sizeof (kbd_magic_prefix) + 1]; - uchar *suffix; - uchar *kbd_magic_keys; + char magic[sizeof (kbd_magic_prefix) + 1]; + char *suffix; + char *kbd_magic_keys; /* * The following string defines the characters that can be appended @@ -247,7 +247,7 @@ static uchar *key_match (const struct kbd_data_t *kbd_data) sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); if (compare_magic(kbd_data, getenv(magic)) == 0) { - uchar cmd_name[sizeof (kbd_command_prefix) + 1]; + char cmd_name[sizeof (kbd_command_prefix) + 1]; char *cmd; sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); @@ -267,7 +267,7 @@ int misc_init_r (void) #ifdef CONFIG_PREBOOT struct kbd_data_t kbd_data; /* Decode keys */ - uchar *str = strdup (key_match (get_keys (&kbd_data))); + char *str = strdup (key_match (get_keys (&kbd_data))); /* Set or delete definition */ setenv ("preboot", str); free (str); diff --git a/board/icecube/icecube.c b/board/icecube/icecube.c index f958b32..700c9d9 100644 --- a/board/icecube/icecube.c +++ b/board/icecube/icecube.c @@ -29,6 +29,10 @@ #include <pci.h> #include <asm/processor.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + #if defined(CONFIG_LITE5200B) #include "mt46v32m16.h" #else @@ -312,7 +316,7 @@ void init_ide_reset (void) { debug ("init_ide_reset\n"); - /* Configure PSC1_4 as GPIO output for ATA reset */ + /* Configure PSC1_4 as GPIO output for ATA reset */ *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4; *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC1_4; /* Deassert reset */ @@ -332,3 +336,11 @@ void ide_set_reset (int idereset) } } #endif /* defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) */ + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + ft_cpu_setup(blob, bd); +} +#endif diff --git a/board/ezkit533/Makefile b/board/idmr/Makefile index 4f3c223..cf07cf4 100644 --- a/board/ezkit533/Makefile +++ b/board/idmr/Makefile @@ -1,8 +1,4 @@ # -# U-boot - Makefile -# -# Copyright (c) 2005 blackfin.uclinux.org -# # (C) Copyright 2000-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # @@ -29,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o flash.o ezkit533.o +COBJS = $(BOARD).o flash.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/idmr/config.mk b/board/idmr/config.mk new file mode 100644 index 0000000..f7c2258 --- /dev/null +++ b/board/idmr/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.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 +# + +TEXT_BASE = 0xff800000 diff --git a/board/idmr/flash.c b/board/idmr/flash.c new file mode 100644 index 0000000..33512b8 --- /dev/null +++ b/board/idmr/flash.c @@ -0,0 +1,356 @@ +/* + * (C) Copyright 2000-2006 + * 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 <common.h> + +#define PHYS_FLASH_1 CFG_FLASH_BASE +#define FLASH_BANK_SIZE 0x800000 +#define EN29LV640 0x227e227e + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +void flash_print_info (flash_info_t * info) +{ + int i; + + switch (info->flash_id & FLASH_VENDMASK) { + case (AMD_MANUFACT & FLASH_VENDMASK): + printf ("AMD: "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case (EN29LV640 & FLASH_TYPEMASK): + printf ("EN29LV640 (16Mbit)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + goto Done; + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; i++) { + if ((i % 5) == 0) { + printf ("\n "); + } + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + + Done: + return; +} + + +unsigned long flash_init (void) +{ + int i, j; + ulong size = 0; + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + ulong flashbase = 0; + + flash_info[i].flash_id = + (AMD_MANUFACT & FLASH_VENDMASK) | + (EN29LV640 & FLASH_TYPEMASK); + flash_info[i].size = FLASH_BANK_SIZE; + flash_info[i].sector_count = CFG_MAX_FLASH_SECT; + memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); + if (i == 0) + flashbase = PHYS_FLASH_1; + else + panic ("configured to many flash banks!\n"); + + for (j = 0; j < flash_info[i].sector_count; j++) { + flash_info[i].start[j] = flashbase + 0x10000 * j; + } + size += flash_info[i].size; + } + + flash_protect (FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE + 0x2ffff, &flash_info[0]); + + return size; +} + + +#define CMD_READ_ARRAY 0x00F0 +#define CMD_UNLOCK1 0x00AA +#define CMD_UNLOCK2 0x0055 +#define CMD_ERASE_SETUP 0x0080 +#define CMD_ERASE_CONFIRM 0x0030 +#define CMD_PROGRAM 0x00A0 +#define CMD_UNLOCK_BYPASS 0x0020 + +#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555<<1))) +#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA<<1))) + +#define BIT_ERASE_DONE 0x0080 +#define BIT_RDY_MASK 0x0080 +#define BIT_PROGRAM_ERROR 0x0020 +#define BIT_TIMEOUT 0x80000000 /* our flag */ + +#define READY 1 +#define ERR 2 +#define TMO 4 + + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + ulong result; + int iflag, prot, sect; + int rc = ERR_OK; + int chip1; + + /* first look for protection bits */ + + if (info->flash_id == FLASH_UNKNOWN) + return ERR_UNKNOWN_FLASH_TYPE; + + if ((s_first < 0) || (s_first > s_last)) { + return ERR_INVAL; + } + + if ((info->flash_id & FLASH_VENDMASK) != + (AMD_MANUFACT & FLASH_VENDMASK)) { + return ERR_UNKNOWN_FLASH_VENDOR; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) + return ERR_PROTECTED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + iflag = disable_interrupts (); + + printf ("\n"); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { + printf ("Erasing sector %2d ... ", sect); + + /* arm simple, non interrupt dependent timer */ + set_timer (0); + + if (info->protect[sect] == 0) { /* not protected */ + volatile u16 *addr = + (volatile u16 *) (info->start[sect]); + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + *addr = CMD_ERASE_CONFIRM; + + /* wait until flash is ready */ + chip1 = 0; + + do { + result = *addr; + + /* check timeout */ + if (get_timer (0) > CFG_FLASH_ERASE_TOUT * CFG_HZ / 1000) { + MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + chip1 = TMO; + break; + } + + if (!chip1 + && (result & 0xFFFF) & BIT_ERASE_DONE) + chip1 = READY; + + } while (!chip1); + + MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + + if (chip1 == ERR) { + rc = ERR_PROG_ERROR; + goto outahere; + } + if (chip1 == TMO) { + rc = ERR_TIMOUT; + goto outahere; + } + + printf ("ok.\n"); + } else { /* it was protected */ + + printf ("protected!\n"); + } + } + + if (ctrlc ()) + printf ("User Interrupt!\n"); + + outahere: + /* allow flash to settle - wait 10 ms */ + printf("Waiting 10 ms..."); + udelay (10000); + +/* for (i = 0; i < 10 * 1000 * 1000; ++i) + asm(" nop"); +*/ + + printf("done\n"); + if (iflag) + enable_interrupts (); + + + return rc; +} + +static int write_word (flash_info_t * info, ulong dest, ulong data) +{ + volatile u16 *addr = (volatile u16 *) dest; + ulong result; + int rc = ERR_OK; + int iflag; + int chip1; + + /* + * Check if Flash is (sufficiently) erased + */ + result = *addr; + if ((result & data) != data) + return ERR_NOT_ERASED; + + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + iflag = disable_interrupts (); + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + MEM_FLASH_ADDR1 = CMD_PROGRAM; + *addr = data; + + /* arm simple, non interrupt dependent timer */ + set_timer (0); + + /* wait until flash is ready */ + chip1 = 0; + do { + result = *addr; + + /* check timeout */ + if (get_timer (0) > CFG_FLASH_ERASE_TOUT * CFG_HZ / 1000) { + chip1 = ERR | TMO; + break; + } + if (!chip1 && ((result & 0x80) == (data & 0x80))) + chip1 = READY; + + } while (!chip1); + + *addr = CMD_READ_ARRAY; + + if (chip1 == ERR || *addr != data) + rc = ERR_PROG_ERROR; + + if (iflag) + enable_interrupts (); + + return rc; +} + + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong wp, data; + int rc; + + if (addr & 1) { + printf ("unaligned destination not supported\n"); + return ERR_ALIGN; + } + +#if 0 + if (cnt & 1) { + printf ("odd transfer sizes not supported\n"); + return ERR_ALIGN; + } +#endif + + wp = addr; + + if (addr & 1) { + data = (*((volatile u8 *) addr) << 8) | *((volatile u8 *) + src); + if ((rc = write_word (info, wp - 1, data)) != 0) { + return (rc); + } + src += 1; + wp += 1; + cnt -= 1; + } + + while (cnt >= 2) { + data = *((volatile u16 *) src); + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + src += 2; + wp += 2; + cnt -= 2; + } + + if (cnt == 1) { + data = (*((volatile u8 *) src) << 8) | + *((volatile u8 *) (wp + 1)); + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + src += 1; + wp += 1; + cnt -= 1; + } + + return ERR_OK; +} diff --git a/board/idmr/idmr.c b/board/idmr/idmr.c new file mode 100644 index 0000000..58cdba1 --- /dev/null +++ b/board/idmr/idmr.c @@ -0,0 +1,169 @@ +/* + * (C) Copyright 2000-2006 + * 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 <common.h> +#include <asm/m5271.h> +#include <asm/immap_5271.h> + +int checkboard (void) { + puts ("Board: iDMR\n"); + return 0; +}; + +long int initdram (int board_type) { + int i; + + /* + * After reset, CS0 is configured to cover entire address space. We + * need to configure it to its proper values, so that writes to + * CFG_SDRAM_BASE and vicinity during SDRAM controller setup below do + * now fall under CS0 (see 16.3.1 of the MCF5271 Reference Manual). + */ + + /* Flash chipselect, CS0 */ + /* ;CSAR0: Flash at 0xFF800000 */ + mbar_writeShort(0x0080, 0xFF80); + + /* CSCR0: Flash 6 waits, 16bit */ + mbar_writeShort(0x008A, 0x1980); + + /* CSMR0: Flash 8MB, R/W, valid */ + mbar_writeLong(0x0084, 0x007F0001); + + + /* + * SDRAM configuration proper + */ + + /* + * Address/Data Pin Assignment Reg.: enable address lines 23-21; do + * not enable data pins D[15:0], as we have 16 bit port to SDRAM + */ + mbar_writeByte(MCF_GPIO_PAR_AD, + MCF_GPIO_AD_ADDR23 | + MCF_GPIO_AD_ADDR22 | + MCF_GPIO_AD_ADDR21); + + /* No need to configure BS pins - reset values are OK */ + + /* Chip Select Pin Assignment Reg.: set CS[1-7] to GPIO */ + mbar_writeByte(MCF_GPIO_PAR_CS, 0x00); + + /* SDRAM Control Pin Assignment Reg. */ + mbar_writeByte(MCF_GPIO_PAR_SDRAM, + MCF_GPIO_SDRAM_CSSDCS_00 | /* no matter: PAR_CS=0 */ + MCF_GPIO_SDRAM_SDWE | + MCF_GPIO_SDRAM_SCAS | + MCF_GPIO_SDRAM_SRAS | + MCF_GPIO_SDRAM_SCKE | + MCF_GPIO_SDRAM_SDCS_01); + + /* + * Wait 100us. We run the bus at 50Mhz, one cycle is 20ns. So 5 + * iterations will do, but we do 10 just to be safe. + */ + for (i = 0; i < 10; ++i) + asm(" nop"); + + + /* 1. Initialize DRAM Control Register: DCR */ + mbar_writeShort(MCF_SDRAMC_DCR, + MCF_SDRAMC_DCR_RTIM(0x10) | /* 65ns */ + MCF_SDRAMC_DCR_RC(0x60)); /* 1562 cycles */ + + + /* + * 2. Initialize DACR0 + * + * CL: 11 (CL=3: 0x03, 0x02; CL=2: 0x1) + * CBM: cmd at A20, bank select bits 21 and up + * PS: 16 bit + */ + mbar_writeLong(MCF_SDRAMC_DACR0, + MCF_SDRAMC_DACRn_BA(CFG_SDRAM_BASE>>18) | + MCF_SDRAMC_DACRn_BA(0x00) | + MCF_SDRAMC_DACRn_CASL(0x03) | + MCF_SDRAMC_DACRn_CBM(0x03) | + MCF_SDRAMC_DACRn_PS(0x03)); + + /* Initialize DMR0 */ + mbar_writeLong(MCF_SDRAMC_DMR0, + MCF_SDRAMC_DMRn_BAM_16M | + MCF_SDRAMC_DMRn_V); + + + /* 3. Set IP bit in DACR to initiate PALL command */ + mbar_writeLong(MCF_SDRAMC_DACR0, + mbar_readLong(MCF_SDRAMC_DACR0) | + MCF_SDRAMC_DACRn_IP); + + /* Write to this block to initiate precharge */ + *(volatile u16 *)(CFG_SDRAM_BASE) = 0xa5a5; + + /* + * Wait at least 20ns to allow banks to precharge (t_RP = 20ns). We + * wait a wee longer, just to be safe. + */ + for (i = 0; i < 5; ++i) + asm(" nop"); + + + /* 4. Set RE bit in DACR */ + mbar_writeLong(MCF_SDRAMC_DACR0, + mbar_readLong(MCF_SDRAMC_DACR0) | + MCF_SDRAMC_DACRn_RE); + + /* + * Wait for at least 8 auto refresh cycles to occur, i.e. at least + * 781 bus cycles. + */ + for (i = 0; i < 1000; ++i) + asm(" nop"); + + /* Finish the configuration by issuing the MRS */ + mbar_writeLong(MCF_SDRAMC_DACR0, + mbar_readLong(MCF_SDRAMC_DACR0) | + MCF_SDRAMC_DACRn_MRS); + + /* + * Write to the SDRAM Mode Register A0-A11 = 0x400 + * + * Write Burst Mode = Programmed Burst Length + * Op Mode = Standard Op + * CAS Latency = 3 + * Burst Type = Sequential + * Burst Length = 1 + */ + *(volatile u32 *)(CFG_SDRAM_BASE + 0x1800) = 0xa5a5a5a5; + + return CFG_SDRAM_SIZE * 1024 * 1024; +}; + + +int testdram (void) { + + /* TODO: XXX XXX XXX */ + printf ("DRAM test not implemented!\n"); + + return (0); +} diff --git a/board/idmr/u-boot.lds b/board/idmr/u-boot.lds new file mode 100644 index 0000000..69f3179 --- /dev/null +++ b/board/idmr/u-boot.lds @@ -0,0 +1,145 @@ +/* + * (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(m68k) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +GROUP(libgcc.a) +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/mcf52x2/start.o (.text) + lib_m68k/traps.o (.text) + cpu/mcf52x2/interrupts.o (.text) + common/dlmalloc.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.ppcenv) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + + .reloc : + { + __got_start = .; + *(.got) + __got_end = .; + _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 = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/jupiter/Makefile b/board/jupiter/Makefile new file mode 100644 index 0000000..aed3af0 --- /dev/null +++ b/board/jupiter/Makefile @@ -0,0 +1,51 @@ + +# +# (C) Copyright 2003-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/jupiter/config.mk b/board/jupiter/config.mk new file mode 100644 index 0000000..5f4da96 --- /dev/null +++ b/board/jupiter/config.mk @@ -0,0 +1,41 @@ +# +# (C) Copyright 2007 +# Heiko Schocher, DENX Software Engineering, hs@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 +# + +# +# Jupiter board: +# +# Valid values for TEXT_BASE are: +# +# 0xFFF00000 boot high (standard configuration) +# 0x00100000 boot from RAM (for testing only) +# + +ifndef TEXT_BASE +## Standard: boot high +TEXT_BASE = 0xFFF00000 +## For testing: boot from RAM +# TEXT_BASE = 0x00100000 +endif + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board +#PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -DDEBUG -I$(TOPDIR)/board diff --git a/board/jupiter/jupiter.c b/board/jupiter/jupiter.c new file mode 100644 index 0000000..04fda4a --- /dev/null +++ b/board/jupiter/jupiter.c @@ -0,0 +1,317 @@ +/* + * (C) Copyright 2007 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * (C) Copyright 2004 + * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.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 <common.h> +#include <mpc5xxx.h> +#include <pci.h> +#include <asm/processor.h> + +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + + +#define SDRAM_DDR 0 +#if 1 +/* Settings Icecube */ +#define SDRAM_MODE 0x00CD0000 +#define SDRAM_CONTROL 0x504F0000 +#define SDRAM_CONFIG1 0xD2322800 +#define SDRAM_CONFIG2 0x8AD70000 +#else +/*Settings Jupiter UB 1.0.0 */ +#define SDRAM_MODE 0x008D0000 +#define SDRAM_CONTROL 0xD04F0000 +#define SDRAM_CONFIG1 0xf7277f00 +#define SDRAM_CONFIG2 0x88b70004 +#endif + +#ifndef CFG_RAMBOOT +static void sdram_start (int hi_addr) +{ + long hi_addr_bit = hi_addr ? 0x01000000 : 0; + + /* unlock mode register */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit; + __asm__ volatile ("sync"); + +#if SDRAM_DDR + /* set mode register: extended mode */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_EMODE; + __asm__ volatile ("sync"); + + /* set mode register: reset DLL */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000; + __asm__ volatile ("sync"); +#endif + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* auto refresh */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* set mode register */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE; + __asm__ volatile ("sync"); + + /* normal operation */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit; + __asm__ volatile ("sync"); +} +#endif + +/* + * ATTENTION: Although partially referenced initdram does NOT make real use + * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE + * is something else than 0x00000000. + */ + +long int initdram (int board_type) +{ + ulong dramsize = 0; + ulong dramsize2 = 0; + uint svr, pvr; + +#ifndef CFG_RAMBOOT + ulong test1, test2; + + /* setup SDRAM chip selects */ + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001e;/* 2G at 0x0 */ + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x80000000;/* disabled */ + __asm__ volatile ("sync"); + + /* setup config registers */ + *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1; + *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2; + __asm__ volatile ("sync"); + +#if SDRAM_DDR + /* set tap delay */ + *(vu_long *)MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY; + __asm__ volatile ("sync"); +#endif + + /* find RAM size using SDRAM CS0 only */ + sdram_start(0); + test1 = get_ram_size((long *)CFG_SDRAM_BASE, 0x80000000); + sdram_start(1); + test2 = get_ram_size((long *)CFG_SDRAM_BASE, 0x80000000); + if (test1 > test2) { + sdram_start(0); + dramsize = test1; + } else { + dramsize = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize < (1 << 20)) { + dramsize = 0; + } + + /* set SDRAM CS0 size according to the amount of RAM found */ + if (dramsize > 0) { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + __builtin_ffs(dramsize >> 20) - 1; + } else { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */ + } + + /* let SDRAM CS1 start right after CS0 */ + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001e;/* 2G */ + + /* find RAM size using SDRAM CS1 only */ + if (!dramsize) + sdram_start(0); + test2 = test1 = get_ram_size((long *)(CFG_SDRAM_BASE + dramsize), 0x80000000); + if (!dramsize) { + sdram_start(1); + test2 = get_ram_size((long *)(CFG_SDRAM_BASE + dramsize), 0x80000000); + } + if (test1 > test2) { + sdram_start(0); + dramsize2 = test1; + } else { + dramsize2 = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize2 < (1 << 20)) { + dramsize2 = 0; + } + + /* set SDRAM CS1 size according to the amount of RAM found */ + if (dramsize2 > 0) { + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + | (0x13 + __builtin_ffs(dramsize2 >> 20) - 1); + } else { + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */ + } + +#else /* CFG_RAMBOOT */ + + /* retrieve size of memory connected to SDRAM CS0 */ + dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF; + if (dramsize >= 0x13) { + dramsize = (1 << (dramsize - 0x13)) << 20; + } else { + dramsize = 0; + } + + /* retrieve size of memory connected to SDRAM CS1 */ + dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF; + if (dramsize2 >= 0x13) { + dramsize2 = (1 << (dramsize2 - 0x13)) << 20; + } else { + dramsize2 = 0; + } + +#endif /* CFG_RAMBOOT */ + + /* + * On MPC5200B we need to set the special configuration delay in the + * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM + * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190: + * + * "The SDelay should be written to a value of 0x00000004. It is + * required to account for changes caused by normal wafer processing + * parameters." + */ + svr = get_svr(); + pvr = get_pvr(); + if ((SVR_MJREV(svr) >= 2) && + (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) { + + *(vu_long *)MPC5XXX_SDRAM_SDELAY = 0x04; + __asm__ volatile ("sync"); + } + + return dramsize + dramsize2; +} + +int checkboard (void) +{ + puts ("Board: Sauter (Jupiter)\n"); + return 0; +} + +void flash_preinit(void) +{ + /* + * Now, when we are in RAM, enable flash write + * access for detection process. + * Note that CS_BOOT cannot be cleared when + * executing in flash. + */ +#if defined(CONFIG_MGT5100) + *(vu_long *)MPC5XXX_ADDECR &= ~(1 << 25); /* disable CS_BOOT */ + *(vu_long *)MPC5XXX_ADDECR |= (1 << 16); /* enable CS0 */ +#endif + *(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ +} + +int board_early_init_r (void) +{ + flash_preinit (); + return 0; +} + +void flash_afterinit(ulong size) +{ + if (size == 0x1000000) { /* adjust mapping */ + *(vu_long *)MPC5XXX_BOOTCS_START = *(vu_long *)MPC5XXX_CS0_START = + START_REG(CFG_BOOTCS_START | size); + *(vu_long *)MPC5XXX_BOOTCS_STOP = *(vu_long *)MPC5XXX_CS0_STOP = + STOP_REG(CFG_BOOTCS_START | size, size); + } +#if defined(CONFIG_MPC5200) + *(vu_long *)MPC5XXX_ADDECR &= ~(1 << 25); /* disable CS_BOOT */ + *(vu_long *)MPC5XXX_ADDECR |= (1 << 16); /* enable CS0 */ +#endif +} + +int update_flash_size (int flash_size) +{ + flash_afterinit (flash_size); + return 0; +} + +int board_early_init_f (void) +{ + *(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ + return 0; +} + +#ifdef CONFIG_PCI +static struct pci_controller hose; + +extern void pci_mpc5xxx_init(struct pci_controller *); + +void pci_init_board(void) +{ + pci_mpc5xxx_init(&hose); +} +#endif + +#if defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) + +void init_ide_reset (void) +{ + debug ("init_ide_reset\n"); + + /* Configure PSC1_4 as GPIO output for ATA reset */ + *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4; + *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC1_4; + /* Deassert reset */ + *(vu_long *) MPC5XXX_WU_GPIO_DATA_O |= GPIO_PSC1_4; +} + +void ide_set_reset (int idereset) +{ + debug ("ide_reset(%d)\n", idereset); + + if (idereset) { + *(vu_long *) MPC5XXX_WU_GPIO_DATA_O &= ~GPIO_PSC1_4; + /* Make a delay. MPC5200 spec says 25 usec min */ + udelay(500000); + } else { + *(vu_long *) MPC5XXX_WU_GPIO_DATA_O |= GPIO_PSC1_4; + } +} +#endif /* defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) */ + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + ft_cpu_setup(blob, bd); +} +#endif diff --git a/board/jupiter/u-boot.lds b/board/jupiter/u-boot.lds new file mode 100644 index 0000000..f23432e --- /dev/null +++ b/board/jupiter/u-boot.lds @@ -0,0 +1,125 @@ +/* + * (C) Copyright 2003 + * 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 : + { + cpu/mpc5xxx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/lpc2292sodimm/Makefile b/board/lpc2292sodimm/Makefile new file mode 100644 index 0000000..5a30198 --- /dev/null +++ b/board/lpc2292sodimm/Makefile @@ -0,0 +1,58 @@ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.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 := lpc2292sodimm.o flash.o mmc.o spi.o mmc_hw.o eth.o +SOBJS := lowlevel_init.o iap_entry.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +# this MUST be compiled as thumb code! +iap_entry.o: + arm-linux-gcc -D__ASSEMBLY__ -g -Os -fno-strict-aliasing \ + -fno-common -ffixed-r8 -msoft-float -D__KERNEL__ \ + -DTEXT_BASE=0x81500000 -I/home/garyj/proj/LPC/u-boot/include \ + -fno-builtin -ffreestanding -nostdinc -isystem \ + /opt/eldk/arm/usr/bin/../lib/gcc/arm-linux/4.0.0/include -pipe \ + -DCONFIG_ARM -D__ARM__ -march=armv4t -mtune=arm7tdmi -mabi=apcs-gnu \ + -c -o iap_entry.o iap_entry.S + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/lpc2292sodimm/config.mk b/board/lpc2292sodimm/config.mk new file mode 100644 index 0000000..b28f418 --- /dev/null +++ b/board/lpc2292sodimm/config.mk @@ -0,0 +1,30 @@ +# +# (C) Copyright 2000 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# (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 +# + +#address where u-boot will be relocated +#TEXT_BASE = 0x0 +TEXT_BASE = 0x81500000 diff --git a/board/lpc2292sodimm/eth.c b/board/lpc2292sodimm/eth.c new file mode 100644 index 0000000..249ab04 --- /dev/null +++ b/board/lpc2292sodimm/eth.c @@ -0,0 +1,885 @@ +/* + * 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 <config.h> +#include <common.h> +#include <net.h> +#include <asm/arch/hardware.h> +#include "spi.h" + +/* + * Control Registers in Bank 0 + */ + +#define CTL_REG_ERDPTL 0x00 +#define CTL_REG_ERDPTH 0x01 +#define CTL_REG_EWRPTL 0x02 +#define CTL_REG_EWRPTH 0x03 +#define CTL_REG_ETXSTL 0x04 +#define CTL_REG_ETXSTH 0x05 +#define CTL_REG_ETXNDL 0x06 +#define CTL_REG_ETXNDH 0x07 +#define CTL_REG_ERXSTL 0x08 +#define CTL_REG_ERXSTH 0x09 +#define CTL_REG_ERXNDL 0x0A +#define CTL_REG_ERXNDA 0x0B +#define CTL_REG_ERXRDPTL 0x0C +#define CTL_REG_ERXRDPTH 0x0D +#define CTL_REG_ERXWRPTL 0x0E +#define CTL_REG_ERXWRPTH 0x0F +#define CTL_REG_EDMASTL 0x10 +#define CTL_REG_EDMASTH 0x11 +#define CTL_REG_EDMANDL 0x12 +#define CTL_REG_EDMANDH 0x13 +#define CTL_REG_EDMADSTL 0x14 +#define CTL_REG_EDMADSTH 0x15 +#define CTL_REG_EDMACSL 0x16 +#define CTL_REG_EDMACSH 0x17 +/* these are common in all banks */ +#define CTL_REG_EIE 0x1B +#define CTL_REG_EIR 0x1C +#define CTL_REG_ESTAT 0x1D +#define CTL_REG_ECON2 0x1E +#define CTL_REG_ECON1 0x1F + +/* + * Control Registers in Bank 1 + */ + +#define CTL_REG_EHT0 0x00 +#define CTL_REG_EHT1 0x01 +#define CTL_REG_EHT2 0x02 +#define CTL_REG_EHT3 0x03 +#define CTL_REG_EHT4 0x04 +#define CTL_REG_EHT5 0x05 +#define CTL_REG_EHT6 0x06 +#define CTL_REG_EHT7 0x07 +#define CTL_REG_EPMM0 0x08 +#define CTL_REG_EPMM1 0x09 +#define CTL_REG_EPMM2 0x0A +#define CTL_REG_EPMM3 0x0B +#define CTL_REG_EPMM4 0x0C +#define CTL_REG_EPMM5 0x0D +#define CTL_REG_EPMM6 0x0E +#define CTL_REG_EPMM7 0x0F +#define CTL_REG_EPMCSL 0x10 +#define CTL_REG_EPMCSH 0x11 +#define CTL_REG_EPMOL 0x14 +#define CTL_REG_EPMOH 0x15 +#define CTL_REG_EWOLIE 0x16 +#define CTL_REG_EWOLIR 0x17 +#define CTL_REG_ERXFCON 0x18 +#define CTL_REG_EPKTCNT 0x19 + +/* + * Control Registers in Bank 2 + */ + +#define CTL_REG_MACON1 0x00 +#define CTL_REG_MACON2 0x01 +#define CTL_REG_MACON3 0x02 +#define CTL_REG_MACON4 0x03 +#define CTL_REG_MABBIPG 0x04 +#define CTL_REG_MAIPGL 0x06 +#define CTL_REG_MAIPGH 0x07 +#define CTL_REG_MACLCON1 0x08 +#define CTL_REG_MACLCON2 0x09 +#define CTL_REG_MAMXFLL 0x0A +#define CTL_REG_MAMXFLH 0x0B +#define CTL_REG_MAPHSUP 0x0D +#define CTL_REG_MICON 0x11 +#define CTL_REG_MICMD 0x12 +#define CTL_REG_MIREGADR 0x14 +#define CTL_REG_MIWRL 0x16 +#define CTL_REG_MIWRH 0x17 +#define CTL_REG_MIRDL 0x18 +#define CTL_REG_MIRDH 0x19 + +/* + * Control Registers in Bank 3 + */ + +#define CTL_REG_MAADR1 0x00 +#define CTL_REG_MAADR0 0x01 +#define CTL_REG_MAADR3 0x02 +#define CTL_REG_MAADR2 0x03 +#define CTL_REG_MAADR5 0x04 +#define CTL_REG_MAADR4 0x05 +#define CTL_REG_EBSTSD 0x06 +#define CTL_REG_EBSTCON 0x07 +#define CTL_REG_EBSTCSL 0x08 +#define CTL_REG_EBSTCSH 0x09 +#define CTL_REG_MISTAT 0x0A +#define CTL_REG_EREVID 0x12 +#define CTL_REG_ECOCON 0x15 +#define CTL_REG_EFLOCON 0x17 +#define CTL_REG_EPAUSL 0x18 +#define CTL_REG_EPAUSH 0x19 + + +/* + * PHY Register + */ + +#define PHY_REG_PHID1 0x02 +#define PHY_REG_PHID2 0x03 + + +/* + * Receive Filter Register (ERXFCON) bits + */ + +#define ENC_RFR_UCEN 0x80 +#define ENC_RFR_ANDOR 0x40 +#define ENC_RFR_CRCEN 0x20 +#define ENC_RFR_PMEN 0x10 +#define ENC_RFR_MPEN 0x08 +#define ENC_RFR_HTEN 0x04 +#define ENC_RFR_MCEN 0x02 +#define ENC_RFR_BCEN 0x01 + +/* + * ECON1 Register Bits + */ + +#define ENC_ECON1_TXRST 0x80 +#define ENC_ECON1_RXRST 0x40 +#define ENC_ECON1_DMAST 0x20 +#define ENC_ECON1_CSUMEN 0x10 +#define ENC_ECON1_TXRTS 0x08 +#define ENC_ECON1_RXEN 0x04 +#define ENC_ECON1_BSEL1 0x02 +#define ENC_ECON1_BSEL0 0x01 + +/* + * ECON2 Register Bits + */ +#define ENC_ECON2_AUTOINC 0x80 +#define ENC_ECON2_PKTDEC 0x40 +#define ENC_ECON2_PWRSV 0x20 +#define ENC_ECON2_VRPS 0x08 + +/* + * EIR Register Bits + */ +#define ENC_EIR_PKTIF 0x40 +#define ENC_EIR_DMAIF 0x20 +#define ENC_EIR_LINKIF 0x10 +#define ENC_EIR_TXIF 0x08 +#define ENC_EIR_WOLIF 0x04 +#define ENC_EIR_TXERIF 0x02 +#define ENC_EIR_RXERIF 0x01 + +/* + * ESTAT Register Bits + */ + +#define ENC_ESTAT_INT 0x80 +#define ENC_ESTAT_LATECOL 0x10 +#define ENC_ESTAT_RXBUSY 0x04 +#define ENC_ESTAT_TXABRT 0x02 +#define ENC_ESTAT_CLKRDY 0x01 + +/* + * EIE Register Bits + */ + +#define ENC_EIE_INTIE 0x80 +#define ENC_EIE_PKTIE 0x40 +#define ENC_EIE_DMAIE 0x20 +#define ENC_EIE_LINKIE 0x10 +#define ENC_EIE_TXIE 0x08 +#define ENC_EIE_WOLIE 0x04 +#define ENC_EIE_TXERIE 0x02 +#define ENC_EIE_RXERIE 0x01 + +/* + * MACON1 Register Bits + */ +#define ENC_MACON1_LOOPBK 0x10 +#define ENC_MACON1_TXPAUS 0x08 +#define ENC_MACON1_RXPAUS 0x04 +#define ENC_MACON1_PASSALL 0x02 +#define ENC_MACON1_MARXEN 0x01 + + +/* + * MACON2 Register Bits + */ +#define ENC_MACON2_MARST 0x80 +#define ENC_MACON2_RNDRST 0x40 +#define ENC_MACON2_MARXRST 0x08 +#define ENC_MACON2_RFUNRST 0x04 +#define ENC_MACON2_MATXRST 0x02 +#define ENC_MACON2_TFUNRST 0x01 + +/* + * MACON3 Register Bits + */ +#define ENC_MACON3_PADCFG2 0x80 +#define ENC_MACON3_PADCFG1 0x40 +#define ENC_MACON3_PADCFG0 0x20 +#define ENC_MACON3_TXCRCEN 0x10 +#define ENC_MACON3_PHDRLEN 0x08 +#define ENC_MACON3_HFRMEN 0x04 +#define ENC_MACON3_FRMLNEN 0x02 +#define ENC_MACON3_FULDPX 0x01 + +/* + * MICMD Register Bits + */ +#define ENC_MICMD_MIISCAN 0x02 +#define ENC_MICMD_MIIRD 0x01 + +/* + * MISTAT Register Bits + */ +#define ENC_MISTAT_NVALID 0x04 +#define ENC_MISTAT_SCAN 0x02 +#define ENC_MISTAT_BUSY 0x01 + +/* + * PHID1 and PHID2 values + */ +#define ENC_PHID1_VALUE 0x0083 +#define ENC_PHID2_VALUE 0x1400 +#define ENC_PHID2_MASK 0xFC00 + + +#define ENC_SPI_SLAVE_CS 0x00010000 /* pin P1.16 */ +#define ENC_RESET 0x00020000 /* pin P1.17 */ + +#define FAILSAFE_VALUE 5000 + +/* + * Controller memory layout: + * + * 0x0000 - 0x17ff 6k bytes receive buffer + * 0x1800 - 0x1fff 2k bytes transmit buffer + */ +/* Use the lower memory for receiver buffer. See errata pt. 5 */ +#define ENC_RX_BUF_START 0x0000 +#define ENC_TX_BUF_START 0x1800 + +/* maximum frame length */ +#define ENC_MAX_FRM_LEN 1518 + +#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS) +#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS) +#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8); + + +static unsigned char encReadReg (unsigned char regNo); +static void encWriteReg (unsigned char regNo, unsigned char data); +static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c); +static void encReadBuff (unsigned short length, unsigned char *pBuff); +static void encWriteBuff (unsigned short length, unsigned char *pBuff); +static void encBitSet (unsigned char regNo, unsigned char data); +static void encBitClr (unsigned char regNo, unsigned char data); +static void encReset (void); +static void encInit (unsigned char *pEthAddr); +static unsigned short phyRead (unsigned char addr); +static void encPoll (void); +static void encRx (void); + +#define m_nic_read(reg) encReadReg(reg) +#define m_nic_write(reg, data) encWriteReg(reg, data) +#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count) +#define m_nic_read_data(len, buf) encReadBuff((len), (buf)) +#define m_nic_write_data(len, buf) encWriteBuff((len), (buf)) + +/* bit field set */ +#define m_nic_bfs(reg, data) encBitSet(reg, data) + +/* bit field clear */ +#define m_nic_bfc(reg, data) encBitClr(reg, data) + +static unsigned char bank = 0; /* current bank in enc28j60 */ +static unsigned char next_pointer_lsb; +static unsigned char next_pointer_msb; + +static unsigned char buffer[ENC_MAX_FRM_LEN]; +static int rxResetCounter = 0; + +#define RX_RESET_COUNTER 1000; + +/*----------------------------------------------------------------------------- + * Returns 0 when failes otherwize 1 + */ +int eth_init (bd_t * bis) +{ + /* configure GPIO */ + (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS; + (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET; + + /* CS and RESET active low */ + PUT32 (IO1SET, ENC_SPI_SLAVE_CS); + PUT32 (IO1SET, ENC_RESET); + + spi_init (); + + /* initialize controller */ + encReset (); + encInit (bis->bi_enetaddr); + + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ + + return 0; +} + +int eth_send (volatile void *packet, int length) +{ + /* check frame length, etc. */ + /* TODO: */ + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + /* set EWRPT */ + m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff)); + m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8)); + + /* set ETXST */ + m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF); + m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8); + + /* write packet */ + m_nic_write_data (length, (unsigned char *) packet); + + /* set ETXND */ + m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF); + m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8); + + /* set ECON1.TXRTS */ + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS); + + return 0; +} + + +/***************************************************************************** + * This function resets the receiver only. This function may be called from + * interrupt-context. + */ +static void encReceiverReset (void) +{ + unsigned char econ1; + + econ1 = m_nic_read (CTL_REG_ECON1); + if ((econ1 & ENC_ECON1_RXRST) == 0) { + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST); + rxResetCounter = RX_RESET_COUNTER; + } +} + +/***************************************************************************** + * receiver reset timer + */ +static void encReceiverResetCallback (void) +{ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ +} + +/*----------------------------------------------------------------------------- + * Check for received packets. Call NetReceive for each packet. The return + * value is ignored by the caller. + */ +int eth_rx (void) +{ + if (rxResetCounter > 0 && --rxResetCounter == 0) { + encReceiverResetCallback (); + } + + encPoll (); + + return 0; +} + +void eth_halt (void) +{ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */ +} + +/*****************************************************************************/ + +static void encPoll (void) +{ + unsigned char eir_reg; + volatile unsigned char estat_reg; + unsigned char pkt_cnt; + + /* clear global interrupt enable bit in enc28j60 */ + m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE); + estat_reg = m_nic_read (CTL_REG_ESTAT); + + eir_reg = m_nic_read (CTL_REG_EIR); + + if (eir_reg & ENC_EIR_TXIF) { + /* clear TXIF bit in EIR */ + m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF); + } + + /* We have to use pktcnt and not pktif bit, see errata pt. 6 */ + + /* move to bank 1 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); + + /* read pktcnt */ + pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); + + if (pkt_cnt > 0) { + if ((eir_reg & ENC_EIR_PKTIF) == 0) { + /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */ + } + encRx (); + /* clear PKTIF bit in EIR, this should not need to be done but it + seems like we get problems if we do not */ + m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF); + } + + if (eir_reg & ENC_EIR_RXERIF) { + printf ("encPoll: rx error\n"); + m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF); + } + if (eir_reg & ENC_EIR_TXERIF) { + printf ("encPoll: tx error\n"); + m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF); + } + + /* set global interrupt enable bit in enc28j60 */ + m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); +} + +static void encRx (void) +{ + unsigned short pkt_len; + unsigned short copy_len; + unsigned short status; + unsigned char eir_reg; + unsigned char pkt_cnt = 0; + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); + m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); + + do { + m_nic_read_data (6, buffer); + next_pointer_lsb = buffer[0]; + next_pointer_msb = buffer[1]; + pkt_len = buffer[2]; + pkt_len |= (unsigned short) buffer[3] << 8; + status = buffer[4]; + status |= (unsigned short) buffer[5] << 8; + + if (pkt_len <= ENC_MAX_FRM_LEN) { + copy_len = pkt_len; + } else { + copy_len = 0; + /* p_priv->stats.rx_dropped++; */ + /* we will drop this packet */ + } + + if ((status & (1L << 7)) == 0) { /* check Received Ok bit */ + copy_len = 0; + /* p_priv->stats.rx_errors++; */ + } + + if (copy_len > 0) { + m_nic_read_data (copy_len, buffer); + } + + /* advance read pointer to next pointer */ + m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); + m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); + + /* decrease packet counter */ + m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC); + + /* move to bank 1 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); + + /* read pktcnt */ + pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, + (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + if (copy_len == 0) { + eir_reg = m_nic_read (CTL_REG_EIR); + encReceiverReset (); + printf ("eth_rx: copy_len=0\n"); + continue; + } + + NetReceive ((unsigned char *) buffer, pkt_len); + + eir_reg = m_nic_read (CTL_REG_EIR); + } while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */ + m_nic_write (CTL_REG_ERXRDPTL, next_pointer_lsb); + m_nic_write (CTL_REG_ERXRDPTH, next_pointer_msb); +} + +static void encWriteReg (unsigned char regNo, unsigned char data) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x40 | regNo); /* write in regNo */ + spi_write (data); + + enc_disable (); + enc_enable (); + + spi_write (0x1f); /* write reg 0x1f */ + + enc_disable (); + spi_unlock (); +} + +static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c) +{ + unsigned char readback; + int i; + + spi_lock (); + + for (i = 0; i < c; i++) { + enc_cfg_spi (); + enc_enable (); + + spi_write (0x40 | regNo); /* write in regNo */ + spi_write (data); + + enc_disable (); + enc_enable (); + + spi_write (0x1f); /* write reg 0x1f */ + + enc_disable (); + + spi_unlock (); /* we must unlock spi first */ + + readback = encReadReg (regNo); + + spi_lock (); + + if (readback == data) + break; + } + spi_unlock (); + + if (i == c) { + printf ("enc28j60: write reg %d failed\n", regNo); + } +} + +static unsigned char encReadReg (unsigned char regNo) +{ + unsigned char rxByte; + + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x1f); /* read reg 0x1f */ + + bank = spi_read () & 0x3; + + enc_disable (); + enc_enable (); + + spi_write (regNo); + rxByte = spi_read (); + + /* check if MAC or MII register */ + if (((bank == 2) && (regNo <= 0x1a)) || + ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) { + /* ignore first byte and read another byte */ + rxByte = spi_read (); + } + + enc_disable (); + spi_unlock (); + + return rxByte; +} + +static void encReadBuff (unsigned short length, unsigned char *pBuff) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x20 | 0x1a); /* read buffer memory */ + + while (length--) { + if (pBuff != NULL) + *pBuff++ = spi_read (); + else + spi_write (0); + } + + enc_disable (); + spi_unlock (); +} + +static void encWriteBuff (unsigned short length, unsigned char *pBuff) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x60 | 0x1a); /* write buffer memory */ + + spi_write (0x00); /* control byte */ + + while (length--) + spi_write (*pBuff++); + + enc_disable (); + spi_unlock (); +} + +static void encBitSet (unsigned char regNo, unsigned char data) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x80 | regNo); /* bit field set */ + spi_write (data); + + enc_disable (); + spi_unlock (); +} + +static void encBitClr (unsigned char regNo, unsigned char data) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0xA0 | regNo); /* bit field clear */ + spi_write (data); + + enc_disable (); + spi_unlock (); +} + +static void encReset (void) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0xff); /* soft reset */ + + enc_disable (); + spi_unlock (); + + /* sleep 1 ms. See errata pt. 2 */ + udelay (1000); + +#if 0 + (*((volatile unsigned long *) IO1CLR)) &= ENC_RESET; + mdelay (5); + (*((volatile unsigned long *) IO1SET)) &= ENC_RESET; +#endif +} + +static void encInit (unsigned char *pEthAddr) +{ + unsigned short phid1 = 0; + unsigned short phid2 = 0; + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + /* + * Setup the buffer space. The reset values are valid for the + * other pointers. + */ +#if 0 + /* We shall not write to ERXST, see errata pt. 5. Instead we + have to make sure that ENC_RX_BUS_START is 0. */ + m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1); + m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1); +#endif + m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1); + m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1); + + next_pointer_lsb = (ENC_RX_BUF_START & 0xFF); + next_pointer_msb = (ENC_RX_BUF_START >> 8); + + /* + * For tracking purposes, the ERXRDPT registers should be programmed with + * the same value. This is the read pointer. + */ + m_nic_write (CTL_REG_ERXRDPTL, (ENC_RX_BUF_START & 0xFF)); + m_nic_write_retry (CTL_REG_ERXRDPTH, (ENC_RX_BUF_START >> 8), 1); + + /* Setup receive filters. */ + + /* move to bank 1 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); + + /* OR-filtering, Unicast, CRC-check and broadcast */ + m_nic_write_retry (CTL_REG_ERXFCON, + (ENC_RFR_UCEN | ENC_RFR_CRCEN | ENC_RFR_BCEN), 1); + + /* Wait for Oscillator Start-up Timer (OST). */ + while ((m_nic_read (CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY) == 0) { + static int cnt = 0; + + if (cnt++ >= 1000) { + cnt = 0; + } + } + + /* verify identification */ + phid1 = phyRead (PHY_REG_PHID1); + phid2 = phyRead (PHY_REG_PHID2); + + if (phid1 != ENC_PHID1_VALUE + || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) { + printf ("ERROR: failed to identify controller\n"); + printf ("phid1 = %x, phid2 = %x\n", + phid1, (phid2 & ENC_PHID2_MASK)); + printf ("should be phid1 = %x, phid2 = %x\n", + ENC_PHID1_VALUE, ENC_PHID2_VALUE); + } + + /* + * --- MAC Initialization --- + */ + + /* Pull MAC out of Reset */ + + /* switch to bank 2 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); + /* clear MAC reset bits */ + m_nic_write_retry (CTL_REG_MACON2, 0, 1); + + /* enable MAC to receive frames */ + m_nic_write_retry (CTL_REG_MACON1, ENC_MACON1_MARXEN, 10); + + /* configure pad, tx-crc and duplex */ + /* TODO maybe enable FRMLNEN */ + m_nic_write_retry (CTL_REG_MACON3, + (ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN), 10); + + /* set maximum frame length */ + m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10); + m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10); + + /* + * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex + * and 0x15 for full duplex. + */ + m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10); + + /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */ + m_nic_write_retry (CTL_REG_MAIPGL, 0x12, 10); + + /* + * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended + * 0x0c for half-duplex. Nothing for full-duplex + */ + m_nic_write_retry (CTL_REG_MAIPGH, 0x0C, 10); + + /* set MAC address */ + + /* switch to bank 3 */ + m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1)); + + m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1); + m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1); + m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1); + m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1); + m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1); + m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1); + + /* + * Receive settings + */ + + /* auto-increment RX-pointer when reading a received packet */ + m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_AUTOINC); + + /* enable interrupts */ + m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); +} + +/***************************************************************************** + * + * Description: + * Read PHY registers. + * + * NOTE! This function will change to Bank 2. + * + * Params: + * [in] addr address of the register to read + * + * Returns: + * The value in the register + */ +static unsigned short phyRead (unsigned char addr) +{ + unsigned short ret = 0; + + /* move to bank 2 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* write address to MIREGADR */ + m_nic_write (CTL_REG_MIREGADR, addr); + + /* set MICMD.MIIRD */ + m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD); + + /* poll MISTAT.BUSY bit until operation is complete */ + while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { + static int cnt = 0; + + if (cnt++ >= 1000) { + /* GJ - this seems extremely dangerous! */ + /* printf("#"); */ + cnt = 0; + } + } + + /* clear MICMD.MIIRD */ + m_nic_write (CTL_REG_MICMD, 0); + + ret = (m_nic_read (CTL_REG_MIRDH) << 8); + ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF); + + return ret; +} diff --git a/board/lpc2292sodimm/flash.c b/board/lpc2292sodimm/flash.c new file mode 100644 index 0000000..55aaabf --- /dev/null +++ b/board/lpc2292sodimm/flash.c @@ -0,0 +1,476 @@ +/* + * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/hardware.h> + +/* IAP commands use 32 bytes at the top of CPU internal sram, we + use 512 bytes below that */ +#define COPY_BUFFER_LOCATION 0x40003de0 + +#define IAP_LOCATION 0x7ffffff1 +#define IAP_CMD_PREPARE 50 +#define IAP_CMD_COPY 51 +#define IAP_CMD_ERASE 52 +#define IAP_CMD_CHECK 53 +#define IAP_CMD_ID 54 +#define IAP_CMD_VERSION 55 +#define IAP_CMD_COMPARE 56 + +#define IAP_RET_CMD_SUCCESS 0 + +#define SST_BASEADDR 0x80000000 +#define SST_ADDR1 ((volatile ushort*)(SST_BASEADDR + (0x5555 << 1))) +#define SST_ADDR2 ((volatile ushort*)(SST_BASEADDR + (0x2AAA << 1))) + + +static unsigned long command[5]; +static unsigned long result[2]; + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +extern void iap_entry(unsigned long * command, unsigned long * result); + +/*----------------------------------------------------------------------- + * + */ +int get_flash_sector(flash_info_t * info, ulong flash_addr) +{ + int i; + + for(i=1; i < (info->sector_count); i++) { + if (flash_addr < (info->start[i])) + break; + } + + return (i-1); +} + +/*----------------------------------------------------------------------- + * This function assumes that flash_addr is aligned on 512 bytes boundary + * in flash. This function also assumes that prepare have been called + * for the sector in question. + */ +int copy_buffer_to_flash(flash_info_t * info, ulong flash_addr) +{ + int first_sector; + int last_sector; + + first_sector = get_flash_sector(info, flash_addr); + last_sector = get_flash_sector(info, flash_addr + 512 - 1); + + /* prepare sectors for write */ + command[0] = IAP_CMD_PREPARE; + command[1] = first_sector; + command[2] = last_sector; + iap_entry(command, result); + if (result[0] != IAP_RET_CMD_SUCCESS) { + printf("IAP prepare failed\n"); + return ERR_PROG_ERROR; + } + + command[0] = IAP_CMD_COPY; + command[1] = flash_addr; + command[2] = COPY_BUFFER_LOCATION; + command[3] = 512; + command[4] = CFG_SYS_CLK_FREQ >> 10; + iap_entry(command, result); + if (result[0] != IAP_RET_CMD_SUCCESS) { + printf("IAP copy failed\n"); + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------- + * + */ +void write_word_sst(ulong addr, ushort data) +{ + ushort tmp; + + *SST_ADDR1 = 0x00AA; + *SST_ADDR2 = 0x0055; + *SST_ADDR1 = 0x00A0; + *((volatile ushort*)addr) = data; + /* do data polling */ + do { + tmp = *((volatile ushort*)addr); + } while (tmp != data); +} + +/*----------------------------------------------------------------------- + */ + +ulong flash_init (void) +{ + int j, k; + ulong size = 0; + ulong flashbase = 0; + + flash_info[0].flash_id = (PHILIPS_LPC2292 & FLASH_VENDMASK); + flash_info[0].size = 0x003E000; /* 256 - 8 KB */ + flash_info[0].sector_count = 17; + memset (flash_info[0].protect, 0, 17); + flashbase = 0x00000000; + for (j = 0, k = 0; j < 8; j++, k++) { + flash_info[0].start[k] = flashbase; + flashbase += 0x00002000; + } + for (j = 0; j < 2; j++, k++) { + flash_info[0].start[k] = flashbase; + flashbase += 0x00010000; + } + for (j = 0; j < 7; j++, k++) { + flash_info[0].start[k] = flashbase; + flashbase += 0x00002000; + } + size += flash_info[0].size; + + flash_info[1].flash_id = (SST_MANUFACT & FLASH_VENDMASK); + flash_info[1].size = 0x00200000; /* 2 MB */ + flash_info[1].sector_count = 512; + memset (flash_info[1].protect, 0, 512); + flashbase = SST_BASEADDR; + for (j=0; j<512; j++) { + flash_info[1].start[j] = flashbase; + flashbase += 0x1000; /* 4 KB sectors */ + } + size += flash_info[1].size; + + /* Protect monitor and environment sectors */ + flash_protect (FLAG_PROTECT_SET, + 0x0, + 0x0 + monitor_flash_len - 1, + &flash_info[0]); + + flash_protect (FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + int erased = 0; + unsigned long j; + unsigned long count; + unsigned char *p; + + switch (info->flash_id & FLASH_VENDMASK) { + case (SST_MANUFACT & FLASH_VENDMASK): + printf("SST: "); + break; + case (PHILIPS_LPC2292 & FLASH_VENDMASK): + printf("Philips: "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; i++) { + if ((i % 5) == 0) { + printf ("\n "); + } + if (i < (info->sector_count - 1)) { + count = info->start[i+1] - info->start[i]; + } + else { + count = info->start[0] + info->size - info->start[i]; + } + p = (unsigned char*)(info->start[i]); + erased = 1; + for (j = 0; j < count; j++) { + if (*p != 0xFF) { + erased = 0; + break; + } + p++; + } + printf (" %08lX%s%s", info->start[i], info->protect[i] ? " RO" : " ", + erased ? " E" : " "); + } + printf ("\n"); +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase_philips (flash_info_t * info, int s_first, int s_last) +{ + int flag; + int prot; + int sect; + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) + return ERR_PROTECTED; + + + flag = disable_interrupts(); + + printf ("Erasing %d sectors starting at sector %2d.\n" + "This make take some time ... ", + s_last - s_first + 1, s_first); + + command[0] = IAP_CMD_PREPARE; + command[1] = s_first; + command[2] = s_last; + iap_entry(command, result); + if (result[0] != IAP_RET_CMD_SUCCESS) { + printf("IAP prepare failed\n"); + return ERR_PROTECTED; + } + + command[0] = IAP_CMD_ERASE; + command[1] = s_first; + command[2] = s_last; + command[3] = CFG_SYS_CLK_FREQ >> 10; + iap_entry(command, result); + if (result[0] != IAP_RET_CMD_SUCCESS) { + printf("IAP erase failed\n"); + return ERR_PROTECTED; + } + + if (flag) + enable_interrupts(); + + return ERR_OK; +} + +int flash_erase_sst (flash_info_t * info, int s_first, int s_last) +{ + int i; + + for (i = s_first; i <= s_last; i++) { + *SST_ADDR1 = 0x00AA; + *SST_ADDR2 = 0x0055; + *SST_ADDR1 = 0x0080; + *SST_ADDR1 = 0x00AA; + *SST_ADDR2 = 0x0055; + *((volatile ushort*)(info->start[i])) = 0x0030; + /* wait for erase to finish */ + udelay(25000); + } + + return ERR_OK; +} + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + switch (info->flash_id & FLASH_VENDMASK) { + case (SST_MANUFACT & FLASH_VENDMASK): + return flash_erase_sst(info, s_first, s_last); + case (PHILIPS_LPC2292 & FLASH_VENDMASK): + return flash_erase_philips(info, s_first, s_last); + default: + return ERR_PROTECTED; + } + return ERR_PROTECTED; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + * + * cnt is in bytes + */ + +int write_buff_sst (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ushort tmp; + ulong i; + uchar* src_org; + uchar* dst_org; + ulong cnt_org = cnt; + int ret = ERR_OK; + + src_org = src; + dst_org = (uchar*)addr; + + if (addr & 1) { /* if odd address */ + tmp = *((uchar*)(addr - 1)); /* little endian */ + tmp |= (*src << 8); + write_word_sst(addr - 1, tmp); + addr += 1; + cnt -= 1; + src++; + } + while (cnt > 1) { + tmp = ((*(src+1)) << 8) + (*src); /* little endian */ + write_word_sst(addr, tmp); + addr += 2; + src += 2; + cnt -= 2; + } + if (cnt > 0) { + tmp = (*((uchar*)(addr + 1))) << 8; + tmp |= *src; + write_word_sst(addr, tmp); + } + + for (i = 0; i < cnt_org; i++) { + if (*dst_org != *src_org) { + printf("Write failed. Byte %lX differs\n", i); + ret = ERR_PROG_ERROR; + break; + } + dst_org++; + src_org++; + } + + return ret; +} + +int write_buff_philips (flash_info_t * info, + uchar * src, + ulong addr, + ulong cnt) +{ + int first_copy_size; + int last_copy_size; + int first_block; + int last_block; + int nbr_mid_blocks; + uchar memmap_value; + ulong i; + uchar* src_org; + uchar* dst_org; + int ret = ERR_OK; + + src_org = src; + dst_org = (uchar*)addr; + + first_block = addr / 512; + last_block = (addr + cnt) / 512; + nbr_mid_blocks = last_block - first_block - 1; + + first_copy_size = 512 - (addr % 512); + last_copy_size = (addr + cnt) % 512; + +#if 0 + printf("\ncopy first block: (1) %lX -> %lX 0x200 bytes, " + "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX 0x200 bytes\n", + (ulong)(first_block * 512), + (ulong)COPY_BUFFER_LOCATION, + (ulong)src, + (ulong)(COPY_BUFFER_LOCATION + 512 - first_copy_size), + first_copy_size, + (ulong)COPY_BUFFER_LOCATION, + (ulong)(first_block * 512)); +#endif + + /* copy first block */ + memcpy((void*)COPY_BUFFER_LOCATION, + (void*)(first_block * 512), 512); + memcpy((void*)(COPY_BUFFER_LOCATION + 512 - first_copy_size), + src, first_copy_size); + copy_buffer_to_flash(info, first_block * 512); + src += first_copy_size; + addr += first_copy_size; + + /* copy middle blocks */ + for (i = 0; i < nbr_mid_blocks; i++) { +#if 0 + printf("copy middle block: %lX -> %lX 512 bytes, " + "%lX -> %lX 512 bytes\n", + (ulong)src, + (ulong)COPY_BUFFER_LOCATION, + (ulong)COPY_BUFFER_LOCATION, + (ulong)addr); +#endif + memcpy((void*)COPY_BUFFER_LOCATION, src, 512); + copy_buffer_to_flash(info, addr); + src += 512; + addr += 512; + } + + + if (last_copy_size > 0) { +#if 0 + printf("copy last block: (1) %lX -> %lX 0x200 bytes, " + "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX x200 bytes\n", + (ulong)(last_block * 512), + (ulong)COPY_BUFFER_LOCATION, + (ulong)src, + (ulong)(COPY_BUFFER_LOCATION), + last_copy_size, + (ulong)COPY_BUFFER_LOCATION, + (ulong)addr); +#endif + /* copy last block */ + memcpy((void*)COPY_BUFFER_LOCATION, + (void*)(last_block * 512), 512); + memcpy((void*)COPY_BUFFER_LOCATION, + src, last_copy_size); + copy_buffer_to_flash(info, addr); + } + + /* verify write */ + memmap_value = GET8(MEMMAP); + + disable_interrupts(); + + PUT8(MEMMAP, 01); /* we must make sure that initial 64 + bytes are taken from flash when we + do the compare */ + + for (i = 0; i < cnt; i++) { + if (*dst_org != *src_org){ + printf("Write failed. Byte %lX differs\n", i); + ret = ERR_PROG_ERROR; + break; + } + dst_org++; + src_org++; + } + + PUT8(MEMMAP, memmap_value); + enable_interrupts(); + + return ret; +} + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + switch (info->flash_id & FLASH_VENDMASK) { + case (SST_MANUFACT & FLASH_VENDMASK): + return write_buff_sst(info, src, addr, cnt); + case (PHILIPS_LPC2292 & FLASH_VENDMASK): + return write_buff_philips(info, src, addr, cnt); + default: + return ERR_PROG_ERROR; + } + return ERR_PROG_ERROR; +} diff --git a/board/lpc2292sodimm/iap_entry.S b/board/lpc2292sodimm/iap_entry.S new file mode 100644 index 0000000..c31d519 --- /dev/null +++ b/board/lpc2292sodimm/iap_entry.S @@ -0,0 +1,7 @@ +IAP_ADDRESS: .word 0x7FFFFFF1 + +.globl iap_entry +iap_entry: + ldr r2, IAP_ADDRESS + bx r2 + mov pc, lr diff --git a/board/lpc2292sodimm/lowlevel_init.S b/board/lpc2292sodimm/lowlevel_init.S new file mode 100644 index 0000000..a0e9747 --- /dev/null +++ b/board/lpc2292sodimm/lowlevel_init.S @@ -0,0 +1,87 @@ +/* + * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> +#include <asm/arch/hardware.h> + +/* some parameters for the board */ +/* setting up the memory */ +#define SRAM_START 0x40000000 +#define SRAM_SIZE 0x00004000 +#define BCFG0_VALUE 0x1000ffef +#define BCFG1_VALUE 0x10001C61 + +_TEXT_BASE: + .word TEXT_BASE +MEMMAP_ADR: + .word MEMMAP +BCFG0_ADR: + .word BCFG0 +_BCFG0_VALUE: + .word BCFG0_VALUE +BCFG1_ADR: + .word BCFG1 +_BCFG1_VALUE: + .word BCFG1_VALUE +PINSEL2_ADR: + .word PINSEL2 +PINSEL2_MASK: + .word 0x00000000 +PINSEL2_VALUE: + .word 0x0F800914 + +.extern _start + +.globl lowlevel_init +lowlevel_init: + /* set up memory control register for bank 0 */ + ldr r0, _BCFG0_VALUE + ldr r1, BCFG0_ADR + str r0, [r1] + + /* set up memory control register for bank 1 */ + ldr r0, _BCFG1_VALUE + ldr r1, BCFG1_ADR + str r0, [r1] + + /* set up PINSEL2 for bus-pins */ + ldr r0, PINSEL2_ADR + ldr r1, [r0] + ldr r2, PINSEL2_MASK + ldr r3, PINSEL2_VALUE + and r1, r1, r2 + orr r1, r1, r3 + str r1, [r0] + + /* move vectors to beginning of SRAM */ + mov r2, #SRAM_START + mov r0, #0 /*_start*/ + ldmneia r0!, {r3-r10} + stmneia r2!, {r3-r10} + ldmneia r0, {r3-r9} + stmneia r2, {r3-r9} + + /* Set-up MEMMAP register, so vectors are taken from SRAM */ + ldr r0, MEMMAP_ADR + mov r1, #0x02 /* vectors re-mapped to static RAM */ + str r1, [r0] + + /* everything is fine now */ + mov pc, lr diff --git a/board/lpc2292sodimm/lpc2292sodimm.c b/board/lpc2292sodimm/lpc2292sodimm.c new file mode 100644 index 0000000..d212c63 --- /dev/null +++ b/board/lpc2292sodimm/lpc2292sodimm.c @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2005 Rowel Atienza <rowel@diwalabs.com> + * Armadillo board HT1070 + * + * 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 <common.h> +#include <clps7111.h> + +/* ------------------------------------------------------------------------- */ + + +/* + * Miscelaneous platform dependent initialisations + */ + +int board_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* Activate LED flasher */ + IO_LEDFLSH = 0x40; + + /* arch number MACH_TYPE_ARMADILLO - not official*/ + gd->bd->bi_arch_number = 83; + + /* location of boot parameters */ + gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + + return 0; +} + +int dram_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return (0); +} diff --git a/board/lpc2292sodimm/mmc.c b/board/lpc2292sodimm/mmc.c new file mode 100644 index 0000000..1c0922f --- /dev/null +++ b/board/lpc2292sodimm/mmc.c @@ -0,0 +1,154 @@ +/* + * 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 <config.h> +#include <common.h> +#include <mmc.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> +#include <part.h> +#include <fat.h> +#include "mmc_hw.h" +#include "spi.h" + +#ifdef CONFIG_MMC + +#undef MMC_DEBUG + +static block_dev_desc_t mmc_dev; + +/* these are filled out by a call to mmc_hw_get_parameters */ +static int hw_size; /* in kbytes */ +static int hw_nr_sects; +static int hw_sect_size; /* in bytes */ + +block_dev_desc_t * mmc_get_dev(int dev) +{ + return (block_dev_desc_t *)(&mmc_dev); +} + +unsigned long mmc_block_read(int dev, + unsigned long start, + lbaint_t blkcnt, + unsigned long *buffer) +{ + unsigned long rc = 0; + unsigned char *p = (unsigned char *)buffer; + unsigned long i; + unsigned long addr = start; + +#ifdef MMC_DEBUG + printf("mmc_block_read: start=%lu, blkcnt=%lu\n", start, + (unsigned long)blkcnt); +#endif + + for(i = 0; i < (unsigned long)blkcnt; i++) { +#ifdef MMC_DEBUG + printf("mmc_read_sector: addr=%lu, buffer=%p\n", addr, p); +#endif + (void)mmc_read_sector(addr, p); + rc++; + addr++; + p += hw_sect_size; + } + + return rc; +} + +/*----------------------------------------------------------------------------- + * Read hardware paramterers (sector size, size, number of sectors) + */ +static int mmc_hw_get_parameters(void) +{ + unsigned char csddata[16]; + unsigned int sizemult; + unsigned int size; + + mmc_read_csd(csddata); + hw_sect_size = 1<<(csddata[5] & 0x0f); + size = ((csddata[6]&0x03)<<10)+(csddata[7]<<2)+(csddata[8]&0xc0); + sizemult = ((csddata[10] & 0x80)>>7)+((csddata[9] & 0x03)<<1); + hw_nr_sects = (size+1)*(1<<(sizemult+2)); + hw_size = hw_nr_sects*hw_sect_size/1024; + +#ifdef MMC_DEBUG + printf("mmc_hw_get_parameters: hw_sect_size=%d, hw_nr_sects=%d, " + "hw_size=%d\n", hw_sect_size, hw_nr_sects, hw_size); +#endif + + return 0; +} + +int mmc_init(int verbose) +{ + int ret = -ENODEV; + + if (verbose) + printf("mmc_init\n"); + + spi_init(); + mmc_hw_init(); + + mmc_hw_get_parameters(); + + mmc_dev.if_type = IF_TYPE_MMC; + mmc_dev.part_type = PART_TYPE_DOS; + mmc_dev.dev = 0; + mmc_dev.lun = 0; + mmc_dev.type = 0; + mmc_dev.blksz = hw_sect_size; + mmc_dev.lba = hw_nr_sects; + sprintf((char*)mmc_dev.vendor, "Unknown vendor"); + sprintf((char*)mmc_dev.product, "Unknown product"); + sprintf((char*)mmc_dev.revision, "N/A"); + mmc_dev.removable = 0; /* should be true??? */ + mmc_dev.block_read = mmc_block_read; + + fat_register_device(&mmc_dev, 1); + + ret = 0; + + return ret; +} + +int mmc_write(uchar * src, ulong dst, int size) +{ +#ifdef MMC_DEBUG + printf("mmc_write: src=%p, dst=%lu, size=%u\n", src, dst, size); +#endif + /* Since mmc2info always returns 0 this function will never be called */ + return 0; +} + +int mmc_read(ulong src, uchar * dst, int size) +{ +#ifdef MMC_DEBUG + printf("mmc_read: src=%lu, dst=%p, size=%u\n", src, dst, size); +#endif + /* Since mmc2info always returns 0 this function will never be called */ + return 0; +} + +int mmc2info(ulong addr) +{ + /* This function is used by cmd_cp to determine if source or destination + address resides on MMC-card or not. We do not support copy to and from + MMC-card so we always return 0. */ + return 0; +} + +#endif /* CONFIG_MMC */ diff --git a/board/lpc2292sodimm/mmc_hw.c b/board/lpc2292sodimm/mmc_hw.c new file mode 100644 index 0000000..31f2a79 --- /dev/null +++ b/board/lpc2292sodimm/mmc_hw.c @@ -0,0 +1,233 @@ +/* + This code was original written by Ulrich Radig and modified by + Embedded Artists AB (www.embeddedartists.com). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <config.h> +#include <common.h> +#include <asm/arch/hardware.h> +#include "spi.h" + +#define MMC_Enable() PUT32(IO1CLR, 1l << 22) +#define MMC_Disable() PUT32(IO1SET, 1l << 22) +#define mmc_spi_cfg() spi_set_clock(8); spi_set_cfg(0, 1, 0); + +static unsigned char Write_Command_MMC (unsigned char *CMD); +static void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer, + unsigned short int Bytes); + +/* initialize the hardware */ +int mmc_hw_init(void) +{ + unsigned long a; + unsigned short int Timeout = 0; + unsigned char b; + unsigned char CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95}; + + /* set-up GPIO and SPI */ + (*((volatile unsigned long *)PINSEL2)) &= ~(1l << 3); /* clear bit 3 */ + (*((volatile unsigned long *)IO1DIR)) |= (1l << 22); /* set bit 22 (output) */ + + MMC_Disable(); + + spi_lock(); + spi_set_clock(248); + spi_set_cfg(0, 1, 0); + MMC_Enable(); + + /* waste some time */ + for(a=0; a < 20000; a++) + asm("nop"); + + /* Put the MMC/SD-card into SPI-mode */ + for (b = 0; b < 10; b++) /* Sends min 74+ clocks to the MMC/SD-card */ + spi_write(0xff); + + /* Sends command CMD0 to MMC/SD-card */ + while (Write_Command_MMC(CMD) != 1) { + if (Timeout++ > 200) { + MMC_Disable(); + spi_unlock(); + return(1); /* Abort with command 1 (return 1) */ + } + } + /* Sends Command CMD1 an MMC/SD-card */ + Timeout = 0; + CMD[0] = 0x41;/* Command 1 */ + CMD[5] = 0xFF; + + while (Write_Command_MMC(CMD) != 0) { + if (Timeout++ > 200) { + MMC_Disable(); + spi_unlock(); + return (2); /* Abort with command 2 (return 2) */ + } + } + + MMC_Disable(); + spi_unlock(); + + return 0; +} + +/* ############################################################################ + Sends a command to the MMC/SD-card + ######################################################################### */ +static unsigned char Write_Command_MMC (unsigned char *CMD) +{ + unsigned char a, tmp = 0xff; + unsigned short int Timeout = 0; + + MMC_Disable(); + spi_write(0xFF); + MMC_Enable(); + + for (a = 0; a < 0x06; a++) + spi_write(*CMD++); + + while (tmp == 0xff) { + tmp = spi_read(); + if (Timeout++ > 5000) + break; + } + + return (tmp); +} + +/* ############################################################################ + Routine to read the CID register from the MMC/SD-card (16 bytes) + ######################################################################### */ +void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer, unsigned short + int Bytes) +{ + unsigned short int a; + + spi_lock(); + mmc_spi_cfg(); + MMC_Enable(); + + if (Write_Command_MMC(CMD) != 0) { + MMC_Disable(); + spi_unlock(); + return; + } + + while (spi_read() != 0xfe) {}; + for (a = 0; a < Bytes; a++) + *Buffer++ = spi_read(); + + /* Read the CRC-byte */ + spi_read(); /* CRC - byte is discarded */ + spi_read(); /* CRC - byte is discarded */ + /* set MMC_Chip_Select to high (MMC/SD-card Inaktiv) */ + MMC_Disable(); + spi_unlock(); + + return; +} + +/* ############################################################################ + Routine to read a block (512 bytes) from the MMC/SD-card + ######################################################################### */ +unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer) +{ + /* Command 16 to read aBlocks from the MMC/SD - caed */ + unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; + + /* The addres on the MMC/SD-card is in bytes, + addr is transformed from blocks to bytes and the result is + placed into the command */ + + addr = addr << 9; /* addr = addr * 512 */ + + CMD[1] = ((addr & 0xFF000000) >> 24); + CMD[2] = ((addr & 0x00FF0000) >> 16); + CMD[3] = ((addr & 0x0000FF00) >> 8 ); + + MMC_Read_Block(CMD, Buffer, 512); + + return (0); +} + +/* ############################################################################ + Routine to write a block (512 byte) to the MMC/SD-card + ######################################################################### */ +unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer) +{ + unsigned char tmp, a; + unsigned short int b; + /* Command 24 to write a block to the MMC/SD - card */ + unsigned char CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF}; + + /* The addres on the MMC/SD-card is in bytes, + addr is transformed from blocks to bytes and the result is + placed into the command */ + + addr = addr << 9; /* addr = addr * 512 */ + + CMD[1] = ((addr & 0xFF000000) >> 24); + CMD[2] = ((addr & 0x00FF0000) >> 16); + CMD[3] = ((addr & 0x0000FF00) >> 8 ); + + spi_lock(); + mmc_spi_cfg(); + MMC_Enable(); + + /* Send command CMD24 to the MMC/SD-card (Write 1 Block/512 Bytes) */ + tmp = Write_Command_MMC(CMD); + if (tmp != 0) { + MMC_Disable(); + spi_unlock(); + return(tmp); + } + + /* Do a short delay and send a clock-pulse to the MMC/SD-card */ + for (a = 0; a < 100; a++) + spi_read(); + + /* Send a start byte to the MMC/SD-card */ + spi_write(0xFE); + + /* Write the block (512 bytes) to the MMC/SD-card */ + for (b = 0; b < 512; b++) + spi_write(*Buffer++); + + /* write the CRC-Byte */ + spi_write(0xFF); /* write a dummy CRC */ + spi_write(0xFF); /* CRC code is not used */ + + /* Wait for MMC/SD-card busy */ + while (spi_read() != 0xff) {}; + + /* set MMC_Chip_Select to high (MMC/SD-card inactive) */ + MMC_Disable(); + spi_unlock(); + return (0); +} + +/* ######################################################################### + Routine to read the CSD register from the MMC/SD-card (16 bytes) + ######################################################################### */ +unsigned char mmc_read_csd (unsigned char *Buffer) +{ + /* Command to read the CSD register */ + unsigned char CMD[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF}; + + MMC_Read_Block(CMD, Buffer, 16); + + return (0); +} diff --git a/board/lpc2292sodimm/mmc_hw.h b/board/lpc2292sodimm/mmc_hw.h new file mode 100644 index 0000000..3687dbf --- /dev/null +++ b/board/lpc2292sodimm/mmc_hw.h @@ -0,0 +1,29 @@ +/* + This module implements a linux character device driver for the 24c256 chip. + Copyright (C) 2006 Embedded Artists AB (www.embeddedartists.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MMC_HW_ +#define _MMC_HW_ + +unsigned char mmc_read_csd(unsigned char *Buffer); +unsigned char mmc_read_sector (unsigned long addr, + unsigned char *Buffer); +unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer); +int mmc_hw_init(void); + +#endif /* _MMC_HW_ */ diff --git a/board/lpc2292sodimm/spi.c b/board/lpc2292sodimm/spi.c new file mode 100644 index 0000000..4ba1468 --- /dev/null +++ b/board/lpc2292sodimm/spi.c @@ -0,0 +1,40 @@ +/* + This module implements an interface to the SPI on the lpc22xx. + Copyright (C) 2006 Embedded Artists AB (www.embeddedartists.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <config.h> +#include <common.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> +#include "spi.h" + +unsigned long spi_flags; +unsigned char spi_idle = 0x00; + +int spi_init(void) +{ + unsigned long pinsel0_value; + + /* activate spi pins */ + pinsel0_value = GET32(PINSEL0); + pinsel0_value &= ~(0xFFl << 8); + pinsel0_value |= (0x55l << 8); + PUT32(PINSEL0, pinsel0_value); + + return 0; +} diff --git a/board/lpc2292sodimm/spi.h b/board/lpc2292sodimm/spi.h new file mode 100644 index 0000000..6ae66e8 --- /dev/null +++ b/board/lpc2292sodimm/spi.h @@ -0,0 +1,82 @@ +/* + This file defines the interface to the lpc22xx SPI module. + Copyright (C) 2006 Embedded Artists AB (www.embeddedartists.com) + + This file may be included in software not adhering to the GPL. + + 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 SPI_H +#define SPI_H + +#include <config.h> +#include <common.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> + +#define SPIF 0x80 + +#define spi_lock() disable_interrupts(); +#define spi_unlock() enable_interrupts(); + +extern unsigned long spi_flags; +extern unsigned char spi_idle; + +int spi_init(void); + +static inline unsigned char spi_read(void) +{ + unsigned char b; + + PUT8(S0SPDR, spi_idle); + while (!(GET8(S0SPSR) & SPIF)); + b = GET8(S0SPDR); + + return b; +} + +static inline void spi_write(unsigned char b) +{ + PUT8(S0SPDR, b); + while (!(GET8(S0SPSR) & SPIF)); + GET8(S0SPDR); /* this will clear the SPIF bit */ +} + +static inline void spi_set_clock(unsigned char clk_value) +{ + PUT8(S0SPCCR, clk_value); +} + +static inline void spi_set_cfg(unsigned char phase, + unsigned char polarity, + unsigned char lsbf) +{ + unsigned char v = 0x20; /* master bit set */ + + if (phase) + v |= 0x08; /* set phase bit */ + if (polarity) { + v |= 0x10; /* set polarity bit */ + spi_idle = 0xFF; + } else { + spi_idle = 0x00; + } + if (lsbf) + v |= 0x40; /* set lsbf bit */ + + PUT8(S0SPCR, v); +} +#endif /* SPI_H */ diff --git a/board/lpc2292sodimm/u-boot.lds b/board/lpc2292sodimm/u-boot.lds new file mode 100644 index 0000000..64d946c --- /dev/null +++ b/board/lpc2292sodimm/u-boot.lds @@ -0,0 +1,55 @@ +/* + * (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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm720t/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mcc200/Makefile b/board/mcc200/Makefile index 75808cb..5869119 100644 --- a/board/mcc200/Makefile +++ b/board/mcc200/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS := $(BOARD).o lcd.o +COBJS := $(BOARD).o lcd.o auto_update.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/mcc200/auto_update.c b/board/mcc200/auto_update.c new file mode 100644 index 0000000..90d03ec --- /dev/null +++ b/board/mcc200/auto_update.c @@ -0,0 +1,522 @@ +/* + * (C) Copyright 2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 <common.h> +#include <command.h> +#include <malloc.h> +#include <image.h> +#include <asm/byteorder.h> +#include <usb.h> +#include <part.h> + +#ifdef CFG_HUSH_PARSER +#include <hush.h> +#endif + + +#ifdef CONFIG_AUTO_UPDATE + +#ifndef CONFIG_USB_OHCI +#error "must define CONFIG_USB_OHCI" +#endif + +#ifndef CONFIG_USB_STORAGE +#error "must define CONFIG_USB_STORAGE" +#endif + +#ifndef CFG_HUSH_PARSER +#error "must define CFG_HUSH_PARSER" +#endif + +#if !(CONFIG_COMMANDS & CFG_CMD_FAT) +#error "must define CFG_CMD_FAT" +#endif + +#undef AU_DEBUG + +#undef debug +#ifdef AU_DEBUG +#define debug(fmt,args...) printf (fmt ,##args) +#else +#define debug(fmt,args...) +#endif /* AU_DEBUG */ + +/* possible names of files on the USB stick. */ +#define AU_FIRMWARE "u-boot.img" +#define AU_KERNEL "kernel.img" +#define AU_ROOTFS "rootfs.img" + +struct flash_layout { + long start; + long end; +}; + +/* layout of the FLASH. ST = start address, ND = end address. */ +#define AU_FL_FIRMWARE_ST 0xfC000000 +#define AU_FL_FIRMWARE_ND 0xfC03FFFF +#define AU_FL_KERNEL_ST 0xfC0C0000 +#define AU_FL_KERNEL_ND 0xfC1BFFFF +#define AU_FL_ROOTFS_ST 0xFC1C0000 +#define AU_FL_ROOTFS_ND 0xFCFBFFFF + +static int au_usb_stor_curr_dev; /* current device */ + +/* index of each file in the following arrays */ +#define IDX_FIRMWARE 0 +#define IDX_KERNEL 1 +#define IDX_ROOTFS 2 + +/* max. number of files which could interest us */ +#define AU_MAXFILES 3 + +/* pointers to file names */ +char *aufile[AU_MAXFILES] = { + AU_FIRMWARE, + AU_KERNEL, + AU_ROOTFS +}; + +/* sizes of flash areas for each file */ +long ausize[AU_MAXFILES] = { + (AU_FL_FIRMWARE_ND + 1) - AU_FL_FIRMWARE_ST, + (AU_FL_KERNEL_ND + 1) - AU_FL_KERNEL_ST, + (AU_FL_ROOTFS_ND + 1) - AU_FL_ROOTFS_ST, +}; + +/* array of flash areas start and end addresses */ +struct flash_layout aufl_layout[AU_MAXFILES] = { + { AU_FL_FIRMWARE_ST, AU_FL_FIRMWARE_ND, }, + { AU_FL_KERNEL_ST, AU_FL_KERNEL_ND, }, + { AU_FL_ROOTFS_ST, AU_FL_ROOTFS_ND, }, +}; + +ulong totsize; + +/* where to load files into memory */ +#define LOAD_ADDR ((unsigned char *)0x00200000) + +/* the root file system is the largest image */ +#define MAX_LOADSZ ausize[IDX_ROOTFS] + +/*i2c address of the keypad status*/ +#define I2C_PSOC_KEYPAD_ADDR 0x53 + +/* keypad mask */ +#define KEYPAD_ROW 2 +#define KEYPAD_COL 2 +#define KEYPAD_MASK_LO ((1<<(KEYPAD_COL-1+(KEYPAD_ROW*3-3)))&0xFF) +#define KEYPAD_MASK_HI ((1<<(KEYPAD_COL-1+(KEYPAD_ROW*3-3)))>>8) + +/* externals */ +extern int fat_register_device(block_dev_desc_t *, int); +extern int file_fat_detectfs(void); +extern long file_fat_read(const char *, void *, unsigned long); +extern int i2c_read (unsigned char, unsigned int, int , unsigned char* , int); +extern int flash_sect_erase(ulong, ulong); +extern int flash_sect_protect (int, ulong, ulong); +extern int flash_write (char *, ulong, ulong); +extern int u_boot_hush_start(void); +#ifdef CONFIG_PROGRESSBAR +extern void show_progress(int, int); +extern void lcd_puts (char *); +extern void lcd_enable(void); +#endif + +int au_check_cksum_valid(int idx, long nbytes) +{ + image_header_t *hdr; + unsigned long checksum; + + hdr = (image_header_t *)LOAD_ADDR; + + if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) { + printf ("Image %s bad total SIZE\n", aufile[idx]); + return -1; + } + /* check the data CRC */ + checksum = ntohl(hdr->ih_dcrc); + + if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) != checksum) { + printf ("Image %s bad data checksum\n", aufile[idx]); + return -1; + } + return 0; +} + +int au_check_header_valid(int idx, long nbytes) +{ + image_header_t *hdr; + unsigned long checksum, fsize; + + hdr = (image_header_t *)LOAD_ADDR; + /* check the easy ones first */ +#undef CHECK_VALID_DEBUG +#ifdef CHECK_VALID_DEBUG + printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); + printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_ARM); + printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); + printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); +#endif + if (nbytes < sizeof(*hdr)) { + printf ("Image %s bad header SIZE\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_PPC) { + printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + /* check the hdr CRC */ + checksum = ntohl(hdr->ih_hcrc); + hdr->ih_hcrc = 0; + + if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + printf ("Image %s bad header checksum\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + hdr->ih_hcrc = htonl(checksum); + /* check the type - could do this all in one gigantic if() */ + if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + printf ("Image %s wrong type\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) { + printf ("Image %s wrong type\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + if ((idx == IDX_ROOTFS) && + ( (hdr->ih_type != IH_TYPE_RAMDISK) && (hdr->ih_type != IH_TYPE_FILESYSTEM) ) + ) { + printf ("Image %s wrong type\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + /* recycle checksum */ + checksum = ntohl(hdr->ih_size); + + fsize = checksum + sizeof(*hdr); + /* for kernel and ramdisk the image header must also fit into flash */ + if (idx == IDX_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) + checksum += sizeof(*hdr); + + /* check the size does not exceed space in flash. HUSH scripts */ + if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { + printf ("Image %s is bigger than FLASH\n", aufile[idx]); + ausize[idx] = 0; + return -1; + } + /* Update with the real filesize */ + ausize[idx] = fsize; + + return checksum; /* return size to be written to flash */ +} + +int au_do_update(int idx, long sz) +{ + image_header_t *hdr; + char *addr; + long start, end; + int off, rc; + uint nbytes; + + hdr = (image_header_t *)LOAD_ADDR; + + /* execute a script */ + if (hdr->ih_type == IH_TYPE_SCRIPT) { + addr = (char *)((char *)hdr + sizeof(*hdr)); + /* stick a NULL at the end of the script, otherwise */ + /* parse_string_outer() runs off the end. */ + addr[ntohl(hdr->ih_size)] = 0; + addr += 8; + parse_string_outer(addr, FLAG_PARSE_SEMICOLON); + return 0; + } + + start = aufl_layout[idx].start; + end = aufl_layout[idx].end; + + /* unprotect the address range */ + /* this assumes that ONLY the firmware is protected! */ + if (idx == IDX_FIRMWARE) { +#undef AU_UPDATE_TEST +#ifdef AU_UPDATE_TEST + /* erase it where Linux goes */ + start = aufl_layout[1].start; + end = aufl_layout[1].end; +#endif + flash_sect_protect(0, start, end); + } + + /* + * erase the address range. + */ + debug ("flash_sect_erase(%lx, %lx);\n", start, end); + flash_sect_erase(start, end); + wait_ms(100); +#ifdef CONFIG_PROGRESSBAR + show_progress(end - start, totsize); +#endif + + /* strip the header - except for the kernel and ramdisk */ + if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) { + addr = (char *)hdr; + off = sizeof(*hdr); + nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + } else { + addr = (char *)((char *)hdr + sizeof(*hdr)); +#ifdef AU_UPDATE_TEST + /* copy it to where Linux goes */ + if (idx == IDX_FIRMWARE) + start = aufl_layout[1].start; +#endif + off = 0; + nbytes = ntohl(hdr->ih_size); + } + + /* copy the data from RAM to FLASH */ + debug ("flash_write(%p, %lx %x)\n", addr, start, nbytes); + rc = flash_write(addr, start, nbytes); + if (rc != 0) { + printf("Flashing failed due to error %d\n", rc); + return -1; + } + +#ifdef CONFIG_PROGRESSBAR + show_progress(nbytes, totsize); +#endif + + /* check the data CRC of the copy */ + if (crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) { + printf ("Image %s Bad Data Checksum after COPY\n", aufile[idx]); + return -1; + } + + /* protect the address range */ + /* this assumes that ONLY the firmware is protected! */ + if (idx == IDX_FIRMWARE) + flash_sect_protect(1, start, end); + return 0; +} + +/* + * this is called from board_init() after the hardware has been set up + * and is usable. That seems like a good time to do this. + * Right now the return value is ignored. + */ +int do_auto_update(void) +{ + block_dev_desc_t *stor_dev; + long sz; + int i, res = 0, bitmap_first, cnt, old_ctrlc, got_ctrlc; + char *env; + long start, end; + uchar keypad_status1[2] = {0,0}, keypad_status2[2] = {0,0}; + + /* + * Read keypad status + */ + i2c_read(I2C_PSOC_KEYPAD_ADDR, 0, 0, keypad_status1, 2); + wait_ms(500); + i2c_read(I2C_PSOC_KEYPAD_ADDR, 0, 0, keypad_status2, 2); + + /* + * Check keypad + */ + if ( !(keypad_status1[1] & KEYPAD_MASK_LO) || + (keypad_status1[1] != keypad_status2[1])) { + return 0; + } + + au_usb_stor_curr_dev = -1; + /* start USB */ + if (usb_stop() < 0) { + debug ("usb_stop failed\n"); + return -1; + } + if (usb_init() < 0) { + debug ("usb_init failed\n"); + return -1; + } + /* + * check whether a storage device is attached (assume that it's + * a USB memory stick, since nothing else should be attached). + */ + au_usb_stor_curr_dev = usb_stor_scan(0); + if (au_usb_stor_curr_dev == -1) { + debug ("No device found. Not initialized?\n"); + return -1; + } + /* check whether it has a partition table */ + stor_dev = get_dev("usb", 0); + if (stor_dev == NULL) { + debug ("uknown device type\n"); + return -1; + } + if (fat_register_device(stor_dev, 1) != 0) { + debug ("Unable to use USB %d:%d for fatls\n", + au_usb_stor_curr_dev, 1); + return -1; + } + if (file_fat_detectfs() != 0) { + debug ("file_fat_detectfs failed\n"); + } + + /* + * now check whether start and end are defined using environment + * variables. + */ + start = -1; + end = 0; + env = getenv("firmware_st"); + if (env != NULL) + start = simple_strtoul(env, NULL, 16); + env = getenv("firmware_nd"); + if (env != NULL) + end = simple_strtoul(env, NULL, 16); + if (start >= 0 && end && end > start) { + ausize[IDX_FIRMWARE] = (end + 1) - start; + aufl_layout[IDX_FIRMWARE].start = start; + aufl_layout[IDX_FIRMWARE].end = end; + } + start = -1; + end = 0; + env = getenv("kernel_st"); + if (env != NULL) + start = simple_strtoul(env, NULL, 16); + env = getenv("kernel_nd"); + if (env != NULL) + end = simple_strtoul(env, NULL, 16); + if (start >= 0 && end && end > start) { + ausize[IDX_KERNEL] = (end + 1) - start; + aufl_layout[IDX_KERNEL].start = start; + aufl_layout[IDX_KERNEL].end = end; + } + start = -1; + end = 0; + env = getenv("rootfs_st"); + if (env != NULL) + start = simple_strtoul(env, NULL, 16); + env = getenv("rootfs_nd"); + if (env != NULL) + end = simple_strtoul(env, NULL, 16); + if (start >= 0 && end && end > start) { + ausize[IDX_ROOTFS] = (end + 1) - start; + aufl_layout[IDX_ROOTFS].start = start; + aufl_layout[IDX_ROOTFS].end = end; + } + + /* make certain that HUSH is runnable */ + u_boot_hush_start(); + /* make sure that we see CTRL-C and save the old state */ + old_ctrlc = disable_ctrlc(0); + + bitmap_first = 0; + + /* validate the images first */ + for (i = 0; i < AU_MAXFILES; i++) { + ulong imsize; + /* just read the header */ + sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t)); + debug ("read %s sz %ld hdr %d\n", + aufile[i], sz, sizeof(image_header_t)); + if (sz <= 0 || sz < sizeof(image_header_t)) { + debug ("%s not found\n", aufile[i]); + ausize[i] = 0; + continue; + } + /* au_check_header_valid() updates ausize[] */ + if ((imsize = au_check_header_valid(i, sz)) < 0) { + debug ("%s header not valid\n", aufile[i]); + continue; + } + /* totsize accounts for image size and flash erase size */ + totsize += (imsize + (aufl_layout[i].end - aufl_layout[i].start)); + } + +#ifdef CONFIG_PROGRESSBAR + if (totsize) { + lcd_puts(" Update in progress\n"); + lcd_enable(); + } +#endif + + /* just loop thru all the possible files */ + for (i = 0; i < AU_MAXFILES && totsize; i++) { + if (!ausize[i]) { + continue; + } + sz = file_fat_read(aufile[i], LOAD_ADDR, ausize[i]); + + debug ("read %s sz %ld hdr %d\n", + aufile[i], sz, sizeof(image_header_t)); + + if (sz != ausize[i]) { + printf ("%s: size %d read %d?\n", aufile[i], ausize[i], sz); + continue; + } + + if (sz <= 0 || sz <= sizeof(image_header_t)) { + debug ("%s not found\n", aufile[i]); + continue; + } + if (au_check_cksum_valid(i, sz) < 0) { + debug ("%s checksum not valid\n", aufile[i]); + continue; + } + /* this is really not a good idea, but it's what the */ + /* customer wants. */ + cnt = 0; + got_ctrlc = 0; + do { + res = au_do_update(i, sz); + /* let the user break out of the loop */ + if (ctrlc() || had_ctrlc()) { + clear_ctrlc(); + if (res < 0) + got_ctrlc = 1; + break; + } + cnt++; +#ifdef AU_TEST_ONLY + } while (res < 0 && cnt < (AU_MAXFILES + 1)); + if (cnt < (AU_MAXFILES + 1)) +#else + } while (res < 0); +#endif + } + usb_stop(); + /* restore the old state */ + disable_ctrlc(old_ctrlc); +#ifdef CONFIG_PROGRESSBAR + if (totsize) { + if (!res) { + lcd_puts("\n Update completed\n"); + } else { + lcd_puts("\n Update error\n"); + } + lcd_enable(); + } +#endif + return 0; +} +#endif /* CONFIG_AUTO_UPDATE */ diff --git a/board/mcc200/lcd.c b/board/mcc200/lcd.c index b262516..98b86d1 100644 --- a/board/mcc200/lcd.c +++ b/board/mcc200/lcd.c @@ -24,13 +24,13 @@ #ifdef CONFIG_LCD -#define SWAPPED_LCD +#undef SWAPPED_LCD /* For the previous h/w version */ /* * The name of the device used for communication * with the PSoC. */ #define PSOC_PSC MPC5XXX_PSC2 -#define PSOC_BAUD 500000UL +#define PSOC_BAUD 230400UL #define RTS_ASSERT 1 #define RTS_NEGATE 0 @@ -181,10 +181,35 @@ void lcd_enable (void) udelay (PSOC_WAIT_TIME); } if (!retries) { - printf ("%s Error: PSoC doesn't respond on " + printf ("%s Warning: PSoC doesn't respond on " "RTS NEGATE\n", __FUNCTION__); } return; } +#ifdef CONFIG_PROGRESSBAR + +#define FONT_WIDTH 8 /* the same as VIDEO_FONT_WIDTH in video_font.h */ +void show_progress (int size, int tot) +{ + int cnt; + int i; + static int rc = 0; + + rc += size; + + cnt = ((LCD_WIDTH/FONT_WIDTH) * rc) / tot; + + rc -= (cnt * tot) / (LCD_WIDTH/FONT_WIDTH); + + for (i = 0; i < cnt; i++) { + lcd_putc(0xdc); + } + + if (cnt) { + lcd_enable(); /* MCC200-specific - send the framebuffer to PSoC */ + } +} + +#endif #endif /* CONFIG_LCD */ diff --git a/board/mcc200/mcc200.c b/board/mcc200/mcc200.c index 5d74bde..af047e2 100644 --- a/board/mcc200/mcc200.c +++ b/board/mcc200/mcc200.c @@ -44,6 +44,7 @@ DECLARE_GLOBAL_DATA_PTR; extern flash_info_t flash_info[]; /* FLASH chips info */ +extern int do_auto_update(void); ulong flash_get_size (ulong base, int banknum); #ifndef CFG_RAMBOOT @@ -91,8 +92,8 @@ static void sdram_start (int hi_addr) /* * ATTENTION: Although partially referenced initdram does NOT make real use - * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE - * is something else than 0x00000000. + * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE + * is something else than 0x00000000. */ long int initdram (int board_type) @@ -289,6 +290,9 @@ int misc_init_r (void) flash_info[0].sector_count = snum; } +#ifdef CONFIG_AUTO_UPDATE + do_auto_update(); +#endif return (0); } diff --git a/board/motionpro/Makefile b/board/motionpro/Makefile new file mode 100644 index 0000000..698ead1 --- /dev/null +++ b/board/motionpro/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2003-2007 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/motionpro/config.mk b/board/motionpro/config.mk new file mode 100644 index 0000000..e7934d2 --- /dev/null +++ b/board/motionpro/config.mk @@ -0,0 +1,30 @@ +# +# (C) Copyright 2006-2007 +# 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 +# + +# +# Promess Motion-PRO +# + +TEXT_BASE = 0xfff00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/motionpro/motionpro.c b/board/motionpro/motionpro.c new file mode 100644 index 0000000..d60d233 --- /dev/null +++ b/board/motionpro/motionpro.c @@ -0,0 +1,172 @@ +/* + * (C) Copyright 2003-2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * modified for Promess PRO - by Andy Joseph, andy@promessdev.com + * modified for Promess PRO-Motion - by Robert McCullough, rob@promessdev.com + * modified by Chris M. Tumas 6/20/06 Change CAS latency to 2 from 3 + * Also changed the refresh for 100Mhz operation + * + * 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 <common.h> +#include <mpc5xxx.h> + + +/* Kollmorgen DPR initialization data */ +struct init_elem { + unsigned long addr; + unsigned len; + char *data; + } init_seq[] = { + {0x500003F2, 2, "\x86\x00"}, /* HW parameter */ + {0x500003F0, 2, "\x00\x00"}, + {0x500003EC, 4, "\x00\x80\xc1\x52"}, /* Magic word */ + }; + +/* + * Initialize Kollmorgen DPR + */ +static void kollmorgen_init(void) +{ + unsigned i, j; + vu_char *p; + + for (i = 0; i < sizeof(init_seq) / sizeof(struct init_elem); ++i) { + p = (vu_char *)init_seq[i].addr; + for (j = 0; j < init_seq[i].len; ++j) + *(p + j) = *(init_seq[i].data + j); + } + + printf("DPR: Kollmorgen DPR initialized\n"); +} + + +/* + * Early board initalization. + */ +int board_early_init_r(void) +{ + /* Now, when we are in RAM, disable Boot Chipselect and enable CS0 */ + *(vu_long *)MPC5XXX_ADDECR &= ~(1 << 25); + *(vu_long *)MPC5XXX_ADDECR |= (1 << 16); + + /* Initialize Kollmorgen DPR */ + kollmorgen_init(); + + return 0; +} + + +#ifndef CFG_RAMBOOT +/* + * Helper function to initialize SDRAM controller. + */ +static void sdram_start (int hi_addr) +{ + long hi_addr_bit = hi_addr ? 0x01000000 : 0; + + /* unlock mode register */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 | + hi_addr_bit; + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | + hi_addr_bit; + + /* auto refresh */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | + hi_addr_bit; + + /* auto refresh, second time */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | + hi_addr_bit; + + /* set mode register */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE; + + /* normal operation */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit; +} +#endif /* !CFG_RAMBOOT */ + + +/* + * Initalize SDRAM - configure SDRAM controller, detect memory size. + */ +long int initdram (int board_type) +{ + ulong dramsize = 0; +#ifndef CFG_RAMBOOT + ulong test1, test2; + + /* configure SDRAM start/end for detection */ + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001e; /* 2G at 0x0 */ + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x80000000; /* disabled */ + + /* setup config registers */ + *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1; + *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2; + + sdram_start(0); + test1 = get_ram_size((long *)CFG_SDRAM_BASE, 0x80000000); + sdram_start(1); + test2 = get_ram_size((long *)CFG_SDRAM_BASE, 0x80000000); + if (test1 > test2) { + sdram_start(0); + dramsize = test1; + } else { + dramsize = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize < (1 << 20)) + dramsize = 0; + + /* set SDRAM CS0 size according to the amount of RAM found */ + if (dramsize > 0) { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + + __builtin_ffs(dramsize >> 20) - 1; + } else { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */ + } + + /* let SDRAM CS1 start right after CS0 and disable it */ + *(vu_long *) MPC5XXX_SDRAM_CS1CFG = dramsize; + +#else /* !CFG_RAMBOOT */ + /* retrieve size of memory connected to SDRAM CS0 */ + dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF; + if (dramsize >= 0x13) + dramsize = (1 << (dramsize - 0x13)) << 20; + else + dramsize = 0; +#endif /* CFG_RAMBOOT */ + + /* return total ram size */ + return dramsize; +} + + +int checkboard (void) +{ + puts("Board: Promess Motion-PRO board\n"); + return 0; +} diff --git a/board/motionpro/u-boot.lds b/board/motionpro/u-boot.lds new file mode 100644 index 0000000..8fa9c0f --- /dev/null +++ b/board/motionpro/u-boot.lds @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2003-2007 + * 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); +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 : + { + cpu/mpc5xxx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/mpc832xemds/Makefile b/board/mpc832xemds/Makefile new file mode 100644 index 0000000..5ec7a87 --- /dev/null +++ b/board/mpc832xemds/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o pci.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/stamp/config.mk b/board/mpc832xemds/config.mk index 0d00730..6c3eca7 100644 --- a/board/stamp/config.mk +++ b/board/mpc832xemds/config.mk @@ -1,5 +1,5 @@ # -# (C) Copyright 2001 +# (C) Copyright 2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -21,5 +21,8 @@ # MA 02111-1307 USA # -TEXT_BASE = 0x07FC0000 -PLATFORM_CPPFLAGS += -I$(TOPDIR) +# +# MPC832XEMDS +# + +TEXT_BASE = 0xFE000000 diff --git a/board/mpc832xemds/mpc832xemds.c b/board/mpc832xemds/mpc832xemds.c new file mode 100644 index 0000000..772da67 --- /dev/null +++ b/board/mpc832xemds/mpc832xemds.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2006 Freescale Semiconductor, Inc. + * + * Dave Liu <daveliu@freescale.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. + */ + +#include <common.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <i2c.h> +#include <spd.h> +#include <miiphy.h> +#include <command.h> +#if defined(CONFIG_PCI) +#include <pci.h> +#endif +#if defined(CONFIG_SPD_EEPROM) +#include <spd_sdram.h> +#else +#include <asm/mmu.h> +#endif +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +const qe_iop_conf_t qe_iop_conf_tab[] = { + /* ETH3 */ + {1, 0, 1, 0, 1}, /* TxD0 */ + {1, 1, 1, 0, 1}, /* TxD1 */ + {1, 2, 1, 0, 1}, /* TxD2 */ + {1, 3, 1, 0, 1}, /* TxD3 */ + {1, 9, 1, 0, 1}, /* TxER */ + {1, 12, 1, 0, 1}, /* TxEN */ + {3, 24, 2, 0, 1}, /* TxCLK->CLK10 */ + + {1, 4, 2, 0, 1}, /* RxD0 */ + {1, 5, 2, 0, 1}, /* RxD1 */ + {1, 6, 2, 0, 1}, /* RxD2 */ + {1, 7, 2, 0, 1}, /* RxD3 */ + {1, 8, 2, 0, 1}, /* RxER */ + {1, 10, 2, 0, 1}, /* RxDV */ + {0, 13, 2, 0, 1}, /* RxCLK->CLK9 */ + {1, 11, 2, 0, 1}, /* COL */ + {1, 13, 2, 0, 1}, /* CRS */ + + /* ETH4 */ + {1, 18, 1, 0, 1}, /* TxD0 */ + {1, 19, 1, 0, 1}, /* TxD1 */ + {1, 20, 1, 0, 1}, /* TxD2 */ + {1, 21, 1, 0, 1}, /* TxD3 */ + {1, 27, 1, 0, 1}, /* TxER */ + {1, 30, 1, 0, 1}, /* TxEN */ + {3, 6, 2, 0, 1}, /* TxCLK->CLK8 */ + + {1, 22, 2, 0, 1}, /* RxD0 */ + {1, 23, 2, 0, 1}, /* RxD1 */ + {1, 24, 2, 0, 1}, /* RxD2 */ + {1, 25, 2, 0, 1}, /* RxD3 */ + {1, 26, 1, 0, 1}, /* RxER */ + {1, 28, 2, 0, 1}, /* Rx_DV */ + {3, 31, 2, 0, 1}, /* RxCLK->CLK7 */ + {1, 29, 2, 0, 1}, /* COL */ + {1, 31, 2, 0, 1}, /* CRS */ + + {3, 4, 3, 0, 2}, /* MDIO */ + {3, 5, 1, 0, 2}, /* MDC */ + + {0, 0, 0, 0, QE_IOP_TAB_END}, /* END of table */ +}; + +int board_early_init_f(void) +{ + volatile u8 *bcsr = (volatile u8 *)CFG_BCSR; + + /* Enable flash write */ + bcsr[9] &= ~0x08; + + return 0; +} + +int fixed_sdram(void); + +long int initdram(int board_type) +{ + volatile immap_t *im = (immap_t *) CFG_IMMR; + u32 msize = 0; + + if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) + return -1; + + /* DDR SDRAM - Main SODIMM */ + im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; + + msize = fixed_sdram(); + + puts("\n DDR RAM: "); + + /* return total bus SDRAM size(bytes) -- DDR */ + return (msize * 1024 * 1024); +} + +/************************************************************************* + * fixed sdram init -- doesn't use serial presence detect. + ************************************************************************/ +int fixed_sdram(void) +{ + volatile immap_t *im = (immap_t *) CFG_IMMR; + u32 msize = 0; + u32 ddr_size; + u32 ddr_size_log2; + + msize = CFG_DDR_SIZE; + for (ddr_size = msize << 20, ddr_size_log2 = 0; + (ddr_size > 1); ddr_size = ddr_size >> 1, ddr_size_log2++) { + if (ddr_size & 1) { + return -1; + } + } + im->sysconf.ddrlaw[0].ar = + LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); +#if (CFG_DDR_SIZE != 128) +#warning Currenly any ddr size other than 128 is not supported +#endif + im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL; + im->ddr.csbnds[0].csbnds = CFG_DDR_CS0_BNDS; + im->ddr.cs_config[0] = CFG_DDR_CS0_CONFIG; + im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0; + im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; + im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; + im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3; + im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG; + im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2; + im->ddr.sdram_mode = CFG_DDR_MODE; + im->ddr.sdram_mode2 = CFG_DDR_MODE2; + im->ddr.sdram_interval = CFG_DDR_INTERVAL; + __asm__ __volatile__ ("sync"); + udelay(200); + + im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; + __asm__ __volatile__ ("sync"); + return msize; +} + +int checkboard(void) +{ + puts("Board: Freescale MPC832XEMDS\n"); + return 0; +} + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + ft_cpu_setup(blob, bd); + + p = ft_get_prop(blob, "/memory/reg", &len); + if (p != NULL) { + *p++ = cpu_to_be32(bd->bi_memstart); + *p = cpu_to_be32(bd->bi_memsize); + } +} +#endif diff --git a/board/mpc832xemds/pci.c b/board/mpc832xemds/pci.c new file mode 100644 index 0000000..d0a407a --- /dev/null +++ b/board/mpc832xemds/pci.c @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2006 Freescale Semiconductor, 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. + */ + +/* + * PCI Configuration space access support for MPC83xx PCI Bridge + */ +#include <asm/mmu.h> +#include <asm/io.h> +#include <common.h> +#include <pci.h> +#include <i2c.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +#include <asm/fsl_i2c.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_PCI) +#define PCI_FUNCTION_CONFIG 0x44 +#define PCI_FUNCTION_CFG_LOCK 0x20 + +/* + * Initialize PCI Devices, report devices found + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc83xxemds_config_table[] = { + { + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_cfgfunc_config_device, + {PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMON_MEMORY | PCI_COMMAND_MASTER} + }, + {} +} +#endif +static struct pci_controller hose[] = { + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc83xxemds_config_table, +#endif + }, +}; + +/********************************************************************** + * pci_init_board() + *********************************************************************/ +void pci_init_board(void) +#ifdef CONFIG_PCISLAVE +{ + u16 reg16; + volatile immap_t *immr; + volatile law83xx_t *pci_law; + volatile pot83xx_t *pci_pot; + volatile pcictrl83xx_t *pci_ctrl; + volatile pciconf83xx_t *pci_conf; + + immr = (immap_t *) CFG_IMMR; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + /* + * Configure PCI Inbound Translation Windows + */ + pci_ctrl[0].pitar0 = 0x0; + pci_ctrl[0].pibar0 = 0x0; + pci_ctrl[0].piwar0 = PIWAR_EN | PIWAR_RTT_SNOOP | + PIWAR_WTT_SNOOP | PIWAR_IWS_4K; + + pci_ctrl[0].pitar1 = 0x0; + pci_ctrl[0].pibar1 = 0x0; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 &= ~PIWAR_EN; + + pci_ctrl[0].pitar2 = 0x0; + pci_ctrl[0].pibar2 = 0x0; + pci_ctrl[0].piebar2 = 0x0; + pci_ctrl[0].piwar2 &= ~PIWAR_EN; + + hose[0].first_busno = 0; + hose[0].last_busno = 0xff; + pci_setup_indirect(&hose[0], + (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304)); + reg16 = 0xff; + + pci_hose_read_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_STATUS, 0xffff); + pci_hose_write_config_byte(&hose[0], PCI_BDF(0, 0, 0), + PCI_LATENCY_TIMER, 0x80); + + /* + * Unlock configuration lock in PCI function configuration register. + */ + pci_hose_read_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_FUNCTION_CONFIG, ®16); + reg16 &= ~(PCI_FUNCTION_CFG_LOCK); + pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_FUNCTION_CONFIG, reg16); + + printf("Enabled PCI 32bit Agent Mode\n"); +} +#else +{ + volatile immap_t *immr; + volatile clk83xx_t *clk; + volatile law83xx_t *pci_law; + volatile pot83xx_t *pci_pot; + volatile pcictrl83xx_t *pci_ctrl; + volatile pciconf83xx_t *pci_conf; + + u8 val8, orig_i2c_bus; + u16 reg16; + u32 val32; + u32 dev; + + immr = (immap_t *) CFG_IMMR; + clk = (clk83xx_t *) & immr->clk; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + /* + * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode + */ + val32 = clk->occr; + udelay(2000); +#if defined(PCI_66M) + clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2; + printf("PCI clock is 66MHz\n"); +#elif defined(PCI_33M) + clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2 | + OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 | OCCR_PCICR; + printf("PCI clock is 33MHz\n"); +#else + clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2; + printf("PCI clock is 66MHz\n"); +#endif + udelay(2000); + + /* + * Configure PCI Local Access Windows + */ + pci_law[0].bar = CFG_PCI_MEM_PHYS & LAWBAR_BAR; + pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_512M; + + pci_law[1].bar = CFG_PCI_IO_PHYS & LAWBAR_BAR; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_1M; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI mem space - prefetch */ + pci_pot[0].potar = (CFG_PCI_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[0].pobar = (CFG_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[0].pocmr = + POCMR_EN | POCMR_SE | (POCMR_CM_256M & POCMR_CM_MASK); + + /* PCI mmio - non-prefetch mem space */ + pci_pot[1].potar = (CFG_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[1].pobar = (CFG_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[1].pocmr = POCMR_EN | (POCMR_CM_256M & POCMR_CM_MASK); + + /* PCI IO space */ + pci_pot[2].potar = (CFG_PCI_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[2].pobar = (CFG_PCI_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[2].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_1M & POCMR_CM_MASK); + + /* + * Configure PCI Inbound Translation Windows + */ + pci_ctrl[0].pitar1 = (CFG_PCI_SLV_MEM_LOCAL >> 12) & PITAR_TA_MASK; + pci_ctrl[0].pibar1 = (CFG_PCI_SLV_MEM_BUS >> 12) & PIBAR_MASK; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 = + PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | + PIWAR_IWS_2G; + + /* + * Assign PIB PMC slot to desired PCI bus + */ + + /* Switch temporarily to I2C bus #2 */ + orig_i2c_bus = i2c_get_bus_num(); + i2c_set_bus_num(1); + + val8 = 0; + i2c_write(0x23, 0x6, 1, &val8, 1); + i2c_write(0x23, 0x7, 1, &val8, 1); + val8 = 0xff; + i2c_write(0x23, 0x2, 1, &val8, 1); + i2c_write(0x23, 0x3, 1, &val8, 1); + + val8 = 0; + i2c_write(0x26, 0x6, 1, &val8, 1); + val8 = 0x34; + i2c_write(0x26, 0x7, 1, &val8, 1); + + val8 = 0xf9; /* PMC2, PMC3 slot to PCI bus */ + i2c_write(0x26, 0x2, 1, &val8, 1); + val8 = 0xff; + i2c_write(0x26, 0x3, 1, &val8, 1); + + val8 = 0; + i2c_write(0x27, 0x6, 1, &val8, 1); + i2c_write(0x27, 0x7, 1, &val8, 1); + val8 = 0xff; + i2c_write(0x27, 0x2, 1, &val8, 1); + val8 = 0xef; + i2c_write(0x27, 0x3, 1, &val8, 1); + asm("eieio"); + + /* Reset to original I2C bus */ + i2c_set_bus_num(orig_i2c_bus); + + /* + * Release PCI RST Output signal + */ + udelay(2000); + pci_ctrl[0].gcr = 1; + udelay(2000); + + hose[0].first_busno = 0; + hose[0].last_busno = 0xff; + + /* PCI memory prefetch space */ + pci_set_region(hose[0].regions + 0, + CFG_PCI_MEM_BASE, + CFG_PCI_MEM_PHYS, + CFG_PCI_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH); + + /* PCI memory space */ + pci_set_region(hose[0].regions + 1, + CFG_PCI_MMIO_BASE, + CFG_PCI_MMIO_PHYS, CFG_PCI_MMIO_SIZE, PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose[0].regions + 2, + CFG_PCI_IO_BASE, + CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose[0].regions + 3, + CFG_PCI_SLV_MEM_LOCAL, + CFG_PCI_SLV_MEM_BUS, + CFG_PCI_SLV_MEM_SIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose[0].region_count = 4; + + pci_setup_indirect(&hose[0], + (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304)); + + pci_register_hose(hose); + + /* + * Write command register + */ + reg16 = 0xff; + dev = PCI_BDF(0, 0, 0); + pci_hose_read_config_word(&hose[0], dev, PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(&hose[0], dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(&hose[0], dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(&hose[0], dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(&hose[0], dev, PCI_CACHE_LINE_SIZE, 0x08); + + printf("PCI 32bit bus on PMC2 & PMC3\n"); + + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); +} +#endif /* CONFIG_PCISLAVE */ + +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); + if (p != NULL) { + p[0] = hose[0].first_busno; + p[1] = hose[0].last_busno; + } +} +#endif /* CONFIG_OF_FLAT_TREE */ +#endif /* CONFIG_PCI */ diff --git a/board/mpc832xemds/u-boot.lds b/board/mpc832xemds/u-boot.lds new file mode 100644 index 0000000..937c87a --- /dev/null +++ b/board/mpc832xemds/u-boot.lds @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2006 + * 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) +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 : + { + cpu/mpc83xx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} +ENTRY(_start) diff --git a/board/mpc8349emds/Makefile b/board/mpc8349emds/Makefile index acc9544..5ec7a87 100644 --- a/board/mpc8349emds/Makefile +++ b/board/mpc8349emds/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS := $(BOARD).o +COBJS := $(BOARD).o pci.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/mpc8349emds/mpc8349emds.c b/board/mpc8349emds/mpc8349emds.c index b5ccb53..071591e 100644 --- a/board/mpc8349emds/mpc8349emds.c +++ b/board/mpc8349emds/mpc8349emds.c @@ -33,6 +33,10 @@ #if defined(CONFIG_SPD_EEPROM) #include <spd_sdram.h> #endif +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + int fixed_sdram(void); void sdram_init(void); @@ -59,7 +63,7 @@ int board_early_init_f (void) long int initdram (int board_type) { - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; + volatile immap_t *im = (immap_t *)CFG_IMMR; u32 msize = 0; if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) @@ -96,7 +100,7 @@ long int initdram (int board_type) ************************************************************************/ int fixed_sdram(void) { - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; + volatile immap_t *im = (immap_t *)CFG_IMMR; u32 msize = 0; u32 ddr_size; u32 ddr_size_log2; @@ -115,6 +119,20 @@ int fixed_sdram(void) #if (CFG_DDR_SIZE != 256) #warning Currenly any ddr size other than 256 is not supported #endif +#ifdef CONFIG_DDR_II + im->ddr.csbnds[2].csbnds = CFG_DDR_CS2_BNDS; + im->ddr.cs_config[2] = CFG_DDR_CS2_CONFIG; + im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0; + im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; + im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; + im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3; + im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG; + im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2; + im->ddr.sdram_mode = CFG_DDR_MODE; + im->ddr.sdram_mode2 = CFG_DDR_MODE2; + im->ddr.sdram_interval = CFG_DDR_INTERVAL; + im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL; +#else im->ddr.csbnds[2].csbnds = 0x0000000f; im->ddr.cs_config[2] = CFG_DDR_CONFIG; @@ -139,6 +157,7 @@ int fixed_sdram(void) im->ddr.sdram_mode = CFG_DDR_MODE; im->ddr.sdram_interval = CFG_DDR_INTERVAL; +#endif udelay(200); /* enable DDR controller */ @@ -167,8 +186,8 @@ int checkboard (void) void sdram_init(void) { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile lbus8349_t *lbc= &immap->lbus; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile lbus83xx_t *lbc= &immap->lbus; uint *sdram_addr = (uint *)CFG_LBC_SDRAM_BASE; puts("\n SDRAM on Local Bus: "); @@ -235,7 +254,7 @@ void sdram_init(void) #else void sdram_init(void) { - put("SDRAM on Local Bus is NOT available!\n"); + puts(" SDRAM on Local Bus is NOT available!\n"); } #endif @@ -245,8 +264,8 @@ void sdram_init(void) */ void ecc_print_status(void) { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile ddr8349_t *ddr = &immap->ddr; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; printf("\nECC mode: %s\n\n", (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); @@ -320,8 +339,8 @@ void ecc_print_status(void) int do_ecc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile ddr8349_t *ddr = &immap->ddr; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; volatile u32 val; u64 *addr, count, val64; register u64 *i; @@ -564,3 +583,23 @@ U_BOOT_CMD( " - re-inits memory" ); #endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + ft_cpu_setup(blob, bd); + + p = ft_get_prop(blob, "/memory/reg", &len); + if (p != NULL) { + *p++ = cpu_to_be32(bd->bi_memstart); + *p = cpu_to_be32(bd->bi_memsize); + } +} +#endif diff --git a/board/mpc8349emds/pci.c b/board/mpc8349emds/pci.c index 63e4405..d6a12b8 100644 --- a/board/mpc8349emds/pci.c +++ b/board/mpc8349emds/pci.c @@ -68,12 +68,13 @@ static struct pci_controller pci_hose[] = { void pib_init(void) { - u8 val8; + u8 val8, orig_i2c_bus; /* * Assign PIB PMC slot to desired PCI bus */ - mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C2_OFFSET); - i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); + /* Switch temporarily to I2C bus #2 */ + orig_i2c_bus = i2c_get_bus_num(); + i2c_set_bus_num(1); val8 = 0; i2c_write(0x23, 0x6, 1, &val8, 1); @@ -118,6 +119,8 @@ pib_init(void) printf("PCI1: 32-bit on PMC1, PMC2\n"); printf("PCI2: 32-bit on PMC3\n"); #endif + /* Reset to original I2C bus */ + i2c_set_bus_num(orig_i2c_bus); } /************************************************************************** @@ -130,18 +133,18 @@ void pci_init_board(void) { volatile immap_t * immr; - volatile clk8349_t * clk; - volatile law8349_t * pci_law; - volatile pot8349_t * pci_pot; - volatile pcictrl8349_t * pci_ctrl; - volatile pciconf8349_t * pci_conf; + volatile clk83xx_t * clk; + volatile law83xx_t * pci_law; + volatile pot83xx_t * pci_pot; + volatile pcictrl83xx_t * pci_ctrl; + volatile pciconf83xx_t * pci_conf; u16 reg16; u32 reg32; u32 dev; struct pci_controller * hose; - immr = (immap_t *)CFG_IMMRBAR; - clk = (clk8349_t *)&immr->clk; + immr = (immap_t *)CFG_IMMR; + clk = (clk83xx_t *)&immr->clk; pci_law = immr->sysconf.pcilaw; pci_pot = immr->ios.pot; pci_ctrl = immr->pci_ctrl; @@ -254,8 +257,8 @@ pci_init_board(void) hose->region_count = 4; pci_setup_indirect(hose, - (CFG_IMMRBAR+0x8300), - (CFG_IMMRBAR+0x8304)); + (CFG_IMMR+0x8300), + (CFG_IMMR+0x8304)); pci_register_hose(hose); @@ -350,8 +353,8 @@ pci_init_board(void) hose->region_count = 4; pci_setup_indirect(hose, - (CFG_IMMRBAR+0x8380), - (CFG_IMMRBAR+0x8384)); + (CFG_IMMR+0x8380), + (CFG_IMMR+0x8384)); pci_register_hose(hose); @@ -379,4 +382,26 @@ pci_init_board(void) } +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); + if (p != NULL) { + p[0] = pci_hose[0].first_busno; + p[1] = pci_hose[0].last_busno; + } + +#ifdef CONFIG_MPC83XX_PCI2 + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8600/bus-range", &len); + if (p != NULL) { + p[0] = pci_hose[1].first_busno; + p[1] = pci_hose[1].last_busno; + } +#endif +} +#endif /* CONFIG_OF_FLAT_TREE */ #endif /* CONFIG_PCI */ diff --git a/board/mpc8349itx/Makefile b/board/mpc8349itx/Makefile new file mode 100644 index 0000000..31bcdb8 --- /dev/null +++ b/board/mpc8349itx/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. +# +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o pci.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) crv $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/mpc8349itx/config.mk b/board/mpc8349itx/config.mk new file mode 100644 index 0000000..1901fdc --- /dev/null +++ b/board/mpc8349itx/config.mk @@ -0,0 +1,37 @@ +# +# Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. +# +# 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 +# + +# +# MPC8349E-mITX and MPC8349E-mITX-GP +# + +sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp + +ifndef TEXT_BASE +TEXT_BASE = 0xFEF00000 +endif + +ifneq ($(OBJTREE),$(SRCTREE)) +# We are building u-boot in a separate directory, use generated +# .lds script from OBJTREE directory. +LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds +endif diff --git a/board/mpc8349itx/mpc8349itx.c b/board/mpc8349itx/mpc8349itx.c new file mode 100644 index 0000000..2b3ded1 --- /dev/null +++ b/board/mpc8349itx/mpc8349itx.c @@ -0,0 +1,407 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * + * 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 <common.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <i2c.h> +#include <spd.h> +#include <miiphy.h> + +#ifdef CONFIG_PCI +#include <asm/mpc8349_pci.h> +#include <pci.h> +#endif + +#ifdef CONFIG_SPD_EEPROM +#include <spd_sdram.h> +#else +#include <asm/mmu.h> +#endif +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +#ifndef CONFIG_SPD_EEPROM +/************************************************************************* + * fixed sdram init -- doesn't use serial presence detect. + ************************************************************************/ +int fixed_sdram(void) +{ + volatile immap_t *im = (immap_t *) CFG_IMMR; + u32 ddr_size; /* The size of RAM, in bytes */ + u32 ddr_size_log2 = 0; + + for (ddr_size = CFG_DDR_SIZE * 0x100000; ddr_size > 1; ddr_size >>= 1) { + if (ddr_size & 1) { + return -1; + } + ddr_size_log2++; + } + + im->sysconf.ddrlaw[0].ar = + LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); + im->sysconf.ddrlaw[0].bar = (CFG_DDR_SDRAM_BASE >> 12) & 0xfffff; + + /* Only one CS0 for DDR */ + im->ddr.csbnds[0].csbnds = 0x0000000f; + im->ddr.cs_config[0] = CFG_DDR_CONFIG; + + debug("cs0_bnds = 0x%08x\n", im->ddr.csbnds[0].csbnds); + debug("cs0_config = 0x%08x\n", im->ddr.cs_config[0]); + + debug("DDR:bar=0x%08x\n", im->sysconf.ddrlaw[0].bar); + debug("DDR:ar=0x%08x\n", im->sysconf.ddrlaw[0].ar); + + im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; + im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2;/* Was "2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT" */ + im->ddr.sdram_cfg = SDRAM_CFG_SREN | SDRAM_CFG_SDRAM_TYPE_DDR; + im->ddr.sdram_mode = + (0x0000 << SDRAM_MODE_ESD_SHIFT) | (0x0032 << SDRAM_MODE_SD_SHIFT); + im->ddr.sdram_interval = + (0x0410 << SDRAM_INTERVAL_REFINT_SHIFT) | (0x0100 << + SDRAM_INTERVAL_BSTOPRE_SHIFT); + im->ddr.sdram_clk_cntl = + DDR_SDRAM_CLK_CNTL_SS_EN | DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05; + + udelay(200); + + im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; + + debug("DDR:timing_cfg_1=0x%08x\n", im->ddr.timing_cfg_1); + debug("DDR:timing_cfg_2=0x%08x\n", im->ddr.timing_cfg_2); + debug("DDR:sdram_mode=0x%08x\n", im->ddr.sdram_mode); + debug("DDR:sdram_interval=0x%08x\n", im->ddr.sdram_interval); + debug("DDR:sdram_cfg=0x%08x\n", im->ddr.sdram_cfg); + + return CFG_DDR_SIZE; +} +#endif + +#ifdef CONFIG_PCI +/* + * Initialize PCI Devices, report devices found + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc83xxmitx_config_table[] = { + { + PCI_ANY_ID, + PCI_ANY_ID, + PCI_ANY_ID, + PCI_ANY_ID, + 0x0f, + PCI_ANY_ID, + pci_cfgfunc_config_device, + { + PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER} + }, + {} +} +#endif + +volatile static struct pci_controller hose[] = { + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc83xxmitx_config_table, +#endif + }, + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc83xxmitx_config_table, +#endif + } +}; +#endif /* CONFIG_PCI */ + +long int initdram(int board_type) +{ + volatile immap_t *im = (immap_t *) CFG_IMMR; + u32 msize = 0; +#ifdef CONFIG_DDR_ECC + volatile ddr83xx_t *ddr = &im->ddr; +#endif + + if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) + return -1; + + /* DDR SDRAM - Main SODIMM */ + im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; +#ifdef CONFIG_SPD_EEPROM + msize = spd_sdram(); +#else + msize = fixed_sdram(); +#endif + +#ifdef CONFIG_DDR_ECC + if (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) + /* Unlike every other board, on the 83xx spd_sdram() returns + megabytes instead of just bytes. That's why we need to + multiple by 1MB when calling ddr_enable_ecc(). */ + ddr_enable_ecc(msize * 1048576); +#endif + + puts(" DDR RAM: "); + /* return total bus RAM size(bytes) */ + return msize * 1024 * 1024; +} + +int checkboard(void) +{ +#ifdef CONFIG_MPC8349ITX + puts("Board: Freescale MPC8349E-mITX\n"); +#else + puts("Board: Freescale MPC8349E-mITX-GP\n"); +#endif + + return 0; +} + +/* + * Implement a work-around for a hardware problem with compact + * flash. + * + * Program the UPM if compact flash is enabled. + */ +int misc_init_f(void) +{ +#ifdef CONFIG_VSC7385 + volatile u32 *vsc7385_cpuctrl; + + /* 0x1c0c0 is the VSC7385 CPU Control (CPUCTRL) Register. The power up + default of VSC7385 L1_IRQ and L2_IRQ requests are active high. That + means it is 0 when the IRQ is not active. This makes the wire-AND + logic always assert IRQ7 to CPU even if there is no request from the + switch. Since the compact flash and the switch share the same IRQ, + the Linux kernel will think that the compact flash is requesting irq + and get stuck when it tries to clear the IRQ. Thus we need to set + the L2_IRQ0 and L2_IRQ1 to active low. + + The following code sets the L1_IRQ and L2_IRQ polarity to active low. + Without this code, compact flash will not work in Linux because + unlike U-Boot, Linux uses the IRQ, so this code is necessary if we + don't enable compact flash for U-Boot. + */ + + vsc7385_cpuctrl = (volatile u32 *)(CFG_VSC7385_BASE + 0x1c0c0); + *vsc7385_cpuctrl |= 0x0c; +#endif + +#ifdef CONFIG_COMPACT_FLASH + /* UPM Table Configuration Code */ + static uint UPMATable[] = { + 0xcffffc00, 0x0fffff00, 0x0fafff00, 0x0fafff00, + 0x0faffd00, 0x0faffc04, 0x0ffffc00, 0x3ffffc01, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfff7fc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + 0xcffffc00, 0x0fffff00, 0x0ff3ff00, 0x0ff3ff00, + 0x0ff3fe00, 0x0ffffc00, 0x3ffffc05, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01 + }; + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile lbus83xx_t *lbus = &immap->lbus; + + lbus->bank[3].br = CFG_BR3_PRELIM; + lbus->bank[3].or = CFG_OR3_PRELIM; + + /* Program the MAMR. RFEN=0, OP=00, UWPL=1, AM=000, DS=01, G0CL=000, + GPL4=0, RLF=0001, WLF=0001, TLF=0001, MAD=000000 + */ + lbus->mamr = 0x08404440; + + upmconfig(0, UPMATable, sizeof(UPMATable) / sizeof(UPMATable[0])); + + puts("UPMA: Configured for compact flash\n"); +#endif + + return 0; +} + +/* + * Make sure the EEPROM has the HRCW correctly programmed. + * Make sure the RTC is correctly programmed. + * + * The MPC8349E-mITX can be configured to load the HRCW from + * EEPROM instead of flash. This is controlled via jumpers + * LGPL0, 1, and 3. Normally, these jumpers are set to 000 (all + * jumpered), but if they're set to 001 or 010, then the HRCW is + * read from the "I2C EEPROM". + * + * This function makes sure that the I2C EEPROM is programmed + * correctly. + */ +int misc_init_r(void) +{ + int rc = 0; + +#ifdef CONFIG_HARD_I2C + + unsigned int orig_bus = i2c_get_bus_num(); + u8 i2c_data; + +#ifdef CFG_I2C_RTC_ADDR + u8 ds1339_data[17]; +#endif + +#ifdef CFG_I2C_EEPROM_ADDR + static u8 eeprom_data[] = /* HRCW data */ + { + 0xAA, 0x55, 0xAA, /* Preamble */ + 0x7C, /* ACS=0, BYTE_EN=1111, CONT=1 */ + 0x02, 0x40, /* RCWL ADDR=0x0_0900 */ + (CFG_HRCW_LOW >> 24) & 0xFF, + (CFG_HRCW_LOW >> 16) & 0xFF, + (CFG_HRCW_LOW >> 8) & 0xFF, + CFG_HRCW_LOW & 0xFF, + 0x7C, /* ACS=0, BYTE_EN=1111, CONT=1 */ + 0x02, 0x41, /* RCWH ADDR=0x0_0904 */ + (CFG_HRCW_HIGH >> 24) & 0xFF, + (CFG_HRCW_HIGH >> 16) & 0xFF, + (CFG_HRCW_HIGH >> 8) & 0xFF, + CFG_HRCW_HIGH & 0xFF + }; + + u8 data[sizeof(eeprom_data)]; +#endif + + printf("Board revision: "); + i2c_set_bus_num(1); + if (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == 0) + printf("%u.%u (PCF8475A)\n", (i2c_data & 0x02) >> 1, i2c_data & 0x01); + else if (i2c_read(CFG_I2C_8574_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == 0) + printf("%u.%u (PCF8475)\n", (i2c_data & 0x02) >> 1, i2c_data & 0x01); + else { + printf("Unknown\n"); + rc = 1; + } + +#ifdef CFG_I2C_EEPROM_ADDR + i2c_set_bus_num(0); + + if (i2c_read(CFG_I2C_EEPROM_ADDR, 0, 2, data, sizeof(data)) == 0) { + if (memcmp(data, eeprom_data, sizeof(data)) != 0) { + if (i2c_write + (CFG_I2C_EEPROM_ADDR, 0, 2, eeprom_data, + sizeof(eeprom_data)) != 0) { + puts("Failure writing the HRCW to EEPROM via I2C.\n"); + rc = 1; + } + } + } else { + puts("Failure reading the HRCW from EEPROM via I2C.\n"); + rc = 1; + } +#endif + +#ifdef CFG_I2C_RTC_ADDR + i2c_set_bus_num(1); + + if (i2c_read(CFG_I2C_RTC_ADDR, 0, 1, ds1339_data, sizeof(ds1339_data)) + == 0) { + + /* Work-around for MPC8349E-mITX bug #13601. + If the RTC does not contain valid register values, the DS1339 + Linux driver will not work. + */ + + /* Make sure status register bits 6-2 are zero */ + ds1339_data[0x0f] &= ~0x7c; + + /* Check for a valid day register value */ + ds1339_data[0x03] &= ~0xf8; + if (ds1339_data[0x03] == 0) { + ds1339_data[0x03] = 1; + } + + /* Check for a valid date register value */ + ds1339_data[0x04] &= ~0xc0; + if ((ds1339_data[0x04] == 0) || + ((ds1339_data[0x04] & 0x0f) > 9) || + (ds1339_data[0x04] >= 0x32)) { + ds1339_data[0x04] = 1; + } + + /* Check for a valid month register value */ + ds1339_data[0x05] &= ~0x60; + + if ((ds1339_data[0x05] == 0) || + ((ds1339_data[0x05] & 0x0f) > 9) || + ((ds1339_data[0x05] >= 0x13) + && (ds1339_data[0x05] <= 0x19))) { + ds1339_data[0x05] = 1; + } + + /* Enable Oscillator and rate select */ + ds1339_data[0x0e] = 0x1c; + + /* Work-around for MPC8349E-mITX bug #13330. + Ensure that the RTC control register contains the value 0x1c. + This affects SATA performance. + */ + + if (i2c_write + (CFG_I2C_RTC_ADDR, 0, 1, ds1339_data, + sizeof(ds1339_data))) { + puts("Failure writing to the RTC via I2C.\n"); + rc = 1; + } + } else { + puts("Failure reading from the RTC via I2C.\n"); + rc = 1; + } +#endif + + i2c_set_bus_num(orig_bus); +#endif + + return rc; +} + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + ft_cpu_setup(blob, bd); + + p = ft_get_prop(blob, "/memory/reg", &len); + if (p != NULL) { + *p++ = cpu_to_be32(bd->bi_memstart); + *p = cpu_to_be32(bd->bi_memsize); + } +} +#endif diff --git a/board/mpc8349itx/pci.c b/board/mpc8349itx/pci.c new file mode 100644 index 0000000..e81ad27 --- /dev/null +++ b/board/mpc8349itx/pci.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * + * 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 <common.h> + +#ifdef CONFIG_PCI + +#include <asm/mmu.h> +#include <asm/global_data.h> +#include <pci.h> +#include <asm/mpc8349_pci.h> +#include <i2c.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* System RAM mapped to PCI space */ +#define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE + +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc8349itx_config_table[] = { + { + PCI_ANY_ID, + PCI_ANY_ID, + PCI_ANY_ID, + PCI_ANY_ID, + PCI_IDSEL_NUMBER, + PCI_ANY_ID, + pci_cfgfunc_config_device, + { + PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER} + }, + {} +}; +#endif + +static struct pci_controller pci_hose[] = { + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc8349itx_config_table, +#endif + }, + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc8349itx_config_table, +#endif + } +}; + +/************************************************************************** + * pci_init_board() + * + * NOTICE: PCI2 is not currently supported + * + */ +void pci_init_board(void) +{ + volatile immap_t *immr; + volatile clk83xx_t *clk; + volatile law83xx_t *pci_law; + volatile pot83xx_t *pci_pot; + volatile pcictrl83xx_t *pci_ctrl; + volatile pciconf83xx_t *pci_conf; + u8 reg8; + u16 reg16; + u32 reg32; + u32 dev; + struct pci_controller *hose; + + immr = (immap_t *) CFG_IMMR; + clk = (clk83xx_t *) & immr->clk; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + + hose = &pci_hose[0]; + + /* + * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode + */ + + reg32 = clk->occr; + udelay(2000); + +#ifdef CONFIG_HARD_I2C + i2c_set_bus_num(1); + /* Read the PCI_M66EN jumper setting */ + if ((i2c_read(CFG_I2C_8574_ADDR2, 0, 0, ®8, sizeof(reg8)) == 0) || + (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, ®8, sizeof(reg8)) == 0)) { + if (reg8 & I2C_8574_PCI66) + clk->occr = 0xff000000; /* 66 MHz PCI */ + else + clk->occr = 0xff600001; /* 33 MHz PCI */ + } else { + clk->occr = 0xff600001; /* 33 MHz PCI */ + } +#else + clk->occr = 0xff000000; /* 66 MHz PCI */ +#endif + + udelay(2000); + + /* + * Release PCI RST Output signal + */ + pci_ctrl[0].gcr = 0; + udelay(2000); + pci_ctrl[0].gcr = 1; + +#ifdef CONFIG_MPC83XX_PCI2 + pci_ctrl[1].gcr = 0; + udelay(2000); + pci_ctrl[1].gcr = 1; +#endif + + /* We need to wait at least a 1sec based on PCI specs */ + { + int i; + + for (i = 0; i < 1000; i++) + udelay(1000); + } + + /* + * Configure PCI Local Access Windows + */ + pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR; + pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_1G; + + pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_32M; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI1 mem space - prefetch */ + pci_pot[0].potar = (CFG_PCI1_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[0].pobar = (CFG_PCI1_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[0].pocmr = POCMR_EN | POCMR_PREFETCH_EN | POCMR_CM_256M; + + /* PCI1 IO space */ + pci_pot[1].potar = (CFG_PCI1_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[1].pobar = (CFG_PCI1_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[1].pocmr = POCMR_EN | POCMR_IO | POCMR_CM_16M; + + /* PCI1 mmio - non-prefetch mem space */ + pci_pot[2].potar = (CFG_PCI1_MMIO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[2].pobar = (CFG_PCI1_MMIO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[2].pocmr = POCMR_EN | POCMR_CM_256M; + + /* + * Configure PCI Inbound Translation Windows + */ + + /* we need RAM mapped to PCI space for the devices to + * access main memory */ + pci_ctrl[0].pitar1 = 0x0; + pci_ctrl[0].pibar1 = 0x0; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | + PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1); + + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* PCI memory prefetch space */ + pci_set_region(hose->regions + 0, + CFG_PCI1_MEM_BASE, + CFG_PCI1_MEM_PHYS, + CFG_PCI1_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH); + + /* PCI memory space */ + pci_set_region(hose->regions + 1, + CFG_PCI1_MMIO_BASE, + CFG_PCI1_MMIO_PHYS, CFG_PCI1_MMIO_SIZE, PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 2, + CFG_PCI1_IO_BASE, + CFG_PCI1_IO_PHYS, CFG_PCI1_IO_SIZE, PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose->regions + 3, + CONFIG_PCI_SYS_MEM_BUS, + CONFIG_PCI_SYS_MEM_PHYS, + gd->ram_size, PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose->region_count = 4; + + pci_setup_indirect(hose, + (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304)); + + pci_register_hose(hose); + + /* + * Write to Command register + */ + reg16 = 0xff; + dev = PCI_BDF(hose->first_busno, 0, 0); + pci_hose_read_config_word(hose, dev, PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); + +#ifdef CONFIG_MPC83XX_PCI2 + hose = &pci_hose[1]; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI2 mem space - prefetch */ + pci_pot[3].potar = (CFG_PCI2_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[3].pobar = (CFG_PCI2_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[3].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_PREFETCH_EN | POCMR_CM_256M; + + /* PCI2 IO space */ + pci_pot[4].potar = (CFG_PCI2_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[4].pobar = (CFG_PCI2_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[4].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_IO | POCMR_CM_16M; + + /* PCI2 mmio - non-prefetch mem space */ + pci_pot[5].potar = (CFG_PCI2_MMIO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[5].pobar = (CFG_PCI2_MMIO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[5].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_CM_256M; + + /* + * Configure PCI Inbound Translation Windows + */ + + /* we need RAM mapped to PCI space for the devices to + * access main memory */ + pci_ctrl[1].pitar1 = 0x0; + pci_ctrl[1].pibar1 = 0x0; + pci_ctrl[1].piebar1 = 0x0; + pci_ctrl[1].piwar1 = + PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | + (__ilog2(gd->ram_size) - 1); + + hose->first_busno = pci_hose[0].last_busno + 1; + hose->last_busno = 0xff; + + /* PCI memory prefetch space */ + pci_set_region(hose->regions + 0, + CFG_PCI2_MEM_BASE, + CFG_PCI2_MEM_PHYS, + CFG_PCI2_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH); + + /* PCI memory space */ + pci_set_region(hose->regions + 1, + CFG_PCI2_MMIO_BASE, + CFG_PCI2_MMIO_PHYS, CFG_PCI2_MMIO_SIZE, PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 2, + CFG_PCI2_IO_BASE, + CFG_PCI2_IO_PHYS, CFG_PCI2_IO_SIZE, PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose->regions + 3, + CONFIG_PCI_SYS_MEM_BUS, + CONFIG_PCI_SYS_MEM_PHYS, + gd->ram_size, PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose->region_count = 4; + + pci_setup_indirect(hose, + (CFG_IMMR + 0x8380), (CFG_IMMR + 0x8384)); + + pci_register_hose(hose); + + /* + * Write to Command register + */ + reg16 = 0xff; + dev = PCI_BDF(hose->first_busno, 0, 0); + pci_hose_read_config_word(hose, dev, PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); +#endif +} + +#endif /* CONFIG_PCI */ +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); + if (p != NULL) { + p[0] = pci_hose[0].first_busno; + p[1] = pci_hose[0].last_busno; + } + +#ifdef CONFIG_MPC83XX_PCI2 + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8600/bus-range", &len); + if (p != NULL) { + p[0] = pci_hose[1].first_busno; + p[1] = pci_hose[1].last_busno; + } +#endif +} +#endif /* CONFIG_OF_FLAT_TREE */ diff --git a/board/mpc8349itx/u-boot.lds b/board/mpc8349itx/u-boot.lds new file mode 100644 index 0000000..f044c0f --- /dev/null +++ b/board/mpc8349itx/u-boot.lds @@ -0,0 +1,120 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * + * 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) +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 : + { + cpu/mpc83xx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} +ENTRY(_start) diff --git a/board/mpc8360emds/Makefile b/board/mpc8360emds/Makefile new file mode 100644 index 0000000..5ec7a87 --- /dev/null +++ b/board/mpc8360emds/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o pci.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/ezkit533/config.mk b/board/mpc8360emds/config.mk index 36c9f99..9ace886 100644 --- a/board/ezkit533/config.mk +++ b/board/mpc8360emds/config.mk @@ -1,5 +1,5 @@ # -# (C) Copyright 2001 +# (C) Copyright 2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -21,5 +21,8 @@ # MA 02111-1307 USA # -TEXT_BASE = 0x01FC0000 -PLATFORM_CPPFLAGS += -I$(TOPDIR) +# +# MPC8360EMDS +# + +TEXT_BASE = 0xFE000000 diff --git a/board/mpc8360emds/mpc8360emds.c b/board/mpc8360emds/mpc8360emds.c new file mode 100644 index 0000000..535884c --- /dev/null +++ b/board/mpc8360emds/mpc8360emds.c @@ -0,0 +1,679 @@ +/* + * Copyright (C) 2006 Freescale Semiconductor, Inc. + * + * Dave Liu <daveliu@freescale.com> + * based on board/mpc8349emds/mpc8349emds.c + * + * 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. + */ + +#include <common.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <i2c.h> +#include <spd.h> +#include <miiphy.h> +#include <command.h> +#if defined(CONFIG_PCI) +#include <pci.h> +#endif +#if defined(CONFIG_SPD_EEPROM) +#include <spd_sdram.h> +#else +#include <asm/mmu.h> +#endif +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +const qe_iop_conf_t qe_iop_conf_tab[] = { + /* GETH1 */ + {0, 3, 1, 0, 1}, /* TxD0 */ + {0, 4, 1, 0, 1}, /* TxD1 */ + {0, 5, 1, 0, 1}, /* TxD2 */ + {0, 6, 1, 0, 1}, /* TxD3 */ + {1, 6, 1, 0, 3}, /* TxD4 */ + {1, 7, 1, 0, 1}, /* TxD5 */ + {1, 9, 1, 0, 2}, /* TxD6 */ + {1, 10, 1, 0, 2}, /* TxD7 */ + {0, 9, 2, 0, 1}, /* RxD0 */ + {0, 10, 2, 0, 1}, /* RxD1 */ + {0, 11, 2, 0, 1}, /* RxD2 */ + {0, 12, 2, 0, 1}, /* RxD3 */ + {0, 13, 2, 0, 1}, /* RxD4 */ + {1, 1, 2, 0, 2}, /* RxD5 */ + {1, 0, 2, 0, 2}, /* RxD6 */ + {1, 4, 2, 0, 2}, /* RxD7 */ + {0, 7, 1, 0, 1}, /* TX_EN */ + {0, 8, 1, 0, 1}, /* TX_ER */ + {0, 15, 2, 0, 1}, /* RX_DV */ + {0, 16, 2, 0, 1}, /* RX_ER */ + {0, 0, 2, 0, 1}, /* RX_CLK */ + {2, 9, 1, 0, 3}, /* GTX_CLK - CLK10 */ + {2, 8, 2, 0, 1}, /* GTX125 - CLK9 */ + /* GETH2 */ + {0, 17, 1, 0, 1}, /* TxD0 */ + {0, 18, 1, 0, 1}, /* TxD1 */ + {0, 19, 1, 0, 1}, /* TxD2 */ + {0, 20, 1, 0, 1}, /* TxD3 */ + {1, 2, 1, 0, 1}, /* TxD4 */ + {1, 3, 1, 0, 2}, /* TxD5 */ + {1, 5, 1, 0, 3}, /* TxD6 */ + {1, 8, 1, 0, 3}, /* TxD7 */ + {0, 23, 2, 0, 1}, /* RxD0 */ + {0, 24, 2, 0, 1}, /* RxD1 */ + {0, 25, 2, 0, 1}, /* RxD2 */ + {0, 26, 2, 0, 1}, /* RxD3 */ + {0, 27, 2, 0, 1}, /* RxD4 */ + {1, 12, 2, 0, 2}, /* RxD5 */ + {1, 13, 2, 0, 3}, /* RxD6 */ + {1, 11, 2, 0, 2}, /* RxD7 */ + {0, 21, 1, 0, 1}, /* TX_EN */ + {0, 22, 1, 0, 1}, /* TX_ER */ + {0, 29, 2, 0, 1}, /* RX_DV */ + {0, 30, 2, 0, 1}, /* RX_ER */ + {0, 31, 2, 0, 1}, /* RX_CLK */ + {2, 2, 1, 0, 2}, /* GTX_CLK = CLK10 */ + {2, 3, 2, 0, 1}, /* GTX125 - CLK4 */ + + {0, 1, 3, 0, 2}, /* MDIO */ + {0, 2, 1, 0, 1}, /* MDC */ + + {0, 0, 0, 0, QE_IOP_TAB_END}, /* END of table */ +}; + +int board_early_init_f(void) +{ + + u8 *bcsr = (u8 *)CFG_BCSR; + const immap_t *immr = (immap_t *)CFG_IMMR; + + /* Enable flash write */ + bcsr[0xa] &= ~0x04; + + /* Disable G1TXCLK, G2TXCLK h/w buffers (rev.2 h/w bug workaround) */ + if (immr->sysconf.spridr == SPR_8360_REV20 || + immr->sysconf.spridr == SPR_8360E_REV20) + bcsr[0xe] = 0x30; + + return 0; +} + +#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) +extern void ddr_enable_ecc(unsigned int dram_size); +#endif +int fixed_sdram(void); +void sdram_init(void); + +long int initdram(int board_type) +{ + volatile immap_t *im = (immap_t *) CFG_IMMR; + u32 msize = 0; + + if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) + return -1; + + /* DDR SDRAM - Main SODIMM */ + im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; +#if defined(CONFIG_SPD_EEPROM) + msize = spd_sdram(); +#else + msize = fixed_sdram(); +#endif + +#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) + /* + * Initialize DDR ECC byte + */ + ddr_enable_ecc(msize * 1024 * 1024); +#endif + /* + * Initialize SDRAM if it is on local bus. + */ + sdram_init(); + puts(" DDR RAM: "); + /* return total bus SDRAM size(bytes) -- DDR */ + return (msize * 1024 * 1024); +} + +#if !defined(CONFIG_SPD_EEPROM) +/************************************************************************* + * fixed sdram init -- doesn't use serial presence detect. + ************************************************************************/ +int fixed_sdram(void) +{ + volatile immap_t *im = (immap_t *) CFG_IMMR; + u32 msize = 0; + u32 ddr_size; + u32 ddr_size_log2; + + msize = CFG_DDR_SIZE; + for (ddr_size = msize << 20, ddr_size_log2 = 0; + (ddr_size > 1); ddr_size = ddr_size >> 1, ddr_size_log2++) { + if (ddr_size & 1) { + return -1; + } + } + im->sysconf.ddrlaw[0].ar = + LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); +#if (CFG_DDR_SIZE != 256) +#warning Currenly any ddr size other than 256 is not supported +#endif +#ifdef CONFIG_DDR_II + im->ddr.csbnds[0].csbnds = CFG_DDR_CS0_BNDS; + im->ddr.cs_config[0] = CFG_DDR_CS0_CONFIG; + im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0; + im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; + im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; + im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3; + im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG; + im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2; + im->ddr.sdram_mode = CFG_DDR_MODE; + im->ddr.sdram_mode2 = CFG_DDR_MODE2; + im->ddr.sdram_interval = CFG_DDR_INTERVAL; + im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL; +#else + im->ddr.csbnds[0].csbnds = 0x00000007; + im->ddr.csbnds[1].csbnds = 0x0008000f; + + im->ddr.cs_config[0] = CFG_DDR_CONFIG; + im->ddr.cs_config[1] = CFG_DDR_CONFIG; + + im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; + im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; + im->ddr.sdram_cfg = CFG_DDR_CONTROL; + + im->ddr.sdram_mode = CFG_DDR_MODE; + im->ddr.sdram_interval = CFG_DDR_INTERVAL; +#endif + udelay(200); + im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; + + return msize; +} +#endif /*!CFG_SPD_EEPROM */ + +int checkboard(void) +{ + puts("Board: Freescale MPC8360EMDS\n"); + return 0; +} + +/* + * if MPC8360EMDS is soldered with SDRAM + */ +#if defined(CFG_BR2_PRELIM) \ + && defined(CFG_OR2_PRELIM) \ + && defined(CFG_LBLAWBAR2_PRELIM) \ + && defined(CFG_LBLAWAR2_PRELIM) +/* + * Initialize SDRAM memory on the Local Bus. + */ + +void sdram_init(void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile lbus83xx_t *lbc = &immap->lbus; + uint *sdram_addr = (uint *) CFG_LBC_SDRAM_BASE; + + puts("\n SDRAM on Local Bus: "); + print_size(CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); + /* + * Setup SDRAM Base and Option Registers, already done in cpu_init.c + */ + /*setup mtrpt, lsrt and lbcr for LB bus */ + lbc->lbcr = CFG_LBC_LBCR; + lbc->mrtpr = CFG_LBC_MRTPR; + lbc->lsrt = CFG_LBC_LSRT; + asm("sync"); + + /* + * Configure the SDRAM controller Machine Mode Register. + */ + lbc->lsdmr = CFG_LBC_LSDMR_5; /* Normal Operation */ + lbc->lsdmr = CFG_LBC_LSDMR_1; /* Precharge All Banks */ + asm("sync"); + *sdram_addr = 0xff; + udelay(100); + + /* + * We need do 8 times auto refresh operation. + */ + lbc->lsdmr = CFG_LBC_LSDMR_2; + asm("sync"); + *sdram_addr = 0xff; /* 1 times */ + udelay(100); + *sdram_addr = 0xff; /* 2 times */ + udelay(100); + *sdram_addr = 0xff; /* 3 times */ + udelay(100); + *sdram_addr = 0xff; /* 4 times */ + udelay(100); + *sdram_addr = 0xff; /* 5 times */ + udelay(100); + *sdram_addr = 0xff; /* 6 times */ + udelay(100); + *sdram_addr = 0xff; /* 7 times */ + udelay(100); + *sdram_addr = 0xff; /* 8 times */ + udelay(100); + + /* Mode register write operation */ + lbc->lsdmr = CFG_LBC_LSDMR_4; + asm("sync"); + *(sdram_addr + 0xcc) = 0xff; + udelay(100); + + /* Normal operation */ + lbc->lsdmr = CFG_LBC_LSDMR_5 | 0x40000000; + asm("sync"); + *sdram_addr = 0xff; + udelay(100); +} +#else +void sdram_init(void) +{ + puts("SDRAM on Local Bus is NOT available!\n"); +} +#endif + +#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) +/* + * ECC user commands + */ +void ecc_print_status(void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; + + printf("\nECC mode: %s\n\n", + (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); + + /* Interrupts */ + printf("Memory Error Interrupt Enable:\n"); + printf(" Multiple-Bit Error Interrupt Enable: %d\n", + (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); + printf(" Single-Bit Error Interrupt Enable: %d\n", + (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); + printf(" Memory Select Error Interrupt Enable: %d\n\n", + (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); + + /* Error disable */ + printf("Memory Error Disable:\n"); + printf(" Multiple-Bit Error Disable: %d\n", + (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); + printf(" Sinle-Bit Error Disable: %d\n", + (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); + printf(" Memory Select Error Disable: %d\n\n", + (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); + + /* Error injection */ + printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", + ddr->data_err_inject_hi, ddr->data_err_inject_lo); + + printf("Memory Data Path Error Injection Mask ECC:\n"); + printf(" ECC Mirror Byte: %d\n", + (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); + printf(" ECC Injection Enable: %d\n", + (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); + printf(" ECC Error Injection Mask: 0x%02x\n\n", + ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); + + /* SBE counter/threshold */ + printf("Memory Single-Bit Error Management (0..255):\n"); + printf(" Single-Bit Error Threshold: %d\n", + (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); + printf(" Single-Bit Error Counter: %d\n\n", + (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); + + /* Error detect */ + printf("Memory Error Detect:\n"); + printf(" Multiple Memory Errors: %d\n", + (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); + printf(" Multiple-Bit Error: %d\n", + (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); + printf(" Single-Bit Error: %d\n", + (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); + printf(" Memory Select Error: %d\n\n", + (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); + + /* Capture data */ + printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); + printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", + ddr->capture_data_hi, ddr->capture_data_lo); + printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", + ddr->capture_ecc & CAPTURE_ECC_ECE); + + printf("Memory Error Attributes Capture:\n"); + printf(" Data Beat Number: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> + ECC_CAPT_ATTR_BNUM_SHIFT); + printf(" Transaction Size: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> + ECC_CAPT_ATTR_TSIZ_SHIFT); + printf(" Transaction Source: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> + ECC_CAPT_ATTR_TSRC_SHIFT); + printf(" Transaction Type: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> + ECC_CAPT_ATTR_TTYP_SHIFT); + printf(" Error Information Valid: %d\n\n", + ddr->capture_attributes & ECC_CAPT_ATTR_VLD); +} + +int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; + volatile u32 val; + u64 *addr; + u32 count; + register u64 *i; + u32 ret[2]; + u32 pattern[2]; + u32 writeback[2]; + + /* The pattern is written into memory to generate error */ + pattern[0] = 0xfedcba98UL; + pattern[1] = 0x76543210UL; + + /* After injecting error, re-initialize the memory with the value */ + writeback[0] = 0x01234567UL; + writeback[1] = 0x89abcdefUL; + + if (argc > 4) { + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (argc == 2) { + if (strcmp(argv[1], "status") == 0) { + ecc_print_status(); + return 0; + } else if (strcmp(argv[1], "captureclear") == 0) { + ddr->capture_address = 0; + ddr->capture_data_hi = 0; + ddr->capture_data_lo = 0; + ddr->capture_ecc = 0; + ddr->capture_attributes = 0; + return 0; + } + } + if (argc == 3) { + if (strcmp(argv[1], "sbecnt") == 0) { + val = simple_strtoul(argv[2], NULL, 10); + if (val > 255) { + printf("Incorrect Counter value, " + "should be 0..255\n"); + return 1; + } + + val = (val << ECC_ERROR_MAN_SBEC_SHIFT); + val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); + + ddr->err_sbe = val; + return 0; + } else if (strcmp(argv[1], "sbethr") == 0) { + val = simple_strtoul(argv[2], NULL, 10); + if (val > 255) { + printf("Incorrect Counter value, " + "should be 0..255\n"); + return 1; + } + + val = (val << ECC_ERROR_MAN_SBET_SHIFT); + val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); + + ddr->err_sbe = val; + return 0; + } else if (strcmp(argv[1], "errdisable") == 0) { + val = ddr->err_disable; + + if (strcmp(argv[2], "+sbe") == 0) { + val |= ECC_ERROR_DISABLE_SBED; + } else if (strcmp(argv[2], "+mbe") == 0) { + val |= ECC_ERROR_DISABLE_MBED; + } else if (strcmp(argv[2], "+mse") == 0) { + val |= ECC_ERROR_DISABLE_MSED; + } else if (strcmp(argv[2], "+all") == 0) { + val |= (ECC_ERROR_DISABLE_SBED | + ECC_ERROR_DISABLE_MBED | + ECC_ERROR_DISABLE_MSED); + } else if (strcmp(argv[2], "-sbe") == 0) { + val &= ~ECC_ERROR_DISABLE_SBED; + } else if (strcmp(argv[2], "-mbe") == 0) { + val &= ~ECC_ERROR_DISABLE_MBED; + } else if (strcmp(argv[2], "-mse") == 0) { + val &= ~ECC_ERROR_DISABLE_MSED; + } else if (strcmp(argv[2], "-all") == 0) { + val &= ~(ECC_ERROR_DISABLE_SBED | + ECC_ERROR_DISABLE_MBED | + ECC_ERROR_DISABLE_MSED); + } else { + printf("Incorrect err_disable field\n"); + return 1; + } + + ddr->err_disable = val; + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); + return 0; + } else if (strcmp(argv[1], "errdetectclr") == 0) { + val = ddr->err_detect; + + if (strcmp(argv[2], "mme") == 0) { + val |= ECC_ERROR_DETECT_MME; + } else if (strcmp(argv[2], "sbe") == 0) { + val |= ECC_ERROR_DETECT_SBE; + } else if (strcmp(argv[2], "mbe") == 0) { + val |= ECC_ERROR_DETECT_MBE; + } else if (strcmp(argv[2], "mse") == 0) { + val |= ECC_ERROR_DETECT_MSE; + } else if (strcmp(argv[2], "all") == 0) { + val |= (ECC_ERROR_DETECT_MME | + ECC_ERROR_DETECT_MBE | + ECC_ERROR_DETECT_SBE | + ECC_ERROR_DETECT_MSE); + } else { + printf("Incorrect err_detect field\n"); + return 1; + } + + ddr->err_detect = val; + return 0; + } else if (strcmp(argv[1], "injectdatahi") == 0) { + val = simple_strtoul(argv[2], NULL, 16); + + ddr->data_err_inject_hi = val; + return 0; + } else if (strcmp(argv[1], "injectdatalo") == 0) { + val = simple_strtoul(argv[2], NULL, 16); + + ddr->data_err_inject_lo = val; + return 0; + } else if (strcmp(argv[1], "injectecc") == 0) { + val = simple_strtoul(argv[2], NULL, 16); + if (val > 0xff) { + printf("Incorrect ECC inject mask, " + "should be 0x00..0xff\n"); + return 1; + } + val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); + + ddr->ecc_err_inject = val; + return 0; + } else if (strcmp(argv[1], "inject") == 0) { + val = ddr->ecc_err_inject; + + if (strcmp(argv[2], "en") == 0) + val |= ECC_ERR_INJECT_EIEN; + else if (strcmp(argv[2], "dis") == 0) + val &= ~ECC_ERR_INJECT_EIEN; + else + printf("Incorrect command\n"); + + ddr->ecc_err_inject = val; + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); + return 0; + } else if (strcmp(argv[1], "mirror") == 0) { + val = ddr->ecc_err_inject; + + if (strcmp(argv[2], "en") == 0) + val |= ECC_ERR_INJECT_EMB; + else if (strcmp(argv[2], "dis") == 0) + val &= ~ECC_ERR_INJECT_EMB; + else + printf("Incorrect command\n"); + + ddr->ecc_err_inject = val; + return 0; + } + } + if (argc == 4) { + if (strcmp(argv[1], "testdw") == 0) { + addr = (u64 *) simple_strtoul(argv[2], NULL, 16); + count = simple_strtoul(argv[3], NULL, 16); + + if ((u32) addr % 8) { + printf("Address not alligned on " + "double word boundary\n"); + return 1; + } + disable_interrupts(); + + for (i = addr; i < addr + count; i++) { + + /* enable injects */ + ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); + + /* write memory location injecting errors */ + ppcDWstore((u32 *) i, pattern); + __asm__ __volatile__("sync"); + + /* disable injects */ + ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); + + /* read data, this generates ECC error */ + ppcDWload((u32 *) i, ret); + __asm__ __volatile__("sync"); + + /* re-initialize memory, double word write the location again, + * generates new ECC code this time */ + ppcDWstore((u32 *) i, writeback); + __asm__ __volatile__("sync"); + } + enable_interrupts(); + return 0; + } + if (strcmp(argv[1], "testword") == 0) { + addr = (u64 *) simple_strtoul(argv[2], NULL, 16); + count = simple_strtoul(argv[3], NULL, 16); + + if ((u32) addr % 8) { + printf("Address not alligned on " + "double word boundary\n"); + return 1; + } + disable_interrupts(); + + for (i = addr; i < addr + count; i++) { + + /* enable injects */ + ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); + + /* write memory location injecting errors */ + *(u32 *) i = 0xfedcba98UL; + __asm__ __volatile__("sync"); + + /* sub double word write, + * bus will read-modify-write, + * generates ECC error */ + *((u32 *) i + 1) = 0x76543210UL; + __asm__ __volatile__("sync"); + + /* disable injects */ + ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; + __asm__ __volatile__("sync"); + __asm__ __volatile__("isync"); + + /* re-initialize memory, + * double word write the location again, + * generates new ECC code this time */ + ppcDWstore((u32 *) i, writeback); + __asm__ __volatile__("sync"); + } + enable_interrupts(); + return 0; + } + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD(ecc, 4, 0, do_ecc, + "ecc - support for DDR ECC features\n", + "status - print out status info\n" + "ecc captureclear - clear capture regs data\n" + "ecc sbecnt <val> - set Single-Bit Error counter\n" + "ecc sbethr <val> - set Single-Bit Threshold\n" + "ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n" + " [-|+]sbe - Single-Bit Error\n" + " [-|+]mbe - Multiple-Bit Error\n" + " [-|+]mse - Memory Select Error\n" + " [-|+]all - all errors\n" + "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" + " mme - Multiple Memory Errors\n" + " sbe - Single-Bit Error\n" + " mbe - Multiple-Bit Error\n" + " mse - Memory Select Error\n" + " all - all errors\n" + "ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n" + "ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n" + "ecc injectecc <ecc> - set ECC Error Injection Mask\n" + "ecc inject <en|dis> - enable/disable error injection\n" + "ecc mirror <en|dis> - enable/disable mirror byte\n" + "ecc testdw <addr> <cnt> - test mem region with double word access:\n" + " - enables injects\n" + " - writes pattern injecting errors with double word access\n" + " - disables injects\n" + " - reads pattern back with double word access, generates error\n" + " - re-inits memory\n" + "ecc testword <addr> <cnt> - test mem region with word access:\n" + " - enables injects\n" + " - writes pattern injecting errors with word access\n" + " - writes pattern with word access, generates error\n" + " - disables injects\n" " - re-inits memory"); +#endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + ft_cpu_setup(blob, bd); + + p = ft_get_prop(blob, "/memory/reg", &len); + if (p != NULL) { + *p++ = cpu_to_be32(bd->bi_memstart); + *p = cpu_to_be32(bd->bi_memsize); + } +} +#endif diff --git a/board/mpc8360emds/pci.c b/board/mpc8360emds/pci.c new file mode 100644 index 0000000..67cd709 --- /dev/null +++ b/board/mpc8360emds/pci.c @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2006 Freescale Semiconductor, 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. + */ + +/* + * PCI Configuration space access support for MPC83xx PCI Bridge + */ +#include <asm/mmu.h> +#include <asm/io.h> +#include <common.h> +#include <pci.h> +#include <i2c.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +#include <asm/fsl_i2c.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_PCI) +#define PCI_FUNCTION_CONFIG 0x44 +#define PCI_FUNCTION_CFG_LOCK 0x20 + +/* + * Initialize PCI Devices, report devices found + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc83xxemds_config_table[] = { + { + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_cfgfunc_config_device, + {PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMON_MEMORY | PCI_COMMAND_MASTER} + }, + {} +} +#endif +static struct pci_controller hose[] = { + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc83xxemds_config_table, +#endif + }, +}; + +/********************************************************************** + * pci_init_board() + *********************************************************************/ +void pci_init_board(void) +#ifdef CONFIG_PCISLAVE +{ + u16 reg16; + volatile immap_t *immr; + volatile law83xx_t *pci_law; + volatile pot83xx_t *pci_pot; + volatile pcictrl83xx_t *pci_ctrl; + volatile pciconf83xx_t *pci_conf; + + immr = (immap_t *) CFG_IMMR; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + /* + * Configure PCI Inbound Translation Windows + */ + pci_ctrl[0].pitar0 = 0x0; + pci_ctrl[0].pibar0 = 0x0; + pci_ctrl[0].piwar0 = PIWAR_EN | PIWAR_RTT_SNOOP | + PIWAR_WTT_SNOOP | PIWAR_IWS_4K; + + pci_ctrl[0].pitar1 = 0x0; + pci_ctrl[0].pibar1 = 0x0; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 &= ~PIWAR_EN; + + pci_ctrl[0].pitar2 = 0x0; + pci_ctrl[0].pibar2 = 0x0; + pci_ctrl[0].piebar2 = 0x0; + pci_ctrl[0].piwar2 &= ~PIWAR_EN; + + hose[0].first_busno = 0; + hose[0].last_busno = 0xff; + pci_setup_indirect(&hose[0], + (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304)); + reg16 = 0xff; + + pci_hose_read_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_STATUS, 0xffff); + pci_hose_write_config_byte(&hose[0], PCI_BDF(0, 0, 0), + PCI_LATENCY_TIMER, 0x80); + + /* + * Unlock configuration lock in PCI function configuration register. + */ + pci_hose_read_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_FUNCTION_CONFIG, ®16); + reg16 &= ~(PCI_FUNCTION_CFG_LOCK); + pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0), + PCI_FUNCTION_CONFIG, reg16); + + printf("Enabled PCI 32bit Agent Mode\n"); +} +#else +{ + volatile immap_t *immr; + volatile clk83xx_t *clk; + volatile law83xx_t *pci_law; + volatile pot83xx_t *pci_pot; + volatile pcictrl83xx_t *pci_ctrl; + volatile pciconf83xx_t *pci_conf; + + u8 val8, orig_i2c_bus; + u16 reg16; + u32 val32; + u32 dev; + + immr = (immap_t *) CFG_IMMR; + clk = (clk83xx_t *) & immr->clk; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + /* + * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode + */ + val32 = clk->occr; + udelay(2000); +#if defined(PCI_66M) + clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2; + printf("PCI clock is 66MHz\n"); +#elif defined(PCI_33M) + clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2 | + OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 | OCCR_PCICR; + printf("PCI clock is 33MHz\n"); +#else + clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2; + printf("PCI clock is 66MHz\n"); +#endif + udelay(2000); + + /* + * Configure PCI Local Access Windows + */ + pci_law[0].bar = CFG_PCI_MEM_PHYS & LAWBAR_BAR; + pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_512M; + + pci_law[1].bar = CFG_PCI_IO_PHYS & LAWBAR_BAR; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_1M; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI mem space - prefetch */ + pci_pot[0].potar = (CFG_PCI_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[0].pobar = (CFG_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[0].pocmr = + POCMR_EN | POCMR_SE | (POCMR_CM_256M & POCMR_CM_MASK); + + /* PCI mmio - non-prefetch mem space */ + pci_pot[1].potar = (CFG_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[1].pobar = (CFG_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[1].pocmr = POCMR_EN | (POCMR_CM_256M & POCMR_CM_MASK); + + /* PCI IO space */ + pci_pot[2].potar = (CFG_PCI_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[2].pobar = (CFG_PCI_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[2].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_1M & POCMR_CM_MASK); + + /* + * Configure PCI Inbound Translation Windows + */ + pci_ctrl[0].pitar1 = (CFG_PCI_SLV_MEM_LOCAL >> 12) & PITAR_TA_MASK; + pci_ctrl[0].pibar1 = (CFG_PCI_SLV_MEM_BUS >> 12) & PIBAR_MASK; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 = + PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | + PIWAR_IWS_2G; + + /* + * Assign PIB PMC slot to desired PCI bus + */ + + /* Switch temporarily to I2C bus #2 */ + orig_i2c_bus = i2c_get_bus_num(); + i2c_set_bus_num(1); + + val8 = 0; + i2c_write(0x23, 0x6, 1, &val8, 1); + i2c_write(0x23, 0x7, 1, &val8, 1); + val8 = 0xff; + i2c_write(0x23, 0x2, 1, &val8, 1); + i2c_write(0x23, 0x3, 1, &val8, 1); + + val8 = 0; + i2c_write(0x26, 0x6, 1, &val8, 1); + val8 = 0x34; + i2c_write(0x26, 0x7, 1, &val8, 1); + + val8 = 0xf3; /*PMC1, PMC2, PMC3 slot to PCI bus */ + i2c_write(0x26, 0x2, 1, &val8, 1); + val8 = 0xff; + i2c_write(0x26, 0x3, 1, &val8, 1); + + val8 = 0; + i2c_write(0x27, 0x6, 1, &val8, 1); + i2c_write(0x27, 0x7, 1, &val8, 1); + val8 = 0xff; + i2c_write(0x27, 0x2, 1, &val8, 1); + val8 = 0xef; + i2c_write(0x27, 0x3, 1, &val8, 1); + asm("eieio"); + + /* Reset to original I2C bus */ + i2c_set_bus_num(orig_i2c_bus); + + /* + * Release PCI RST Output signal + */ + udelay(2000); + pci_ctrl[0].gcr = 1; + udelay(2000); + + hose[0].first_busno = 0; + hose[0].last_busno = 0xff; + + /* PCI memory prefetch space */ + pci_set_region(hose[0].regions + 0, + CFG_PCI_MEM_BASE, + CFG_PCI_MEM_PHYS, + CFG_PCI_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH); + + /* PCI memory space */ + pci_set_region(hose[0].regions + 1, + CFG_PCI_MMIO_BASE, + CFG_PCI_MMIO_PHYS, CFG_PCI_MMIO_SIZE, PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose[0].regions + 2, + CFG_PCI_IO_BASE, + CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose[0].regions + 3, + CFG_PCI_SLV_MEM_LOCAL, + CFG_PCI_SLV_MEM_BUS, + CFG_PCI_SLV_MEM_SIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose[0].region_count = 4; + + pci_setup_indirect(&hose[0], + (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304)); + + pci_register_hose(hose); + + /* + * Write command register + */ + reg16 = 0xff; + dev = PCI_BDF(0, 0, 0); + pci_hose_read_config_word(&hose[0], dev, PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(&hose[0], dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(&hose[0], dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(&hose[0], dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(&hose[0], dev, PCI_CACHE_LINE_SIZE, 0x08); + + printf("PCI 32bit bus on PMC1 & PMC2 & PMC3\n"); + + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); +} +#endif /* CONFIG_PCISLAVE */ + +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); + if (p != NULL) { + p[0] = hose[0].first_busno; + p[1] = hose[0].last_busno; + } +} +#endif /* CONFIG_OF_FLAT_TREE */ +#endif /* CONFIG_PCI */ diff --git a/board/mpc8360emds/u-boot.lds b/board/mpc8360emds/u-boot.lds new file mode 100644 index 0000000..937c87a --- /dev/null +++ b/board/mpc8360emds/u-boot.lds @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2006 + * 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) +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 : + { + cpu/mpc83xx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} +ENTRY(_start) diff --git a/board/mpl/common/memtst.c b/board/mpl/common/memtst.c index ff1190a..1d28513 100644 --- a/board/mpl/common/memtst.c +++ b/board/mpl/common/memtst.c @@ -48,7 +48,7 @@ int testdram (void) #include <common.h> #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/board/mpl/mip405/mip405.c b/board/mpl/mip405/mip405.c index 34f3289..4b1c1c0 100644 --- a/board/mpl/mip405/mip405.c +++ b/board/mpl/mip405/mip405.c @@ -65,7 +65,7 @@ #include <common.h> #include "mip405.h" #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h> #include <miiphy.h> #include "../common/common_util.h" #include <i2c.h> @@ -73,9 +73,6 @@ DECLARE_GLOBAL_DATA_PTR; -extern block_dev_desc_t * scsi_get_dev(int dev); -extern block_dev_desc_t * ide_get_dev(int dev); - #undef SDRAM_DEBUG #define ENABLE_ECC /* for ecc boards */ #define FALSE 0 diff --git a/board/nc650/nand.c b/board/nc650/nand.c index de54386..6bb7c31 100644 --- a/board/nc650/nand.c +++ b/board/nc650/nand.c @@ -106,12 +106,13 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) * Members with a "?" were not set in the merged testing-NAND branch, * so they are not set here either. */ -void board_nand_init(struct nand_chip *nand) +int board_nand_init(struct nand_chip *nand) { nand->hwcontrol = nc650_hwcontrol; nand->eccmode = NAND_ECC_SOFT; nand->chip_delay = 12; /* nand->options = NAND_SAMSUNG_LP_OPTIONS;*/ + return 0; } #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ diff --git a/board/netstar/nand.c b/board/netstar/nand.c index f470c1a..7852365 100644 --- a/board/netstar/nand.c +++ b/board/netstar/nand.c @@ -55,12 +55,13 @@ static int netstar_nand_ready(struct mtd_info *mtd) } ***/ -void board_nand_init(struct nand_chip *nand) +int board_nand_init(struct nand_chip *nand) { nand->options = NAND_SAMSUNG_LP_OPTIONS; nand->eccmode = NAND_ECC_SOFT; nand->hwcontrol = netstar_nand_hwcontrol; /* nand->dev_ready = netstar_nand_ready; */ nand->chip_delay = 18; + return 0; } #endif diff --git a/board/prodrive/alpr/Makefile b/board/prodrive/alpr/Makefile new file mode 100644 index 0000000..00dc180 --- /dev/null +++ b/board/prodrive/alpr/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o fpga.o nand.o +SOBJS = init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend *~ + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/prodrive/alpr/alpr.c b/board/prodrive/alpr/alpr.c new file mode 100644 index 0000000..5abc87d --- /dev/null +++ b/board/prodrive/alpr/alpr.c @@ -0,0 +1,317 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> +#include <asm/processor.h> +#include <spd_sdram.h> +#include <ppc4xx_enet.h> +#include <miiphy.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern int alpr_fpga_init(void); + +int board_early_init_f (void) +{ + /*------------------------------------------------------------------------- + * Initialize EBC CONFIG + *-------------------------------------------------------------------------*/ + mtebc(xbcfg, EBC_CFG_LE_UNLOCK | + EBC_CFG_PTD_DISABLE | EBC_CFG_RTC_64PERCLK | + EBC_CFG_ATC_PREVIOUS | EBC_CFG_DTC_PREVIOUS | + EBC_CFG_CTC_PREVIOUS | EBC_CFG_EMC_NONDEFAULT | + EBC_CFG_PME_DISABLE | EBC_CFG_PR_32); + + /*-------------------------------------------------------------------- + * Setup the interrupt controller polarities, triggers, etc. + *-------------------------------------------------------------------*/ + mtdcr (uic0sr, 0xffffffff); /* clear all */ + mtdcr (uic0er, 0x00000000); /* disable all */ + mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */ + mtdcr (uic0pr, 0xfffffe03); /* per manual */ + mtdcr (uic0tr, 0x01c00000); /* per manual */ + mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic0sr, 0xffffffff); /* clear all */ + + mtdcr (uic1sr, 0xffffffff); /* clear all */ + mtdcr (uic1er, 0x00000000); /* disable all */ + mtdcr (uic1cr, 0x00000000); /* all non-critical */ + mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */ + mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */ + mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic1sr, 0xffffffff); /* clear all */ + + mtdcr (uic2sr, 0xffffffff); /* clear all */ + mtdcr (uic2er, 0x00000000); /* disable all */ + mtdcr (uic2cr, 0x00000000); /* all non-critical */ + mtdcr (uic2pr, 0xffffffff); /* per ref-board manual */ + mtdcr (uic2tr, 0x00ff8c0f); /* per ref-board manual */ + mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic2sr, 0xffffffff); /* clear all */ + + mtdcr (uicb0sr, 0xfc000000); /* clear all */ + mtdcr (uicb0er, 0x00000000); /* disable all */ + mtdcr (uicb0cr, 0x00000000); /* all non-critical */ + mtdcr (uicb0pr, 0xfc000000); /* */ + mtdcr (uicb0tr, 0x00000000); /* */ + mtdcr (uicb0vr, 0x00000001); /* */ + + /* Setup shutdown/SSD empty interrupt as inputs */ + out32(GPIO0_TCR, in32(GPIO0_TCR) & ~(CFG_GPIO_SHUTDOWN | CFG_GPIO_SSD_EMPTY)); + out32(GPIO0_ODR, in32(GPIO0_ODR) & ~(CFG_GPIO_SHUTDOWN | CFG_GPIO_SSD_EMPTY)); + + /* Setup GPIO/IRQ multiplexing */ + mtsdr(sdr_pfc0, 0x01a33e00); + + return 0; +} + +int last_stage_init(void) +{ + unsigned short reg; + + /* + * Configure LED's of both Marvell 88E1111 PHY's + * + * This has to be done after the 4xx ethernet driver is loaded, + * so "last_stage_init()" is the right place. + */ + miiphy_read("ppc_4xx_eth2", CONFIG_PHY2_ADDR, 0x18, ®); + reg |= 0x0001; + miiphy_write("ppc_4xx_eth2", CONFIG_PHY2_ADDR, 0x18, reg); + miiphy_read("ppc_4xx_eth3", CONFIG_PHY3_ADDR, 0x18, ®); + reg |= 0x0001; + miiphy_write("ppc_4xx_eth3", CONFIG_PHY3_ADDR, 0x18, reg); + + return 0; +} + +static int board_rev(void) +{ + /* Setup as input */ + out32(GPIO0_TCR, in32(GPIO0_TCR) & ~(CFG_GPIO_REV0 | CFG_GPIO_REV1)); + out32(GPIO0_ODR, in32(GPIO0_ODR) & ~(CFG_GPIO_REV0 | CFG_GPIO_REV1)); + + return (in32(GPIO0_IR) >> 16) & 0x3; +} + +int checkboard (void) +{ + char *s = getenv ("serial#"); + + printf ("Board: ALPR"); + if (s != NULL) { + puts (", serial# "); + puts (s); + } + printf(" (Rev. %d)\n", board_rev()); + + return (0); +} + +#if defined(CFG_DRAM_TEST) +int testdram (void) +{ + uint *pstart = (uint *) 0x00000000; + uint *pend = (uint *) 0x08000000; + uint *p; + + for (p = pstart; p < pend; p++) + *p = 0xaaaaaaaa; + + for (p = pstart; p < pend; p++) { + if (*p != 0xaaaaaaaa) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + + for (p = pstart; p < pend; p++) + *p = 0x55555555; + + for (p = pstart; p < pend; p++) { + if (*p != 0x55555555) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + return 0; +} +#endif + +/************************************************************************* + * pci_pre_init + * + * This routine is called just prior to registering the hose and gives + * the board the opportunity to check things. Returning a value of zero + * indicates that things are bad & PCI initialization should be aborted. + * + * Different boards may wish to customize the pci controller structure + * (add regions, override default access routines, etc) or perform + * certain pre-initialization actions. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) +int pci_pre_init(struct pci_controller * hose ) +{ + unsigned long strap; + + /*--------------------------------------------------------------------------+ + * The ocotea board is always configured as the host & requires the + * PCI arbiter to be enabled. + *--------------------------------------------------------------------------*/ + mfsdr(sdr_sdstp1, strap); + if( (strap & SDR0_SDSTP1_PAE_MASK) == 0 ){ + printf("PCI: SDR0_STRP1[%08lX] - PCI Arbiter disabled.\n",strap); + return 0; + } + + /* FPGA Init */ + alpr_fpga_init (); + + return 1; +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ + +/************************************************************************* + * pci_target_init + * + * The bootstrap configuration provides default settings for the pci + * inbound map (PIM). But the bootstrap config choices are limited and + * may not be sufficient for a given board. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) +void pci_target_init(struct pci_controller * hose ) +{ + /*--------------------------------------------------------------------------+ + * Disable everything + *--------------------------------------------------------------------------*/ + out32r( PCIX0_PIM0SA, 0 ); /* disable */ + out32r( PCIX0_PIM1SA, 0 ); /* disable */ + out32r( PCIX0_PIM2SA, 0 ); /* disable */ + out32r( PCIX0_EROMBA, 0 ); /* disable expansion rom */ + + /*--------------------------------------------------------------------------+ + * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 strapping + * options to not support sizes such as 128/256 MB. + *--------------------------------------------------------------------------*/ + out32r( PCIX0_PIM0LAL, CFG_SDRAM_BASE ); + out32r( PCIX0_PIM0LAH, 0 ); + out32r( PCIX0_PIM0SA, ~(gd->ram_size - 1) | 1 ); + + out32r( PCIX0_BAR0, 0 ); + + /*--------------------------------------------------------------------------+ + * Program the board's subsystem id/vendor id + *--------------------------------------------------------------------------*/ + out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID ); + out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_DEVICEID ); + + out16r( PCIX0_CMD, in16r(PCIX0_CMD) | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ + +/************************************************************************* + * is_pci_host + * + * This routine is called to determine if a pci scan should be + * performed. With various hardware environments (especially cPCI and + * PPMC) it's insufficient to depend on the state of the arbiter enable + * bit in the strap register, or generic host/adapter assumptions. + * + * Rather than hard-code a bad assumption in the general 440 code, the + * 440 pci code requires the board to decide at runtime. + * + * Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * + ************************************************************************/ +#if defined(CONFIG_PCI) + +static void wait_for_pci_ready(void) +{ + /* + * Configure EREADY as input + */ + out32(GPIO0_TCR, in32(GPIO0_TCR) & ~CFG_GPIO_EREADY); + udelay(1000); + + for (;;) { + if (in32(GPIO0_IR) & CFG_GPIO_EREADY) + return; + } + +} + +int is_pci_host(struct pci_controller *hose) +{ + wait_for_pci_ready(); + return 1; /* return 1 for host controller */ +} +#endif /* defined(CONFIG_PCI) */ + +/************************************************************************* + * pci_master_init + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) +void pci_master_init(struct pci_controller *hose) +{ + /*--------------------------------------------------------------------------+ + | PowerPC440 PCI Master configuration. + | Map PLB/processor addresses to PCI memory space. + | PLB address 0xA0000000-0xCFFFFFFF ==> PCI address 0x80000000-0xCFFFFFFF + | Use byte reversed out routines to handle endianess. + | Make this region non-prefetchable. + +--------------------------------------------------------------------------*/ + out32r( PCIX0_POM0SA, 0 ); /* disable */ + out32r( PCIX0_POM1SA, 0 ); /* disable */ + out32r( PCIX0_POM2SA, 0 ); /* disable */ + + out32r(PCIX0_POM0LAL, CFG_PCI_MEMBASE); /* PMM0 Local Address */ + out32r(PCIX0_POM0LAH, 0x00000003); /* PMM0 Local Address */ + out32r(PCIX0_POM0PCIAL, CFG_PCI_MEMBASE); /* PMM0 PCI Low Address */ + out32r(PCIX0_POM0PCIAH, 0x00000000); /* PMM0 PCI High Address */ + out32r(PCIX0_POM0SA, ~(0x10000000 - 1) | 1); /* 256MB + enable region */ + + out32r(PCIX0_POM1LAL, CFG_PCI_MEMBASE2); /* PMM0 Local Address */ + out32r(PCIX0_POM1LAH, 0x00000003); /* PMM0 Local Address */ + out32r(PCIX0_POM1PCIAL, CFG_PCI_MEMBASE2); /* PMM0 PCI Low Address */ + out32r(PCIX0_POM1PCIAH, 0x00000000); /* PMM0 PCI High Address */ + out32r(PCIX0_POM1SA, ~(0x10000000 - 1) | 1); /* 256MB + enable region */ +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) */ + +#ifdef CONFIG_POST +/* + * Returns 1 if keys pressed to start the power-on long-running tests + * Called from board_init_f(). + */ +int post_hotkeys_pressed(void) +{ + + return (ctrlc()); +} +#endif diff --git a/board/amcc/yellowstone/config.mk b/board/prodrive/alpr/config.mk index 4ab0ea0..9e18335 100644 --- a/board/amcc/yellowstone/config.mk +++ b/board/prodrive/alpr/config.mk @@ -1,5 +1,5 @@ # -# (C) Copyright 2002 +# (C) Copyright 2004 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -22,15 +22,15 @@ # # -# esd ADCIOP boards +# AMCC 440GX Reference Platform (Ocotea) board # -#TEXT_BASE = 0x00001000 +#TEXT_BASE = 0xFFFE0000 ifeq ($(ramsym),1) -TEXT_BASE = 0xFBD00000 +TEXT_BASE = 0x07FD0000 else -TEXT_BASE = 0xFFF80000 +TEXT_BASE = 0xFFFC0000 endif PLATFORM_CPPFLAGS += -DCONFIG_440=1 diff --git a/board/prodrive/alpr/fpga.c b/board/prodrive/alpr/fpga.c new file mode 100644 index 0000000..e94360f --- /dev/null +++ b/board/prodrive/alpr/fpga.c @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2006 + * Heiko Schocher, DENX Software Engineering, hs@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 + * + */ + +/* + * Altera FPGA configuration support for the ALPR computer from prodrive + */ + +#include <common.h> +#include <altera.h> +#include <ACEX1K.h> +#include <command.h> +#include <asm-ppc/processor.h> +#include <ppc440.h> +#include "fpga.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_FPGA) + +#ifdef FPGA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +static unsigned long regval; + +#define SET_GPIO_REG_0(reg, bit) { \ + regval = in32(reg); \ + regval &= ~(0x80000000 >> bit); \ + out32(reg, regval); \ + } + +#define SET_GPIO_REG_1(reg, bit) { \ + regval = in32(reg); \ + regval |= (0x80000000 >> bit); \ + out32(reg, regval); \ + } + +#define SET_GPIO_0(bit) SET_GPIO_REG_0(GPIO0_OR, bit) +#define SET_GPIO_1(bit) SET_GPIO_REG_1(GPIO0_OR, bit) + +#define FPGA_PRG (0x80000000 >> CFG_GPIO_PROG_EN) +#define FPGA_CONFIG (0x80000000 >> CFG_GPIO_CONFIG) +#define FPGA_DATA (0x80000000 >> CFG_GPIO_DATA) +#define FPGA_CLK (0x80000000 >> CFG_GPIO_CLK) +#define OLD_VAL (FPGA_PRG | FPGA_CONFIG) + +#define SET_FPGA(data) out32(GPIO0_OR, data) + +#define FPGA_WRITE_1 { \ + SET_FPGA(OLD_VAL | 0 | FPGA_DATA); /* set data to 1 */ \ + SET_FPGA(OLD_VAL | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ + +#define FPGA_WRITE_0 { \ + SET_FPGA(OLD_VAL | 0 | 0 ); /* set data to 0 */ \ + SET_FPGA(OLD_VAL | FPGA_CLK | 0 );} /* set data to 1 */ + +/* Plattforminitializations */ +/* Here we have to set the FPGA Chain */ +/* PROGRAM_PROG_EN = HIGH */ +/* PROGRAM_SEL_DPR = LOW */ +int fpga_pre_fn (int cookie) +{ + unsigned long reg; + + reg = in32(GPIO0_IR); + /* Enable the FPGA Chain */ + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_PROG_EN); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_PROG_EN); + SET_GPIO_1(CFG_GPIO_PROG_EN); + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_SEL_DPR); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_SEL_DPR); + SET_GPIO_0((CFG_GPIO_SEL_DPR)); + + /* initialize the GPIO Pins */ + /* output */ + SET_GPIO_0(CFG_GPIO_CLK); + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_CLK); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CLK); + + /* output */ + SET_GPIO_0(CFG_GPIO_DATA); + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_DATA); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_DATA); + + /* First we set STATUS to 0 then as an input */ + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_STATUS); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_STATUS); + SET_GPIO_0(CFG_GPIO_STATUS); + SET_GPIO_REG_0(GPIO0_TCR, CFG_GPIO_STATUS); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_STATUS); + + /* output */ + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_CONFIG); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CONFIG); + SET_GPIO_0(CFG_GPIO_CONFIG); + + /* input */ + SET_GPIO_0(CFG_GPIO_CON_DON); + SET_GPIO_REG_0(GPIO0_TCR, CFG_GPIO_CON_DON); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CON_DON); + + /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */ + SET_GPIO_0(CFG_GPIO_CONFIG); + return FPGA_SUCCESS; +} + +/* Set the state of CONFIG Pin */ +int fpga_config_fn (int assert_config, int flush, int cookie) +{ + if (assert_config) { + SET_GPIO_1(CFG_GPIO_CONFIG); + } else { + SET_GPIO_0(CFG_GPIO_CONFIG); + } + return FPGA_SUCCESS; +} + +/* Returns the state of STATUS Pin */ +int fpga_status_fn (int cookie) +{ + unsigned long reg; + + reg = in32(GPIO0_IR); + if (reg &= (0x80000000 >> CFG_GPIO_STATUS)) { + PRINTF("STATUS = HIGH\n"); + return FPGA_FAIL; + } + PRINTF("STATUS = LOW\n"); + return FPGA_SUCCESS; +} + +/* Returns the state of CONF_DONE Pin */ +int fpga_done_fn (int cookie) +{ + unsigned long reg; + reg = in32(GPIO0_IR); + if (reg &= (0x80000000 >> CFG_GPIO_CON_DON)) { + PRINTF("CONF_DON = HIGH\n"); + return FPGA_FAIL; + } + PRINTF("CONF_DON = LOW\n"); + return FPGA_SUCCESS; +} + +/* writes the complete buffer to the FPGA + writing the complete buffer in one function is much faster, + then calling it for every bit */ +int fpga_write_fn (void *buf, size_t len, int flush, int cookie) +{ + size_t bytecount = 0; + unsigned char *data = (unsigned char *) buf; + unsigned char val=0; + int i; + int len_40 = len / 40; + + while (bytecount < len) { + val = data[bytecount++]; + i = 8; + do { + if (val & 0x01) { + FPGA_WRITE_1; + } else { + FPGA_WRITE_0; + } + val >>= 1; + i --; + } while (i > 0); + +#ifdef CFG_FPGA_PROG_FEEDBACK + if (bytecount % len_40 == 0) { + putc ('.'); /* let them know we are alive */ +#ifdef CFG_FPGA_CHECK_CTRLC + if (ctrlc ()) + return FPGA_FAIL; +#endif + } +#endif + } + return FPGA_SUCCESS; +} + +/* called, when programming is aborted */ +int fpga_abort_fn (int cookie) +{ + SET_GPIO_1((CFG_GPIO_SEL_DPR)); + return FPGA_SUCCESS; +} + +/* called, when programming was succesful */ +int fpga_post_fn (int cookie) +{ + return fpga_abort_fn (cookie); +} + +/* Note that these are pointers to code that is in Flash. They will be + * relocated at runtime. + */ +Altera_CYC2_Passive_Serial_fns fpga_fns = { + fpga_pre_fn, + fpga_config_fn, + fpga_status_fn, + fpga_done_fn, + fpga_write_fn, + fpga_abort_fn, + fpga_post_fn +}; + +Altera_desc fpga[CONFIG_FPGA_COUNT] = { + {Altera_CYC2, + passive_serial, + Altera_EP2C35_SIZE, + (void *) &fpga_fns, + NULL, + 0} +}; + +/* + * Initialize the fpga. Return 1 on success, 0 on failure. + */ +int alpr_fpga_init (void) +{ + int i; + + PRINTF ("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n", __FUNCTION__, __LINE__, gd->reloc_off); + fpga_init (gd->reloc_off); + + for (i = 0; i < CONFIG_FPGA_COUNT; i++) { + PRINTF ("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i); + fpga_add (fpga_altera, &fpga[i]); + } + return 1; +} + +#endif diff --git a/board/prodrive/alpr/init.S b/board/prodrive/alpr/init.S new file mode 100644 index 0000000..135674c --- /dev/null +++ b/board/prodrive/alpr/init.S @@ -0,0 +1,103 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@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 <ppc_asm.tmpl> +#include <config.h> + +/* General */ +#define TLB_VALID 0x00000200 + +/* Supported page sizes */ +#define SZ_1K 0x00000000 +#define SZ_4K 0x00000010 +#define SZ_16K 0x00000020 +#define SZ_64K 0x00000030 +#define SZ_256K 0x00000040 +#define SZ_1M 0x00000050 +#define SZ_16M 0x00000070 +#define SZ_256M 0x00000090 + +/* Storage attributes */ +#define SA_W 0x00000800 /* Write-through */ +#define SA_I 0x00000400 /* Caching inhibited */ +#define SA_M 0x00000200 /* Memory coherence */ +#define SA_G 0x00000100 /* Guarded */ +#define SA_E 0x00000080 /* Endian */ + +/* Access control */ +#define AC_X 0x00000024 /* Execute */ +#define AC_W 0x00000012 /* Write */ +#define AC_R 0x00000009 /* Read */ + +/* Some handy macros */ + +#define EPN(e) ((e) & 0xfffffc00) +#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) +#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) +#define TLB2(a) ( (a)&0x00000fbf ) + +#define tlbtab_start\ + mflr r1 ;\ + bl 0f ; + +#define tlbtab_end\ + .long 0, 0, 0 ; \ +0: mflr r0 ; \ + mtlr r1 ; \ + blr ; + +#define tlbentry(epn,sz,rpn,erpn,attr)\ + .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) + + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + * Pointer to the table is returned in r1 + * + *************************************************************************/ + + .section .bootpg,"ax" + .globl tlbtab + +tlbtab: + tlbtab_start + tlbentry( 0xff000000, SZ_16M, 0xff000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X ) + tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X ) + tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) + + /* PCI */ + tlbentry( CFG_PCI_MEMBASE, SZ_256M, CFG_PCI_MEMBASE, 3, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE1, SZ_256M, CFG_PCI_MEMBASE1, 3, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE2, SZ_256M, CFG_PCI_MEMBASE2, 3, AC_R|AC_W|SA_G|SA_I ) + + /* NAND */ + tlbentry( CFG_NAND_BASE, SZ_4K, CFG_NAND_BASE, 1, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbtab_end diff --git a/board/prodrive/alpr/nand.c b/board/prodrive/alpr/nand.c new file mode 100644 index 0000000..d66b088 --- /dev/null +++ b/board/prodrive/alpr/nand.c @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2006 + * Heiko Schocher, DENX Software Engineering, hs@denx.de + * + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@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 <common.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <asm/processor.h> +#include <nand.h> + +struct alpr_ndfc_regs { + u8 cmd[4]; + u8 addr_wait; + u8 term; + u8 dummy; + u8 dummy2; + u8 data; +}; + +static u8 hwctl; +static struct alpr_ndfc_regs *alpr_ndfc = NULL; + +#define readb(addr) (u8)(*(volatile u8 *)(addr)) +#define writeb(d,addr) *(volatile u8 *)(addr) = ((u8)(d)) + +/* + * The ALPR has a NAND Flash Controller (NDFC) that handles all accesses to + * the NAND devices. The NDFC has command, address and data registers that + * when accessed will set up the NAND flash pins appropriately. We'll use the + * hwcontrol function to save the configuration in a global variable. + * We can then use this information in the read and write functions to + * determine which NDFC register to access. + * + * There are 2 NAND devices on the board, a Hynix HY27US08561A (1 GByte). + */ +static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd) +{ + switch (cmd) { + case NAND_CTL_SETCLE: + hwctl |= 0x1; + break; + case NAND_CTL_CLRCLE: + hwctl &= ~0x1; + break; + case NAND_CTL_SETALE: + hwctl |= 0x2; + break; + case NAND_CTL_CLRALE: + hwctl &= ~0x2; + break; + case NAND_CTL_SETNCE: + break; + case NAND_CTL_CLRNCE: + writeb(0x00, &(alpr_ndfc->term)); + break; + } +} + +static void alpr_nand_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *nand = mtd->priv; + + if (hwctl & 0x1) + /* + * IO_ADDR_W used as CMD[i] reg to support multiple NAND + * chips. + */ + writeb(byte, nand->IO_ADDR_W); + else if (hwctl & 0x2) { + writeb(byte, &(alpr_ndfc->addr_wait)); + } else + writeb(byte, &(alpr_ndfc->data)); +} + +static u_char alpr_nand_read_byte(struct mtd_info *mtd) +{ + return readb(&(alpr_ndfc->data)); +} + +static void alpr_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + struct nand_chip *nand = mtd->priv; + int i; + + for (i = 0; i < len; i++) { + if (hwctl & 0x1) + /* + * IO_ADDR_W used as CMD[i] reg to support multiple NAND + * chips. + */ + writeb(buf[i], nand->IO_ADDR_W); + else if (hwctl & 0x2) + writeb(buf[i], &(alpr_ndfc->addr_wait)); + else + writeb(buf[i], &(alpr_ndfc->data)); + } +} + +static void alpr_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + buf[i] = readb(&(alpr_ndfc->data)); + } +} + +static int alpr_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) + if (buf[i] != readb(&(alpr_ndfc->data))) + return i; + + return 0; +} + +static int alpr_nand_dev_ready(struct mtd_info *mtd) +{ + volatile u_char val; + + /* + * Blocking read to wait for NAND to be ready + */ + val = readb(&(alpr_ndfc->addr_wait)); + + /* + * Return always true + */ + return 1; +} + +int board_nand_init(struct nand_chip *nand) +{ + alpr_ndfc = (struct alpr_ndfc_regs *)CFG_NAND_BASE; + + nand->eccmode = NAND_ECC_SOFT; + + /* Reference hardware control function */ + nand->hwcontrol = alpr_nand_hwcontrol; + /* Set command delay time */ + nand->write_byte = alpr_nand_write_byte; + nand->read_byte = alpr_nand_read_byte; + nand->write_buf = alpr_nand_write_buf; + nand->read_buf = alpr_nand_read_buf; + nand->verify_buf = alpr_nand_verify_buf; + nand->dev_ready = alpr_nand_dev_ready; + + return 0; +} +#endif diff --git a/board/prodrive/alpr/u-boot.lds b/board/prodrive/alpr/u-boot.lds new file mode 100644 index 0000000..4f04089 --- /dev/null +++ b/board/prodrive/alpr/u-boot.lds @@ -0,0 +1,157 @@ +/* + * (C) Copyright 2004 + * 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 +{ + .resetvec 0xFFFFFFFC : + { + *(.resetvec) + } = 0xffff + + .bootpg 0xFFFFF000 : + { + cpu/ppc4xx/start.o (.bootpg) + } = 0xffff + + /* 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/prodrive/alpr/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) + *(.eh_frame) + } + .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/board/prodrive/common/flash.c b/board/prodrive/common/flash.c index 8630cc1..363631f 100644 --- a/board/prodrive/common/flash.c +++ b/board/prodrive/common/flash.c @@ -48,6 +48,7 @@ void flash_print_info(flash_info_t *info) case FLASH_MAN_AMD: printf ("AMD "); break; case FLASH_MAN_FUJ: printf ("FUJITSU "); break; case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_STM: printf ("ST "); break; case FLASH_MAN_EXCEL: printf ("Excel Semiconductor "); break; default: printf ("Unknown Vendor "); break; } @@ -156,6 +157,9 @@ static ulong flash_get_size(vu_long *addr, flash_info_t *info) case (CFG_FLASH_WORD_SIZE)SST_MANUFACT: info->flash_id = FLASH_MAN_SST; break; + case (CFG_FLASH_WORD_SIZE)STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT: info->flash_id = FLASH_MAN_EXCEL; break; diff --git a/board/prodrive/p3mx/64460.h b/board/prodrive/p3mx/64460.h new file mode 100644 index 0000000..8bb0ebf --- /dev/null +++ b/board/prodrive/p3mx/64460.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.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 + */ + +/* + * main board support/init for the Galileo Eval board DB64460. + */ + +#ifndef __64460_H__ +#define __64460_H__ + +/* CPU Configuration bits */ +#define CPU_CONF_ADDR_MISS_EN (1 << 8) +#define CPU_CONF_SINGLE_CPU (1 << 11) +#define CPU_CONF_ENDIANESS (1 << 12) +#define CPU_CONF_PIPELINE (1 << 13) +#define CPU_CONF_STOP_RETRY (1 << 17) +#define CPU_CONF_MULTI_DECODE (1 << 18) +#define CPU_CONF_DP_VALID (1 << 19) +#define CPU_CONF_PERR_PROP (1 << 22) +#define CPU_CONF_AACK_DELAY_2 (1 << 25) +#define CPU_CONF_AP_VALID (1 << 26) +#define CPU_CONF_REMAP_WR_DIS (1 << 27) + +/* CPU Master Control bits */ +#define CPU_MAST_CTL_ARB_EN (1 << 8) +#define CPU_MAST_CTL_MASK_BR_1 (1 << 9) +#define CPU_MAST_CTL_M_WR_TRIG (1 << 10) +#define CPU_MAST_CTL_M_RD_TRIG (1 << 11) +#define CPU_MAST_CTL_CLEAN_BLK (1 << 12) +#define CPU_MAST_CTL_FLUSH_BLK (1 << 13) + +#endif /* __64460_H__ */ diff --git a/board/prodrive/p3mx/Makefile b/board/prodrive/p3mx/Makefile new file mode 100644 index 0000000..bf74a5a --- /dev/null +++ b/board/prodrive/p3mx/Makefile @@ -0,0 +1,55 @@ +# +# (C) Copyright 2002-2006 +# 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 +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../../Marvell/common) +endif + +LIB = $(obj)lib$(BOARD).a + +SOBJS = misc.o +COBJS = $(BOARD).o mpsc.o mv_eth.o pci.o sdram_init.o serial.o \ + ../../Marvell/common/i2c.o ../../Marvell/common/memory.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend *~ + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/prodrive/p3mx/config.mk b/board/prodrive/p3mx/config.mk new file mode 100644 index 0000000..35bf1c1 --- /dev/null +++ b/board/prodrive/p3mx/config.mk @@ -0,0 +1,28 @@ +# +# (C) Copyright 2002-2006 +# 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 +# + +# +# p3mx boards (P3M750 & P3M7448) +# + +TEXT_BASE = 0xfff00000 diff --git a/board/prodrive/p3mx/eth.h b/board/prodrive/p3mx/eth.h new file mode 100644 index 0000000..aab32d2 --- /dev/null +++ b/board/prodrive/p3mx/eth.h @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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 + */ + +/* + * eth.h - header file for the polled mode GT ethernet driver + */ + +#ifndef __EVB64360_ETH_H__ +#define __EVB64360_ETH_H__ + +#include <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> + + +int db64360_eth0_poll(void); +int db64360_eth0_transmit(unsigned int s, volatile char *p); +void db64360_eth0_disable(void); +bool network_start(bd_t *bis); + + +#endif /* __EVB64360_ETH_H__ */ diff --git a/board/prodrive/p3mx/misc.S b/board/prodrive/p3mx/misc.S new file mode 100644 index 0000000..160b1d3 --- /dev/null +++ b/board/prodrive/p3mx/misc.S @@ -0,0 +1,245 @@ +#include <config.h> +#include <74xx_7xx.h> +#include "version.h" + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#include "../../Marvell/include/mv_gen_reg.h" + +#ifdef CONFIG_ECC + /* Galileo specific asm code for initializing ECC */ + .globl board_relocate_rom +board_relocate_rom: + mflr r7 + /* update the location of the GT registers */ + lis r11, CFG_GT_REGS@h + /* if we're using ECC, we must use the DMA engine to copy ourselves */ + bl start_idma_transfer_0 + bl wait_for_idma_0 + bl stop_idma_engine_0 + + mtlr r7 + blr + + .globl board_init_ecc +board_init_ecc: + mflr r7 + /* NOTE: r10 still contains the location we've been relocated to + * which happens to be TOP_OF_RAM - CFG_MONITOR_LEN */ + + /* now that we're running from ram, init the rest of main memory + * for ECC use */ + lis r8, CFG_MONITOR_LEN@h + ori r8, r8, CFG_MONITOR_LEN@l + + divw r3, r10, r8 + + /* set up the counter, and init the starting address */ + mtctr r3 + li r12, 0 + + /* bytes per transfer */ + mr r5, r8 +about_to_init_ecc: +1: mr r3, r12 + mr r4, r12 + bl start_idma_transfer_0 + bl wait_for_idma_0 + bl stop_idma_engine_0 + add r12, r12, r8 + bdnz 1b + + mtlr r7 + blr + + /* r3: dest addr + * r4: source addr + * r5: byte count + * r11: gt regbase + * trashes: r6, r5 + */ +start_idma_transfer_0: + /* set the byte count, including the OWN bit */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_BYTE_COUNT + stwbrx r5, 0, (r6) + + /* set the source address */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_SOURCE_ADDRESS + stwbrx r4, 0, (r6) + + /* set the dest address */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_DESTINATION_ADDRESS + stwbrx r3, 0, (r6) + + /* set the next record pointer */ + li r5, 0 + mr r6, r11 + ori r6, r6, CHANNEL0NEXT_RECORD_POINTER + stwbrx r5, 0, (r6) + + /* set the low control register */ + /* bit 9 is NON chained mode, bit 31 is new style descriptors. + bit 12 is channel enable */ + ori r5, r5, (1 << 12) | (1 << 12) | (1 << 11) + /* 15 shifted by 16 (oris) == bit 31 */ + oris r5, r5, (1 << 15) + mr r6, r11 + ori r6, r6, CHANNEL0CONTROL + stwbrx r5, 0, (r6) + + blr + + /* this waits for the bytecount to return to zero, indicating + * that the trasfer is complete */ +wait_for_idma_0: + mr r5, r11 + lis r6, 0xff + ori r6, r6, 0xffff + ori r5, r5, CHANNEL0_DMA_BYTE_COUNT +1: lwbrx r4, 0, (r5) + and. r4, r4, r6 + bne 1b + + blr + + /* this turns off channel 0 of the idma engine */ +stop_idma_engine_0: + /* shut off the DMA engine */ + li r5, 0 + mr r6, r11 + ori r6, r6, CHANNEL0CONTROL + stwbrx r5, 0, (r6) + + blr +#endif + +#ifdef CFG_BOARD_ASM_INIT + /* NOTE: trashes r3-r7 */ + .globl board_asm_init +board_asm_init: + /* just move the GT registers to where they belong */ + lis r3, CFG_DFL_GT_REGS@h + ori r3, r3, CFG_DFL_GT_REGS@l + lis r4, CFG_GT_REGS@h + ori r4, r4, CFG_GT_REGS@l + li r5, INTERNAL_SPACE_DECODE + + /* test to see if we've already moved */ + lwbrx r6, r5, r4 + andi. r6, r6, 0xffff + /* check loading of R7 is: 0x0F80 should: 0xf800: DONE */ +/* rlwinm r7, r4, 8, 16, 31 + rlwinm r7, r4, 12, 16, 31 */ /* original */ + rlwinm r7, r4, 16, 16, 31 + /* -----------------------------------------------------*/ + cmp cr0, r7, r6 + beqlr + + /* nope, have to move the registers */ + lwbrx r6, r5, r3 + andis. r6, r6, 0xffff + or r6, r6, r7 + stwbrx r6, r5, r3 + + /* now, poll for the change */ +1: lwbrx r7, r5, r4 + cmp cr0, r7, r6 + bne 1b + + lis r3, CFG_INT_SRAM_BASE@h + ori r3, r3, CFG_INT_SRAM_BASE@l + rlwinm r3, r3, 16, 16, 31 + lis r4, CFG_GT_REGS@h + ori r4, r4, CFG_GT_REGS@l + li r5, INTEGRATED_SRAM_BASE_ADDR + stwbrx r3, r5, r4 + +2: lwbrx r6, r5, r4 + cmp cr0, r3, r6 + bne 2b + + /* done! */ + blr +#endif + +/* For use of the debug LEDs */ + .global led_on0_relocated +led_on0_relocated: + xor r21, r21, r21 + xor r18, r18, r18 + lis r18, 0xFC80 + ori r18, r18, 0x8000 +/* stw r21, 0x0(r18) */ + sync + blr + + .global led_off0_relocated +led_off0_relocated: + xor r21, r21, r21 + xor r18, r18, r18 + lis r18, 0xFC81 + ori r18, r18, 0x4000 +/* stw r21, 0x0(r18) */ + sync + blr + + .global led_on0 +led_on0: + xor r18, r18, r18 + lis r18, 0x1c80 + ori r18, r18, 0x8000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off0 +led_off0: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x4000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_on1 +led_on1: + xor r18, r18, r18 + lis r18, 0x1c80 + ori r18, r18, 0xc000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off1 +led_off1: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x8000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_on2 +led_on2: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x0000 +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off2 +led_off2: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0xc000 +/* stw r18, 0x0(r18) */ + sync + blr diff --git a/board/prodrive/p3mx/mpsc.c b/board/prodrive/p3mx/mpsc.c new file mode 100644 index 0000000..da95cfa --- /dev/null +++ b/board/prodrive/p3mx/mpsc.c @@ -0,0 +1,1013 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, Mission Critical Linux, 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 + */ + +/************************************************************************* + * changes for Marvell DB64460 eval board 2003 by Ingo Assmus <ingo.assmus@keymile.com> + * + ************************************************************************/ + +/* + * mpsc.c - driver for console over the MPSC. + */ + + +#include <common.h> +#include <config.h> +#include <asm/cache.h> + +#include <malloc.h> +#include "mpsc.h" + +#include "mv_regs.h" + +#include "../../Marvell/include/memory.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* Define this if you wish to use the MPSC as a register based UART. + * This will force the serial port to not use the SDMA engine at all. + */ +#undef CONFIG_MPSC_DEBUG_PORT + + +int (*mpsc_putchar) (char ch) = mpsc_putchar_early; +char (*mpsc_getchar) (void) = mpsc_getchar_debug; +int (*mpsc_test_char) (void) = mpsc_test_char_debug; + + +static volatile unsigned int *rx_desc_base = NULL; +static unsigned int rx_desc_index = 0; +static volatile unsigned int *tx_desc_base = NULL; +static unsigned int tx_desc_index = 0; + +/* local function declarations */ +static int galmpsc_connect (int channel, int connect); +static int galmpsc_route_rx_clock (int channel, int brg); +static int galmpsc_route_tx_clock (int channel, int brg); +static int galmpsc_write_config_regs (int mpsc, int mode); +static int galmpsc_config_channel_regs (int mpsc); +static int galmpsc_set_char_length (int mpsc, int value); +static int galmpsc_set_stop_bit_length (int mpsc, int value); +static int galmpsc_set_parity (int mpsc, int value); +static int galmpsc_enter_hunt (int mpsc); +static int galmpsc_set_brkcnt (int mpsc, int value); +static int galmpsc_set_tcschar (int mpsc, int value); +static int galmpsc_set_snoop (int mpsc, int value); +static int galmpsc_shutdown (int mpsc); + +static int galsdma_set_RFT (int channel); +static int galsdma_set_SFM (int channel); +static int galsdma_set_rxle (int channel); +static int galsdma_set_txle (int channel); +static int galsdma_set_burstsize (int channel, unsigned int value); +static int galsdma_set_RC (int channel, unsigned int value); + +static int galbrg_set_CDV (int channel, int value); +static int galbrg_enable (int channel); +static int galbrg_disable (int channel); +static int galbrg_set_clksrc (int channel, int value); +static int galbrg_set_CUV (int channel, int value); + +static void galsdma_enable_rx (void); +static int galsdma_set_mem_space (unsigned int memSpace, + unsigned int memSpaceTarget, + unsigned int memSpaceAttr, + unsigned int baseAddress, + unsigned int size); + + +#define SOFTWARE_CACHE_MANAGEMENT + +#ifdef SOFTWARE_CACHE_MANAGEMENT +#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));} +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));} +#define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));} +#else +#define FLUSH_DCACHE(a,b) +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) +#define INVALIDATE_DCACHE(a,b) +#endif + +#ifdef CONFIG_MPSC_DEBUG_PORT +static void mpsc_debug_init (void) +{ + + volatile unsigned int temp; + + /* Clear the CFR (CHR4) */ + /* Write random 'Z' bit (bit 29) of CHR4 to enable debug uart *UNDOCUMENTED FEATURE* */ + temp = GTREGREAD (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP)); + temp &= 0xffffff00; + temp |= BIT29; + GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP), + temp); + + /* Set the Valid bit 'V' (bit 12) and int generation bit 'INT' (bit 15) */ + temp = GTREGREAD (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP)); + temp |= (BIT12 | BIT15); + GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP), + temp); + + /* Set int mask */ + temp = GTREGREAD (GALMPSC_0_INT_MASK); + temp |= BIT6; + GT_REG_WRITE (GALMPSC_0_INT_MASK, temp); +} +#endif + +char mpsc_getchar_debug (void) +{ + volatile int temp; + volatile unsigned int cause; + + cause = GTREGREAD (GALMPSC_0_INT_CAUSE); + while ((cause & BIT6) == 0) { + cause = GTREGREAD (GALMPSC_0_INT_CAUSE); + } + + temp = GTREGREAD (GALMPSC_CHANNELREG_10 + + (CHANNEL * GALMPSC_REG_GAP)); + /* By writing 1's to the set bits, the register is cleared */ + GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (CHANNEL * GALMPSC_REG_GAP), + temp); + GT_REG_WRITE (GALMPSC_0_INT_CAUSE, cause & ~BIT6); + return (temp >> 16) & 0xff; +} + +/* special function for running out of flash. doesn't modify any + * global variables [josh] */ +int mpsc_putchar_early (char ch) +{ + int mpsc = CHANNEL; + int temp = + GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + galmpsc_set_tcschar (mpsc, ch); + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), + temp | 0x200); + +#define MAGIC_FACTOR (10*1000000) + + udelay (MAGIC_FACTOR / gd->baudrate); + return 0; +} + +/* This is used after relocation, see serial.c and mpsc_init2 */ +static int mpsc_putchar_sdma (char ch) +{ + volatile unsigned int *p; + unsigned int temp; + + + /* align the descriptor */ + p = tx_desc_base; + memset ((void *) p, 0, 8 * sizeof (unsigned int)); + + /* fill one 64 bit buffer */ + /* word swap, pad with 0 */ + p[4] = 0; /* x */ + p[5] = (unsigned int) ch; /* x */ + + /* CHANGED completely according to GT64260A dox - NTL */ + p[0] = 0x00010001; /* 0 */ + p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* 4 */ + p[2] = 0; /* 8 */ + p[3] = (unsigned int) &p[4]; /* c */ + +#if 0 + p[9] = DESC_FIRST | DESC_LAST; + p[10] = (unsigned int) &p[0]; + p[11] = (unsigned int) &p[12]; +#endif + + FLUSH_DCACHE (&p[0], &p[8]); + + GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF), + (unsigned int) &p[0]); + GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF), + (unsigned int) &p[0]); + + temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); + temp |= (TX_DEMAND | TX_STOP); + GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); + + INVALIDATE_DCACHE (&p[1], &p[2]); + + while (p[1] & DESC_OWNER_BIT) { + udelay (100); + INVALIDATE_DCACHE (&p[1], &p[2]); + } + return 0; +} + +char mpsc_getchar_sdma (void) +{ + static unsigned int done = 0; + volatile char ch; + unsigned int len = 0, idx = 0, temp; + + volatile unsigned int *p; + + + do { + p = &rx_desc_base[rx_desc_index * 8]; + + INVALIDATE_DCACHE (&p[0], &p[1]); + /* Wait for character */ + while (p[1] & DESC_OWNER_BIT) { + udelay (100); + INVALIDATE_DCACHE (&p[0], &p[1]); + } + + /* Handle error case */ + if (p[1] & (1 << 15)) { + printf ("oops, error: %08x\n", p[1]); + + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + + (CHANNEL * GALMPSC_REG_GAP)); + temp |= (1 << 23); + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + + (CHANNEL * GALMPSC_REG_GAP), temp); + + /* Can't poll on abort bit, so we just wait. */ + udelay (100); + + galsdma_enable_rx (); + } + + /* Number of bytes left in this descriptor */ + len = p[0] & 0xffff; + + if (len) { + /* Where to look */ + idx = 5; + if (done > 3) + idx = 4; + if (done > 7) + idx = 7; + if (done > 11) + idx = 6; + + INVALIDATE_DCACHE (&p[idx], &p[idx + 1]); + ch = p[idx] & 0xff; + done++; + } + + if (done < len) { + /* this descriptor has more bytes still + * shift down the char we just read, and leave the + * buffer in place for the next time around + */ + p[idx] = p[idx] >> 8; + FLUSH_DCACHE (&p[idx], &p[idx + 1]); + } + + if (done == len) { + /* nothing left in this descriptor. + * go to next one + */ + p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; + p[0] = 0x00100000; + FLUSH_DCACHE (&p[0], &p[1]); + /* Next descriptor */ + rx_desc_index = (rx_desc_index + 1) % RX_DESC; + done = 0; + } + } while (len == 0); /* galileo bug.. len might be zero */ + + return ch; +} + + +int mpsc_test_char_debug (void) +{ + if ((GTREGREAD (GALMPSC_0_INT_CAUSE) & BIT6) == 0) + return 0; + else { + return 1; + } +} + + +int mpsc_test_char_sdma (void) +{ + volatile unsigned int *p = &rx_desc_base[rx_desc_index * 8]; + + INVALIDATE_DCACHE (&p[1], &p[2]); + + if (p[1] & DESC_OWNER_BIT) + return 0; + else + return 1; +} + +int mpsc_init (int baud) +{ + /* BRG CONFIG */ + galbrg_set_baudrate (CHANNEL, baud); + galbrg_set_clksrc (CHANNEL, 8); /* set source=Tclk */ + galbrg_set_CUV (CHANNEL, 0); /* set up CountUpValue */ + galbrg_enable (CHANNEL); /* Enable BRG */ + + /* Set up clock routing */ + galmpsc_connect (CHANNEL, GALMPSC_CONNECT); /* connect it */ + + galmpsc_route_rx_clock (CHANNEL, CHANNEL); /* chosse BRG0 for Rx */ + galmpsc_route_tx_clock (CHANNEL, CHANNEL); /* chose BRG0 for Tx */ + + /* reset MPSC state */ + galmpsc_shutdown (CHANNEL); + + /* SDMA CONFIG */ + galsdma_set_burstsize (CHANNEL, L1_CACHE_BYTES / 8); /* in 64 bit words (8 bytes) */ + galsdma_set_txle (CHANNEL); + galsdma_set_rxle (CHANNEL); + galsdma_set_RC (CHANNEL, 0xf); + galsdma_set_SFM (CHANNEL); + galsdma_set_RFT (CHANNEL); + + /* MPSC CONFIG */ + galmpsc_write_config_regs (CHANNEL, GALMPSC_UART); + galmpsc_config_channel_regs (CHANNEL); + galmpsc_set_char_length (CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */ + galmpsc_set_parity (CHANNEL, GALMPSC_PARITY_NONE); /* N */ + galmpsc_set_stop_bit_length (CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */ + +#ifdef CONFIG_MPSC_DEBUG_PORT + mpsc_debug_init (); +#endif + + /* COMM_MPSC CONFIG */ +#ifdef SOFTWARE_CACHE_MANAGEMENT + galmpsc_set_snoop (CHANNEL, 0); /* disable snoop */ +#else + galmpsc_set_snoop (CHANNEL, 1); /* enable snoop */ +#endif + + return 0; +} + + +void mpsc_sdma_init (void) +{ + /* Setup SDMA channel0 SDMA_CONFIG_REG*/ + GT_REG_WRITE (SDMA_CONFIG_REG (0), 0x000020ff); + + /* Enable MPSC-Window0 for DRAM Bank 0 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT, + MV64460_SDMA_DRAM_CS_0_TARGET, + 0, + memoryGetBankBaseAddress(0), + memoryGetBankSize(0)) != true) + printf ("%s: SDMA_Window0 memory setup failed !!! \n", + __FUNCTION__); + + + /* Enable MPSC-Window1 for DRAM Bank 1 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_1_BIT, + MV64460_SDMA_DRAM_CS_1_TARGET, + 0, + memoryGetBankBaseAddress(1), + memoryGetBankSize(1)) != true) + printf ("%s: SDMA_Window1 memory setup failed !!! \n", + __FUNCTION__); + + + /* Disable MPSC-Window2 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_2_BIT, + MV64460_SDMA_DRAM_CS_2_TARGET, + 0, + memoryGetBankBaseAddress(2), + memoryGetBankSize(2)) != true) + printf ("%s: SDMA_Window2 memory setup failed !!! \n", + __FUNCTION__); + + + /* Disable MPSC-Window3 */ + if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_3_BIT, + MV64460_SDMA_DRAM_CS_3_TARGET, + 0, + memoryGetBankBaseAddress(3), + memoryGetBankSize(3)) != true) + printf ("%s: SDMA_Window3 memory setup failed !!! \n", + __FUNCTION__); + + /* Setup MPSC0 access mode Window0 full access */ + GT_SET_REG_BITS (MPSC0_ACCESS_PROTECTION_REG, + (MV64460_SDMA_WIN_ACCESS_FULL << + (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); + + /* Setup MPSC1 access mode Window1 full access */ + GT_SET_REG_BITS (MPSC1_ACCESS_PROTECTION_REG, + (MV64460_SDMA_WIN_ACCESS_FULL << + (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); + + /* Setup MPSC internal address space base address */ + GT_REG_WRITE (CUNIT_INTERNAL_SPACE_BASE_ADDR_REG, CFG_GT_REGS); + + /* no high address remap*/ + GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG0, 0x00); + GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG1, 0x00); + + /* clear interrupt cause register for MPSC (fault register)*/ + GT_REG_WRITE (CUNIT_INTERRUPT_CAUSE_REG, 0x00); +} + + +void mpsc_init2 (void) +{ + int i; + +#ifndef CONFIG_MPSC_DEBUG_PORT + mpsc_putchar = mpsc_putchar_sdma; + mpsc_getchar = mpsc_getchar_sdma; + mpsc_test_char = mpsc_test_char_sdma; +#endif + /* RX descriptors */ + rx_desc_base = (unsigned int *) malloc (((RX_DESC + 1) * 8) * + sizeof (unsigned int)); + + /* align descriptors */ + rx_desc_base = (unsigned int *) + (((unsigned int) rx_desc_base + 32) & 0xFFFFFFF0); + + rx_desc_index = 0; + + memset ((void *) rx_desc_base, 0, + (RX_DESC * 8) * sizeof (unsigned int)); + + for (i = 0; i < RX_DESC; i++) { + rx_desc_base[i * 8 + 3] = (unsigned int) &rx_desc_base[i * 8 + 4]; /* Buffer */ + rx_desc_base[i * 8 + 2] = (unsigned int) &rx_desc_base[(i + 1) * 8]; /* Next descriptor */ + rx_desc_base[i * 8 + 1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* Command & control */ + rx_desc_base[i * 8] = 0x00100000; + } + rx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &rx_desc_base[0]; + + FLUSH_DCACHE (&rx_desc_base[0], &rx_desc_base[RX_DESC * 8]); + GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR + (CHANNEL * GALSDMA_REG_DIFF), + (unsigned int) &rx_desc_base[0]); + + /* TX descriptors */ + tx_desc_base = (unsigned int *) malloc (((TX_DESC + 1) * 8) * + sizeof (unsigned int)); + + /* align descriptors */ + tx_desc_base = (unsigned int *) + (((unsigned int) tx_desc_base + 32) & 0xFFFFFFF0); + + tx_desc_index = -1; + + memset ((void *) tx_desc_base, 0, + (TX_DESC * 8) * sizeof (unsigned int)); + + for (i = 0; i < TX_DESC; i++) { + tx_desc_base[i * 8 + 5] = (unsigned int) 0x23232323; + tx_desc_base[i * 8 + 4] = (unsigned int) 0x23232323; + tx_desc_base[i * 8 + 3] = + (unsigned int) &tx_desc_base[i * 8 + 4]; + tx_desc_base[i * 8 + 2] = + (unsigned int) &tx_desc_base[(i + 1) * 8]; + tx_desc_base[i * 8 + 1] = + DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; + + /* set sbytecnt and shadow byte cnt to 1 */ + tx_desc_base[i * 8] = 0x00010001; + } + tx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &tx_desc_base[0]; + + FLUSH_DCACHE (&tx_desc_base[0], &tx_desc_base[TX_DESC * 8]); + + udelay (100); + + galsdma_enable_rx (); + + return; +} + +int galbrg_set_baudrate (int channel, int rate) +{ + int clock; + + galbrg_disable (channel); /*ok */ + +#ifdef ZUMA_NTL + /* from tclk */ + clock = (CFG_TCLK / (16 * rate)) - 1; +#else + clock = (CFG_TCLK / (16 * rate)) - 1; +#endif + + galbrg_set_CDV (channel, clock); /* set timer Reg. for BRG */ + + galbrg_enable (channel); + + gd->baudrate = rate; + + return 0; +} + +/* ------------------------------------------------------------------ */ + +/* Below are all the private functions that no one else needs */ + +static int galbrg_set_CDV (int channel, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp &= 0xFFFF0000; + temp |= (value & 0x0000FFFF); + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} + +static int galbrg_enable (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x00010000; + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} + +static int galbrg_disable (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp &= 0xFFFEFFFF; + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} + +static int galbrg_set_clksrc (int channel, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp &= 0xFFC3FFFF; /* Bit 18 - 21 (MV 64260 18-22) */ + temp |= (value << 18); + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + return 0; +} + +static int galbrg_set_CUV (int channel, int value) +{ + /* set CountUpValue */ + GT_REG_WRITE (GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); + + return 0; +} + +#if 0 +static int galbrg_reset (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x20000; + GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} +#endif + +static int galsdma_set_RFT (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000001; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_SFM (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000002; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_rxle (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000040; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_txle (int channel) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp |= 0x00000080; + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_RC (int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp &= ~0x0000003c; + temp |= (value << 2); + GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), + temp); + + return 0; +} + +static int galsdma_set_burstsize (int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); + temp &= 0xFFFFCFFF; + switch (value) { + case 8: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x3 << 12))); + break; + + case 4: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x2 << 12))); + break; + + case 2: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x1 << 12))); + break; + + case 1: + GT_REG_WRITE (GALSDMA_0_CONF_REG + + (channel * GALSDMA_REG_DIFF), + (temp | (0x0 << 12))); + break; + + default: + return -1; + break; + } + + return 0; +} + +static int galmpsc_connect (int channel, int connect) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_ROUTING_REGISTER); + + if ((channel == 0) && connect) + temp &= ~0x00000007; + else if ((channel == 1) && connect) + temp &= ~(0x00000007 << 6); + else if ((channel == 0) && !connect) + temp |= 0x00000007; + else + temp |= (0x00000007 << 6); + + /* Just in case... */ + temp &= 0x3fffffff; + + GT_REG_WRITE (GALMPSC_ROUTING_REGISTER, temp); + + return 0; +} + +static int galmpsc_route_rx_clock (int channel, int brg) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_RxC_ROUTE); + + if (channel == 0) { + temp &= ~0x0000000F; + temp |= brg; + } else { + temp &= ~0x00000F00; + temp |= (brg << 8); + } + + GT_REG_WRITE (GALMPSC_RxC_ROUTE, temp); + + return 0; +} + +static int galmpsc_route_tx_clock (int channel, int brg) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_TxC_ROUTE); + + if (channel == 0) { + temp &= ~0x0000000F; + temp |= brg; + } else { + temp &= ~0x00000F00; + temp |= (brg << 8); + } + + GT_REG_WRITE (GALMPSC_TxC_ROUTE, temp); + + return 0; +} + +static int galmpsc_write_config_regs (int mpsc, int mode) +{ + if (mode == GALMPSC_UART) { + /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ + GT_REG_WRITE (GALMPSC_MCONF_LOW + (mpsc * GALMPSC_REG_GAP), + 0x000004c4); + + /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ + GT_REG_WRITE (GALMPSC_MCONF_HIGH + (mpsc * GALMPSC_REG_GAP), + 0x024003f8); + /* 22 2222 1111 */ + /* 54 3210 9876 */ + /* 0000 0010 0000 0000 */ + /* 1 */ + /* 098 7654 3210 */ + /* 0000 0011 1111 1000 */ + } else + return -1; + + return 0; +} + +static int galmpsc_config_channel_regs (int mpsc) +{ + GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_3 + (mpsc * GALMPSC_REG_GAP), 1); + GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_6 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_7 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_8 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_9 + (mpsc * GALMPSC_REG_GAP), 0); + GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (mpsc * GALMPSC_REG_GAP), 0); + + galmpsc_set_brkcnt (mpsc, 0x3); + galmpsc_set_tcschar (mpsc, 0xab); + + return 0; +} + +static int galmpsc_set_brkcnt (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); + temp &= 0x0000FFFF; + temp |= (value << 16); + GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_tcschar (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); + temp &= 0xFFFF0000; + temp |= value; + GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_char_length (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); + temp &= 0xFFFFCFFF; + temp |= (value << 12); + GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_stop_bit_length (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); + temp &= 0xFFFFBFFF; + temp |= (value << 14); + GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_set_parity (int mpsc, int value) +{ + unsigned int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + if (value != -1) { + temp &= 0xFFF3FFF3; + temp |= ((value << 18) | (value << 2)); + temp |= ((value << 17) | (value << 1)); + } else { + temp &= 0xFFF1FFF1; + } + + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); + + return 0; +} + +static int galmpsc_enter_hunt (int mpsc) +{ + int temp; + + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + temp |= 0x80000000; + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); + + while (GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)) & + MPSC_ENTER_HUNT) { + udelay (1); + } + return 0; +} + + +static int galmpsc_shutdown (int mpsc) +{ + unsigned int temp; + + /* cause RX abort (clears RX) */ + temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); + temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; + temp &= ~MPSC_ENTER_HUNT; + GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); + + GT_REG_WRITE (GALSDMA_0_COM_REG, 0); + GT_REG_WRITE (GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); + + /* shut down the MPSC */ + GT_REG_WRITE (GALMPSC_MCONF_LOW, 0); + GT_REG_WRITE (GALMPSC_MCONF_HIGH, 0); + GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), 0); + + udelay (100); + + /* shut down the sdma engines. */ + /* reset config to default */ + GT_REG_WRITE (GALSDMA_0_CONF_REG, 0x000000fc); + + udelay (100); + + /* clear the SDMA current and first TX and RX pointers */ + GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR, 0); + GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR, 0); + GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR, 0); + + udelay (100); + + return 0; +} + +static void galsdma_enable_rx (void) +{ + int temp; + + /* Enable RX processing */ + temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); + temp |= RX_ENABLE; + GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); + + galmpsc_enter_hunt (CHANNEL); +} + +static int galmpsc_set_snoop (int mpsc, int value) +{ + int reg = + mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : + MPSC_0_ADDRESS_CONTROL_LOW; + int temp = GTREGREAD (reg); + + if (value) + temp |= (1 << 6) | (1 << 14) | (1 << 22) | (1 << 30); + else + temp &= ~((1 << 6) | (1 << 14) | (1 << 22) | (1 << 30)); + GT_REG_WRITE (reg, temp); + return 0; +} + +/******************************************************************************* +* galsdma_set_mem_space - Set MV64460 IDMA memory decoding map. +* +* DESCRIPTION: +* the MV64460 SDMA has its own address decoding map that is de-coupled +* from the CPU interface address decoding windows. The SDMA channels +* share four address windows. Each region can be individually configured +* by this function by associating it to a target interface and setting +* base and size values. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* The size must be a series of 1s followed by a series of zeros +* +* OUTPUT: +* None. +* +* RETURN: +* True for success, false otherwise. +* +*******************************************************************************/ + +static int galsdma_set_mem_space (unsigned int memSpace, + unsigned int memSpaceTarget, + unsigned int memSpaceAttr, + unsigned int baseAddress, unsigned int size) +{ + unsigned int temp; + + if (size == 0) { + GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG, + 1 << memSpace); + return true; + } + + /* The base address must be aligned to the size. */ + if (baseAddress % size != 0) { + return false; + } + if (size < 0x10000) { + return false; + } + + /* Align size and base to 64K */ + baseAddress &= 0xffff0000; + size &= 0xffff0000; + temp = size >> 16; + + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + while ((temp > 0) && (temp & 0x1)) { + temp = temp >> 1; + } + + if (temp != 0) { + GT_REG_WRITE (MV64460_CUNIT_BASE_ADDR_REG0 + memSpace * 8, + (baseAddress | memSpaceTarget | memSpaceAttr)); + GT_REG_WRITE ((MV64460_CUNIT_SIZE0 + memSpace * 8), + (size - 1) & 0xffff0000); + GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG, + 1 << memSpace); + } else { + /* An invalid size was specified */ + return false; + } + return true; +} diff --git a/board/prodrive/p3mx/mpsc.h b/board/prodrive/p3mx/mpsc.h new file mode 100644 index 0000000..a03d1cc --- /dev/null +++ b/board/prodrive/p3mx/mpsc.h @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, Mission Critical Linux, 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 + */ + +/************************************************************************* + * changes for Marvell DB64360 eval board 2003 by Ingo Assmus <ingo.assmus@keymile.com> + * + ************************************************************************/ + + +/* + * mpsc.h - header file for MPSC in uart mode (console driver) + */ + +#ifndef __MPSC_H__ +#define __MPSC_H__ + +/* include actual Galileo defines */ +#include "../../Marvell/include/mv_gen_reg.h" + +/* driver related defines */ + +int mpsc_init(int baud); +void mpsc_sdma_init(void); +void mpsc_init2(void); +int galbrg_set_baudrate(int channel, int rate); + +int mpsc_putchar_early(char ch); +char mpsc_getchar_debug(void); +int mpsc_test_char_debug(void); + +int mpsc_test_char_sdma(void); + +extern int (*mpsc_putchar)(char ch); +extern char (*mpsc_getchar)(void); +extern int (*mpsc_test_char)(void); + +#define CHANNEL CONFIG_MPSC_PORT + +#define TX_DESC 5 +#define RX_DESC 20 + +#define DESC_FIRST 0x00010000 +#define DESC_LAST 0x00020000 +#define DESC_OWNER_BIT 0x80000000 + +#define TX_DEMAND 0x00800000 +#define TX_STOP 0x00010000 +#define RX_ENABLE 0x00000080 + +#define SDMA_RX_ABORT (1 << 15) +#define SDMA_TX_ABORT (1 << 31) +#define MPSC_TX_ABORT (1 << 7) +#define MPSC_RX_ABORT (1 << 23) +#define MPSC_ENTER_HUNT (1 << 31) + +/* MPSC defines */ + +#define GALMPSC_CONNECT 0x1 +#define GALMPSC_DISCONNECT 0x0 + +#define GALMPSC_UART 0x1 + +#define GALMPSC_STOP_BITS_1 0x0 +#define GALMPSC_STOP_BITS_2 0x1 +#define GALMPSC_CHAR_LENGTH_8 0x3 +#define GALMPSC_CHAR_LENGTH_7 0x2 + +#define GALMPSC_PARITY_ODD 0x0 +#define GALMPSC_PARITY_EVEN 0x2 +#define GALMPSC_PARITY_MARK 0x3 +#define GALMPSC_PARITY_SPACE 0x1 +#define GALMPSC_PARITY_NONE -1 + +#define GALMPSC_SERIAL_MULTIPLEX SERIAL_PORT_MULTIPLEX /* 0xf010 */ +#define GALMPSC_ROUTING_REGISTER MAIN_ROUTING_REGISTER /* 0xb400 */ +#define GALMPSC_RxC_ROUTE RECEIVE_CLOCK_ROUTING_REGISTER /* 0xb404 */ +#define GALMPSC_TxC_ROUTE TRANSMIT_CLOCK_ROUTING_REGISTER /* 0xb408 */ +#define GALMPSC_MCONF_LOW MPSC0_MAIN_CONFIGURATION_LOW /* 0x8000 */ +#define GALMPSC_MCONF_HIGH MPSC0_MAIN_CONFIGURATION_HIGH /* 0x8004 */ +#define GALMPSC_PROTOCONF_REG MPSC0_PROTOCOL_CONFIGURATION /* 0x8008 */ + +#define GALMPSC_REG_GAP 0x1000 + +#define GALMPSC_MCONF_CHREG_BASE CHANNEL0_REGISTER1 /* 0x800c */ +#define GALMPSC_CHANNELREG_1 CHANNEL0_REGISTER1 /* 0x800c */ +#define GALMPSC_CHANNELREG_2 CHANNEL0_REGISTER2 /* 0x8010 */ +#define GALMPSC_CHANNELREG_3 CHANNEL0_REGISTER3 /* 0x8014 */ +#define GALMPSC_CHANNELREG_4 CHANNEL0_REGISTER4 /* 0x8018 */ +#define GALMPSC_CHANNELREG_5 CHANNEL0_REGISTER5 /* 0x801c */ +#define GALMPSC_CHANNELREG_6 CHANNEL0_REGISTER6 /* 0x8020 */ +#define GALMPSC_CHANNELREG_7 CHANNEL0_REGISTER7 /* 0x8024 */ +#define GALMPSC_CHANNELREG_8 CHANNEL0_REGISTER8 /* 0x8028 */ +#define GALMPSC_CHANNELREG_9 CHANNEL0_REGISTER9 /* 0x802c */ +#define GALMPSC_CHANNELREG_10 CHANNEL0_REGISTER10 /* 0x8030 */ +#define GALMPSC_CHANNELREG_11 CHANNEL0_REGISTER11 /* 0x8034 */ + +#define GALSDMA_COMMAND_FIRST (1 << 16) +#define GALSDMA_COMMAND_LAST (1 << 17) +#define GALSDMA_COMMAND_ENABLEINT (1 << 23) +#define GALSDMA_COMMAND_AUTO (1 << 30) +#define GALSDMA_COMMAND_OWNER (1 << 31) + +#define GALSDMA_RX 0 +#define GALSDMA_TX 1 + +/* CHANNEL2 should be CHANNEL1, according to documentation, + * but to work with the current GTREGS file... + */ +#define GALSDMA_0_CONF_REG CHANNEL0_CONFIGURATION_REGISTER /* 0x4000 */ +#define GALSDMA_1_CONF_REG CHANNEL2_CONFIGURATION_REGISTER /* 0x6000 */ +#define GALSDMA_0_COM_REG CHANNEL0_COMMAND_REGISTER /* 0x4008 */ +#define GALSDMA_1_COM_REG CHANNEL2_COMMAND_REGISTER /* 0x6008 */ +#define GALSDMA_0_CUR_RX_PTR CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER /* 0x4810 */ +#define GALSDMA_0_CUR_TX_PTR CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER /* 0x4c10 */ +#define GALSDMA_0_FIR_TX_PTR CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER /* 0x4c14 */ +#define GALSDMA_1_CUR_RX_PTR CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER /* 0x6810 */ +#define GALSDMA_1_CUR_TX_PTR CHANNEL2_CURRENT_TX_DESCRIPTOR_POINTER /* 0x6c10 */ +#define GALSDMA_1_FIR_TX_PTR CHANNEL2_FIRST_TX_DESCRIPTOR_POINTER /* 0x6c14 */ +#define GALSDMA_REG_DIFF 0x2000 + +/* WRONG in gt64260R.h */ +#define GALSDMA_INT_CAUSE 0xb800 /* SDMA_CAUSE */ +#define GALSDMA_INT_MASK 0xb880 /* SDMA_MASK */ +#define GALMPSC_0_INT_CAUSE 0xb804 +#define GALMPSC_0_INT_MASK 0xb884 + +#define GALSDMA_MODE_UART 0 +#define GALSDMA_MODE_BISYNC 1 +#define GALSDMA_MODE_HDLC 2 +#define GALSDMA_MODE_TRANSPARENT 3 + +#define GALBRG_0_CONFREG BRG0_CONFIGURATION_REGISTER /* 0xb200 */ +#define GALBRG_REG_GAP 0x0008 +#define GALBRG_0_BTREG BRG0_BAUDE_TUNING_REGISTER /* 0xb204 */ + +#endif /* __MPSC_H__ */ diff --git a/board/prodrive/p3mx/mv_eth.c b/board/prodrive/p3mx/mv_eth.c new file mode 100644 index 0000000..8203b3c --- /dev/null +++ b/board/prodrive/p3mx/mv_eth.c @@ -0,0 +1,3344 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * based on - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + 3 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 + */ + +/* + * mv_eth.c - header file for the polled mode GT ethernet driver + */ +#include <common.h> +#include <net.h> +#include <malloc.h> +#include <miiphy.h> + +#include "mv_eth.h" + +/* enable Debug outputs */ + +#undef DEBUG_MV_ETH + +#ifdef DEBUG_MV_ETH +#define DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +/* PHY DFCDL Registers */ +#define ETH_PHY_DFCDL_CONFIG0_REG 0x2100 +#define ETH_PHY_DFCDL_CONFIG1_REG 0x2104 +#define ETH_PHY_DFCDL_ADDR_REG 0x2110 +#define ETH_PHY_DFCDL_DATA0_REG 0x2114 + +#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ +#define PHY_UPDATE_TIMEOUT 10000 + +#undef MV64460_CHECKSUM_OFFLOAD +/************************************************************************* +* The first part is the high level driver of the gigE ethernet ports. * +*************************************************************************/ + +/* Definition for configuring driver */ +/* #define UPDATE_STATS_BY_SOFTWARE */ +#undef MV64460_RX_QUEUE_FILL_ON_TASK + +/* Constants */ +#define MAGIC_ETH_RUNNING 8031971 +#define MV64460_INTERNAL_SRAM_SIZE _256K +#define EXTRA_BYTES 32 +#define WRAP ETH_HLEN + 2 + 4 + 16 +#define BUFFER_MTU dev->mtu + WRAP +#define INT_CAUSE_UNMASK_ALL 0x0007ffff +#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff +#ifdef MV64460_RX_FILL_ON_TASK +#define INT_CAUSE_MASK_ALL 0x00000000 +#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL +#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT +#endif + +/* Read/Write to/from MV64460 internal registers */ +#define MV_REG_READ(offset) my_le32_to_cpu(* (volatile unsigned int *) (INTERNAL_REG_BASE_ADDR + offset)) +#define MV_REG_WRITE(offset,data) *(volatile unsigned int *) (INTERNAL_REG_BASE_ADDR + offset) = my_cpu_to_le32 (data) +#define MV_SET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)((INTERNAL_REG_BASE_ADDR) + (regOffset)))) |= ((unsigned int)my_cpu_to_le32(bits))) +#define MV_RESET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)((INTERNAL_REG_BASE_ADDR) + (regOffset)))) &= ~((unsigned int)my_cpu_to_le32(bits))) + +#define my_cpu_to_le32(x) my_le32_to_cpu((x)) + +/* Static function declarations */ +static int mv64460_eth_real_open (struct eth_device *eth); +static int mv64460_eth_real_stop (struct eth_device *eth); +static struct net_device_stats *mv64460_eth_get_stats (struct eth_device + *dev); +static void eth_port_init_mac_tables (ETH_PORT eth_port_num); +static void mv64460_eth_update_stat (struct eth_device *dev); +bool db64460_eth_start (struct eth_device *eth); +unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, + unsigned int mib_offset); +int mv64460_eth_receive (struct eth_device *dev); + +int mv64460_eth_xmit (struct eth_device *, volatile void *packet, int length); + +int mv_miiphy_read(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short *value); +int mv_miiphy_write(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short value); + +int phy_setup_aneg (char *devname, unsigned char addr); + +#ifndef UPDATE_STATS_BY_SOFTWARE +static void mv64460_eth_print_stat (struct eth_device *dev); +#endif +/* Processes a received packet */ +extern void NetReceive (volatile uchar *, int); + +extern unsigned int INTERNAL_REG_BASE_ADDR; + +unsigned long my_le32_to_cpu (unsigned long x) +{ + return (((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)); +} + +/************************************************* + *Helper functions - used inside the driver only * + *************************************************/ +#ifdef DEBUG_MV_ETH +void print_globals (struct eth_device *dev) +{ + printf ("Ethernet PRINT_Globals-Debug function\n"); + printf ("Base Address for ETH_PORT_INFO: %08x\n", + (unsigned int) dev->priv); + printf ("Base Address for mv64460_eth_priv: %08x\n", + (unsigned int) &(((ETH_PORT_INFO *) dev->priv)-> + port_private)); + + printf ("GT Internal Base Address: %08x\n", + INTERNAL_REG_BASE_ADDR); + printf ("Base Address for TX-DESCs: %08x Number of allocated Buffers %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_tx_desc_area_base[0], MV64460_TX_QUEUE_SIZE); + printf ("Base Address for RX-DESCs: %08x Number of allocated Buffers %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_rx_desc_area_base[0], MV64460_RX_QUEUE_SIZE); + printf ("Base Address for RX-Buffer: %08x allocated Bytes %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> + p_rx_buffer_base[0], + (MV64460_RX_QUEUE_SIZE * MV64460_RX_BUFFER_SIZE) + 32); + printf ("Base Address for TX-Buffer: %08x allocated Bytes %d\n", + (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> + p_tx_buffer_base[0], + (MV64460_TX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE) + 32); +} +#endif + +/********************************************************************** + * mv64460_eth_print_phy_status + * + * Prints gigabit ethenret phy status + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ +void mv64460_eth_print_phy_status (struct eth_device *dev) +{ + struct mv64460_eth_priv *port_private; + unsigned int port_num; + ETH_PORT_INFO *ethernet_private = (ETH_PORT_INFO *) dev->priv; + unsigned int port_status, phy_reg_data; + + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Check Link status on phy */ + eth_port_read_smi_reg (port_num, 1, &phy_reg_data); + if (!(phy_reg_data & 0x20)) { + printf ("Ethernet port changed link status to DOWN\n"); + } else { + port_status = + MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num)); + printf ("Ethernet status port %d: Link up", port_num); + printf (", %s", + (port_status & BIT2) ? "Full Duplex" : "Half Duplex"); + if (port_status & BIT4) + printf (", Speed 1 Gbps"); + else + printf (", %s", + (port_status & BIT5) ? "Speed 100 Mbps" : + "Speed 10 Mbps"); + printf ("\n"); + } +} + +/********************************************************************** + * u-boot entry functions for mv64460_eth + * + **********************************************************************/ +int db64460_eth_probe (struct eth_device *dev) +{ + return ((int) db64460_eth_start (dev)); +} + +int db64460_eth_poll (struct eth_device *dev) +{ + return mv64460_eth_receive (dev); +} + +int db64460_eth_transmit (struct eth_device *dev, volatile void *packet, + int length) +{ + mv64460_eth_xmit (dev, packet, length); + return 0; +} + +void db64460_eth_disable (struct eth_device *dev) +{ + mv64460_eth_stop (dev); +} + +#define DFCDL(write,read) ((write << 6) | read) +unsigned int ethDfcdls[] = { + DFCDL(0,0), DFCDL(1,1), DFCDL(2,2), DFCDL(3,3), + DFCDL(4,4), DFCDL(5,5), DFCDL(6,6), DFCDL(7,7), + DFCDL(8,8), DFCDL(9,9), DFCDL(10,10), DFCDL(11,11), + DFCDL(12,12), DFCDL(13,13), DFCDL(14,14), DFCDL(15,15), + DFCDL(16,16), DFCDL(17,17), DFCDL(18,18), DFCDL(19,19), + DFCDL(20,20), DFCDL(21,21), DFCDL(22,22), DFCDL(23,23), + DFCDL(24,24), DFCDL(25,25), DFCDL(26,26), DFCDL(27,27), + DFCDL(28,28), DFCDL(29,29), DFCDL(30,30), DFCDL(31,31), + DFCDL(32,32), DFCDL(33,33), DFCDL(34,34), DFCDL(35,35), + DFCDL(36,36), DFCDL(37,37), DFCDL(38,38), DFCDL(39,39), + DFCDL(40,40), DFCDL(41,41), DFCDL(42,42), DFCDL(43,43), + DFCDL(44,44), DFCDL(45,45), DFCDL(46,46), DFCDL(47,47), + DFCDL(48,48), DFCDL(49,49), DFCDL(50,50), DFCDL(51,51), + DFCDL(52,52), DFCDL(53,53), DFCDL(54,54), DFCDL(55,55), + DFCDL(56,56), DFCDL(57,57), DFCDL(58,58), DFCDL(59,59), + DFCDL(60,60), DFCDL(61,61), DFCDL(62,62), DFCDL(63,63), +}; + +void mv_eth_phy_init (void) +{ + int i; + + MV_REG_WRITE (ETH_PHY_DFCDL_ADDR_REG, 0); + + for (i = 0; i < 64; i++) { + MV_REG_WRITE (ETH_PHY_DFCDL_DATA0_REG, ethDfcdls[i]); + } + + MV_REG_WRITE (ETH_PHY_DFCDL_CONFIG0_REG, 0x300000); +} + +void mv6446x_eth_initialize (bd_t * bis) +{ + struct eth_device *dev; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + int devnum, x, temp; + char *s, *e, buf[64]; + + /* P3M750 only + * Set RGMII clock drives strength + */ + temp = MV_REG_READ(0x20A0); + temp |= 0x04000080; + MV_REG_WRITE(0x20A0, temp); + + mv_eth_phy_init(); + + for (devnum = 0; devnum < MV_ETH_DEVS; devnum++) { + dev = calloc (sizeof (*dev), 1); + if (!dev) { + printf ("%s: mv_enet%d allocation failure, %s\n", + __FUNCTION__, devnum, "eth_device structure"); + return; + } + + /* must be less than NAMESIZE (16) */ + sprintf (dev->name, "mv_enet%d", devnum); + +#ifdef DEBUG + printf ("Initializing %s\n", dev->name); +#endif + + /* Extract the MAC address from the environment */ + switch (devnum) { + case 0: + s = "ethaddr"; + break; + case 1: + s = "eth1addr"; + break; + case 2: + s = "eth2addr"; + break; + default: /* this should never happen */ + printf ("%s: Invalid device number %d\n", + __FUNCTION__, devnum); + return; + } + + temp = getenv_r (s, buf, sizeof (buf)); + s = (temp > 0) ? buf : NULL; + +#ifdef DEBUG + printf ("Setting MAC %d to %s\n", devnum, s); +#endif + for (x = 0; x < 6; ++x) { + dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + /* ronen - set the MAC addr in the HW */ + eth_port_uc_addr_set (devnum, dev->enetaddr, 0); + + dev->init = (void *) db64460_eth_probe; + dev->halt = (void *) ethernet_phy_reset; + dev->send = (void *) db64460_eth_transmit; + dev->recv = (void *) db64460_eth_poll; + + ethernet_private = calloc (sizeof (*ethernet_private), 1); + dev->priv = (void *)ethernet_private; + if (!ethernet_private) { + printf ("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Private Device Structure"); + free (dev); + return; + } + /* start with an zeroed ETH_PORT_INFO */ + memset (ethernet_private, 0, sizeof (ETH_PORT_INFO)); + memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); + + /* set pointer to memory for stats data structure etc... */ + port_private = calloc (sizeof (*ethernet_private), 1); + ethernet_private->port_private = (void *)port_private; + if (!port_private) { + printf ("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Port Private Device Structure"); + + free (ethernet_private); + free (dev); + return; + } + + port_private->stats = + calloc (sizeof (struct net_device_stats), 1); + if (!port_private->stats) { + printf ("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Net stat Structure"); + + free (port_private); + free (ethernet_private); + free (dev); + return; + } + memset (ethernet_private->port_private, 0, + sizeof (struct mv64460_eth_priv)); + switch (devnum) { + case 0: + ethernet_private->port_num = ETH_0; + break; + case 1: + ethernet_private->port_num = ETH_1; + break; + case 2: + ethernet_private->port_num = ETH_2; + break; + default: + printf ("Invalid device number %d\n", devnum); + break; + }; + + port_private->port_num = devnum; + /* + * Read MIB counter on the GT in order to reset them, + * then zero all the stats fields in memory + */ + mv64460_eth_update_stat (dev); + memset (port_private->stats, 0, + sizeof (struct net_device_stats)); + /* Extract the MAC address from the environment */ + switch (devnum) { + case 0: + s = "ethaddr"; + break; + case 1: + s = "eth1addr"; + break; + case 2: + s = "eth2addr"; + break; + default: /* this should never happen */ + printf ("%s: Invalid device number %d\n", + __FUNCTION__, devnum); + return; + } + + temp = getenv_r (s, buf, sizeof (buf)); + s = (temp > 0) ? buf : NULL; + +#ifdef DEBUG + printf ("Setting MAC %d to %s\n", devnum, s); +#endif + for (x = 0; x < 6; ++x) { + dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + + DP (printf ("Allocating descriptor and buffer rings\n")); + + ethernet_private->p_rx_desc_area_base[0] = + (ETH_RX_DESC *) memalign (16, + RX_DESC_ALIGNED_SIZE * + MV64460_RX_QUEUE_SIZE + 1); + ethernet_private->p_tx_desc_area_base[0] = + (ETH_TX_DESC *) memalign (16, + TX_DESC_ALIGNED_SIZE * + MV64460_TX_QUEUE_SIZE + 1); + + ethernet_private->p_rx_buffer_base[0] = + (char *) memalign (16, + MV64460_RX_QUEUE_SIZE * + MV64460_TX_BUFFER_SIZE + 1); + ethernet_private->p_tx_buffer_base[0] = + (char *) memalign (16, + MV64460_RX_QUEUE_SIZE * + MV64460_TX_BUFFER_SIZE + 1); + +#ifdef DEBUG_MV_ETH + /* DEBUG OUTPUT prints adresses of globals */ + print_globals (dev); +#endif + eth_register (dev); + + miiphy_register(dev->name, mv_miiphy_read, mv_miiphy_write); + } + DP (printf ("%s: exit\n", __FUNCTION__)); + +} + +/********************************************************************** + * mv64460_eth_open + * + * This function is called when openning the network device. The function + * should initialize all the hardware, initialize cyclic Rx/Tx + * descriptors chain and buffers and allocate an IRQ to the network + * device. + * + * Input : a pointer to the network device structure + * / / ronen - changed the output to match net/eth.c needs + * Output : nonzero of success , zero if fails. + * under construction + **********************************************************************/ + +int mv64460_eth_open (struct eth_device *dev) +{ + return (mv64460_eth_real_open (dev)); +} + +/* Helper function for mv64460_eth_open */ +static int mv64460_eth_real_open (struct eth_device *dev) +{ + + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + u32 port_status; + ushort reg_short; + int speed; + int duplex; + int i; + int reg; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + /* ronen - when we update the MAC env params we only update dev->enetaddr + see ./net/eth.c eth_set_enetaddr() */ + memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); + + port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop RX Queues */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), 0x0000ff00); + + /* Clear the ethernet port interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); + + /* Unmask RX buffer and TX end interrupt */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), + INT_CAUSE_UNMASK_ALL); + + /* Unmask phy and link status changes interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), + INT_CAUSE_UNMASK_ALL_EXT); + + /* Set phy address of the port */ + ethernet_private->port_phy_addr = 0x1 + (port_num << 1); + reg = ethernet_private->port_phy_addr; + + /* Activate the DMA channels etc */ + eth_port_init (ethernet_private); + + /* "Allocate" setup TX rings */ + + for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) { + unsigned int size; + + port_private->tx_ring_size[queue] = MV64460_TX_QUEUE_SIZE; + size = (port_private->tx_ring_size[queue] * TX_DESC_ALIGNED_SIZE); /*size = no of DESCs times DESC-size */ + ethernet_private->tx_desc_area_size[queue] = size; + + /* first clear desc area completely */ + memset ((void *) ethernet_private->p_tx_desc_area_base[queue], + 0, ethernet_private->tx_desc_area_size[queue]); + + /* initialize tx desc ring with low level driver */ + if (ether_init_tx_desc_ring + (ethernet_private, ETH_Q0, + port_private->tx_ring_size[queue], + MV64460_TX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , + (unsigned int) ethernet_private-> + p_tx_desc_area_base[queue], + (unsigned int) ethernet_private-> + p_tx_buffer_base[queue]) == false) + printf ("### Error initializing TX Ring\n"); + } + + /* "Allocate" setup RX rings */ + for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) { + unsigned int size; + + /* Meantime RX Ring are fixed - but must be configurable by user */ + port_private->rx_ring_size[queue] = MV64460_RX_QUEUE_SIZE; + size = (port_private->rx_ring_size[queue] * + RX_DESC_ALIGNED_SIZE); + ethernet_private->rx_desc_area_size[queue] = size; + + /* first clear desc area completely */ + memset ((void *) ethernet_private->p_rx_desc_area_base[queue], + 0, ethernet_private->rx_desc_area_size[queue]); + if ((ether_init_rx_desc_ring + (ethernet_private, ETH_Q0, + port_private->rx_ring_size[queue], + MV64460_RX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , + (unsigned int) ethernet_private-> + p_rx_desc_area_base[queue], + (unsigned int) ethernet_private-> + p_rx_buffer_base[queue])) == false) + printf ("### Error initializing RX Ring\n"); + } + + eth_port_start (ethernet_private); + + /* Set maximum receive buffer to 9700 bytes */ + MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num), + (0x5 << 17) | + (MV_REG_READ + (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num)) + & 0xfff1ffff)); + + /* + * Set ethernet MTU for leaky bucket mechanism to 0 - this will + * disable the leaky bucket mechanism . + */ + + MV_REG_WRITE (MV64460_ETH_MAXIMUM_TRANSMIT_UNIT (port_num), 0); + port_status = MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num)); + +#if defined(CONFIG_PHY_RESET) + /* + * Reset the phy, only if its the first time through + * otherwise, just check the speeds & feeds + */ + if (port_private->first_init == 0) { + port_private->first_init = 1; + ethernet_phy_reset (port_num); + + /* Start/Restart autonegotiation */ + phy_setup_aneg (dev->name, reg); + udelay (1000); + } +#endif /* defined(CONFIG_PHY_RESET) */ + + miiphy_read (dev->name, reg, PHY_BMSR, ®_short); + + /* + * Wait if PHY is capable of autonegotiation and autonegotiation is not complete + */ + if ((reg_short & PHY_BMSR_AUTN_ABLE) + && !(reg_short & PHY_BMSR_AUTN_COMP)) { + puts ("Waiting for PHY auto negotiation to complete"); + i = 0; + while (!(reg_short & PHY_BMSR_AUTN_COMP)) { + /* + * Timeout reached ? + */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts (" TIMEOUT !\n"); + break; + } + + if ((i++ % 1000) == 0) { + putc ('.'); + } + udelay (1000); /* 1 ms */ + miiphy_read (dev->name, reg, PHY_BMSR, ®_short); + + } + puts (" done\n"); + udelay (500000); /* another 500 ms (results in faster booting) */ + } + + speed = miiphy_speed (dev->name, reg); + duplex = miiphy_duplex (dev->name, reg); + + printf ("ENET Speed is %d Mbps - %s duplex connection\n", + (int) speed, (duplex == HALF) ? "HALF" : "FULL"); + + port_private->eth_running = MAGIC_ETH_RUNNING; + return 1; +} + +static int mv64460_eth_free_tx_rings (struct eth_device *dev) +{ + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + volatile ETH_TX_DESC *p_tx_curr_desc; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop Tx Queues */ + MV_REG_WRITE (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Free TX rings */ + DP (printf ("Clearing previously allocated TX queues... ")); + for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) { + /* Free on TX rings */ + for (p_tx_curr_desc = + ethernet_private->p_tx_desc_area_base[queue]; + ((unsigned int) p_tx_curr_desc <= (unsigned int) + ethernet_private->p_tx_desc_area_base[queue] + + ethernet_private->tx_desc_area_size[queue]); + p_tx_curr_desc = + (ETH_TX_DESC *) ((unsigned int) p_tx_curr_desc + + TX_DESC_ALIGNED_SIZE)) { + /* this is inside for loop */ + if (p_tx_curr_desc->return_info != 0) { + p_tx_curr_desc->return_info = 0; + DP (printf ("freed\n")); + } + } + DP (printf ("Done\n")); + } + return 0; +} + +static int mv64460_eth_free_rx_rings (struct eth_device *dev) +{ + unsigned int queue; + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + volatile ETH_RX_DESC *p_rx_curr_desc; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop RX Queues */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), + 0x0000ff00); + + /* Free RX rings */ + DP (printf ("Clearing previously allocated RX queues... ")); + for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) { + /* Free preallocated skb's on RX rings */ + for (p_rx_curr_desc = + ethernet_private->p_rx_desc_area_base[queue]; + (((unsigned int) p_rx_curr_desc < + ((unsigned int) ethernet_private-> + p_rx_desc_area_base[queue] + + ethernet_private->rx_desc_area_size[queue]))); + p_rx_curr_desc = + (ETH_RX_DESC *) ((unsigned int) p_rx_curr_desc + + RX_DESC_ALIGNED_SIZE)) { + if (p_rx_curr_desc->return_info != 0) { + p_rx_curr_desc->return_info = 0; + DP (printf ("freed\n")); + } + } + DP (printf ("Done\n")); + } + return 0; +} + +/********************************************************************** + * mv64460_eth_stop + * + * This function is used when closing the network device. + * It updates the hardware, + * release all memory that holds buffers and descriptors and release the IRQ. + * Input : a pointer to the device structure + * Output : zero if success , nonzero if fails + *********************************************************************/ + +int mv64460_eth_stop (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + /* Disable all gigE address decoder */ + MV_REG_WRITE (MV64460_ETH_BASE_ADDR_ENABLE_REG, 0x3f); + DP (printf ("%s Ethernet stop called ... \n", __FUNCTION__)); + mv64460_eth_real_stop (dev); + + return 0; +}; + +/* Helper function for mv64460_eth_stop */ + +static int mv64460_eth_real_stop (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + mv64460_eth_free_tx_rings (dev); + mv64460_eth_free_rx_rings (dev); + + eth_port_reset (ethernet_private->port_num); + /* Disable ethernet port interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); + MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); + /* Mask RX buffer and TX end interrupt */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), 0); + /* Mask phy and link status changes interrupts */ + MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), 0); + MV_RESET_REG_BITS (MV64460_CPU_INTERRUPT0_MASK_HIGH, + BIT0 << port_num); + /* Print Network statistics */ +#ifndef UPDATE_STATS_BY_SOFTWARE + /* + * Print statistics (only if ethernet is running), + * then zero all the stats fields in memory + */ + if (port_private->eth_running == MAGIC_ETH_RUNNING) { + port_private->eth_running = 0; + mv64460_eth_print_stat (dev); + } + memset (port_private->stats, 0, sizeof (struct net_device_stats)); +#endif + DP (printf ("\nEthernet stopped ... \n")); + return 0; +} + +/********************************************************************** + * mv64460_eth_start_xmit + * + * This function is queues a packet in the Tx descriptor for + * required port. + * + * Input : skb - a pointer to socket buffer + * dev - a pointer to the required port + * + * Output : zero upon success + **********************************************************************/ + +int mv64460_eth_xmit (struct eth_device *dev, volatile void *dataPtr, + int dataSize) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + PKT_INFO pkt_info; + ETH_FUNC_RET_STATUS status; + struct net_device_stats *stats; + ETH_FUNC_RET_STATUS release_result; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + stats = port_private->stats; + + /* Update packet info data structure */ + pkt_info.cmd_sts = ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC; /* DMA owned, first last */ + pkt_info.byte_cnt = dataSize; + pkt_info.buf_ptr = (unsigned int) dataPtr; + pkt_info.return_info = 0; + + status = eth_port_send (ethernet_private, ETH_Q0, &pkt_info); + if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) { + printf ("Error on transmitting packet .."); + if (status == ETH_QUEUE_FULL) + printf ("ETH Queue is full. \n"); + if (status == ETH_QUEUE_LAST_RESOURCE) + printf ("ETH Queue: using last available resource. \n"); + return 1; + } + + /* Update statistics and start of transmittion time */ + stats->tx_bytes += dataSize; + stats->tx_packets++; + + /* Check if packet(s) is(are) transmitted correctly (release everything) */ + do { + release_result = + eth_tx_return_desc (ethernet_private, ETH_Q0, + &pkt_info); + switch (release_result) { + case ETH_OK: + DP (printf ("descriptor released\n")); + if (pkt_info.cmd_sts & BIT0) { + printf ("Error in TX\n"); + stats->tx_errors++; + } + break; + case ETH_RETRY: + DP (printf ("transmission still in process\n")); + break; + + case ETH_ERROR: + printf ("routine can not access Tx desc ring\n"); + break; + + case ETH_END_OF_JOB: + DP (printf ("the routine has nothing to release\n")); + break; + default: /* should not happen */ + break; + } + } while (release_result == ETH_OK); + + return 0; /* success */ +} + +/********************************************************************** + * mv64460_eth_receive + * + * This function is forward packets that are received from the port's + * queues toward kernel core or FastRoute them to another interface. + * + * Input : dev - a pointer to the required interface + * max - maximum number to receive (0 means unlimted) + * + * Output : number of served packets + **********************************************************************/ + +int mv64460_eth_receive (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + PKT_INFO pkt_info; + struct net_device_stats *stats; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + while ((eth_port_receive (ethernet_private, ETH_Q0, &pkt_info) == ETH_OK)) { +#ifdef DEBUG_MV_ETH + if (pkt_info.byte_cnt != 0) { + printf ("%s: Received %d byte Packet @ 0x%x\n", + __FUNCTION__, pkt_info.byte_cnt, + pkt_info.buf_ptr); + if(pkt_info.buf_ptr != 0){ + for(i=0; i < pkt_info.byte_cnt; i++){ + if((i % 4) == 0){ + printf("\n0x"); + } + printf("%02x", ((char*)pkt_info.buf_ptr)[i]); + } + printf("\n"); + } + } +#endif + /* Update statistics. Note byte count includes 4 byte CRC count */ + stats->rx_packets++; + stats->rx_bytes += pkt_info.byte_cnt; + + /* + * In case received a packet without first / last bits on OR the error + * summary bit is on, the packets needs to be dropeed. + */ + if (((pkt_info. + cmd_sts & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) != + (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) + || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) { + stats->rx_dropped++; + + printf ("Received packet spread on multiple descriptors\n"); + + /* Is this caused by an error ? */ + if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY) { + stats->rx_errors++; + } + + /* free these descriptors again without forwarding them to the higher layers */ + pkt_info.buf_ptr &= ~0x7; /* realign buffer again */ + pkt_info.byte_cnt = 0x0000; /* Reset Byte count */ + + if (eth_rx_return_buff + (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) { + printf ("Error while returning the RX Desc to Ring\n"); + } else { + DP (printf ("RX Desc returned to Ring\n")); + } + /* /free these descriptors again */ + } else { + +/* !!! call higher layer processing */ +#ifdef DEBUG_MV_ETH + printf ("\nNow send it to upper layer protocols (NetReceive) ...\n"); +#endif + /* let the upper layer handle the packet */ + NetReceive ((uchar *) pkt_info.buf_ptr, + (int) pkt_info.byte_cnt); + +/* **************************************************************** */ +/* free descriptor */ + pkt_info.buf_ptr &= ~0x7; /* realign buffer again */ + pkt_info.byte_cnt = 0x0000; /* Reset Byte count */ + DP (printf ("RX: pkt_info.buf_ptr = %x\n", pkt_info.buf_ptr)); + if (eth_rx_return_buff + (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) { + printf ("Error while returning the RX Desc to Ring\n"); + } else { + DP (printf ("RX: Desc returned to Ring\n")); + } + +/* **************************************************************** */ + + } + } + mv64460_eth_get_stats (dev); /* update statistics */ + return 1; +} + +/********************************************************************** + * mv64460_eth_get_stats + * + * Returns a pointer to the interface statistics. + * + * Input : dev - a pointer to the required interface + * + * Output : a pointer to the interface's statistics + **********************************************************************/ + +static struct net_device_stats *mv64460_eth_get_stats (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + + mv64460_eth_update_stat (dev); + + return port_private->stats; +} + +/********************************************************************** + * mv64460_eth_update_stat + * + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void mv64460_eth_update_stat (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + struct net_device_stats *stats; + unsigned int port_num; + volatile unsigned int dummy; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + /* These are false updates */ + stats->rx_packets += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_FRAMES_RECEIVED); + stats->tx_packets += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_FRAMES_SENT); + stats->rx_bytes += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_RECEIVED_LOW); + /* + * Ideally this should be as follows - + * + * stats->rx_bytes += stats->rx_bytes + + * ((unsigned long) ethReadMibCounter (ethernet_private->port_num , + * ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32); + * + * But the unsigned long in PowerPC and MIPS are 32bit. So the next read + * is just a dummy read for proper work of the GigE port + */ + dummy = eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH); + stats->tx_bytes += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_SENT_LOW); + dummy = eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_SENT_HIGH); + stats->rx_errors += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_MAC_RECEIVE_ERROR); + + /* Rx dropped is for received packet with CRC error */ + stats->rx_dropped += + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_BAD_CRC_EVENT); + stats->multicast += (unsigned long) + eth_read_mib_counter (ethernet_private->port_num, + ETH_MIB_MULTICAST_FRAMES_RECEIVED); + stats->collisions += + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_COLLISION) + + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_LATE_COLLISION); + /* detailed rx errors */ + stats->rx_length_errors += + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_UNDERSIZE_RECEIVED) + + + (unsigned long) eth_read_mib_counter (ethernet_private-> + port_num, + ETH_MIB_OVERSIZE_RECEIVED); + /* detailed tx errors */ +} + +#ifndef UPDATE_STATS_BY_SOFTWARE +/********************************************************************** + * mv64460_eth_print_stat + * + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void mv64460_eth_print_stat (struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct mv64460_eth_priv *port_private; + struct net_device_stats *stats; + unsigned int port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = + (struct mv64460_eth_priv *) ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + /* These are false updates */ + printf ("\n### Network statistics: ###\n"); + printf ("--------------------------\n"); + printf (" Packets received: %ld\n", stats->rx_packets); + printf (" Packets send: %ld\n", stats->tx_packets); + printf (" Received bytes: %ld\n", stats->rx_bytes); + printf (" Send bytes: %ld\n", stats->tx_bytes); + if (stats->rx_errors != 0) + printf (" Rx Errors: %ld\n", + stats->rx_errors); + if (stats->rx_dropped != 0) + printf (" Rx dropped (CRC Errors): %ld\n", + stats->rx_dropped); + if (stats->multicast != 0) + printf (" Rx mulicast frames: %ld\n", + stats->multicast); + if (stats->collisions != 0) + printf (" No. of collisions: %ld\n", + stats->collisions); + if (stats->rx_length_errors != 0) + printf (" Rx length errors: %ld\n", + stats->rx_length_errors); +} +#endif + +/************************************************************************** + *network_start - Network Kick Off Routine UBoot + *Inputs : + *Outputs : + **************************************************************************/ + +bool db64460_eth_start (struct eth_device *dev) +{ + return (mv64460_eth_open (dev)); /* calls real open */ +} + +/************************************************************************* +************************************************************************** +************************************************************************** +* The second part is the low level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ +/* + * based on Linux code + * arch/ppc/galileo/EVB64460/mv64460_eth.c - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + + * 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. + * + */ + +/******************************************************************************** + * Marvell's Gigabit Ethernet controller low level driver + * + * DESCRIPTION: + * This file introduce low level API to Marvell's Gigabit Ethernet + * controller. This Gigabit Ethernet Controller driver API controls + * 1) Operations (i.e. port init, start, reset etc'). + * 2) Data flow (i.e. port send, receive etc'). + * Each Gigabit Ethernet port is controlled via ETH_PORT_INFO + * struct. + * This struct includes user configuration information as well as + * driver internal data needed for its operations. + * + * Supported Features: + * - This low level driver is OS independent. Allocating memory for + * the descriptor rings and buffers are not within the scope of + * this driver. + * - The user is free from Rx/Tx queue managing. + * - This low level driver introduce functionality API that enable + * the to operate Marvell's Gigabit Ethernet Controller in a + * convenient way. + * - Simple Gigabit Ethernet port operation API. + * - Simple Gigabit Ethernet port data flow API. + * - Data flow and operation API support per queue functionality. + * - Support cached descriptors for better performance. + * - Enable access to all four DRAM banks and internal SRAM memory + * spaces. + * - PHY access and control API. + * - Port control register configuration API. + * - Full control over Unicast and Multicast MAC configurations. + * + * Operation flow: + * + * Initialization phase + * This phase complete the initialization of the ETH_PORT_INFO + * struct. + * User information regarding port configuration has to be set + * prior to calling the port initialization routine. For example, + * the user has to assign the port_phy_addr field which is board + * depended parameter. + * In this phase any port Tx/Rx activity is halted, MIB counters + * are cleared, PHY address is set according to user parameter and + * access to DRAM and internal SRAM memory spaces. + * + * Driver ring initialization + * Allocating memory for the descriptor rings and buffers is not + * within the scope of this driver. Thus, the user is required to + * allocate memory for the descriptors ring and buffers. Those + * memory parameters are used by the Rx and Tx ring initialization + * routines in order to curve the descriptor linked list in a form + * of a ring. + * Note: Pay special attention to alignment issues when using + * cached descriptors/buffers. In this phase the driver store + * information in the ETH_PORT_INFO struct regarding each queue + * ring. + * + * Driver start + * This phase prepares the Ethernet port for Rx and Tx activity. + * It uses the information stored in the ETH_PORT_INFO struct to + * initialize the various port registers. + * + * Data flow: + * All packet references to/from the driver are done using PKT_INFO + * struct. + * This struct is a unified struct used with Rx and Tx operations. + * This way the user is not required to be familiar with neither + * Tx nor Rx descriptors structures. + * The driver's descriptors rings are management by indexes. + * Those indexes controls the ring resources and used to indicate + * a SW resource error: + * 'current' + * This index points to the current available resource for use. For + * example in Rx process this index will point to the descriptor + * that will be passed to the user upon calling the receive routine. + * In Tx process, this index will point to the descriptor + * that will be assigned with the user packet info and transmitted. + * 'used' + * This index points to the descriptor that need to restore its + * resources. For example in Rx process, using the Rx buffer return + * API will attach the buffer returned in packet info to the + * descriptor pointed by 'used'. In Tx process, using the Tx + * descriptor return will merely return the user packet info with + * the command status of the transmitted buffer pointed by the + * 'used' index. Nevertheless, it is essential to use this routine + * to update the 'used' index. + * 'first' + * This index supports Tx Scatter-Gather. It points to the first + * descriptor of a packet assembled of multiple buffers. For example + * when in middle of Such packet we have a Tx resource error the + * 'curr' index get the value of 'first' to indicate that the ring + * returned to its state before trying to transmit this packet. + * + * Receive operation: + * The eth_port_receive API set the packet information struct, + * passed by the caller, with received information from the + * 'current' SDMA descriptor. + * It is the user responsibility to return this resource back + * to the Rx descriptor ring to enable the reuse of this source. + * Return Rx resource is done using the eth_rx_return_buff API. + * + * Transmit operation: + * The eth_port_send API supports Scatter-Gather which enables to + * send a packet spanned over multiple buffers. This means that + * for each packet info structure given by the user and put into + * the Tx descriptors ring, will be transmitted only if the 'LAST' + * bit will be set in the packet info command status field. This + * API also consider restriction regarding buffer alignments and + * sizes. + * The user must return a Tx resource after ensuring the buffer + * has been transmitted to enable the Tx ring indexes to update. + * + * BOARD LAYOUT + * This device is on-board. No jumper diagram is necessary. + * + * EXTERNAL INTERFACE + * + * Prior to calling the initialization routine eth_port_init() the user + * must set the following fields under ETH_PORT_INFO struct: + * port_num User Ethernet port number. + * port_phy_addr User PHY address of Ethernet port. + * port_mac_addr[6] User defined port MAC address. + * port_config User port configuration value. + * port_config_extend User port config extend value. + * port_sdma_config User port SDMA config value. + * port_serial_control User port serial control value. + * *port_virt_to_phys () User function to cast virtual addr to CPU bus addr. + * *port_private User scratch pad for user specific data structures. + * + * This driver introduce a set of default values: + * PORT_CONFIG_VALUE Default port configuration value + * PORT_CONFIG_EXTEND_VALUE Default port extend configuration value + * PORT_SDMA_CONFIG_VALUE Default sdma control value + * PORT_SERIAL_CONTROL_VALUE Default port serial control value + * + * This driver data flow is done using the PKT_INFO struct which is + * a unified struct for Rx and Tx operations: + * byte_cnt Tx/Rx descriptor buffer byte count. + * l4i_chk CPU provided TCP Checksum. For Tx operation only. + * cmd_sts Tx/Rx descriptor command status. + * buf_ptr Tx/Rx descriptor buffer pointer. + * return_info Tx/Rx user resource return information. + * + * + * EXTERNAL SUPPORT REQUIREMENTS + * + * This driver requires the following external support: + * + * D_CACHE_FLUSH_LINE (address, address offset) + * + * This macro applies assembly code to flush and invalidate cache + * line. + * address - address base. + * address offset - address offset + * + * + * CPU_PIPE_FLUSH + * + * This macro applies assembly code to flush the CPU pipeline. + * + *******************************************************************************/ +/* includes */ + +/* defines */ +/* SDMA command macros */ +#define ETH_ENABLE_TX_QUEUE(tx_queue, eth_port) \ + MV_REG_WRITE(MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), (1 << tx_queue)) + +#define ETH_DISABLE_TX_QUEUE(tx_queue, eth_port) \ + MV_REG_WRITE(MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port),\ + (1 << (8 + tx_queue))) + +#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \ +MV_REG_WRITE(MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), (1 << rx_queue)) + +#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \ +MV_REG_WRITE(MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), (1 << (8 + rx_queue))) + +#define CURR_RFD_GET(p_curr_desc, queue) \ + ((p_curr_desc) = p_eth_port_ctrl->p_rx_curr_desc_q[queue]) + +#define CURR_RFD_SET(p_curr_desc, queue) \ + (p_eth_port_ctrl->p_rx_curr_desc_q[queue] = (p_curr_desc)) + +#define USED_RFD_GET(p_used_desc, queue) \ + ((p_used_desc) = p_eth_port_ctrl->p_rx_used_desc_q[queue]) + +#define USED_RFD_SET(p_used_desc, queue)\ +(p_eth_port_ctrl->p_rx_used_desc_q[queue] = (p_used_desc)) + + +#define CURR_TFD_GET(p_curr_desc, queue) \ + ((p_curr_desc) = p_eth_port_ctrl->p_tx_curr_desc_q[queue]) + +#define CURR_TFD_SET(p_curr_desc, queue) \ + (p_eth_port_ctrl->p_tx_curr_desc_q[queue] = (p_curr_desc)) + +#define USED_TFD_GET(p_used_desc, queue) \ + ((p_used_desc) = p_eth_port_ctrl->p_tx_used_desc_q[queue]) + +#define USED_TFD_SET(p_used_desc, queue) \ + (p_eth_port_ctrl->p_tx_used_desc_q[queue] = (p_used_desc)) + +#define FIRST_TFD_GET(p_first_desc, queue) \ + ((p_first_desc) = p_eth_port_ctrl->p_tx_first_desc_q[queue]) + +#define FIRST_TFD_SET(p_first_desc, queue) \ + (p_eth_port_ctrl->p_tx_first_desc_q[queue] = (p_first_desc)) + + +/* Macros that save access to desc in order to find next desc pointer */ +#define RX_NEXT_DESC_PTR(p_rx_desc, queue) (ETH_RX_DESC*)(((((unsigned int)p_rx_desc - (unsigned int)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + RX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->rx_desc_area_size[queue]) + (unsigned int)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + +#define TX_NEXT_DESC_PTR(p_tx_desc, queue) (ETH_TX_DESC*)(((((unsigned int)p_tx_desc - (unsigned int)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + TX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->tx_desc_area_size[queue]) + (unsigned int)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + +#define LINK_UP_TIMEOUT 100000 +#define PHY_BUSY_TIMEOUT 10000000 + +/* locals */ + +/* PHY routines */ +static void ethernet_phy_set (ETH_PORT eth_port_num, int phy_addr); +static int ethernet_phy_get (ETH_PORT eth_port_num); + +/* Ethernet Port routines */ +static void eth_set_access_control (ETH_PORT eth_port_num, + ETH_WIN_PARAM * param); +static bool eth_port_uc_addr (ETH_PORT eth_port_num, unsigned char uc_nibble, + ETH_QUEUE queue, int option); +#if 0 /* FIXME */ +static bool eth_port_smc_addr (ETH_PORT eth_port_num, + unsigned char mc_byte, + ETH_QUEUE queue, int option); +static bool eth_port_omc_addr (ETH_PORT eth_port_num, + unsigned char crc8, + ETH_QUEUE queue, int option); +#endif + +static void eth_b_copy (unsigned int src_addr, unsigned int dst_addr, + int byte_count); + +void eth_dbg (ETH_PORT_INFO * p_eth_port_ctrl); + + +typedef enum _memory_bank { BANK0, BANK1, BANK2, BANK3 } MEMORY_BANK; +u32 mv_get_dram_bank_base_addr (MEMORY_BANK bank) +{ + u32 result = 0; + u32 enable = MV_REG_READ (MV64460_BASE_ADDR_ENABLE); + + if (enable & (1 << bank)) + return 0; + if (bank == BANK0) + result = MV_REG_READ (MV64460_CS_0_BASE_ADDR); + if (bank == BANK1) + result = MV_REG_READ (MV64460_CS_1_BASE_ADDR); + if (bank == BANK2) + result = MV_REG_READ (MV64460_CS_2_BASE_ADDR); + if (bank == BANK3) + result = MV_REG_READ (MV64460_CS_3_BASE_ADDR); + result &= 0x0000ffff; + result = result << 16; + return result; +} + +u32 mv_get_dram_bank_size (MEMORY_BANK bank) +{ + u32 result = 0; + u32 enable = MV_REG_READ (MV64460_BASE_ADDR_ENABLE); + + if (enable & (1 << bank)) + return 0; + if (bank == BANK0) + result = MV_REG_READ (MV64460_CS_0_SIZE); + if (bank == BANK1) + result = MV_REG_READ (MV64460_CS_1_SIZE); + if (bank == BANK2) + result = MV_REG_READ (MV64460_CS_2_SIZE); + if (bank == BANK3) + result = MV_REG_READ (MV64460_CS_3_SIZE); + result += 1; + result &= 0x0000ffff; + result = result << 16; + return result; +} + +u32 mv_get_internal_sram_base (void) +{ + u32 result; + + result = MV_REG_READ (MV64460_INTEGRATED_SRAM_BASE_ADDR); + result &= 0x0000ffff; + result = result << 16; + return result; +} + +/******************************************************************************* +* eth_port_init - Initialize the Ethernet port driver +* +* DESCRIPTION: +* This function prepares the ethernet port to start its activity: +* 1) Completes the ethernet port driver struct initialization toward port +* start routine. +* 2) Resets the device to a quiescent state in case of warm reboot. +* 3) Enable SDMA access to all four DRAM banks as well as internal SRAM. +* 4) Clean MAC tables. The reset status of those tables is unknown. +* 5) Set PHY address. +* Note: Call this routine prior to eth_port_start routine and after setting +* user values in the user fields of Ethernet port control struct (i.e. +* port_phy_addr). +* +* INPUT: +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* +* OUTPUT: +* See description. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_init (ETH_PORT_INFO * p_eth_port_ctrl) +{ + int queue; + ETH_WIN_PARAM win_param; + + p_eth_port_ctrl->port_config = PORT_CONFIG_VALUE; + p_eth_port_ctrl->port_config_extend = PORT_CONFIG_EXTEND_VALUE; + p_eth_port_ctrl->port_sdma_config = PORT_SDMA_CONFIG_VALUE; + p_eth_port_ctrl->port_serial_control = PORT_SERIAL_CONTROL_VALUE; + + p_eth_port_ctrl->port_rx_queue_command = 0; + p_eth_port_ctrl->port_tx_queue_command = 0; + + /* Zero out SW structs */ + for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) { + CURR_RFD_SET ((ETH_RX_DESC *) 0x00000000, queue); + USED_RFD_SET ((ETH_RX_DESC *) 0x00000000, queue); + p_eth_port_ctrl->rx_resource_err[queue] = false; + } + + for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { + CURR_TFD_SET ((ETH_TX_DESC *) 0x00000000, queue); + USED_TFD_SET ((ETH_TX_DESC *) 0x00000000, queue); + FIRST_TFD_SET ((ETH_TX_DESC *) 0x00000000, queue); + p_eth_port_ctrl->tx_resource_err[queue] = false; + } + + eth_port_reset (p_eth_port_ctrl->port_num); + + /* Set access parameters for DRAM bank 0 */ + win_param.win = ETH_WIN0; /* Use Ethernet window 0 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS0; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK0); + win_param.size = mv_get_dram_bank_size (BANK0); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for DRAM bank 1 */ + win_param.win = ETH_WIN1; /* Use Ethernet window 1 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS1; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK1); + win_param.size = mv_get_dram_bank_size (BANK1); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for DRAM bank 2 */ + win_param.win = ETH_WIN2; /* Use Ethernet window 2 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS2; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK2); + win_param.size = mv_get_dram_bank_size (BANK2); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for DRAM bank 3 */ + win_param.win = ETH_WIN3; /* Use Ethernet window 3 */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.attributes = EBAR_ATTR_DRAM_CS3; /* Enable DRAM bank */ +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = mv_get_dram_bank_base_addr (BANK3); + win_param.size = mv_get_dram_bank_size (BANK3); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + /* Set access parameters for Internal SRAM */ + win_param.win = ETH_WIN4; /* Use Ethernet window 0 */ + win_param.target = EBAR_TARGET_CBS; /* Target - Internal SRAM */ + win_param.attributes = EBAR_ATTR_CBS_SRAM | EBAR_ATTR_CBS_SRAM_BLOCK0; + win_param.high_addr = 0; + win_param.base_addr = mv_get_internal_sram_base (); /* Get base addr */ + win_param.size = MV64460_INTERNAL_SRAM_SIZE; /* Get bank size */ + win_param.enable = 1; /* Enable the access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control (p_eth_port_ctrl->port_num, &win_param); + + eth_port_init_mac_tables (p_eth_port_ctrl->port_num); + + ethernet_phy_set (p_eth_port_ctrl->port_num, + p_eth_port_ctrl->port_phy_addr); + + return; + +} + +/******************************************************************************* +* eth_port_start - Start the Ethernet port activity. +* +* DESCRIPTION: +* This routine prepares the Ethernet port for Rx and Tx activity: +* 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that +* has been initialized a descriptor's ring (using ether_init_tx_desc_ring +* for Tx and ether_init_rx_desc_ring for Rx) +* 2. Initialize and enable the Ethernet configuration port by writing to +* the port's configuration and command registers. +* 3. Initialize and enable the SDMA by writing to the SDMA's +* configuration and command registers. +* After completing these steps, the ethernet port SDMA can starts to +* perform Rx and Tx activities. +* +* Note: Each Rx and Tx queue descriptor's list must be initialized prior +* to calling this function (use ether_init_tx_desc_ring for Tx queues and +* ether_init_rx_desc_ring for Rx queues). +* +* INPUT: +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* +* OUTPUT: +* Ethernet port is ready to receive and transmit. +* +* RETURN: +* false if the port PHY is not up. +* true otherwise. +* +*******************************************************************************/ +static bool eth_port_start (ETH_PORT_INFO * p_eth_port_ctrl) +{ + int queue; + volatile ETH_TX_DESC *p_tx_curr_desc; + volatile ETH_RX_DESC *p_rx_curr_desc; + unsigned int phy_reg_data; + ETH_PORT eth_port_num = p_eth_port_ctrl->port_num; + + /* Assignment of Tx CTRP of given queue */ + for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { + CURR_TFD_GET (p_tx_curr_desc, queue); + MV_REG_WRITE ((MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_0 + (eth_port_num) + + (4 * queue)), + ((unsigned int) p_tx_curr_desc)); + + } + + /* Assignment of Rx CRDP of given queue */ + for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) { + CURR_RFD_GET (p_rx_curr_desc, queue); + MV_REG_WRITE ((MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_0 + (eth_port_num) + + (4 * queue)), + ((unsigned int) p_rx_curr_desc)); + + if (p_rx_curr_desc != NULL) + /* Add the assigned Ethernet address to the port's address table */ + eth_port_uc_addr_set (p_eth_port_ctrl->port_num, + p_eth_port_ctrl->port_mac_addr, + queue); + } + + /* Assign port configuration and command. */ + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_REG (eth_port_num), + p_eth_port_ctrl->port_config); + + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_EXTEND_REG (eth_port_num), + p_eth_port_ctrl->port_config_extend); + + MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + p_eth_port_ctrl->port_serial_control); + + MV_SET_REG_BITS (MV64460_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + ETH_SERIAL_PORT_ENABLE); + + /* Assign port SDMA configuration */ + MV_REG_WRITE (MV64460_ETH_SDMA_CONFIG_REG (eth_port_num), + p_eth_port_ctrl->port_sdma_config); + + MV_REG_WRITE (MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT + (eth_port_num), 0x3fffffff); + MV_REG_WRITE (MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG + (eth_port_num), 0x03fffcff); + /* Turn off the port/queue bandwidth limitation */ + MV_REG_WRITE (MV64460_ETH_MAXIMUM_TRANSMIT_UNIT (eth_port_num), 0x0); + + /* Enable port Rx. */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (eth_port_num), + p_eth_port_ctrl->port_rx_queue_command); + + /* Check if link is up */ + eth_port_read_smi_reg (eth_port_num, 1, &phy_reg_data); + + if (!(phy_reg_data & 0x20)) + return false; + + return true; +} + +/******************************************************************************* +* eth_port_uc_addr_set - This function Set the port Unicast address. +* +* DESCRIPTION: +* This function Set the port Ethernet MAC address. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* char * p_addr Address to be set +* ETH_QUEUE queue Rx queue number for this MAC address. +* +* OUTPUT: +* Set MAC address low and high registers. also calls eth_port_uc_addr() +* To set the unicast table with the proper information. +* +* RETURN: +* N/A. +* +*******************************************************************************/ +static void eth_port_uc_addr_set (ETH_PORT eth_port_num, + unsigned char *p_addr, ETH_QUEUE queue) +{ + unsigned int mac_h; + unsigned int mac_l; + + mac_l = (p_addr[4] << 8) | (p_addr[5]); + mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | + (p_addr[2] << 8) | (p_addr[3] << 0); + + MV_REG_WRITE (MV64460_ETH_MAC_ADDR_LOW (eth_port_num), mac_l); + MV_REG_WRITE (MV64460_ETH_MAC_ADDR_HIGH (eth_port_num), mac_h); + + /* Accept frames of this address */ + eth_port_uc_addr (eth_port_num, p_addr[5], queue, ACCEPT_MAC_ADDR); + + return; +} + +/******************************************************************************* +* eth_port_uc_addr - This function Set the port unicast address table +* +* DESCRIPTION: +* This function locates the proper entry in the Unicast table for the +* specified MAC nibble and sets its properties according to function +* parameters. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char uc_nibble Unicast MAC Address last nibble. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* This function add/removes MAC addresses from the port unicast address +* table. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_uc_addr (ETH_PORT eth_port_num, + unsigned char uc_nibble, + ETH_QUEUE queue, int option) +{ + unsigned int unicast_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the Unicast table entry */ + uc_nibble = (0xf & uc_nibble); + tbl_offset = (uc_nibble / 4) * 4; /* Register offset from unicast table base */ + reg_offset = uc_nibble % 4; /* Entry offset within the above register */ + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified unicast DA table entry */ + unicast_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset), unicast_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at unicast DA filter table entry */ + unicast_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset), unicast_reg); + + break; + + default: + return false; + } + return true; +} + +#if 0 /* FIXME */ +/******************************************************************************* +* eth_port_mc_addr - Multicast address settings. +* +* DESCRIPTION: +* This API controls the MV device MAC multicast support. +* The MV device supports multicast using two tables: +* 1) Special Multicast Table for MAC addresses of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_fF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* In this case, the function calls eth_port_smc_addr() routine to set the +* Special Multicast Table. +* 2) Other Multicast Table for multicast of another type. A CRC-8bit +* is used as an index to the Other Multicast Table entries in the +* DA-Filter table. +* In this case, the function calculates the CRC-8bit value and calls +* eth_port_omc_addr() routine to set the Other Multicast Table. +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char *p_addr Unicast MAC Address. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* true is output succeeded. +* false if add_address_table_entry( ) failed. +* +*******************************************************************************/ +static void eth_port_mc_addr (ETH_PORT eth_port_num, + unsigned char *p_addr, + ETH_QUEUE queue, int option) +{ + unsigned int mac_h; + unsigned int mac_l; + unsigned char crc_result = 0; + int mac_array[48]; + int crc[8]; + int i; + + if ((p_addr[0] == 0x01) && + (p_addr[1] == 0x00) && + (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) { + + eth_port_smc_addr (eth_port_num, p_addr[5], queue, option); + } else { + /* Calculate CRC-8 out of the given address */ + mac_h = (p_addr[0] << 8) | (p_addr[1]); + mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) | + (p_addr[4] << 8) | (p_addr[5] << 0); + + for (i = 0; i < 32; i++) + mac_array[i] = (mac_l >> i) & 0x1; + for (i = 32; i < 48; i++) + mac_array[i] = (mac_h >> (i - 32)) & 0x1; + + crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ + mac_array[39] ^ mac_array[35] ^ mac_array[34] ^ + mac_array[31] ^ mac_array[30] ^ mac_array[28] ^ + mac_array[23] ^ mac_array[21] ^ mac_array[19] ^ + mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ + mac_array[12] ^ mac_array[8] ^ mac_array[7] ^ + mac_array[6] ^ mac_array[0]; + + crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ + mac_array[43] ^ mac_array[41] ^ mac_array[39] ^ + mac_array[36] ^ mac_array[34] ^ mac_array[32] ^ + mac_array[30] ^ mac_array[29] ^ mac_array[28] ^ + mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ + mac_array[21] ^ mac_array[20] ^ mac_array[18] ^ + mac_array[17] ^ mac_array[16] ^ mac_array[15] ^ + mac_array[14] ^ mac_array[13] ^ mac_array[12] ^ + mac_array[9] ^ mac_array[6] ^ mac_array[1] ^ + mac_array[0]; + + crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ + mac_array[43] ^ mac_array[42] ^ mac_array[39] ^ + mac_array[37] ^ mac_array[34] ^ mac_array[33] ^ + mac_array[29] ^ mac_array[28] ^ mac_array[25] ^ + mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ + mac_array[15] ^ mac_array[13] ^ mac_array[12] ^ + mac_array[10] ^ mac_array[8] ^ mac_array[6] ^ + mac_array[2] ^ mac_array[1] ^ mac_array[0]; + + crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ + mac_array[43] ^ mac_array[40] ^ mac_array[38] ^ + mac_array[35] ^ mac_array[34] ^ mac_array[30] ^ + mac_array[29] ^ mac_array[26] ^ mac_array[25] ^ + mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ + mac_array[14] ^ mac_array[13] ^ mac_array[11] ^ + mac_array[9] ^ mac_array[7] ^ mac_array[3] ^ + mac_array[2] ^ mac_array[1]; + + crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ + mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ + mac_array[35] ^ mac_array[31] ^ mac_array[30] ^ + mac_array[27] ^ mac_array[26] ^ mac_array[24] ^ + mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ + mac_array[14] ^ mac_array[12] ^ mac_array[10] ^ + mac_array[8] ^ mac_array[4] ^ mac_array[3] ^ + mac_array[2]; + + crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ + mac_array[42] ^ mac_array[40] ^ mac_array[37] ^ + mac_array[36] ^ mac_array[32] ^ mac_array[31] ^ + mac_array[28] ^ mac_array[27] ^ mac_array[25] ^ + mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ + mac_array[15] ^ mac_array[13] ^ mac_array[11] ^ + mac_array[9] ^ mac_array[5] ^ mac_array[4] ^ + mac_array[3]; + + crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ + mac_array[41] ^ mac_array[38] ^ mac_array[37] ^ + mac_array[33] ^ mac_array[32] ^ mac_array[29] ^ + mac_array[28] ^ mac_array[26] ^ mac_array[21] ^ + mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ + mac_array[14] ^ mac_array[12] ^ mac_array[10] ^ + mac_array[6] ^ mac_array[5] ^ mac_array[4]; + + crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ + mac_array[39] ^ mac_array[38] ^ mac_array[34] ^ + mac_array[33] ^ mac_array[30] ^ mac_array[29] ^ + mac_array[27] ^ mac_array[22] ^ mac_array[20] ^ + mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ + mac_array[13] ^ mac_array[11] ^ mac_array[7] ^ + mac_array[6] ^ mac_array[5]; + + for (i = 0; i < 8; i++) + crc_result = crc_result | (crc[i] << i); + + eth_port_omc_addr (eth_port_num, crc_result, queue, option); + } + return; +} + +/******************************************************************************* +* eth_port_smc_addr - Special Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device special MAC multicast support. +* The Special Multicast Table for MAC addresses supports MAC of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_fF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* This function set the Special Multicast Table appropriate entry +* according to the argument given. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char mc_byte Multicast addr last byte (MAC DA[7:0] bits). +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_smc_addr (ETH_PORT eth_port_num, + unsigned char mc_byte, + ETH_QUEUE queue, int option) +{ + unsigned int smc_table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the SMC table entry */ + tbl_offset = (mc_byte / 4) * 4; /* Register offset from SMC table base */ + reg_offset = mc_byte % 4; /* Entry offset within the above register */ + queue &= 0x7; + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified Special DA table entry */ + smc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + smc_table_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), smc_table_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at specified Special DA table entry */ + smc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + smc_table_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), smc_table_reg); + break; + + default: + return false; + } + return true; +} + +/******************************************************************************* +* eth_port_omc_addr - Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device Other MAC multicast support. +* The Other Multicast Table is used for multicast of another type. +* A CRC-8bit is used as an index to the Other Multicast Table entries +* in the DA-Filter table. +* The function gets the CRC-8bit value from the calling routine and +* set the Other Multicast Table appropriate entry according to the +* CRC-8 argument given. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* unsigned char crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1). +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_omc_addr (ETH_PORT eth_port_num, + unsigned char crc8, + ETH_QUEUE queue, int option) +{ + unsigned int omc_table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the OMC table entry */ + tbl_offset = (crc8 / 4) * 4; /* Register offset from OMC table base */ + reg_offset = crc8 % 4; /* Entry offset within the above register */ + queue &= 0x7; + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified Other DA table entry */ + omc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + omc_table_reg &= (0x0E << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), omc_table_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at specified Other DA table entry */ + omc_table_reg = + MV_REG_READ ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset)); + omc_table_reg |= ((0x01 | queue) << (8 * reg_offset)); + + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + tbl_offset), omc_table_reg); + break; + + default: + return false; + } + return true; +} +#endif + +/******************************************************************************* +* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables +* +* DESCRIPTION: +* Go through all the DA filter tables (Unicast, Special Multicast & Other +* Multicast) and set each entry to 0. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* Multicast and Unicast packets are rejected. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_init_mac_tables (ETH_PORT eth_port_num) +{ + int table_index; + + /* Clear DA filter unicast table (Ex_dFUT) */ + for (table_index = 0; table_index <= 0xC; table_index += 4) + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + table_index), 0); + + for (table_index = 0; table_index <= 0xFC; table_index += 4) { + /* Clear DA filter special multicast table (Ex_dFSMT) */ + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE (eth_port_num) + table_index), 0); + /* Clear DA filter other multicast table (Ex_dFOMT) */ + MV_REG_WRITE ((MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE (eth_port_num) + table_index), 0); + } +} + +/******************************************************************************* +* eth_clear_mib_counters - Clear all MIB counters +* +* DESCRIPTION: +* This function clears all MIB counters of a specific ethernet port. +* A read from the MIB counter will reset the counter. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* After reading all MIB counters, the counters resets. +* +* RETURN: +* MIB counter value. +* +*******************************************************************************/ +static void eth_clear_mib_counters (ETH_PORT eth_port_num) +{ + int i; + unsigned int dummy; + + /* Perform dummy reads from MIB counters */ + for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; + i += 4) + dummy = MV_REG_READ ((MV64460_ETH_MIB_COUNTERS_BASE + (eth_port_num) + i)); + + return; +} + +/******************************************************************************* +* eth_read_mib_counter - Read a MIB counter +* +* DESCRIPTION: +* This function reads a MIB counter of a specific ethernet port. +* NOTE - If read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, then the +* following read must be from ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH +* register. The same applies for ETH_MIB_GOOD_OCTETS_SENT_LOW and +* ETH_MIB_GOOD_OCTETS_SENT_HIGH +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* unsigned int mib_offset MIB counter offset (use ETH_MIB_... macros). +* +* OUTPUT: +* After reading the MIB counter, the counter resets. +* +* RETURN: +* MIB counter value. +* +*******************************************************************************/ +unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, + unsigned int mib_offset) +{ + return (MV_REG_READ (MV64460_ETH_MIB_COUNTERS_BASE (eth_port_num) + + mib_offset)); +} + +/******************************************************************************* +* ethernet_phy_set - Set the ethernet port PHY address. +* +* DESCRIPTION: +* This routine set the ethernet port PHY address according to given +* parameter. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* Set PHY Address Register with given PHY address parameter. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void ethernet_phy_set (ETH_PORT eth_port_num, int phy_addr) +{ + unsigned int reg_data; + + reg_data = MV_REG_READ (MV64460_ETH_PHY_ADDR_REG); + + reg_data &= ~(0x1F << (5 * eth_port_num)); + reg_data |= (phy_addr << (5 * eth_port_num)); + + MV_REG_WRITE (MV64460_ETH_PHY_ADDR_REG, reg_data); + + return; +} + +/******************************************************************************* + * ethernet_phy_get - Get the ethernet port PHY address. + * + * DESCRIPTION: + * This routine returns the given ethernet port PHY address. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * None. + * + * RETURN: + * PHY address. + * + *******************************************************************************/ +static int ethernet_phy_get (ETH_PORT eth_port_num) +{ + unsigned int reg_data; + + reg_data = MV_REG_READ (MV64460_ETH_PHY_ADDR_REG); + + return ((reg_data >> (5 * eth_port_num)) & 0x1f); +} + +/***********************************************************/ +/* (Re)start autonegotiation */ +/***********************************************************/ +int phy_setup_aneg (char *devname, unsigned char addr) +{ + unsigned short ctl, adv; + + /* Setup standard advertise */ + miiphy_read (devname, addr, PHY_ANAR, &adv); + adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 | + PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | + PHY_ANLPAR_10); + miiphy_write (devname, addr, PHY_ANAR, adv); + + miiphy_read (devname, addr, PHY_1000BTCR, &adv); + adv |= (0x0300); + miiphy_write (devname, addr, PHY_1000BTCR, adv); + + /* Start/Restart aneg */ + miiphy_read (devname, addr, PHY_BMCR, &ctl); + ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); + miiphy_write (devname, addr, PHY_BMCR, ctl); + + return 0; +} + +/******************************************************************************* + * ethernet_phy_reset - Reset Ethernet port PHY. + * + * DESCRIPTION: + * This routine utilize the SMI interface to reset the ethernet port PHY. + * The routine waits until the link is up again or link up is timeout. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * The ethernet port PHY renew its link. + * + * RETURN: + * None. + * + *******************************************************************************/ +static bool ethernet_phy_reset (ETH_PORT eth_port_num) +{ + unsigned int time_out = 50; + unsigned int phy_reg_data; + + eth_port_read_smi_reg (eth_port_num, 20, &phy_reg_data); + phy_reg_data |= 0x0083; /* Set bit 7 to 1 for different RGMII timing */ + eth_port_write_smi_reg (eth_port_num, 20, phy_reg_data); + + /* Reset the PHY */ + eth_port_read_smi_reg (eth_port_num, 0, &phy_reg_data); + phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */ + eth_port_write_smi_reg (eth_port_num, 0, phy_reg_data); + + /* Poll on the PHY LINK */ + do { + eth_port_read_smi_reg (eth_port_num, 1, &phy_reg_data); + + if (time_out-- == 0) + return false; + } + while (!(phy_reg_data & 0x20)); + + return true; +} + +/******************************************************************************* + * eth_port_reset - Reset Ethernet port + * + * DESCRIPTION: + * This routine resets the chip by aborting any SDMA engine activity and + * clearing the MIB counters. The Receiver and the Transmit unit are in + * idle state after this command is performed and the port is disabled. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * Channel activity is halted. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_port_reset (ETH_PORT eth_port_num) +{ + unsigned int reg_data; + + /* Stop Tx port activity. Check port Tx activity. */ + reg_data = + MV_REG_READ (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + MV_REG_WRITE (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num), (reg_data << 8)); + + /* Wait for all Tx activity to terminate. */ + do { + /* Check port cause register that all Tx queues are stopped */ + reg_data = + MV_REG_READ + (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num)); + } + while (reg_data & 0xFF); + } + + /* Stop Rx port activity. Check port Rx activity. */ + reg_data = + MV_REG_READ (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num), (reg_data << 8)); + + /* Wait for all Rx activity to terminate. */ + do { + /* Check port cause register that all Rx queues are stopped */ + reg_data = + MV_REG_READ + (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num)); + } + while (reg_data & 0xFF); + } + + /* Clear all MIB counters */ + eth_clear_mib_counters (eth_port_num); + + /* Reset the Enable bit in the Configuration Register */ + reg_data = + MV_REG_READ (MV64460_ETH_PORT_SERIAL_CONTROL_REG + (eth_port_num)); + reg_data &= ~ETH_SERIAL_PORT_ENABLE; + MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num), + reg_data); + + return; +} + +#if 0 /* Not needed here */ +/******************************************************************************* + * ethernet_set_config_reg - Set specified bits in configuration register. + * + * DESCRIPTION: + * This function sets specified bits in the given ethernet + * configuration register. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int value 32 bit value. + * + * OUTPUT: + * The set bits in the value parameter are set in the configuration + * register. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void ethernet_set_config_reg (ETH_PORT eth_port_num, + unsigned int value) +{ + unsigned int eth_config_reg; + + eth_config_reg = + MV_REG_READ (MV64460_ETH_PORT_CONFIG_REG (eth_port_num)); + eth_config_reg |= value; + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_REG (eth_port_num), + eth_config_reg); + + return; +} +#endif + +#if 0 /* FIXME */ +/******************************************************************************* + * ethernet_reset_config_reg - Reset specified bits in configuration register. + * + * DESCRIPTION: + * This function resets specified bits in the given Ethernet + * configuration register. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int value 32 bit value. + * + * OUTPUT: + * The set bits in the value parameter are reset in the configuration + * register. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void ethernet_reset_config_reg (ETH_PORT eth_port_num, + unsigned int value) +{ + unsigned int eth_config_reg; + + eth_config_reg = MV_REG_READ (MV64460_ETH_PORT_CONFIG_EXTEND_REG + (eth_port_num)); + eth_config_reg &= ~value; + MV_REG_WRITE (MV64460_ETH_PORT_CONFIG_EXTEND_REG (eth_port_num), + eth_config_reg); + + return; +} +#endif + +#if 0 /* Not needed here */ +/******************************************************************************* + * ethernet_get_config_reg - Get the port configuration register + * + * DESCRIPTION: + * This function returns the configuration register value of the given + * ethernet port. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * None. + * + * RETURN: + * Port configuration register value. + * + *******************************************************************************/ +static unsigned int ethernet_get_config_reg (ETH_PORT eth_port_num) +{ + unsigned int eth_config_reg; + + eth_config_reg = MV_REG_READ (MV64460_ETH_PORT_CONFIG_EXTEND_REG + (eth_port_num)); + return eth_config_reg; +} + +#endif + +/******************************************************************************* + * eth_port_read_smi_reg - Read PHY registers + * + * DESCRIPTION: + * This routine utilize the SMI interface to interact with the PHY in + * order to perform PHY register read. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int phy_reg PHY register address offset. + * unsigned int *value Register value buffer. + * + * OUTPUT: + * Write the value of a specified PHY register into given buffer. + * + * RETURN: + * false if the PHY is busy or read data is not in valid state. + * true otherwise. + * + *******************************************************************************/ +static bool eth_port_read_smi_reg (ETH_PORT eth_port_num, + unsigned int phy_reg, unsigned int *value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + int phy_addr; + + phy_addr = ethernet_phy_get (eth_port_num); + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_READ); + + time_out = PHY_BUSY_TIMEOUT; /* initialize the time out var again */ + + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ + + /* Wait for the data to update in the SMI register */ +#define PHY_UPDATE_TIMEOUT 10000 + for (time_out = 0; time_out < PHY_UPDATE_TIMEOUT; time_out++); + + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + + *value = reg_value & 0xffff; + + return true; +} + +int mv_miiphy_read(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short *value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_READ); + + time_out = PHY_BUSY_TIMEOUT; /* initialize the time out var again */ + + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while ((reg_value & ETH_SMI_READ_VALID) != ETH_SMI_READ_VALID); /* Bit set equ operation done */ + + /* Wait for the data to update in the SMI register */ + for (time_out = 0; time_out < PHY_UPDATE_TIMEOUT; time_out++); + + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + + *value = reg_value & 0xffff; + + return 0; +} + +/******************************************************************************* + * eth_port_write_smi_reg - Write to PHY registers + * + * DESCRIPTION: + * This routine utilize the SMI interface to interact with the PHY in + * order to perform writes to PHY registers. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * unsigned int phy_reg PHY register address offset. + * unsigned int value Register value. + * + * OUTPUT: + * Write the given value to the specified PHY register. + * + * RETURN: + * false if the PHY is busy. + * true otherwise. + * + *******************************************************************************/ +static bool eth_port_write_smi_reg (ETH_PORT eth_port_num, + unsigned int phy_reg, unsigned int value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + int phy_addr; + + phy_addr = ethernet_phy_get (eth_port_num); + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_WRITE | (value & 0xffff)); + return true; +} + +int mv_miiphy_write(char *devname, unsigned char phy_addr, + unsigned char phy_reg, unsigned short value) +{ + unsigned int reg_value; + unsigned int time_out = PHY_BUSY_TIMEOUT; + + /* first check that it is not busy */ + do { + reg_value = MV_REG_READ (MV64460_ETH_SMI_REG); + if (time_out-- == 0) { + return false; + } + } + while (reg_value & ETH_SMI_BUSY); + + /* not busy */ + MV_REG_WRITE (MV64460_ETH_SMI_REG, + (phy_addr << 16) | (phy_reg << 21) | + ETH_SMI_OPCODE_WRITE | (value & 0xffff)); + return 0; +} + +/******************************************************************************* + * eth_set_access_control - Config address decode parameters for Ethernet unit + * + * DESCRIPTION: + * This function configures the address decode parameters for the Gigabit + * Ethernet Controller according the given parameters struct. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_WIN_PARAM *param Address decode parameter struct. + * + * OUTPUT: + * An access window is opened using the given access parameters. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_set_access_control (ETH_PORT eth_port_num, + ETH_WIN_PARAM * param) +{ + unsigned int access_prot_reg; + + /* Set access control register */ + access_prot_reg = MV_REG_READ (MV64460_ETH_ACCESS_PROTECTION_REG + (eth_port_num)); + access_prot_reg &= (~(3 << (param->win * 2))); /* clear window permission */ + access_prot_reg |= (param->access_ctrl << (param->win * 2)); + MV_REG_WRITE (MV64460_ETH_ACCESS_PROTECTION_REG (eth_port_num), + access_prot_reg); + + /* Set window Size reg (SR) */ + MV_REG_WRITE ((MV64460_ETH_SIZE_REG_0 + + (ETH_SIZE_REG_GAP * param->win)), + (((param->size / 0x10000) - 1) << 16)); + + /* Set window Base address reg (BA) */ + MV_REG_WRITE ((MV64460_ETH_BAR_0 + (ETH_BAR_GAP * param->win)), + (param->target | param->attributes | param->base_addr)); + /* High address remap reg (HARR) */ + if (param->win < 4) + MV_REG_WRITE ((MV64460_ETH_HIGH_ADDR_REMAP_REG_0 + + (ETH_HIGH_ADDR_REMAP_REG_GAP * param->win)), + param->high_addr); + + /* Base address enable reg (BARER) */ + if (param->enable == 1) + MV_RESET_REG_BITS (MV64460_ETH_BASE_ADDR_ENABLE_REG, + (1 << param->win)); + else + MV_SET_REG_BITS (MV64460_ETH_BASE_ADDR_ENABLE_REG, + (1 << param->win)); +} + +/******************************************************************************* + * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory. + * + * DESCRIPTION: + * This function prepares a Rx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * int rx_desc_num Number of Rx descriptors + * int rx_buff_size Size of Rx buffer + * unsigned int rx_desc_base_addr Rx descriptors memory area base addr. + * unsigned int rx_buff_base_addr Rx buffer memory area base addr. + * + * OUTPUT: + * The routine updates the Ethernet port control struct with information + * regarding the Rx descriptors and buffers. + * + * RETURN: + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. + * + *******************************************************************************/ +static bool ether_init_rx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + int rx_desc_num, + int rx_buff_size, + unsigned int rx_desc_base_addr, + unsigned int rx_buff_base_addr) +{ + ETH_RX_DESC *p_rx_desc; + ETH_RX_DESC *p_rx_prev_desc; /* pointer to link with the last descriptor */ + unsigned int buffer_addr; + int ix; /* a counter */ + + p_rx_desc = (ETH_RX_DESC *) rx_desc_base_addr; + p_rx_prev_desc = p_rx_desc; + buffer_addr = rx_buff_base_addr; + + /* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */ + if (rx_buff_base_addr & 0xF) + return false; + + /* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes */ + if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE)) + return false; + + /* Rx buffers must be 64-bit aligned. */ + if ((rx_buff_base_addr + rx_buff_size) & 0x7) + return false; + + /* initialize the Rx descriptors ring */ + for (ix = 0; ix < rx_desc_num; ix++) { + p_rx_desc->buf_size = rx_buff_size; + p_rx_desc->byte_cnt = 0x0000; + p_rx_desc->cmd_sts = + ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT; + p_rx_desc->next_desc_ptr = + ((unsigned int) p_rx_desc) + RX_DESC_ALIGNED_SIZE; + p_rx_desc->buf_ptr = buffer_addr; + p_rx_desc->return_info = 0x00000000; + D_CACHE_FLUSH_LINE (p_rx_desc, 0); + buffer_addr += rx_buff_size; + p_rx_prev_desc = p_rx_desc; + p_rx_desc = (ETH_RX_DESC *) + ((unsigned int) p_rx_desc + RX_DESC_ALIGNED_SIZE); + } + + /* Closing Rx descriptors ring */ + p_rx_prev_desc->next_desc_ptr = (rx_desc_base_addr); + D_CACHE_FLUSH_LINE (p_rx_prev_desc, 0); + + /* Save Rx desc pointer to driver struct. */ + CURR_RFD_SET ((ETH_RX_DESC *) rx_desc_base_addr, rx_queue); + USED_RFD_SET ((ETH_RX_DESC *) rx_desc_base_addr, rx_queue); + + p_eth_port_ctrl->p_rx_desc_area_base[rx_queue] = + (ETH_RX_DESC *) rx_desc_base_addr; + p_eth_port_ctrl->rx_desc_area_size[rx_queue] = + rx_desc_num * RX_DESC_ALIGNED_SIZE; + + p_eth_port_ctrl->port_rx_queue_command |= (1 << rx_queue); + + return true; +} + +/******************************************************************************* + * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory. + * + * DESCRIPTION: + * This function prepares a Tx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * int tx_desc_num Number of Tx descriptors + * int tx_buff_size Size of Tx buffer + * unsigned int tx_desc_base_addr Tx descriptors memory area base addr. + * unsigned int tx_buff_base_addr Tx buffer memory area base addr. + * + * OUTPUT: + * The routine updates the Ethernet port control struct with information + * regarding the Tx descriptors and buffers. + * + * RETURN: + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. + * + *******************************************************************************/ +static bool ether_init_tx_desc_ring (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + int tx_desc_num, + int tx_buff_size, + unsigned int tx_desc_base_addr, + unsigned int tx_buff_base_addr) +{ + + ETH_TX_DESC *p_tx_desc; + ETH_TX_DESC *p_tx_prev_desc; + unsigned int buffer_addr; + int ix; /* a counter */ + + /* save the first desc pointer to link with the last descriptor */ + p_tx_desc = (ETH_TX_DESC *) tx_desc_base_addr; + p_tx_prev_desc = p_tx_desc; + buffer_addr = tx_buff_base_addr; + + /* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */ + if (tx_buff_base_addr & 0xF) + return false; + + /* Tx buffers are limited to 64K bytes and Minimum size is 8 bytes */ + if ((tx_buff_size > TX_BUFFER_MAX_SIZE) + || (tx_buff_size < TX_BUFFER_MIN_SIZE)) + return false; + + /* Initialize the Tx descriptors ring */ + for (ix = 0; ix < tx_desc_num; ix++) { + p_tx_desc->byte_cnt = 0x0000; + p_tx_desc->l4i_chk = 0x0000; + p_tx_desc->cmd_sts = 0x00000000; + p_tx_desc->next_desc_ptr = + ((unsigned int) p_tx_desc) + TX_DESC_ALIGNED_SIZE; + + p_tx_desc->buf_ptr = buffer_addr; + p_tx_desc->return_info = 0x00000000; + D_CACHE_FLUSH_LINE (p_tx_desc, 0); + buffer_addr += tx_buff_size; + p_tx_prev_desc = p_tx_desc; + p_tx_desc = (ETH_TX_DESC *) + ((unsigned int) p_tx_desc + TX_DESC_ALIGNED_SIZE); + + } + /* Closing Tx descriptors ring */ + p_tx_prev_desc->next_desc_ptr = tx_desc_base_addr; + D_CACHE_FLUSH_LINE (p_tx_prev_desc, 0); + /* Set Tx desc pointer in driver struct. */ + CURR_TFD_SET ((ETH_TX_DESC *) tx_desc_base_addr, tx_queue); + USED_TFD_SET ((ETH_TX_DESC *) tx_desc_base_addr, tx_queue); + + /* Init Tx ring base and size parameters */ + p_eth_port_ctrl->p_tx_desc_area_base[tx_queue] = + (ETH_TX_DESC *) tx_desc_base_addr; + p_eth_port_ctrl->tx_desc_area_size[tx_queue] = + (tx_desc_num * TX_DESC_ALIGNED_SIZE); + + /* Add the queue to the list of Tx queues of this port */ + p_eth_port_ctrl->port_tx_queue_command |= (1 << tx_queue); + + return true; +} + +/******************************************************************************* + * eth_port_send - Send an Ethernet packet + * + * DESCRIPTION: + * This routine send a given packet described by p_pktinfo parameter. It + * supports transmitting of a packet spaned over multiple buffers. The + * routine updates 'curr' and 'first' indexes according to the packet + * segment passed to the routine. In case the packet segment is first, + * the 'first' index is update. In any case, the 'curr' index is updated. + * If the routine get into Tx resource error it assigns 'curr' index as + * 'first'. This way the function can abort Tx process of multiple + * descriptors per packet. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Tx ring 'curr' and 'first' indexes are updated. + * + * RETURN: + * ETH_QUEUE_FULL in case of Tx resource error. + * ETH_ERROR in case the routine can not access Tx desc ring. + * ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_TX_DESC *p_tx_desc_first; + volatile ETH_TX_DESC *p_tx_desc_curr; + volatile ETH_TX_DESC *p_tx_next_desc_curr; + volatile ETH_TX_DESC *p_tx_desc_used; + unsigned int command_status; + + /* Do not process Tx ring in case of Tx ring resource error */ + if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true) + return ETH_QUEUE_FULL; + + /* Get the Tx Desc ring indexes */ + CURR_TFD_GET (p_tx_desc_curr, tx_queue); + USED_TFD_GET (p_tx_desc_used, tx_queue); + + if (p_tx_desc_curr == NULL) + return ETH_ERROR; + + /* The following parameters are used to save readings from memory */ + p_tx_next_desc_curr = TX_NEXT_DESC_PTR (p_tx_desc_curr, tx_queue); + command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC; + + if (command_status & (ETH_TX_FIRST_DESC)) { + /* Update first desc */ + FIRST_TFD_SET (p_tx_desc_curr, tx_queue); + p_tx_desc_first = p_tx_desc_curr; + } else { + FIRST_TFD_GET (p_tx_desc_first, tx_queue); + command_status |= ETH_BUFFER_OWNED_BY_DMA; + } + + /* Buffers with a payload smaller than 8 bytes must be aligned to 64-bit */ + /* boundary. We use the memory allocated for Tx descriptor. This memory */ + /* located in TX_BUF_OFFSET_IN_DESC offset within the Tx descriptor. */ + if (p_pkt_info->byte_cnt <= 8) { + printf ("You have failed in the < 8 bytes errata - fixme\n"); /* RABEEH - TBD */ + return ETH_ERROR; + + p_tx_desc_curr->buf_ptr = + (unsigned int) p_tx_desc_curr + TX_BUF_OFFSET_IN_DESC; + eth_b_copy (p_pkt_info->buf_ptr, p_tx_desc_curr->buf_ptr, + p_pkt_info->byte_cnt); + } else + p_tx_desc_curr->buf_ptr = p_pkt_info->buf_ptr; + + p_tx_desc_curr->byte_cnt = p_pkt_info->byte_cnt; + p_tx_desc_curr->return_info = p_pkt_info->return_info; + + if (p_pkt_info->cmd_sts & (ETH_TX_LAST_DESC)) { + /* Set last desc with DMA ownership and interrupt enable. */ + p_tx_desc_curr->cmd_sts = command_status | + ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; + + if (p_tx_desc_curr != p_tx_desc_first) + p_tx_desc_first->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA; + + /* Flush CPU pipe */ + + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_curr, 0); + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_first, 0); + CPU_PIPE_FLUSH; + + /* Apply send command */ + ETH_ENABLE_TX_QUEUE (tx_queue, p_eth_port_ctrl->port_num); + + /* Finish Tx packet. Update first desc in case of Tx resource error */ + p_tx_desc_first = p_tx_next_desc_curr; + FIRST_TFD_SET (p_tx_desc_first, tx_queue); + + } else { + p_tx_desc_curr->cmd_sts = command_status; + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_curr, 0); + } + + /* Check for ring index overlap in the Tx desc ring */ + if (p_tx_next_desc_curr == p_tx_desc_used) { + /* Update the current descriptor */ + CURR_TFD_SET (p_tx_desc_first, tx_queue); + + p_eth_port_ctrl->tx_resource_err[tx_queue] = true; + return ETH_QUEUE_LAST_RESOURCE; + } else { + /* Update the current descriptor */ + CURR_TFD_SET (p_tx_next_desc_curr, tx_queue); + return ETH_OK; + } +} + +/******************************************************************************* + * eth_tx_return_desc - Free all used Tx descriptors + * + * DESCRIPTION: + * This routine returns the transmitted packet information to the caller. + * It uses the 'first' index to support Tx desc return in case a transmit + * of a packet spanned over multiple buffer still in process. + * In case the Tx queue was in "resource error" condition, where there are + * no available Tx resources, the function resets the resource error flag. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Tx ring 'first' and 'used' indexes are updated. + * + * RETURN: + * ETH_ERROR in case the routine can not access Tx desc ring. + * ETH_RETRY in case there is transmission in process. + * ETH_END_OF_JOB if the routine has nothing to release. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_tx_return_desc (ETH_PORT_INFO * + p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_TX_DESC *p_tx_desc_used = NULL; + volatile ETH_TX_DESC *p_tx_desc_first = NULL; + unsigned int command_status; + + /* Get the Tx Desc ring indexes */ + USED_TFD_GET (p_tx_desc_used, tx_queue); + FIRST_TFD_GET (p_tx_desc_first, tx_queue); + + /* Sanity check */ + if (p_tx_desc_used == NULL) + return ETH_ERROR; + + command_status = p_tx_desc_used->cmd_sts; + + /* Still transmitting... */ + if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_used, 0); + return ETH_RETRY; + } + + /* Stop release. About to overlap the current available Tx descriptor */ + if ((p_tx_desc_used == p_tx_desc_first) && + (p_eth_port_ctrl->tx_resource_err[tx_queue] == false)) { + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_used, 0); + return ETH_END_OF_JOB; + } + + /* Pass the packet information to the caller */ + p_pkt_info->cmd_sts = command_status; + p_pkt_info->return_info = p_tx_desc_used->return_info; + p_tx_desc_used->return_info = 0; + + /* Update the next descriptor to release. */ + USED_TFD_SET (TX_NEXT_DESC_PTR (p_tx_desc_used, tx_queue), tx_queue); + + /* Any Tx return cancels the Tx resource error status */ + if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true) + p_eth_port_ctrl->tx_resource_err[tx_queue] = false; + + D_CACHE_FLUSH_LINE ((unsigned int) p_tx_desc_used, 0); + + return ETH_OK; + +} + +/******************************************************************************* + * eth_port_receive - Get received information from Rx ring. + * + * DESCRIPTION: + * This routine returns the received data to the caller. There is no + * data copying during routine operation. All information is returned + * using pointer to packet information struct passed from the caller. + * If the routine exhausts Rx ring resources then the resource error flag + * is set. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Rx ring current and used indexes are updated. + * + * RETURN: + * ETH_ERROR in case the routine can not access Rx desc ring. + * ETH_QUEUE_FULL if Rx ring resources are exhausted. + * ETH_END_OF_JOB if there is no received data. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_RX_DESC *p_rx_curr_desc; + volatile ETH_RX_DESC *p_rx_next_curr_desc; + volatile ETH_RX_DESC *p_rx_used_desc; + unsigned int command_status; + + /* Do not process Rx ring in case of Rx ring resource error */ + if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) { + printf ("\nRx Queue is full ...\n"); + return ETH_QUEUE_FULL; + } + + /* Get the Rx Desc ring 'curr and 'used' indexes */ + CURR_RFD_GET (p_rx_curr_desc, rx_queue); + USED_RFD_GET (p_rx_used_desc, rx_queue); + + /* Sanity check */ + if (p_rx_curr_desc == NULL) + return ETH_ERROR; + + /* The following parameters are used to save readings from memory */ + p_rx_next_curr_desc = RX_NEXT_DESC_PTR (p_rx_curr_desc, rx_queue); + command_status = p_rx_curr_desc->cmd_sts; + + /* Nothing to receive... */ + if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { +/* DP(printf("Rx: command_status: %08x\n", command_status)); */ + D_CACHE_FLUSH_LINE ((unsigned int) p_rx_curr_desc, 0); +/* DP(printf("\nETH_END_OF_JOB ...\n"));*/ + return ETH_END_OF_JOB; + } + + p_pkt_info->byte_cnt = (p_rx_curr_desc->byte_cnt) - RX_BUF_OFFSET; + p_pkt_info->cmd_sts = command_status; + p_pkt_info->buf_ptr = (p_rx_curr_desc->buf_ptr) + RX_BUF_OFFSET; + p_pkt_info->return_info = p_rx_curr_desc->return_info; + p_pkt_info->l4i_chk = p_rx_curr_desc->buf_size; /* IP fragment indicator */ + + /* Clean the return info field to indicate that the packet has been */ + /* moved to the upper layers */ + p_rx_curr_desc->return_info = 0; + + /* Update 'curr' in data structure */ + CURR_RFD_SET (p_rx_next_curr_desc, rx_queue); + + /* Rx descriptors resource exhausted. Set the Rx ring resource error flag */ + if (p_rx_next_curr_desc == p_rx_used_desc) + p_eth_port_ctrl->rx_resource_err[rx_queue] = true; + + D_CACHE_FLUSH_LINE ((unsigned int) p_rx_curr_desc, 0); + CPU_PIPE_FLUSH; + + return ETH_OK; +} + +/******************************************************************************* + * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring. + * + * DESCRIPTION: + * This routine returns a Rx buffer back to the Rx ring. It retrieves the + * next 'used' descriptor and attached the returned buffer to it. + * In case the Rx ring was in "resource error" condition, where there are + * no available Rx resources, the function resets the resource error flag. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info Information on the returned buffer. + * + * OUTPUT: + * New available Rx resource in Rx descriptor ring. + * + * RETURN: + * ETH_ERROR in case the routine can not access Rx desc ring. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_rx_return_buff (ETH_PORT_INFO * + p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_RX_DESC *p_used_rx_desc; /* Where to return Rx resource */ + + /* Get 'used' Rx descriptor */ + USED_RFD_GET (p_used_rx_desc, rx_queue); + + /* Sanity check */ + if (p_used_rx_desc == NULL) + return ETH_ERROR; + + p_used_rx_desc->buf_ptr = p_pkt_info->buf_ptr; + p_used_rx_desc->return_info = p_pkt_info->return_info; + p_used_rx_desc->byte_cnt = p_pkt_info->byte_cnt; + p_used_rx_desc->buf_size = MV64460_RX_BUFFER_SIZE; /* Reset Buffer size */ + + /* Flush the write pipe */ + CPU_PIPE_FLUSH; + + /* Return the descriptor to DMA ownership */ + p_used_rx_desc->cmd_sts = + ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT; + + /* Flush descriptor and CPU pipe */ + D_CACHE_FLUSH_LINE ((unsigned int) p_used_rx_desc, 0); + CPU_PIPE_FLUSH; + + /* Move the used descriptor pointer to the next descriptor */ + USED_RFD_SET (RX_NEXT_DESC_PTR (p_used_rx_desc, rx_queue), rx_queue); + + /* Any Rx return cancels the Rx resource error status */ + if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) + p_eth_port_ctrl->rx_resource_err[rx_queue] = false; + + return ETH_OK; +} + +/******************************************************************************* + * eth_port_set_rx_coal - Sets coalescing interrupt mechanism on RX path + * + * DESCRIPTION: + * This routine sets the RX coalescing interrupt mechanism parameter. + * This parameter is a timeout counter, that counts in 64 t_clk + * chunks ; that when timeout event occurs a maskable interrupt + * occurs. + * The parameter is calculated using the tClk of the MV-643xx chip + * , and the required delay of the interrupt in usec. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet port number + * unsigned int t_clk t_clk of the MV-643xx chip in HZ units + * unsigned int delay Delay in usec + * + * OUTPUT: + * Interrupt coalescing mechanism value is set in MV-643xx chip. + * + * RETURN: + * The interrupt coalescing value set in the gigE port. + * + *******************************************************************************/ +#if 0 /* FIXME */ +static unsigned int eth_port_set_rx_coal (ETH_PORT eth_port_num, + unsigned int t_clk, + unsigned int delay) +{ + unsigned int coal; + + coal = ((t_clk / 1000000) * delay) / 64; + /* Set RX Coalescing mechanism */ + MV_REG_WRITE (MV64460_ETH_SDMA_CONFIG_REG (eth_port_num), + ((coal & 0x3fff) << 8) | + (MV_REG_READ + (MV64460_ETH_SDMA_CONFIG_REG (eth_port_num)) + & 0xffc000ff)); + return coal; +} + +#endif +/******************************************************************************* + * eth_port_set_tx_coal - Sets coalescing interrupt mechanism on TX path + * + * DESCRIPTION: + * This routine sets the TX coalescing interrupt mechanism parameter. + * This parameter is a timeout counter, that counts in 64 t_clk + * chunks ; that when timeout event occurs a maskable interrupt + * occurs. + * The parameter is calculated using the t_cLK frequency of the + * MV-643xx chip and the required delay in the interrupt in uSec + * + * INPUT: + * ETH_PORT eth_port_num Ethernet port number + * unsigned int t_clk t_clk of the MV-643xx chip in HZ units + * unsigned int delay Delay in uSeconds + * + * OUTPUT: + * Interrupt coalescing mechanism value is set in MV-643xx chip. + * + * RETURN: + * The interrupt coalescing value set in the gigE port. + * + *******************************************************************************/ +#if 0 /* FIXME */ +static unsigned int eth_port_set_tx_coal (ETH_PORT eth_port_num, + unsigned int t_clk, + unsigned int delay) +{ + unsigned int coal; + + coal = ((t_clk / 1000000) * delay) / 64; + /* Set TX Coalescing mechanism */ + MV_REG_WRITE (MV64460_ETH_TX_FIFO_URGENT_THRESHOLD_REG (eth_port_num), + coal << 4); + return coal; +} +#endif + +/******************************************************************************* + * eth_b_copy - Copy bytes from source to destination + * + * DESCRIPTION: + * This function supports the eight bytes limitation on Tx buffer size. + * The routine will zero eight bytes starting from the destination address + * followed by copying bytes from the source address to the destination. + * + * INPUT: + * unsigned int src_addr 32 bit source address. + * unsigned int dst_addr 32 bit destination address. + * int byte_count Number of bytes to copy. + * + * OUTPUT: + * See description. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_b_copy (unsigned int src_addr, unsigned int dst_addr, + int byte_count) +{ + /* Zero the dst_addr area */ + *(unsigned int *) dst_addr = 0x0; + + while (byte_count != 0) { + *(char *) dst_addr = *(char *) src_addr; + dst_addr++; + src_addr++; + byte_count--; + } +} diff --git a/board/prodrive/p3mx/mv_eth.h b/board/prodrive/p3mx/mv_eth.h new file mode 100644 index 0000000..334b049 --- /dev/null +++ b/board/prodrive/p3mx/mv_eth.h @@ -0,0 +1,840 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * based on - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + */ + +/* + * mv_eth.h - header file for the polled mode GT ethernet driver + */ + +#ifndef __DB64460_ETH_H__ +#define __DB64460_ETH_H__ + +#include <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> +#include <net.h> +#include "mv_regs.h" +#include "ppc_error_no.h" +#include "../../Marvell/include/core.h" + +/************************************************************************* +************************************************************************** +************************************************************************** +* The first part is the high level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* In case not using SG on Tx, define MAX_SKB_FRAGS as 0 */ +#ifndef MAX_SKB_FRAGS +#define MAX_SKB_FRAGS 0 +#endif + +/* Port attributes */ +/*#define MAX_RX_QUEUE_NUM 8*/ +/*#define MAX_TX_QUEUE_NUM 8*/ +#define MAX_RX_QUEUE_NUM 1 +#define MAX_TX_QUEUE_NUM 1 + + +/* Use one TX queue and one RX queue */ +#define MV64460_TX_QUEUE_NUM 1 +#define MV64460_RX_QUEUE_NUM 1 + +/* + * Number of RX / TX descriptors on RX / TX rings. + * Note that allocating RX descriptors is done by allocating the RX + * ring AND a preallocated RX buffers (skb's) for each descriptor. + * The TX descriptors only allocates the TX descriptors ring, + * with no pre allocated TX buffers (skb's are allocated by higher layers. + */ + +/* Default TX ring size is 10 descriptors */ +#ifdef CONFIG_MV64460_ETH_TXQUEUE_SIZE +#define MV64460_TX_QUEUE_SIZE CONFIG_MV64460_ETH_TXQUEUE_SIZE +#else +#define MV64460_TX_QUEUE_SIZE 4 +#endif + +/* Default RX ring size is 4 descriptors */ +#ifdef CONFIG_MV64460_ETH_RXQUEUE_SIZE +#define MV64460_RX_QUEUE_SIZE CONFIG_MV64460_ETH_RXQUEUE_SIZE +#else +#define MV64460_RX_QUEUE_SIZE 4 +#endif + +#ifdef CONFIG_RX_BUFFER_SIZE +#define MV64460_RX_BUFFER_SIZE CONFIG_RX_BUFFER_SIZE +#else +#define MV64460_RX_BUFFER_SIZE 1600 +#endif + +#ifdef CONFIG_TX_BUFFER_SIZE +#define MV64460_TX_BUFFER_SIZE CONFIG_TX_BUFFER_SIZE +#else +#define MV64460_TX_BUFFER_SIZE 1600 +#endif + +/* + * Network device statistics. Akin to the 2.0 ether stats but + * with byte counters. + */ + +struct net_device_stats +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; + + /* for cslip etc */ + unsigned long rx_compressed; + unsigned long tx_compressed; +}; + + +/* Private data structure used for ethernet device */ +struct mv64460_eth_priv { + unsigned int port_num; + struct net_device_stats *stats; + + /* to buffer area aligned */ + char * p_eth_tx_buffer[MV64460_TX_QUEUE_SIZE+1]; /*pointers to alligned tx buffs in memory space */ + char * p_eth_rx_buffer[MV64460_RX_QUEUE_SIZE+1]; /*pointers to allinged rx buffs in memory space */ + + /* Size of Tx Ring per queue */ + unsigned int tx_ring_size [MAX_TX_QUEUE_NUM]; + + /* Size of Rx Ring per queue */ + unsigned int rx_ring_size [MAX_RX_QUEUE_NUM]; + + /* Magic Number for Ethernet running */ + unsigned int eth_running; + + int first_init; +}; + +int mv64460_eth_init (struct eth_device *dev); +int mv64460_eth_stop (struct eth_device *dev); +int mv64460_eth_start_xmit (struct eth_device*, volatile void* packet, int length); +/* return db64460_eth0_poll(); */ + +int mv64460_eth_open (struct eth_device *dev); + + +/************************************************************************* +************************************************************************** +************************************************************************** +* The second part is the low level driver of the gigE ethernet ports. * +************************************************************************** +************************************************************************** +*************************************************************************/ + + +/******************************************************************************** + * Header File for : MV-643xx network interface header + * + * DESCRIPTION: + * This header file contains macros typedefs and function declaration for + * the Marvell Gig Bit Ethernet Controller. + * + * DEPENDENCIES: + * None. + * + *******************************************************************************/ + + +#ifdef CONFIG_SPECIAL_CONSISTENT_MEMORY +#ifdef CONFIG_MV64460_SRAM_CACHEABLE +/* In case SRAM is cacheable but not cache coherent */ +#define D_CACHE_FLUSH_LINE(addr, offset) \ +{ \ + __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ +} +#else +/* In case SRAM is cache coherent or non-cacheable */ +#define D_CACHE_FLUSH_LINE(addr, offset) ; +#endif +#else +#ifdef CONFIG_NOT_COHERENT_CACHE +/* In case of descriptors on DDR but not cache coherent */ +#define D_CACHE_FLUSH_LINE(addr, offset) \ +{ \ + __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ +} +#else +/* In case of descriptors on DDR and cache coherent */ +#define D_CACHE_FLUSH_LINE(addr, offset) ; +#endif /* CONFIG_NOT_COHERENT_CACHE */ +#endif /* CONFIG_SPECIAL_CONSISTENT_MEMORY */ + + +#define CPU_PIPE_FLUSH \ +{ \ + __asm__ __volatile__ ("eieio"); \ +} + + +/* defines */ + +/* Default port configuration value */ +#define PORT_CONFIG_VALUE \ + ETH_UNICAST_NORMAL_MODE | \ + ETH_DEFAULT_RX_QUEUE_0 | \ + ETH_DEFAULT_RX_ARP_QUEUE_0 | \ + ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \ + ETH_RECEIVE_BC_IF_IP | \ + ETH_RECEIVE_BC_IF_ARP | \ + ETH_CAPTURE_TCP_FRAMES_DIS | \ + ETH_CAPTURE_UDP_FRAMES_DIS | \ + ETH_DEFAULT_RX_TCP_QUEUE_0 | \ + ETH_DEFAULT_RX_UDP_QUEUE_0 | \ + ETH_DEFAULT_RX_BPDU_QUEUE_0 + +/* Default port extend configuration value */ +#define PORT_CONFIG_EXTEND_VALUE \ + ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \ + ETH_PARTITION_DISABLE + + +/* Default sdma control value */ +#ifdef CONFIG_NOT_COHERENT_CACHE +#define PORT_SDMA_CONFIG_VALUE \ + ETH_RX_BURST_SIZE_16_64BIT | \ + GT_ETH_IPG_INT_RX(0) | \ + ETH_TX_BURST_SIZE_16_64BIT; +#else +#define PORT_SDMA_CONFIG_VALUE \ + ETH_RX_BURST_SIZE_4_64BIT | \ + GT_ETH_IPG_INT_RX(0) | \ + ETH_TX_BURST_SIZE_4_64BIT; +#endif + +#define GT_ETH_IPG_INT_RX(value) \ + ((value & 0x3fff) << 8) + +/* Default port serial control value */ +#define PORT_SERIAL_CONTROL_VALUE \ + ETH_FORCE_LINK_PASS | \ + ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \ + ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \ + ETH_ADV_SYMMETRIC_FLOW_CTRL | \ + ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ + ETH_FORCE_BP_MODE_NO_JAM | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL | \ + ETH_RETRANSMIT_16_ETTEMPTS | \ + ETH_ENABLE_AUTO_NEG_SPEED_GMII | \ + ETH_DTE_ADV_0 | \ + ETH_DISABLE_AUTO_NEG_BYPASS | \ + ETH_AUTO_NEG_NO_CHANGE | \ + ETH_MAX_RX_PACKET_1552BYTE | \ + ETH_CLR_EXT_LOOPBACK | \ + ETH_SET_FULL_DUPLEX_MODE | \ + ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX; + +#define RX_BUFFER_MAX_SIZE 0xFFFF +#define TX_BUFFER_MAX_SIZE 0xFFFF /* Buffer are limited to 64k */ + +#define RX_BUFFER_MIN_SIZE 0x8 +#define TX_BUFFER_MIN_SIZE 0x8 + +/* Tx WRR confoguration macros */ +#define PORT_MAX_TRAN_UNIT 0x24 /* MTU register (default) 9KByte */ +#define PORT_MAX_TOKEN_BUCKET_SIZE 0x_fFFF /* PMTBS register (default) */ +#define PORT_TOKEN_RATE 1023 /* PTTBRC register (default) */ + +/* MAC accepet/reject macros */ +#define ACCEPT_MAC_ADDR 0 +#define REJECT_MAC_ADDR 1 + +/* Size of a Tx/Rx descriptor used in chain list data structure */ +#define RX_DESC_ALIGNED_SIZE 0x20 +#define TX_DESC_ALIGNED_SIZE 0x20 + +/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */ +#define TX_BUF_OFFSET_IN_DESC 0x18 +/* Buffer offset from buffer pointer */ +#define RX_BUF_OFFSET 0x2 + +/* Gap define */ +#define ETH_BAR_GAP 0x8 +#define ETH_SIZE_REG_GAP 0x8 +#define ETH_HIGH_ADDR_REMAP_REG_GAP 0x4 +#define ETH_PORT_ACCESS_CTRL_GAP 0x4 + +/* Gigabit Ethernet Unit Global Registers */ + +/* MIB Counters register definitions */ +#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0 +#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4 +#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8 +#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc +#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10 +#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14 +#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18 +#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c +#define ETH_MIB_FRAMES_64_OCTETS 0x20 +#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24 +#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28 +#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c +#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30 +#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34 +#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38 +#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c +#define ETH_MIB_GOOD_FRAMES_SENT 0x40 +#define ETH_MIB_EXCESSIVE_COLLISION 0x44 +#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48 +#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c +#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50 +#define ETH_MIB_FC_SENT 0x54 +#define ETH_MIB_GOOD_FC_RECEIVED 0x58 +#define ETH_MIB_BAD_FC_RECEIVED 0x5c +#define ETH_MIB_UNDERSIZE_RECEIVED 0x60 +#define ETH_MIB_FRAGMENTS_RECEIVED 0x64 +#define ETH_MIB_OVERSIZE_RECEIVED 0x68 +#define ETH_MIB_JABBER_RECEIVED 0x6c +#define ETH_MIB_MAC_RECEIVE_ERROR 0x70 +#define ETH_MIB_BAD_CRC_EVENT 0x74 +#define ETH_MIB_COLLISION 0x78 +#define ETH_MIB_LATE_COLLISION 0x7c + +/* Port serial status reg (PSR) */ +#define ETH_INTERFACE_GMII_MII 0 +#define ETH_INTERFACE_PCM BIT0 +#define ETH_LINK_IS_DOWN 0 +#define ETH_LINK_IS_UP BIT1 +#define ETH_PORT_AT_HALF_DUPLEX 0 +#define ETH_PORT_AT_FULL_DUPLEX BIT2 +#define ETH_RX_FLOW_CTRL_DISABLED 0 +#define ETH_RX_FLOW_CTRL_ENBALED BIT3 +#define ETH_GMII_SPEED_100_10 0 +#define ETH_GMII_SPEED_1000 BIT4 +#define ETH_MII_SPEED_10 0 +#define ETH_MII_SPEED_100 BIT5 +#define ETH_NO_TX 0 +#define ETH_TX_IN_PROGRESS BIT7 +#define ETH_BYPASS_NO_ACTIVE 0 +#define ETH_BYPASS_ACTIVE BIT8 +#define ETH_PORT_NOT_AT_PARTITION_STATE 0 +#define ETH_PORT_AT_PARTITION_STATE BIT9 +#define ETH_PORT_TX_FIFO_NOT_EMPTY 0 +#define ETH_PORT_TX_FIFO_EMPTY BIT10 + + +/* These macros describes the Port configuration reg (Px_cR) bits */ +#define ETH_UNICAST_NORMAL_MODE 0 +#define ETH_UNICAST_PROMISCUOUS_MODE BIT0 +#define ETH_DEFAULT_RX_QUEUE_0 0 +#define ETH_DEFAULT_RX_QUEUE_1 BIT1 +#define ETH_DEFAULT_RX_QUEUE_2 BIT2 +#define ETH_DEFAULT_RX_QUEUE_3 (BIT2 | BIT1) +#define ETH_DEFAULT_RX_QUEUE_4 BIT3 +#define ETH_DEFAULT_RX_QUEUE_5 (BIT3 | BIT1) +#define ETH_DEFAULT_RX_QUEUE_6 (BIT3 | BIT2) +#define ETH_DEFAULT_RX_QUEUE_7 (BIT3 | BIT2 | BIT1) +#define ETH_DEFAULT_RX_ARP_QUEUE_0 0 +#define ETH_DEFAULT_RX_ARP_QUEUE_1 BIT4 +#define ETH_DEFAULT_RX_ARP_QUEUE_2 BIT5 +#define ETH_DEFAULT_RX_ARP_QUEUE_3 (BIT5 | BIT4) +#define ETH_DEFAULT_RX_ARP_QUEUE_4 BIT6 +#define ETH_DEFAULT_RX_ARP_QUEUE_5 (BIT6 | BIT4) +#define ETH_DEFAULT_RX_ARP_QUEUE_6 (BIT6 | BIT5) +#define ETH_DEFAULT_RX_ARP_QUEUE_7 (BIT6 | BIT5 | BIT4) +#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0 +#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP BIT7 +#define ETH_RECEIVE_BC_IF_IP 0 +#define ETH_REJECT_BC_IF_IP BIT8 +#define ETH_RECEIVE_BC_IF_ARP 0 +#define ETH_REJECT_BC_IF_ARP BIT9 +#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY BIT12 +#define ETH_CAPTURE_TCP_FRAMES_DIS 0 +#define ETH_CAPTURE_TCP_FRAMES_EN BIT14 +#define ETH_CAPTURE_UDP_FRAMES_DIS 0 +#define ETH_CAPTURE_UDP_FRAMES_EN BIT15 +#define ETH_DEFAULT_RX_TCP_QUEUE_0 0 +#define ETH_DEFAULT_RX_TCP_QUEUE_1 BIT16 +#define ETH_DEFAULT_RX_TCP_QUEUE_2 BIT17 +#define ETH_DEFAULT_RX_TCP_QUEUE_3 (BIT17 | BIT16) +#define ETH_DEFAULT_RX_TCP_QUEUE_4 BIT18 +#define ETH_DEFAULT_RX_TCP_QUEUE_5 (BIT18 | BIT16) +#define ETH_DEFAULT_RX_TCP_QUEUE_6 (BIT18 | BIT17) +#define ETH_DEFAULT_RX_TCP_QUEUE_7 (BIT18 | BIT17 | BIT16) +#define ETH_DEFAULT_RX_UDP_QUEUE_0 0 +#define ETH_DEFAULT_RX_UDP_QUEUE_1 BIT19 +#define ETH_DEFAULT_RX_UDP_QUEUE_2 BIT20 +#define ETH_DEFAULT_RX_UDP_QUEUE_3 (BIT20 | BIT19) +#define ETH_DEFAULT_RX_UDP_QUEUE_4 (BIT21 +#define ETH_DEFAULT_RX_UDP_QUEUE_5 (BIT21 | BIT19) +#define ETH_DEFAULT_RX_UDP_QUEUE_6 (BIT21 | BIT20) +#define ETH_DEFAULT_RX_UDP_QUEUE_7 (BIT21 | BIT20 | BIT19) +#define ETH_DEFAULT_RX_BPDU_QUEUE_0 0 +#define ETH_DEFAULT_RX_BPDU_QUEUE_1 BIT22 +#define ETH_DEFAULT_RX_BPDU_QUEUE_2 BIT23 +#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22) +#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24 +#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22) +#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23) +#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22) + + +/* These macros describes the Port configuration extend reg (Px_cXR) bits*/ +#define ETH_CLASSIFY_EN BIT0 +#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0 +#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 BIT1 +#define ETH_PARTITION_DISABLE 0 +#define ETH_PARTITION_ENABLE BIT2 + + +/* Tx/Rx queue command reg (RQCR/TQCR)*/ +#define ETH_QUEUE_0_ENABLE BIT0 +#define ETH_QUEUE_1_ENABLE BIT1 +#define ETH_QUEUE_2_ENABLE BIT2 +#define ETH_QUEUE_3_ENABLE BIT3 +#define ETH_QUEUE_4_ENABLE BIT4 +#define ETH_QUEUE_5_ENABLE BIT5 +#define ETH_QUEUE_6_ENABLE BIT6 +#define ETH_QUEUE_7_ENABLE BIT7 +#define ETH_QUEUE_0_DISABLE BIT8 +#define ETH_QUEUE_1_DISABLE BIT9 +#define ETH_QUEUE_2_DISABLE BIT10 +#define ETH_QUEUE_3_DISABLE BIT11 +#define ETH_QUEUE_4_DISABLE BIT12 +#define ETH_QUEUE_5_DISABLE BIT13 +#define ETH_QUEUE_6_DISABLE BIT14 +#define ETH_QUEUE_7_DISABLE BIT15 + +/* These macros describes the Port Sdma configuration reg (SDCR) bits */ +#define ETH_RIFB BIT0 +#define ETH_RX_BURST_SIZE_1_64BIT 0 +#define ETH_RX_BURST_SIZE_2_64BIT BIT1 +#define ETH_RX_BURST_SIZE_4_64BIT BIT2 +#define ETH_RX_BURST_SIZE_8_64BIT (BIT2 | BIT1) +#define ETH_RX_BURST_SIZE_16_64BIT BIT3 +#define ETH_BLM_RX_NO_SWAP BIT4 +#define ETH_BLM_RX_BYTE_SWAP 0 +#define ETH_BLM_TX_NO_SWAP BIT5 +#define ETH_BLM_TX_BYTE_SWAP 0 +#define ETH_DESCRIPTORS_BYTE_SWAP BIT6 +#define ETH_DESCRIPTORS_NO_SWAP 0 +#define ETH_TX_BURST_SIZE_1_64BIT 0 +#define ETH_TX_BURST_SIZE_2_64BIT BIT22 +#define ETH_TX_BURST_SIZE_4_64BIT BIT23 +#define ETH_TX_BURST_SIZE_8_64BIT (BIT23 | BIT22) +#define ETH_TX_BURST_SIZE_16_64BIT BIT24 + +/* These macros describes the Port serial control reg (PSCR) bits */ +#define ETH_SERIAL_PORT_DISABLE 0 +#define ETH_SERIAL_PORT_ENABLE BIT0 +#define ETH_FORCE_LINK_PASS BIT1 +#define ETH_DO_NOT_FORCE_LINK_PASS 0 +#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0 +#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX BIT2 +#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0 +#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL BIT3 +#define ETH_ADV_NO_FLOW_CTRL 0 +#define ETH_ADV_SYMMETRIC_FLOW_CTRL BIT4 +#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0 +#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS BIT5 +#define ETH_FORCE_BP_MODE_NO_JAM 0 +#define ETH_FORCE_BP_MODE_JAM_TX BIT7 +#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR BIT8 +#define ETH_FORCE_LINK_FAIL 0 +#define ETH_DO_NOT_FORCE_LINK_FAIL BIT10 +#define ETH_RETRANSMIT_16_ETTEMPTS 0 +#define ETH_RETRANSMIT_FOREVER BIT11 +#define ETH_DISABLE_AUTO_NEG_SPEED_GMII BIT13 +#define ETH_ENABLE_AUTO_NEG_SPEED_GMII 0 +#define ETH_DTE_ADV_0 0 +#define ETH_DTE_ADV_1 BIT14 +#define ETH_DISABLE_AUTO_NEG_BYPASS 0 +#define ETH_ENABLE_AUTO_NEG_BYPASS BIT15 +#define ETH_AUTO_NEG_NO_CHANGE 0 +#define ETH_RESTART_AUTO_NEG BIT16 +#define ETH_MAX_RX_PACKET_1518BYTE 0 +#define ETH_MAX_RX_PACKET_1522BYTE BIT17 +#define ETH_MAX_RX_PACKET_1552BYTE BIT18 +#define ETH_MAX_RX_PACKET_9022BYTE (BIT18 | BIT17) +#define ETH_MAX_RX_PACKET_9192BYTE BIT19 +#define ETH_MAX_RX_PACKET_9700BYTE (BIT19 | BIT17) +#define ETH_SET_EXT_LOOPBACK BIT20 +#define ETH_CLR_EXT_LOOPBACK 0 +#define ETH_SET_FULL_DUPLEX_MODE BIT21 +#define ETH_SET_HALF_DUPLEX_MODE 0 +#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX BIT22 +#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0 +#define ETH_SET_GMII_SPEED_TO_10_100 0 +#define ETH_SET_GMII_SPEED_TO_1000 BIT23 +#define ETH_SET_MII_SPEED_TO_10 0 +#define ETH_SET_MII_SPEED_TO_100 BIT24 + + +/* SMI reg */ +#define ETH_SMI_BUSY BIT28 /* 0 - Write, 1 - Read */ +#define ETH_SMI_READ_VALID BIT27 /* 0 - Write, 1 - Read */ +#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read operation */ +#define ETH_SMI_OPCODE_READ BIT26 /* Operation is in progress */ + +/* SDMA command status fields macros */ + +/* Tx & Rx descriptors status */ +#define ETH_ERROR_SUMMARY (BIT0) + +/* Tx & Rx descriptors command */ +#define ETH_BUFFER_OWNED_BY_DMA (BIT31) + +/* Tx descriptors status */ +#define ETH_LC_ERROR (0 ) +#define ETH_UR_ERROR (BIT1 ) +#define ETH_RL_ERROR (BIT2 ) +#define ETH_LLC_SNAP_FORMAT (BIT9 ) + +/* Rx descriptors status */ +#define ETH_CRC_ERROR (0 ) +#define ETH_OVERRUN_ERROR (BIT1 ) +#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 ) +#define ETH_RESOURCE_ERROR ((BIT2 | BIT1)) +#define ETH_VLAN_TAGGED (BIT19) +#define ETH_BPDU_FRAME (BIT20) +#define ETH_TCP_FRAME_OVER_IP_V_4 (0 ) +#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21) +#define ETH_OTHER_FRAME_TYPE (BIT22) +#define ETH_LAYER_2_IS_ETH_V_2 (BIT23) +#define ETH_FRAME_TYPE_IP_V_4 (BIT24) +#define ETH_FRAME_HEADER_OK (BIT25) +#define ETH_RX_LAST_DESC (BIT26) +#define ETH_RX_FIRST_DESC (BIT27) +#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28) +#define ETH_RX_ENABLE_INTERRUPT (BIT29) +#define ETH_LAYER_4_CHECKSUM_OK (BIT30) + +/* Rx descriptors byte count */ +#define ETH_FRAME_FRAGMENTED (BIT2) + +/* Tx descriptors command */ +#define ETH_LAYER_4_CHECKSUM_FIRST_DESC (BIT10) +#define ETH_FRAME_SET_TO_VLAN (BIT15) +#define ETH_TCP_FRAME (0 ) +#define ETH_UDP_FRAME (BIT16) +#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17) +#define ETH_GEN_IP_V_4_CHECKSUM (BIT18) +#define ETH_ZERO_PADDING (BIT19) +#define ETH_TX_LAST_DESC (BIT20) +#define ETH_TX_FIRST_DESC (BIT21) +#define ETH_GEN_CRC (BIT22) +#define ETH_TX_ENABLE_INTERRUPT (BIT23) +#define ETH_AUTO_MODE (BIT30) + +/* Address decode parameters */ +/* Ethernet Base Address Register bits */ +#define EBAR_TARGET_DRAM 0x00000000 +#define EBAR_TARGET_DEVICE 0x00000001 +#define EBAR_TARGET_CBS 0x00000002 +#define EBAR_TARGET_PCI0 0x00000003 +#define EBAR_TARGET_PCI1 0x00000004 +#define EBAR_TARGET_CUNIT 0x00000005 +#define EBAR_TARGET_AUNIT 0x00000006 +#define EBAR_TARGET_GUNIT 0x00000007 + +/* Window attributes */ +#define EBAR_ATTR_DRAM_CS0 0x00000E00 +#define EBAR_ATTR_DRAM_CS1 0x00000D00 +#define EBAR_ATTR_DRAM_CS2 0x00000B00 +#define EBAR_ATTR_DRAM_CS3 0x00000700 + +/* DRAM Target interface */ +#define EBAR_ATTR_DRAM_NO_CACHE_COHERENCY 0x00000000 +#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WT 0x00001000 +#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WB 0x00002000 + +/* Device Bus Target interface */ +#define EBAR_ATTR_DEVICE_DEVCS0 0x00001E00 +#define EBAR_ATTR_DEVICE_DEVCS1 0x00001D00 +#define EBAR_ATTR_DEVICE_DEVCS2 0x00001B00 +#define EBAR_ATTR_DEVICE_DEVCS3 0x00001700 +#define EBAR_ATTR_DEVICE_BOOTCS3 0x00000F00 + +/* PCI Target interface */ +#define EBAR_ATTR_PCI_BYTE_SWAP 0x00000000 +#define EBAR_ATTR_PCI_NO_SWAP 0x00000100 +#define EBAR_ATTR_PCI_BYTE_WORD_SWAP 0x00000200 +#define EBAR_ATTR_PCI_WORD_SWAP 0x00000300 +#define EBAR_ATTR_PCI_NO_SNOOP_NOT_ASSERT 0x00000000 +#define EBAR_ATTR_PCI_NO_SNOOP_ASSERT 0x00000400 +#define EBAR_ATTR_PCI_IO_SPACE 0x00000000 +#define EBAR_ATTR_PCI_MEMORY_SPACE 0x00000800 +#define EBAR_ATTR_PCI_REQ64_FORCE 0x00000000 +#define EBAR_ATTR_PCI_REQ64_SIZE 0x00001000 + +/* CPU 60x bus or internal SRAM interface */ +#define EBAR_ATTR_CBS_SRAM_BLOCK0 0x00000000 +#define EBAR_ATTR_CBS_SRAM_BLOCK1 0x00000100 +#define EBAR_ATTR_CBS_SRAM 0x00000000 +#define EBAR_ATTR_CBS_CPU_BUS 0x00000800 + +/* Window access control */ +#define EWIN_ACCESS_NOT_ALLOWED 0 +#define EWIN_ACCESS_READ_ONLY BIT0 +#define EWIN_ACCESS_FULL (BIT1 | BIT0) +#define EWIN0_ACCESS_MASK 0x0003 +#define EWIN1_ACCESS_MASK 0x000C +#define EWIN2_ACCESS_MASK 0x0030 +#define EWIN3_ACCESS_MASK 0x00C0 + +/* typedefs */ + +typedef enum _eth_port +{ + ETH_0 = 0, + ETH_1 = 1, + ETH_2 = 2 +}ETH_PORT; + +typedef enum _eth_func_ret_status +{ + ETH_OK, /* Returned as expected. */ + ETH_ERROR, /* Fundamental error. */ + ETH_RETRY, /* Could not process request. Try later. */ + ETH_END_OF_JOB, /* Ring has nothing to process. */ + ETH_QUEUE_FULL, /* Ring resource error. */ + ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */ +}ETH_FUNC_RET_STATUS; + +typedef enum _eth_queue +{ + ETH_Q0 = 0, + ETH_Q1 = 1, + ETH_Q2 = 2, + ETH_Q3 = 3, + ETH_Q4 = 4, + ETH_Q5 = 5, + ETH_Q6 = 6, + ETH_Q7 = 7 +} ETH_QUEUE; + +typedef enum _addr_win +{ + ETH_WIN0, + ETH_WIN1, + ETH_WIN2, + ETH_WIN3, + ETH_WIN4, + ETH_WIN5 +} ETH_ADDR_WIN; + +typedef enum _eth_target +{ + ETH_TARGET_DRAM , + ETH_TARGET_DEVICE, + ETH_TARGET_CBS , + ETH_TARGET_PCI0 , + ETH_TARGET_PCI1 +}ETH_TARGET; + +typedef struct _eth_rx_desc +{ + unsigned short byte_cnt ; /* Descriptor buffer byte count */ + unsigned short buf_size ; /* Buffer size */ + unsigned int cmd_sts ; /* Descriptor command status */ + unsigned int next_desc_ptr; /* Next descriptor pointer */ + unsigned int buf_ptr ; /* Descriptor buffer pointer */ + unsigned int return_info ; /* User resource return information */ +} ETH_RX_DESC; + + +typedef struct _eth_tx_desc +{ + unsigned short byte_cnt ; /* Descriptor buffer byte count */ + unsigned short l4i_chk ; /* CPU provided TCP Checksum */ + unsigned int cmd_sts ; /* Descriptor command status */ + unsigned int next_desc_ptr; /* Next descriptor pointer */ + unsigned int buf_ptr ; /* Descriptor buffer pointer */ + unsigned int return_info ; /* User resource return information */ +} ETH_TX_DESC; + +/* Unified struct for Rx and Tx operations. The user is not required to */ +/* be familier with neither Tx nor Rx descriptors. */ +typedef struct _pkt_info +{ + unsigned short byte_cnt ; /* Descriptor buffer byte count */ + unsigned short l4i_chk ; /* Tx CPU provided TCP Checksum */ + unsigned int cmd_sts ; /* Descriptor command status */ + unsigned int buf_ptr ; /* Descriptor buffer pointer */ + unsigned int return_info ; /* User resource return information */ +} PKT_INFO; + + +typedef struct _eth_win_param +{ + ETH_ADDR_WIN win; /* Window number. See ETH_ADDR_WIN enum */ + ETH_TARGET target; /* System targets. See ETH_TARGET enum */ + unsigned short attributes; /* BAR attributes. See above macros. */ + unsigned int base_addr; /* Window base address in unsigned int form */ + unsigned int high_addr; /* Window high address in unsigned int form */ + unsigned int size; /* Size in MBytes. Must be % 64Kbyte. */ + bool enable; /* Enable/disable access to the window. */ + unsigned short access_ctrl; /* Access ctrl register. see above macros */ +} ETH_WIN_PARAM; + + +/* Ethernet port specific infomation */ + +typedef struct _eth_port_ctrl +{ + ETH_PORT port_num; /* User Ethernet port number */ + int port_phy_addr; /* User phy address of Ethrnet port */ + unsigned char port_mac_addr[6]; /* User defined port MAC address. */ + unsigned int port_config; /* User port configuration value */ + unsigned int port_config_extend; /* User port config extend value */ + unsigned int port_sdma_config; /* User port SDMA config value */ + unsigned int port_serial_control; /* User port serial control value */ + unsigned int port_tx_queue_command; /* Port active Tx queues summary */ + unsigned int port_rx_queue_command; /* Port active Rx queues summary */ + + /* User function to cast virtual address to CPU bus address */ + unsigned int (*port_virt_to_phys)(unsigned int addr); + /* User scratch pad for user specific data structures */ + void *port_private; + + bool rx_resource_err[MAX_RX_QUEUE_NUM]; /* Rx ring resource error flag */ + bool tx_resource_err[MAX_TX_QUEUE_NUM]; /* Tx ring resource error flag */ + + /* Tx/Rx rings managment indexes fields. For driver use */ + + /* Next available Rx resource */ + volatile ETH_RX_DESC *p_rx_curr_desc_q[MAX_RX_QUEUE_NUM]; + /* Returning Rx resource */ + volatile ETH_RX_DESC *p_rx_used_desc_q[MAX_RX_QUEUE_NUM]; + + /* Next available Tx resource */ + volatile ETH_TX_DESC *p_tx_curr_desc_q[MAX_TX_QUEUE_NUM]; + /* Returning Tx resource */ + volatile ETH_TX_DESC *p_tx_used_desc_q[MAX_TX_QUEUE_NUM]; + /* An extra Tx index to support transmit of multiple buffers per packet */ + volatile ETH_TX_DESC *p_tx_first_desc_q[MAX_TX_QUEUE_NUM]; + + /* Tx/Rx rings size and base variables fields. For driver use */ + + volatile ETH_RX_DESC *p_rx_desc_area_base[MAX_RX_QUEUE_NUM]; + unsigned int rx_desc_area_size[MAX_RX_QUEUE_NUM]; + char *p_rx_buffer_base[MAX_RX_QUEUE_NUM]; + + volatile ETH_TX_DESC *p_tx_desc_area_base[MAX_TX_QUEUE_NUM]; + unsigned int tx_desc_area_size[MAX_TX_QUEUE_NUM]; + char *p_tx_buffer_base[MAX_TX_QUEUE_NUM]; + +} ETH_PORT_INFO; + + +/* ethernet.h API list */ + +/* Port operation control routines */ +static void eth_port_init (ETH_PORT_INFO *p_eth_port_ctrl); +static void eth_port_reset(ETH_PORT eth_port_num); +static bool eth_port_start(ETH_PORT_INFO *p_eth_port_ctrl); + + +/* Port MAC address routines */ +static void eth_port_uc_addr_set (ETH_PORT eth_port_num, + unsigned char *p_addr, + ETH_QUEUE queue); +#if 0 /* FIXME */ +static void eth_port_mc_addr (ETH_PORT eth_port_num, + unsigned char *p_addr, + ETH_QUEUE queue, + int option); +#endif + +/* PHY and MIB routines */ +static bool ethernet_phy_reset(ETH_PORT eth_port_num); + +static bool eth_port_write_smi_reg(ETH_PORT eth_port_num, + unsigned int phy_reg, + unsigned int value); + +static bool eth_port_read_smi_reg(ETH_PORT eth_port_num, + unsigned int phy_reg, + unsigned int* value); + +static void eth_clear_mib_counters(ETH_PORT eth_port_num); + +/* Port data flow control routines */ +static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO *p_pkt_info); +static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO *p_pkt_info); +static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO *p_pkt_info); +static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO *p_pkt_info); + + +static bool ether_init_tx_desc_ring(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE tx_queue, + int tx_desc_num, + int tx_buff_size, + unsigned int tx_desc_base_addr, + unsigned int tx_buff_base_addr); + +static bool ether_init_rx_desc_ring(ETH_PORT_INFO *p_eth_port_ctrl, + ETH_QUEUE rx_queue, + int rx_desc_num, + int rx_buff_size, + unsigned int rx_desc_base_addr, + unsigned int rx_buff_base_addr); + +#endif /* MV64460_ETH_ */ diff --git a/board/prodrive/p3mx/mv_regs.h b/board/prodrive/p3mx/mv_regs.h new file mode 100644 index 0000000..068590f --- /dev/null +++ b/board/prodrive/p3mx/mv_regs.h @@ -0,0 +1,1125 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * based on - Driver for MV64460X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + */ + +/******************************************************************************** +* gt64460r.h - GT-64460 Internal registers definition file. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv_regsh +#define __INCmv_regsh + +#define MV64460 + +/* Supported by the Atlantis */ +#define MV64460_INCLUDE_PCI_1 +#define MV64460_INCLUDE_PCI_0_ARBITER +#define MV64460_INCLUDE_PCI_1_ARBITER +#define MV64460_INCLUDE_SNOOP_SUPPORT +#define MV64460_INCLUDE_P2P +#define MV64460_INCLUDE_ETH_PORT_2 +#define MV64460_INCLUDE_CPU_MAPPING +#define MV64460_INCLUDE_MPSC + +/* Not supported features */ +#undef INCLUDE_CNTMR_4_7 +#undef INCLUDE_DMA_4_7 + +/****************************************/ +/* Processor Address Space */ +/****************************************/ + +/* DDR SDRAM BAR and size registers */ + +#define MV64460_CS_0_BASE_ADDR 0x008 +#define MV64460_CS_0_SIZE 0x010 +#define MV64460_CS_1_BASE_ADDR 0x208 +#define MV64460_CS_1_SIZE 0x210 +#define MV64460_CS_2_BASE_ADDR 0x018 +#define MV64460_CS_2_SIZE 0x020 +#define MV64460_CS_3_BASE_ADDR 0x218 +#define MV64460_CS_3_SIZE 0x220 + +/* Devices BAR and size registers */ + +#define MV64460_DEV_CS0_BASE_ADDR 0x028 +#define MV64460_DEV_CS0_SIZE 0x030 +#define MV64460_DEV_CS1_BASE_ADDR 0x228 +#define MV64460_DEV_CS1_SIZE 0x230 +#define MV64460_DEV_CS2_BASE_ADDR 0x248 +#define MV64460_DEV_CS2_SIZE 0x250 +#define MV64460_DEV_CS3_BASE_ADDR 0x038 +#define MV64460_DEV_CS3_SIZE 0x040 +#define MV64460_BOOTCS_BASE_ADDR 0x238 +#define MV64460_BOOTCS_SIZE 0x240 + +/* PCI 0 BAR and size registers */ + +#define MV64460_PCI_0_IO_BASE_ADDR 0x048 +#define MV64460_PCI_0_IO_SIZE 0x050 +#define MV64460_PCI_0_MEMORY0_BASE_ADDR 0x058 +#define MV64460_PCI_0_MEMORY0_SIZE 0x060 +#define MV64460_PCI_0_MEMORY1_BASE_ADDR 0x080 +#define MV64460_PCI_0_MEMORY1_SIZE 0x088 +#define MV64460_PCI_0_MEMORY2_BASE_ADDR 0x258 +#define MV64460_PCI_0_MEMORY2_SIZE 0x260 +#define MV64460_PCI_0_MEMORY3_BASE_ADDR 0x280 +#define MV64460_PCI_0_MEMORY3_SIZE 0x288 + +/* PCI 1 BAR and size registers */ +#define MV64460_PCI_1_IO_BASE_ADDR 0x090 +#define MV64460_PCI_1_IO_SIZE 0x098 +#define MV64460_PCI_1_MEMORY0_BASE_ADDR 0x0a0 +#define MV64460_PCI_1_MEMORY0_SIZE 0x0a8 +#define MV64460_PCI_1_MEMORY1_BASE_ADDR 0x0b0 +#define MV64460_PCI_1_MEMORY1_SIZE 0x0b8 +#define MV64460_PCI_1_MEMORY2_BASE_ADDR 0x2a0 +#define MV64460_PCI_1_MEMORY2_SIZE 0x2a8 +#define MV64460_PCI_1_MEMORY3_BASE_ADDR 0x2b0 +#define MV64460_PCI_1_MEMORY3_SIZE 0x2b8 + +/* SRAM base address */ +#define MV64460_INTEGRATED_SRAM_BASE_ADDR 0x268 + +/* internal registers space base address */ +#define MV64460_INTERNAL_SPACE_BASE_ADDR 0x068 + +/* Enables the CS , DEV_CS , PCI 0 and PCI 1 + windows above */ +#define MV64460_BASE_ADDR_ENABLE 0x278 + +/****************************************/ +/* PCI remap registers */ +/****************************************/ + /* PCI 0 */ +#define MV64460_PCI_0_IO_ADDR_REMAP 0x0f0 +#define MV64460_PCI_0_MEMORY0_LOW_ADDR_REMAP 0x0f8 +#define MV64460_PCI_0_MEMORY0_HIGH_ADDR_REMAP 0x320 +#define MV64460_PCI_0_MEMORY1_LOW_ADDR_REMAP 0x100 +#define MV64460_PCI_0_MEMORY1_HIGH_ADDR_REMAP 0x328 +#define MV64460_PCI_0_MEMORY2_LOW_ADDR_REMAP 0x2f8 +#define MV64460_PCI_0_MEMORY2_HIGH_ADDR_REMAP 0x330 +#define MV64460_PCI_0_MEMORY3_LOW_ADDR_REMAP 0x300 +#define MV64460_PCI_0_MEMORY3_HIGH_ADDR_REMAP 0x338 + /* PCI 1 */ +#define MV64460_PCI_1_IO_ADDR_REMAP 0x108 +#define MV64460_PCI_1_MEMORY0_LOW_ADDR_REMAP 0x110 +#define MV64460_PCI_1_MEMORY0_HIGH_ADDR_REMAP 0x340 +#define MV64460_PCI_1_MEMORY1_LOW_ADDR_REMAP 0x118 +#define MV64460_PCI_1_MEMORY1_HIGH_ADDR_REMAP 0x348 +#define MV64460_PCI_1_MEMORY2_LOW_ADDR_REMAP 0x310 +#define MV64460_PCI_1_MEMORY2_HIGH_ADDR_REMAP 0x350 +#define MV64460_PCI_1_MEMORY3_LOW_ADDR_REMAP 0x318 +#define MV64460_PCI_1_MEMORY3_HIGH_ADDR_REMAP 0x358 + +#define MV64460_CPU_PCI_0_HEADERS_RETARGET_CONTROL 0x3b0 +#define MV64460_CPU_PCI_0_HEADERS_RETARGET_BASE 0x3b8 +#define MV64460_CPU_PCI_1_HEADERS_RETARGET_CONTROL 0x3c0 +#define MV64460_CPU_PCI_1_HEADERS_RETARGET_BASE 0x3c8 +#define MV64460_CPU_GE_HEADERS_RETARGET_CONTROL 0x3d0 +#define MV64460_CPU_GE_HEADERS_RETARGET_BASE 0x3d8 +#define MV64460_CPU_IDMA_HEADERS_RETARGET_CONTROL 0x3e0 +#define MV64460_CPU_IDMA_HEADERS_RETARGET_BASE 0x3e8 + +/****************************************/ +/* CPU Control Registers */ +/****************************************/ + +#define MV64460_CPU_CONFIG 0x000 +#define MV64460_CPU_MODE 0x120 +#define MV64460_CPU_MASTER_CONTROL 0x160 +#define MV64460_CPU_CROSS_BAR_CONTROL_LOW 0x150 +#define MV64460_CPU_CROSS_BAR_CONTROL_HIGH 0x158 +#define MV64460_CPU_CROSS_BAR_TIMEOUT 0x168 + +/****************************************/ +/* SMP RegisterS */ +/****************************************/ + +#define MV64460_SMP_WHO_AM_I 0x200 +#define MV64460_SMP_CPU0_DOORBELL 0x214 +#define MV64460_SMP_CPU0_DOORBELL_CLEAR 0x21C +#define MV64460_SMP_CPU1_DOORBELL 0x224 +#define MV64460_SMP_CPU1_DOORBELL_CLEAR 0x22C +#define MV64460_SMP_CPU0_DOORBELL_MASK 0x234 +#define MV64460_SMP_CPU1_DOORBELL_MASK 0x23C +#define MV64460_SMP_SEMAPHOR0 0x244 +#define MV64460_SMP_SEMAPHOR1 0x24c +#define MV64460_SMP_SEMAPHOR2 0x254 +#define MV64460_SMP_SEMAPHOR3 0x25c +#define MV64460_SMP_SEMAPHOR4 0x264 +#define MV64460_SMP_SEMAPHOR5 0x26c +#define MV64460_SMP_SEMAPHOR6 0x274 +#define MV64460_SMP_SEMAPHOR7 0x27c + +/****************************************/ +/* CPU Sync Barrier Register */ +/****************************************/ + +#define MV64460_CPU_0_SYNC_BARRIER_TRIGGER 0x0c0 +#define MV64460_CPU_0_SYNC_BARRIER_VIRTUAL 0x0c8 +#define MV64460_CPU_1_SYNC_BARRIER_TRIGGER 0x0d0 +#define MV64460_CPU_1_SYNC_BARRIER_VIRTUAL 0x0d8 + +/****************************************/ +/* CPU Access Protect */ +/****************************************/ + +#define MV64460_CPU_PROTECT_WINDOW_0_BASE_ADDR 0x180 +#define MV64460_CPU_PROTECT_WINDOW_0_SIZE 0x188 +#define MV64460_CPU_PROTECT_WINDOW_1_BASE_ADDR 0x190 +#define MV64460_CPU_PROTECT_WINDOW_1_SIZE 0x198 +#define MV64460_CPU_PROTECT_WINDOW_2_BASE_ADDR 0x1a0 +#define MV64460_CPU_PROTECT_WINDOW_2_SIZE 0x1a8 +#define MV64460_CPU_PROTECT_WINDOW_3_BASE_ADDR 0x1b0 +#define MV64460_CPU_PROTECT_WINDOW_3_SIZE 0x1b8 + + +/****************************************/ +/* CPU Error Report */ +/****************************************/ + +#define MV64460_CPU_ERROR_ADDR_LOW 0x070 +#define MV64460_CPU_ERROR_ADDR_HIGH 0x078 +#define MV64460_CPU_ERROR_DATA_LOW 0x128 +#define MV64460_CPU_ERROR_DATA_HIGH 0x130 +#define MV64460_CPU_ERROR_PARITY 0x138 +#define MV64460_CPU_ERROR_CAUSE 0x140 +#define MV64460_CPU_ERROR_MASK 0x148 + +/****************************************/ +/* CPU Interface Debug Registers */ +/****************************************/ + +#define MV64460_PUNIT_SLAVE_DEBUG_LOW 0x360 +#define MV64460_PUNIT_SLAVE_DEBUG_HIGH 0x368 +#define MV64460_PUNIT_MASTER_DEBUG_LOW 0x370 +#define MV64460_PUNIT_MASTER_DEBUG_HIGH 0x378 +#define MV64460_PUNIT_MMASK 0x3e4 + +/****************************************/ +/* Integrated SRAM Registers */ +/****************************************/ + +#define MV64460_SRAM_CONFIG 0x380 +#define MV64460_SRAM_TEST_MODE 0X3F4 +#define MV64460_SRAM_ERROR_CAUSE 0x388 +#define MV64460_SRAM_ERROR_ADDR 0x390 +#define MV64460_SRAM_ERROR_ADDR_HIGH 0X3F8 +#define MV64460_SRAM_ERROR_DATA_LOW 0x398 +#define MV64460_SRAM_ERROR_DATA_HIGH 0x3a0 +#define MV64460_SRAM_ERROR_DATA_PARITY 0x3a8 + +/****************************************/ +/* SDRAM Configuration */ +/****************************************/ + +#define MV64460_SDRAM_CONFIG 0x1400 +#define MV64460_D_UNIT_CONTROL_LOW 0x1404 +#define MV64460_D_UNIT_CONTROL_HIGH 0x1424 +#define MV64460_D_UNIT_MMASK 0x14B0 +#define MV64460_SDRAM_TIMING_CONTROL_LOW 0x1408 +#define MV64460_SDRAM_TIMING_CONTROL_HIGH 0x140c +#define MV64460_SDRAM_ADDR_CONTROL 0x1410 +#define MV64460_SDRAM_OPEN_PAGES_CONTROL 0x1414 +#define MV64460_SDRAM_OPERATION 0x1418 +#define MV64460_SDRAM_MODE 0x141c +#define MV64460_EXTENDED_DRAM_MODE 0x1420 +#define MV64460_SDRAM_CROSS_BAR_CONTROL_LOW 0x1430 +#define MV64460_SDRAM_CROSS_BAR_CONTROL_HIGH 0x1434 +#define MV64460_SDRAM_CROSS_BAR_TIMEOUT 0x1438 +#define MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION 0x14c0 +#define MV64460_SDRAM_DATA_PADS_CALIBRATION 0x14c4 + +/****************************************/ +/* SDRAM Error Report */ +/****************************************/ + +#define MV64460_SDRAM_ERROR_DATA_LOW 0x1444 +#define MV64460_SDRAM_ERROR_DATA_HIGH 0x1440 +#define MV64460_SDRAM_ERROR_ADDR 0x1450 +#define MV64460_SDRAM_RECEIVED_ECC 0x1448 +#define MV64460_SDRAM_CALCULATED_ECC 0x144c +#define MV64460_SDRAM_ECC_CONTROL 0x1454 +#define MV64460_SDRAM_ECC_ERROR_COUNTER 0x1458 + +/******************************************/ +/* Controlled Delay Line (CDL) Registers */ +/******************************************/ + +#define MV64460_DFCDL_CONFIG0 0x1480 +#define MV64460_DFCDL_CONFIG1 0x1484 +#define MV64460_DLL_WRITE 0x1488 +#define MV64460_DLL_READ 0x148c +#define MV64460_SRAM_ADDR 0x1490 +#define MV64460_SRAM_DATA0 0x1494 +#define MV64460_SRAM_DATA1 0x1498 +#define MV64460_SRAM_DATA2 0x149c +#define MV64460_DFCL_PROBE 0x14a0 + +/******************************************/ +/* Debug Registers */ +/******************************************/ + +#define MV64460_DUNIT_DEBUG_LOW 0x1460 +#define MV64460_DUNIT_DEBUG_HIGH 0x1464 +#define MV64460_DUNIT_MMASK 0X1b40 + +/****************************************/ +/* Device Parameters */ +/****************************************/ + +#define MV64460_DEVICE_BANK0_PARAMETERS 0x45c +#define MV64460_DEVICE_BANK1_PARAMETERS 0x460 +#define MV64460_DEVICE_BANK2_PARAMETERS 0x464 +#define MV64460_DEVICE_BANK3_PARAMETERS 0x468 +#define MV64460_DEVICE_BOOT_BANK_PARAMETERS 0x46c +#define MV64460_DEVICE_INTERFACE_CONTROL 0x4c0 +#define MV64460_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW 0x4c8 +#define MV64460_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH 0x4cc +#define MV64460_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT 0x4c4 + +/****************************************/ +/* Device interrupt registers */ +/****************************************/ + +#define MV64460_DEVICE_INTERRUPT_CAUSE 0x4d0 +#define MV64460_DEVICE_INTERRUPT_MASK 0x4d4 +#define MV64460_DEVICE_ERROR_ADDR 0x4d8 +#define MV64460_DEVICE_ERROR_DATA 0x4dc +#define MV64460_DEVICE_ERROR_PARITY 0x4e0 + +/****************************************/ +/* Device debug registers */ +/****************************************/ + +#define MV64460_DEVICE_DEBUG_LOW 0x4e4 +#define MV64460_DEVICE_DEBUG_HIGH 0x4e8 +#define MV64460_RUNIT_MMASK 0x4f0 + +/****************************************/ +/* PCI Slave Address Decoding registers */ +/****************************************/ + +#define MV64460_PCI_0_CS_0_BANK_SIZE 0xc08 +#define MV64460_PCI_1_CS_0_BANK_SIZE 0xc88 +#define MV64460_PCI_0_CS_1_BANK_SIZE 0xd08 +#define MV64460_PCI_1_CS_1_BANK_SIZE 0xd88 +#define MV64460_PCI_0_CS_2_BANK_SIZE 0xc0c +#define MV64460_PCI_1_CS_2_BANK_SIZE 0xc8c +#define MV64460_PCI_0_CS_3_BANK_SIZE 0xd0c +#define MV64460_PCI_1_CS_3_BANK_SIZE 0xd8c +#define MV64460_PCI_0_DEVCS_0_BANK_SIZE 0xc10 +#define MV64460_PCI_1_DEVCS_0_BANK_SIZE 0xc90 +#define MV64460_PCI_0_DEVCS_1_BANK_SIZE 0xd10 +#define MV64460_PCI_1_DEVCS_1_BANK_SIZE 0xd90 +#define MV64460_PCI_0_DEVCS_2_BANK_SIZE 0xd18 +#define MV64460_PCI_1_DEVCS_2_BANK_SIZE 0xd98 +#define MV64460_PCI_0_DEVCS_3_BANK_SIZE 0xc14 +#define MV64460_PCI_1_DEVCS_3_BANK_SIZE 0xc94 +#define MV64460_PCI_0_DEVCS_BOOT_BANK_SIZE 0xd14 +#define MV64460_PCI_1_DEVCS_BOOT_BANK_SIZE 0xd94 +#define MV64460_PCI_0_P2P_MEM0_BAR_SIZE 0xd1c +#define MV64460_PCI_1_P2P_MEM0_BAR_SIZE 0xd9c +#define MV64460_PCI_0_P2P_MEM1_BAR_SIZE 0xd20 +#define MV64460_PCI_1_P2P_MEM1_BAR_SIZE 0xda0 +#define MV64460_PCI_0_P2P_I_O_BAR_SIZE 0xd24 +#define MV64460_PCI_1_P2P_I_O_BAR_SIZE 0xda4 +#define MV64460_PCI_0_CPU_BAR_SIZE 0xd28 +#define MV64460_PCI_1_CPU_BAR_SIZE 0xda8 +#define MV64460_PCI_0_INTERNAL_SRAM_BAR_SIZE 0xe00 +#define MV64460_PCI_1_INTERNAL_SRAM_BAR_SIZE 0xe80 +#define MV64460_PCI_0_EXPANSION_ROM_BAR_SIZE 0xd2c +#define MV64460_PCI_1_EXPANSION_ROM_BAR_SIZE 0xd9c +#define MV64460_PCI_0_BASE_ADDR_REG_ENABLE 0xc3c +#define MV64460_PCI_1_BASE_ADDR_REG_ENABLE 0xcbc +#define MV64460_PCI_0_CS_0_BASE_ADDR_REMAP 0xc48 +#define MV64460_PCI_1_CS_0_BASE_ADDR_REMAP 0xcc8 +#define MV64460_PCI_0_CS_1_BASE_ADDR_REMAP 0xd48 +#define MV64460_PCI_1_CS_1_BASE_ADDR_REMAP 0xdc8 +#define MV64460_PCI_0_CS_2_BASE_ADDR_REMAP 0xc4c +#define MV64460_PCI_1_CS_2_BASE_ADDR_REMAP 0xccc +#define MV64460_PCI_0_CS_3_BASE_ADDR_REMAP 0xd4c +#define MV64460_PCI_1_CS_3_BASE_ADDR_REMAP 0xdcc +#define MV64460_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP 0xF04 +#define MV64460_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP 0xF84 +#define MV64460_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP 0xF08 +#define MV64460_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP 0xF88 +#define MV64460_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP 0xF0C +#define MV64460_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP 0xF8C +#define MV64460_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP 0xF10 +#define MV64460_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP 0xF90 +#define MV64460_PCI_0_DEVCS_0_BASE_ADDR_REMAP 0xc50 +#define MV64460_PCI_1_DEVCS_0_BASE_ADDR_REMAP 0xcd0 +#define MV64460_PCI_0_DEVCS_1_BASE_ADDR_REMAP 0xd50 +#define MV64460_PCI_1_DEVCS_1_BASE_ADDR_REMAP 0xdd0 +#define MV64460_PCI_0_DEVCS_2_BASE_ADDR_REMAP 0xd58 +#define MV64460_PCI_1_DEVCS_2_BASE_ADDR_REMAP 0xdd8 +#define MV64460_PCI_0_DEVCS_3_BASE_ADDR_REMAP 0xc54 +#define MV64460_PCI_1_DEVCS_3_BASE_ADDR_REMAP 0xcd4 +#define MV64460_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP 0xd54 +#define MV64460_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP 0xdd4 +#define MV64460_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW 0xd5c +#define MV64460_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW 0xddc +#define MV64460_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH 0xd60 +#define MV64460_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH 0xde0 +#define MV64460_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW 0xd64 +#define MV64460_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW 0xde4 +#define MV64460_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH 0xd68 +#define MV64460_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH 0xde8 +#define MV64460_PCI_0_P2P_I_O_BASE_ADDR_REMAP 0xd6c +#define MV64460_PCI_1_P2P_I_O_BASE_ADDR_REMAP 0xdec +#define MV64460_PCI_0_CPU_BASE_ADDR_REMAP_LOW 0xd70 +#define MV64460_PCI_1_CPU_BASE_ADDR_REMAP_LOW 0xdf0 +#define MV64460_PCI_0_CPU_BASE_ADDR_REMAP_HIGH 0xd74 +#define MV64460_PCI_1_CPU_BASE_ADDR_REMAP_HIGH 0xdf4 +#define MV64460_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf00 +#define MV64460_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP 0xf80 +#define MV64460_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP 0xf38 +#define MV64460_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP 0xfb8 +#define MV64460_PCI_0_ADDR_DECODE_CONTROL 0xd3c +#define MV64460_PCI_1_ADDR_DECODE_CONTROL 0xdbc +#define MV64460_PCI_0_HEADERS_RETARGET_CONTROL 0xF40 +#define MV64460_PCI_1_HEADERS_RETARGET_CONTROL 0xFc0 +#define MV64460_PCI_0_HEADERS_RETARGET_BASE 0xF44 +#define MV64460_PCI_1_HEADERS_RETARGET_BASE 0xFc4 +#define MV64460_PCI_0_HEADERS_RETARGET_HIGH 0xF48 +#define MV64460_PCI_1_HEADERS_RETARGET_HIGH 0xFc8 + +/***********************************/ +/* PCI Control Register Map */ +/***********************************/ + +#define MV64460_PCI_0_DLL_STATUS_AND_COMMAND 0x1d20 +#define MV64460_PCI_1_DLL_STATUS_AND_COMMAND 0x1da0 +#define MV64460_PCI_0_MPP_PADS_DRIVE_CONTROL 0x1d1C +#define MV64460_PCI_1_MPP_PADS_DRIVE_CONTROL 0x1d9C +#define MV64460_PCI_0_COMMAND 0xc00 +#define MV64460_PCI_1_COMMAND 0xc80 +#define MV64460_PCI_0_MODE 0xd00 +#define MV64460_PCI_1_MODE 0xd80 +#define MV64460_PCI_0_RETRY 0xc04 +#define MV64460_PCI_1_RETRY 0xc84 +#define MV64460_PCI_0_READ_BUFFER_DISCARD_TIMER 0xd04 +#define MV64460_PCI_1_READ_BUFFER_DISCARD_TIMER 0xd84 +#define MV64460_PCI_0_MSI_TRIGGER_TIMER 0xc38 +#define MV64460_PCI_1_MSI_TRIGGER_TIMER 0xcb8 +#define MV64460_PCI_0_ARBITER_CONTROL 0x1d00 +#define MV64460_PCI_1_ARBITER_CONTROL 0x1d80 +#define MV64460_PCI_0_CROSS_BAR_CONTROL_LOW 0x1d08 +#define MV64460_PCI_1_CROSS_BAR_CONTROL_LOW 0x1d88 +#define MV64460_PCI_0_CROSS_BAR_CONTROL_HIGH 0x1d0c +#define MV64460_PCI_1_CROSS_BAR_CONTROL_HIGH 0x1d8c +#define MV64460_PCI_0_CROSS_BAR_TIMEOUT 0x1d04 +#define MV64460_PCI_1_CROSS_BAR_TIMEOUT 0x1d84 +#define MV64460_PCI_0_SYNC_BARRIER_TRIGGER_REG 0x1D18 +#define MV64460_PCI_1_SYNC_BARRIER_TRIGGER_REG 0x1D98 +#define MV64460_PCI_0_SYNC_BARRIER_VIRTUAL_REG 0x1d10 +#define MV64460_PCI_1_SYNC_BARRIER_VIRTUAL_REG 0x1d90 +#define MV64460_PCI_0_P2P_CONFIG 0x1d14 +#define MV64460_PCI_1_P2P_CONFIG 0x1d94 + +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_0_LOW 0x1e00 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_0_HIGH 0x1e04 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_0 0x1e08 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_1_LOW 0x1e10 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_1_HIGH 0x1e14 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_1 0x1e18 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_2_LOW 0x1e20 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_2_HIGH 0x1e24 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_2 0x1e28 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_3_LOW 0x1e30 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_3_HIGH 0x1e34 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_3 0x1e38 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_4_LOW 0x1e40 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_4_HIGH 0x1e44 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_4 0x1e48 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_5_LOW 0x1e50 +#define MV64460_PCI_0_ACCESS_CONTROL_BASE_5_HIGH 0x1e54 +#define MV64460_PCI_0_ACCESS_CONTROL_SIZE_5 0x1e58 + +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_0_LOW 0x1e80 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_0_HIGH 0x1e84 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_0 0x1e88 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_1_LOW 0x1e90 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_1_HIGH 0x1e94 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_1 0x1e98 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_2_LOW 0x1ea0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_2_HIGH 0x1ea4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_2 0x1ea8 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_3_LOW 0x1eb0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_3_HIGH 0x1eb4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_3 0x1eb8 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_4_LOW 0x1ec0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_4_HIGH 0x1ec4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_4 0x1ec8 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_5_LOW 0x1ed0 +#define MV64460_PCI_1_ACCESS_CONTROL_BASE_5_HIGH 0x1ed4 +#define MV64460_PCI_1_ACCESS_CONTROL_SIZE_5 0x1ed8 + +/****************************************/ +/* PCI Configuration Access Registers */ +/****************************************/ + +#define MV64460_PCI_0_CONFIG_ADDR 0xcf8 +#define MV64460_PCI_0_CONFIG_DATA_VIRTUAL_REG 0xcfc +#define MV64460_PCI_1_CONFIG_ADDR 0xc78 +#define MV64460_PCI_1_CONFIG_DATA_VIRTUAL_REG 0xc7c +#define MV64460_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xc34 +#define MV64460_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG 0xcb4 + +/****************************************/ +/* PCI Error Report Registers */ +/****************************************/ + +#define MV64460_PCI_0_SERR_MASK 0xc28 +#define MV64460_PCI_1_SERR_MASK 0xca8 +#define MV64460_PCI_0_ERROR_ADDR_LOW 0x1d40 +#define MV64460_PCI_1_ERROR_ADDR_LOW 0x1dc0 +#define MV64460_PCI_0_ERROR_ADDR_HIGH 0x1d44 +#define MV64460_PCI_1_ERROR_ADDR_HIGH 0x1dc4 +#define MV64460_PCI_0_ERROR_ATTRIBUTE 0x1d48 +#define MV64460_PCI_1_ERROR_ATTRIBUTE 0x1dc8 +#define MV64460_PCI_0_ERROR_COMMAND 0x1d50 +#define MV64460_PCI_1_ERROR_COMMAND 0x1dd0 +#define MV64460_PCI_0_ERROR_CAUSE 0x1d58 +#define MV64460_PCI_1_ERROR_CAUSE 0x1dd8 +#define MV64460_PCI_0_ERROR_MASK 0x1d5c +#define MV64460_PCI_1_ERROR_MASK 0x1ddc + +/****************************************/ +/* PCI Debug Registers */ +/****************************************/ + +#define MV64460_PCI_0_MMASK 0X1D24 +#define MV64460_PCI_1_MMASK 0X1DA4 + +/*********************************************/ +/* PCI Configuration, Function 0, Registers */ +/*********************************************/ + +#define MV64460_PCI_DEVICE_AND_VENDOR_ID 0x000 +#define MV64460_PCI_STATUS_AND_COMMAND 0x004 +#define MV64460_PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define MV64460_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 0x00C + +#define MV64460_PCI_SCS_0_BASE_ADDR_LOW 0x010 +#define MV64460_PCI_SCS_0_BASE_ADDR_HIGH 0x014 +#define MV64460_PCI_SCS_1_BASE_ADDR_LOW 0x018 +#define MV64460_PCI_SCS_1_BASE_ADDR_HIGH 0x01C +#define MV64460_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW 0x020 +#define MV64460_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH 0x024 +#define MV64460_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID 0x02c +#define MV64460_PCI_EXPANSION_ROM_BASE_ADDR_REG 0x030 +#define MV64460_PCI_CAPABILTY_LIST_POINTER 0x034 +#define MV64460_PCI_INTERRUPT_PIN_AND_LINE 0x03C + /* capability list */ +#define MV64460_PCI_POWER_MANAGEMENT_CAPABILITY 0x040 +#define MV64460_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL 0x044 +#define MV64460_PCI_VPD_ADDR 0x048 +#define MV64460_PCI_VPD_DATA 0x04c +#define MV64460_PCI_MSI_MESSAGE_CONTROL 0x050 +#define MV64460_PCI_MSI_MESSAGE_ADDR 0x054 +#define MV64460_PCI_MSI_MESSAGE_UPPER_ADDR 0x058 +#define MV64460_PCI_MSI_MESSAGE_DATA 0x05c +#define MV64460_PCI_X_COMMAND 0x060 +#define MV64460_PCI_X_STATUS 0x064 +#define MV64460_PCI_COMPACT_PCI_HOT_SWAP 0x068 + +/***********************************************/ +/* PCI Configuration, Function 1, Registers */ +/***********************************************/ + +#define MV64460_PCI_SCS_2_BASE_ADDR_LOW 0x110 +#define MV64460_PCI_SCS_2_BASE_ADDR_HIGH 0x114 +#define MV64460_PCI_SCS_3_BASE_ADDR_LOW 0x118 +#define MV64460_PCI_SCS_3_BASE_ADDR_HIGH 0x11c +#define MV64460_PCI_INTERNAL_SRAM_BASE_ADDR_LOW 0x120 +#define MV64460_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH 0x124 + +/***********************************************/ +/* PCI Configuration, Function 2, Registers */ +/***********************************************/ + +#define MV64460_PCI_DEVCS_0_BASE_ADDR_LOW 0x210 +#define MV64460_PCI_DEVCS_0_BASE_ADDR_HIGH 0x214 +#define MV64460_PCI_DEVCS_1_BASE_ADDR_LOW 0x218 +#define MV64460_PCI_DEVCS_1_BASE_ADDR_HIGH 0x21c +#define MV64460_PCI_DEVCS_2_BASE_ADDR_LOW 0x220 +#define MV64460_PCI_DEVCS_2_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 3, Registers */ +/***********************************************/ + +#define MV64460_PCI_DEVCS_3_BASE_ADDR_LOW 0x310 +#define MV64460_PCI_DEVCS_3_BASE_ADDR_HIGH 0x314 +#define MV64460_PCI_BOOT_CS_BASE_ADDR_LOW 0x318 +#define MV64460_PCI_BOOT_CS_BASE_ADDR_HIGH 0x31c +#define MV64460_PCI_CPU_BASE_ADDR_LOW 0x220 +#define MV64460_PCI_CPU_BASE_ADDR_HIGH 0x224 + +/***********************************************/ +/* PCI Configuration, Function 4, Registers */ +/***********************************************/ + +#define MV64460_PCI_P2P_MEM0_BASE_ADDR_LOW 0x410 +#define MV64460_PCI_P2P_MEM0_BASE_ADDR_HIGH 0x414 +#define MV64460_PCI_P2P_MEM1_BASE_ADDR_LOW 0x418 +#define MV64460_PCI_P2P_MEM1_BASE_ADDR_HIGH 0x41c +#define MV64460_PCI_P2P_I_O_BASE_ADDR 0x420 +#define MV64460_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR 0x424 + +/****************************************/ +/* Messaging Unit Registers (I20) */ +/****************************************/ + +#define MV64460_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE 0x010 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE 0x014 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 0x018 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE 0x01C +#define MV64460_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE 0x020 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x024 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x028 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 0x02C +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE 0x030 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE 0x034 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x040 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE 0x044 +#define MV64460_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 0x050 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 0x054 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x060 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x064 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x068 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x06C +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE 0x070 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE 0x074 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE 0x0F8 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE 0x0FC + +#define MV64460_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE 0x090 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE 0x094 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 0x098 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE 0x09C +#define MV64460_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE 0x0A0 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0A4 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0A8 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 0x0AC +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE 0x0B0 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE 0x0B4 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C0 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE 0x0C4 +#define MV64460_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 0x0D0 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 0x0D4 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0E0 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0E4 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x0E8 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x0EC +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE 0x0F0 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE 0x0F4 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE 0x078 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE 0x07C + +#define MV64460_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C10 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C14 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 0x1C18 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE 0x1C1C +#define MV64460_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE 0x1C20 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C24 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C28 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 0x1C2C +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE 0x1C30 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE 0x1C34 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C40 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE 0x1C44 +#define MV64460_I2O_QUEUE_CONTROL_REG_CPU0_SIDE 0x1C50 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 0x1C54 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C60 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C64 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1C68 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1C6C +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE 0x1C70 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE 0x1C74 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE 0x1CF8 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE 0x1CFC +#define MV64460_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C90 +#define MV64460_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C94 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 0x1C98 +#define MV64460_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE 0x1C9C +#define MV64460_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE 0x1CA0 +#define MV64460_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CA4 +#define MV64460_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CA8 +#define MV64460_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 0x1CAC +#define MV64460_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE 0x1CB0 +#define MV64460_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE 0x1CB4 +#define MV64460_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC0 +#define MV64460_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE 0x1CC4 +#define MV64460_I2O_QUEUE_CONTROL_REG_CPU1_SIDE 0x1CD0 +#define MV64460_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 0x1CD4 +#define MV64460_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CE0 +#define MV64460_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CE4 +#define MV64460_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1CE8 +#define MV64460_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1CEC +#define MV64460_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE 0x1CF0 +#define MV64460_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE 0x1CF4 +#define MV64460_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE 0x1C78 +#define MV64460_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE 0x1C7C + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ + +#define MV64460_ETH_PHY_ADDR_REG 0x2000 +#define MV64460_ETH_SMI_REG 0x2004 +#define MV64460_ETH_UNIT_DEFAULT_ADDR_REG 0x2008 +#define MV64460_ETH_UNIT_DEFAULTID_REG 0x200c +#define MV64460_ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080 +#define MV64460_ETH_UNIT_INTERRUPT_MASK_REG 0x2084 +#define MV64460_ETH_UNIT_INTERNAL_USE_REG 0x24fc +#define MV64460_ETH_UNIT_ERROR_ADDR_REG 0x2094 +#define MV64460_ETH_BAR_0 0x2200 +#define MV64460_ETH_BAR_1 0x2208 +#define MV64460_ETH_BAR_2 0x2210 +#define MV64460_ETH_BAR_3 0x2218 +#define MV64460_ETH_BAR_4 0x2220 +#define MV64460_ETH_BAR_5 0x2228 +#define MV64460_ETH_SIZE_REG_0 0x2204 +#define MV64460_ETH_SIZE_REG_1 0x220c +#define MV64460_ETH_SIZE_REG_2 0x2214 +#define MV64460_ETH_SIZE_REG_3 0x221c +#define MV64460_ETH_SIZE_REG_4 0x2224 +#define MV64460_ETH_SIZE_REG_5 0x222c +#define MV64460_ETH_HEADERS_RETARGET_BASE_REG 0x2230 +#define MV64460_ETH_HEADERS_RETARGET_CONTROL_REG 0x2234 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_0 0x2280 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_1 0x2284 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_2 0x2288 +#define MV64460_ETH_HIGH_ADDR_REMAP_REG_3 0x228c +#define MV64460_ETH_BASE_ADDR_ENABLE_REG 0x2290 +#define MV64460_ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2)) +#define MV64460_ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7)) +#define MV64460_ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10)) +#define MV64460_ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10)) +#define MV64460_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10)) +#define MV64460_ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10)) +#define MV64460_ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10)) +#define MV64460_ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10)) +#define MV64460_ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10)) +#define MV64460_ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10)) +#define MV64460_ETH_DSCP_0(port) (0x2420 + (port<<10)) +#define MV64460_ETH_DSCP_1(port) (0x2424 + (port<<10)) +#define MV64460_ETH_DSCP_2(port) (0x2428 + (port<<10)) +#define MV64460_ETH_DSCP_3(port) (0x242c + (port<<10)) +#define MV64460_ETH_DSCP_4(port) (0x2430 + (port<<10)) +#define MV64460_ETH_DSCP_5(port) (0x2434 + (port<<10)) +#define MV64460_ETH_DSCP_6(port) (0x2438 + (port<<10)) +#define MV64460_ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10)) +#define MV64460_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10)) +#define MV64460_ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10)) +#define MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10)) +#define MV64460_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10)) +#define MV64460_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10)) +#define MV64460_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10)) +#define MV64460_ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10)) +#define MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10)) +#define MV64460_ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10)) +#define MV64460_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10)) +#define MV64460_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10)) +#define MV64460_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10)) +#define MV64460_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10)) +#define MV64460_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10) +#define MV64460_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10)) +#define MV64460_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10)) +#define MV64460_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10)) +#define MV64460_ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10)) +#define MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) +#define MV64460_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10)) +#define MV64460_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10)) +#define MV64460_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10)) +#define MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10)) +#define MV64460_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10)) +#define MV64460_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10)) +#define MV64460_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10)) +#define MV64460_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10)) +#define MV64460_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10)) + +/*******************************************/ +/* CUNIT Registers */ +/*******************************************/ + + /* Address Decoding Register Map */ + +#define MV64460_CUNIT_BASE_ADDR_REG0 0xf200 +#define MV64460_CUNIT_BASE_ADDR_REG1 0xf208 +#define MV64460_CUNIT_BASE_ADDR_REG2 0xf210 +#define MV64460_CUNIT_BASE_ADDR_REG3 0xf218 +#define MV64460_CUNIT_SIZE0 0xf204 +#define MV64460_CUNIT_SIZE1 0xf20c +#define MV64460_CUNIT_SIZE2 0xf214 +#define MV64460_CUNIT_SIZE3 0xf21c +#define MV64460_CUNIT_HIGH_ADDR_REMAP_REG0 0xf240 +#define MV64460_CUNIT_HIGH_ADDR_REMAP_REG1 0xf244 +#define MV64460_CUNIT_BASE_ADDR_ENABLE_REG 0xf250 +#define MV64460_MPSC0_ACCESS_PROTECTION_REG 0xf254 +#define MV64460_MPSC1_ACCESS_PROTECTION_REG 0xf258 +#define MV64460_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG 0xf25C + + /* Error Report Registers */ + +#define MV64460_CUNIT_INTERRUPT_CAUSE_REG 0xf310 +#define MV64460_CUNIT_INTERRUPT_MASK_REG 0xf314 +#define MV64460_CUNIT_ERROR_ADDR 0xf318 + + /* Cunit Control Registers */ + +#define MV64460_CUNIT_ARBITER_CONTROL_REG 0xf300 +#define MV64460_CUNIT_CONFIG_REG 0xb40c +#define MV64460_CUNIT_CRROSBAR_TIMEOUT_REG 0xf304 + + /* Cunit Debug Registers */ + +#define MV64460_CUNIT_DEBUG_LOW 0xf340 +#define MV64460_CUNIT_DEBUG_HIGH 0xf344 +#define MV64460_CUNIT_MMASK 0xf380 + + /* Cunit Base Address Enable Window Bits*/ +#define MV64460_CUNIT_BASE_ADDR_WIN_0_BIT 0x0 +#define MV64460_CUNIT_BASE_ADDR_WIN_1_BIT 0x1 +#define MV64460_CUNIT_BASE_ADDR_WIN_2_BIT 0x2 +#define MV64460_CUNIT_BASE_ADDR_WIN_3_BIT 0x3 + + /* MPSCs Clocks Routing Registers */ + +#define MV64460_MPSC_ROUTING_REG 0xb400 +#define MV64460_MPSC_RX_CLOCK_ROUTING_REG 0xb404 +#define MV64460_MPSC_TX_CLOCK_ROUTING_REG 0xb408 + + /* MPSCs Interrupts Registers */ + +#define MV64460_MPSC_CAUSE_REG(port) (0xb804 + (port<<3)) +#define MV64460_MPSC_MASK_REG(port) (0xb884 + (port<<3)) + +#define MV64460_MPSC_MAIN_CONFIG_LOW(port) (0x8000 + (port<<12)) +#define MV64460_MPSC_MAIN_CONFIG_HIGH(port) (0x8004 + (port<<12)) +#define MV64460_MPSC_PROTOCOL_CONFIG(port) (0x8008 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG1(port) (0x800c + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG2(port) (0x8010 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG3(port) (0x8014 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG4(port) (0x8018 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG5(port) (0x801c + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG6(port) (0x8020 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG7(port) (0x8024 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG8(port) (0x8028 + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG9(port) (0x802c + (port<<12)) +#define MV64460_MPSC_CHANNEL_REG10(port) (0x8030 + (port<<12)) + + /* MPSC0 Registers */ + + +/***************************************/ +/* SDMA Registers */ +/***************************************/ + +#define MV64460_SDMA_CONFIG_REG(channel) (0x4000 + (channel<<13)) +#define MV64460_SDMA_COMMAND_REG(channel) (0x4008 + (channel<<13)) +#define MV64460_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel) (0x4810 + (channel<<13)) +#define MV64460_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel) (0x4c10 + (channel<<13)) +#define MV64460_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel) (0x4c14 + (channel<<13)) + +#define MV64460_SDMA_CAUSE_REG 0xb800 +#define MV64460_SDMA_MASK_REG 0xb880 + + +/****************************************/ +/* SDMA Address Space Targets */ +/****************************************/ + +#define MV64460_SDMA_DRAM_CS_0_TARGET 0x0e00 +#define MV64460_SDMA_DRAM_CS_1_TARGET 0x0d00 +#define MV64460_SDMA_DRAM_CS_2_TARGET 0x0b00 +#define MV64460_SDMA_DRAM_CS_3_TARGET 0x0700 + +#define MV64460_SDMA_DEV_CS_0_TARGET 0x1e01 +#define MV64460_SDMA_DEV_CS_1_TARGET 0x1d01 +#define MV64460_SDMA_DEV_CS_2_TARGET 0x1b01 +#define MV64460_SDMA_DEV_CS_3_TARGET 0x1701 + +#define MV64460_SDMA_BOOT_CS_TARGET 0x0f00 + +#define MV64460_SDMA_SRAM_TARGET 0x0003 +#define MV64460_SDMA_60X_BUS_TARGET 0x4003 + +#define MV64460_PCI_0_TARGET 0x0003 +#define MV64460_PCI_1_TARGET 0x0004 + + +/* Devices BAR and size registers */ + +#define MV64460_DEV_CS0_BASE_ADDR 0x028 +#define MV64460_DEV_CS0_SIZE 0x030 +#define MV64460_DEV_CS1_BASE_ADDR 0x228 +#define MV64460_DEV_CS1_SIZE 0x230 +#define MV64460_DEV_CS2_BASE_ADDR 0x248 +#define MV64460_DEV_CS2_SIZE 0x250 +#define MV64460_DEV_CS3_BASE_ADDR 0x038 +#define MV64460_DEV_CS3_SIZE 0x040 +#define MV64460_BOOTCS_BASE_ADDR 0x238 +#define MV64460_BOOTCS_SIZE 0x240 + +/* SDMA Window access protection */ +#define MV64460_SDMA_WIN_ACCESS_NOT_ALLOWED 0 +#define MV64460_SDMA_WIN_ACCESS_READ_ONLY 1 +#define MV64460_SDMA_WIN_ACCESS_FULL 2 + +/* BRG Interrupts */ + +#define MV64460_BRG_CONFIG_REG(brg) (0xb200 + (brg<<3)) +#define MV64460_BRG_BAUDE_TUNING_REG(brg) (0xb204 + (brg<<3)) +#define MV64460_BRG_CAUSE_REG 0xb834 +#define MV64460_BRG_MASK_REG 0xb8b4 + +/****************************************/ +/* DMA Channel Control */ +/****************************************/ + +#define MV64460_DMA_CHANNEL0_CONTROL 0x840 +#define MV64460_DMA_CHANNEL0_CONTROL_HIGH 0x880 +#define MV64460_DMA_CHANNEL1_CONTROL 0x844 +#define MV64460_DMA_CHANNEL1_CONTROL_HIGH 0x884 +#define MV64460_DMA_CHANNEL2_CONTROL 0x848 +#define MV64460_DMA_CHANNEL2_CONTROL_HIGH 0x888 +#define MV64460_DMA_CHANNEL3_CONTROL 0x84C +#define MV64460_DMA_CHANNEL3_CONTROL_HIGH 0x88C + + +/****************************************/ +/* IDMA Registers */ +/****************************************/ + +#define MV64460_DMA_CHANNEL0_BYTE_COUNT 0x800 +#define MV64460_DMA_CHANNEL1_BYTE_COUNT 0x804 +#define MV64460_DMA_CHANNEL2_BYTE_COUNT 0x808 +#define MV64460_DMA_CHANNEL3_BYTE_COUNT 0x80C +#define MV64460_DMA_CHANNEL0_SOURCE_ADDR 0x810 +#define MV64460_DMA_CHANNEL1_SOURCE_ADDR 0x814 +#define MV64460_DMA_CHANNEL2_SOURCE_ADDR 0x818 +#define MV64460_DMA_CHANNEL3_SOURCE_ADDR 0x81c +#define MV64460_DMA_CHANNEL0_DESTINATION_ADDR 0x820 +#define MV64460_DMA_CHANNEL1_DESTINATION_ADDR 0x824 +#define MV64460_DMA_CHANNEL2_DESTINATION_ADDR 0x828 +#define MV64460_DMA_CHANNEL3_DESTINATION_ADDR 0x82C +#define MV64460_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER 0x830 +#define MV64460_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER 0x834 +#define MV64460_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER 0x838 +#define MV64460_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER 0x83C +#define MV64460_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER 0x870 +#define MV64460_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER 0x874 +#define MV64460_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER 0x878 +#define MV64460_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER 0x87C + + /* IDMA Address Decoding Base Address Registers */ + +#define MV64460_DMA_BASE_ADDR_REG0 0xa00 +#define MV64460_DMA_BASE_ADDR_REG1 0xa08 +#define MV64460_DMA_BASE_ADDR_REG2 0xa10 +#define MV64460_DMA_BASE_ADDR_REG3 0xa18 +#define MV64460_DMA_BASE_ADDR_REG4 0xa20 +#define MV64460_DMA_BASE_ADDR_REG5 0xa28 +#define MV64460_DMA_BASE_ADDR_REG6 0xa30 +#define MV64460_DMA_BASE_ADDR_REG7 0xa38 + + /* IDMA Address Decoding Size Address Register */ + +#define MV64460_DMA_SIZE_REG0 0xa04 +#define MV64460_DMA_SIZE_REG1 0xa0c +#define MV64460_DMA_SIZE_REG2 0xa14 +#define MV64460_DMA_SIZE_REG3 0xa1c +#define MV64460_DMA_SIZE_REG4 0xa24 +#define MV64460_DMA_SIZE_REG5 0xa2c +#define MV64460_DMA_SIZE_REG6 0xa34 +#define MV64460_DMA_SIZE_REG7 0xa3C + + /* IDMA Address Decoding High Address Remap and Access + Protection Registers */ + +#define MV64460_DMA_HIGH_ADDR_REMAP_REG0 0xa60 +#define MV64460_DMA_HIGH_ADDR_REMAP_REG1 0xa64 +#define MV64460_DMA_HIGH_ADDR_REMAP_REG2 0xa68 +#define MV64460_DMA_HIGH_ADDR_REMAP_REG3 0xa6C +#define MV64460_DMA_BASE_ADDR_ENABLE_REG 0xa80 +#define MV64460_DMA_CHANNEL0_ACCESS_PROTECTION_REG 0xa70 +#define MV64460_DMA_CHANNEL1_ACCESS_PROTECTION_REG 0xa74 +#define MV64460_DMA_CHANNEL2_ACCESS_PROTECTION_REG 0xa78 +#define MV64460_DMA_CHANNEL3_ACCESS_PROTECTION_REG 0xa7c +#define MV64460_DMA_ARBITER_CONTROL 0x860 +#define MV64460_DMA_CROSS_BAR_TIMEOUT 0x8d0 + + /* IDMA Headers Retarget Registers */ + +#define MV64460_DMA_HEADERS_RETARGET_CONTROL 0xa84 +#define MV64460_DMA_HEADERS_RETARGET_BASE 0xa88 + + /* IDMA Interrupt Register */ + +#define MV64460_DMA_INTERRUPT_CAUSE_REG 0x8c0 +#define MV64460_DMA_INTERRUPT_CAUSE_MASK 0x8c4 +#define MV64460_DMA_ERROR_ADDR 0x8c8 +#define MV64460_DMA_ERROR_SELECT 0x8cc + + /* IDMA Debug Register ( for internal use ) */ + +#define MV64460_DMA_DEBUG_LOW 0x8e0 +#define MV64460_DMA_DEBUG_HIGH 0x8e4 +#define MV64460_DMA_SPARE 0xA8C + +/****************************************/ +/* Timer_Counter */ +/****************************************/ + +#define MV64460_TIMER_COUNTER0 0x850 +#define MV64460_TIMER_COUNTER1 0x854 +#define MV64460_TIMER_COUNTER2 0x858 +#define MV64460_TIMER_COUNTER3 0x85C +#define MV64460_TIMER_COUNTER_0_3_CONTROL 0x864 +#define MV64460_TIMER_COUNTER_0_3_INTERRUPT_CAUSE 0x868 +#define MV64460_TIMER_COUNTER_0_3_INTERRUPT_MASK 0x86c + +/****************************************/ +/* Watchdog registers */ +/****************************************/ + +#define MV64460_WATCHDOG_CONFIG_REG 0xb410 +#define MV64460_WATCHDOG_VALUE_REG 0xb414 + +/****************************************/ +/* I2C Registers */ +/****************************************/ + +#define MV64460_I2C_SLAVE_ADDR 0xc000 +#define MV64460_I2C_EXTENDED_SLAVE_ADDR 0xc010 +#define MV64460_I2C_DATA 0xc004 +#define MV64460_I2C_CONTROL 0xc008 +#define MV64460_I2C_STATUS_BAUDE_RATE 0xc00C +#define MV64460_I2C_SOFT_RESET 0xc01c + +/****************************************/ +/* GPP Interface Registers */ +/****************************************/ + +#define MV64460_GPP_IO_CONTROL 0xf100 +#define MV64460_GPP_LEVEL_CONTROL 0xf110 +#define MV64460_GPP_VALUE 0xf104 +#define MV64460_GPP_INTERRUPT_CAUSE 0xf108 +#define MV64460_GPP_INTERRUPT_MASK0 0xf10c +#define MV64460_GPP_INTERRUPT_MASK1 0xf114 +#define MV64460_GPP_VALUE_SET 0xf118 +#define MV64460_GPP_VALUE_CLEAR 0xf11c + +/****************************************/ +/* Interrupt Controller Registers */ +/****************************************/ + +/****************************************/ +/* Interrupts */ +/****************************************/ + +#define MV64460_MAIN_INTERRUPT_CAUSE_LOW 0x004 +#define MV64460_MAIN_INTERRUPT_CAUSE_HIGH 0x00c +#define MV64460_CPU_INTERRUPT0_MASK_LOW 0x014 +#define MV64460_CPU_INTERRUPT0_MASK_HIGH 0x01c +#define MV64460_CPU_INTERRUPT0_SELECT_CAUSE 0x024 +#define MV64460_CPU_INTERRUPT1_MASK_LOW 0x034 +#define MV64460_CPU_INTERRUPT1_MASK_HIGH 0x03c +#define MV64460_CPU_INTERRUPT1_SELECT_CAUSE 0x044 +#define MV64460_INTERRUPT0_MASK_0_LOW 0x054 +#define MV64460_INTERRUPT0_MASK_0_HIGH 0x05c +#define MV64460_INTERRUPT0_SELECT_CAUSE 0x064 +#define MV64460_INTERRUPT1_MASK_0_LOW 0x074 +#define MV64460_INTERRUPT1_MASK_0_HIGH 0x07c +#define MV64460_INTERRUPT1_SELECT_CAUSE 0x084 + +/****************************************/ +/* MPP Interface Registers */ +/****************************************/ + +#define MV64460_MPP_CONTROL0 0xf000 +#define MV64460_MPP_CONTROL1 0xf004 +#define MV64460_MPP_CONTROL2 0xf008 +#define MV64460_MPP_CONTROL3 0xf00c + +/****************************************/ +/* Serial Initialization registers */ +/****************************************/ + +#define MV64460_SERIAL_INIT_LAST_DATA 0xf324 +#define MV64460_SERIAL_INIT_CONTROL 0xf328 +#define MV64460_SERIAL_INIT_STATUS 0xf32c + + +#endif /* __INCgt64460rh */ diff --git a/board/prodrive/p3mx/p3mx.c b/board/prodrive/p3mx/p3mx.c new file mode 100644 index 0000000..d54ddaf --- /dev/null +++ b/board/prodrive/p3mx/p3mx.c @@ -0,0 +1,864 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Based on original work by + * Roel Loeffen, (C) Copyright 2006 Prodrive B.V. + * Josh Huber, (C) Copyright 2001 Mission Critical Linux, 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 + * + * modifications for the DB64360 eval board based by Ingo.Assmus@keymile.com + * modifications for the cpci750 by reinhard.arlt@esd-electronics.com + * modifications for the P3M750 by roel.loeffen@prodrive.nl + */ + +/* + * p3m750.c - main board support/init for the Prodrive p3m750/p3m7448. + */ + +#include <common.h> +#include <74xx_7xx.h> +#include "../../Marvell/include/memory.h" +#include "../../Marvell/include/pci.h" +#include "../../Marvell/include/mv_gen_reg.h" +#include <net.h> +#include <i2c.h> + +#include "eth.h" +#include "mpsc.h" +#include "64460.h" +#include "mv_regs.h" +#include "p3mx.h" + +DECLARE_GLOBAL_DATA_PTR; + +#undef DEBUG +/*#define DEBUG */ + +#ifdef CONFIG_PCI +#define MAP_PCI +#endif /* of CONFIG_PCI */ + +#ifdef DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +extern void flush_data_cache (void); +extern void invalidate_l1_instruction_cache (void); +extern flash_info_t flash_info[]; + +/* ------------------------------------------------------------------------- */ + +/* this is the current GT register space location */ +/* it starts at CFG_DFL_GT_REGS but moves later to CFG_GT_REGS */ + +/* Unfortunately, we cant change it while we are in flash, so we initialize it + * to the "final" value. This means that any debug_led calls before + * board_early_init_f wont work right (like in cpu_init_f). + * See also my_remap_gt_regs below. (NTL) + */ + +void board_prebootm_init (void); +unsigned int INTERNAL_REG_BASE_ADDR = CFG_GT_REGS; +int display_mem_map (void); +void set_led(int); + +/* ------------------------------------------------------------------------- */ + +/* + * This is a version of the GT register space remapping function that + * doesn't touch globals (meaning, it's ok to run from flash.) + * + * Unfortunately, this has the side effect that a writable + * INTERNAL_REG_BASE_ADDR is impossible. Oh well. + */ + +void my_remap_gt_regs (u32 cur_loc, u32 new_loc) +{ + u32 temp; + + /* check and see if it's already moved */ + temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); + if ((temp & 0xffff) == new_loc >> 16) + return; + + temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & + 0xffff0000) | (new_loc >> 16); + + out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); + + while (GTREGREAD (INTERNAL_SPACE_DECODE) != temp); +} + +#ifdef CONFIG_PCI + +static void gt_pci_config (void) +{ + unsigned int stat; + unsigned int val = 0x00fff864; /* DINK32: BusNum 23:16, DevNum 15:11, */ + /* FuncNum 10:8, RegNum 7:2 */ + + /* + * In PCIX mode devices provide their own bus and device numbers. + * We query the Discovery II's + * config registers by writing ones to the bus and device. + * We then update the Virtual register with the correct value for the + * bus and device. + */ + if ((GTREGREAD (PCI_0_MODE) & (BIT4 | BIT5)) != 0) { /* if PCI-X */ + GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); + + GT_REG_READ (PCI_0_CONFIG_DATA_VIRTUAL_REG, &stat); + + GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); + GT_REG_WRITE (PCI_0_CONFIG_DATA_VIRTUAL_REG, + (stat & 0xffff0000) | CFG_PCI_IDSEL); + + } + if ((GTREGREAD (PCI_1_MODE) & (BIT4 | BIT5)) != 0) { /* if PCI-X */ + GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); + GT_REG_READ (PCI_1_CONFIG_DATA_VIRTUAL_REG, &stat); + + GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); + GT_REG_WRITE (PCI_1_CONFIG_DATA_VIRTUAL_REG, + (stat & 0xffff0000) | CFG_PCI_IDSEL); + } + + /* Enable master */ + PCI_MASTER_ENABLE (0, SELF); + PCI_MASTER_ENABLE (1, SELF); + + /* Enable PCI0/1 Mem0 and IO 0 disable all others */ + GT_REG_READ (BASE_ADDR_ENABLE, &stat); + stat |= (1 << 11) | (1 << 12) | (1 << 13) | (1 << 16) | (1 << 17) | + (1 << 18); + stat &= ~((1 << 9) | (1 << 10) | (1 << 14) | (1 << 15)); + GT_REG_WRITE (BASE_ADDR_ENABLE, stat); + + /* ronen: + * add write to pci remap registers for 64460. + * in 64360 when writing to pci base go and overide remap automaticaly, + * in 64460 it doesn't + */ + GT_REG_WRITE (PCI_0_IO_BASE_ADDR, CFG_PCI0_IO_SPACE >> 16); + GT_REG_WRITE (PCI_0I_O_ADDRESS_REMAP, CFG_PCI0_IO_SPACE_PCI >> 16); + GT_REG_WRITE (PCI_0_IO_SIZE, (CFG_PCI0_IO_SIZE - 1) >> 16); + + GT_REG_WRITE (PCI_0_MEMORY0_BASE_ADDR, CFG_PCI0_MEM_BASE >> 16); + GT_REG_WRITE (PCI_0MEMORY0_ADDRESS_REMAP, CFG_PCI0_MEM_BASE >> 16); + GT_REG_WRITE (PCI_0_MEMORY0_SIZE, (CFG_PCI0_MEM_SIZE - 1) >> 16); + + GT_REG_WRITE (PCI_1_IO_BASE_ADDR, CFG_PCI1_IO_SPACE >> 16); + GT_REG_WRITE (PCI_1I_O_ADDRESS_REMAP, CFG_PCI1_IO_SPACE_PCI >> 16); + GT_REG_WRITE (PCI_1_IO_SIZE, (CFG_PCI1_IO_SIZE - 1) >> 16); + + GT_REG_WRITE (PCI_1_MEMORY0_BASE_ADDR, CFG_PCI1_MEM_BASE >> 16); + GT_REG_WRITE (PCI_1MEMORY0_ADDRESS_REMAP, CFG_PCI1_MEM_BASE >> 16); + GT_REG_WRITE (PCI_1_MEMORY0_SIZE, (CFG_PCI1_MEM_SIZE - 1) >> 16); + + /* PCI interface settings */ + /* Timeout set to retry forever */ + GT_REG_WRITE (PCI_0TIMEOUT_RETRY, 0x0); + GT_REG_WRITE (PCI_1TIMEOUT_RETRY, 0x0); + + /* ronen - enable only CS0 and Internal reg!! */ + GT_REG_WRITE (PCI_0BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); + GT_REG_WRITE (PCI_1BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); + + /* ronen: + * update the pci internal registers base address. + */ +#ifdef MAP_PCI + for (stat = 0; stat <= PCI_HOST1; stat++) + pciWriteConfigReg (stat, + PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, + SELF, CFG_GT_REGS); +#endif + +} +#endif + +/* Setup CPU interface paramaters */ +static void gt_cpu_config (void) +{ + cpu_t cpu = get_cpu_type (); + ulong tmp; + + /* cpu configuration register */ + tmp = GTREGREAD (CPU_CONFIGURATION); + /* set the SINGLE_CPU bit see MV64460 */ +#ifndef CFG_GT_DUAL_CPU /* SINGLE_CPU seems to cause JTAG problems */ + tmp |= CPU_CONF_SINGLE_CPU; +#endif + tmp &= ~CPU_CONF_AACK_DELAY_2; + tmp |= CPU_CONF_DP_VALID; + tmp |= CPU_CONF_AP_VALID; + tmp |= CPU_CONF_PIPELINE; + GT_REG_WRITE (CPU_CONFIGURATION, tmp); /* Marvell (VXWorks) writes 0x20220FF */ + + /* CPU master control register */ + tmp = GTREGREAD (CPU_MASTER_CONTROL); + tmp |= CPU_MAST_CTL_ARB_EN; + + if ((cpu == CPU_7400) || + (cpu == CPU_7410) || (cpu == CPU_7455) || (cpu == CPU_7450)) { + + tmp |= CPU_MAST_CTL_CLEAN_BLK; + tmp |= CPU_MAST_CTL_FLUSH_BLK; + + } else { + /* cleanblock must be cleared for CPUs + * that do not support this command (603e, 750) + * see Res#1 */ + tmp &= ~CPU_MAST_CTL_CLEAN_BLK; + tmp &= ~CPU_MAST_CTL_FLUSH_BLK; + } + GT_REG_WRITE (CPU_MASTER_CONTROL, tmp); +} + +/* + * board_early_init_f. + * + * set up gal. device mappings, etc. + */ +int board_early_init_f (void) +{ + /* set up the GT the way the kernel wants it + * the call to move the GT register space will obviously + * fail if it has already been done, but we're going to assume + * that if it's not at the power-on location, it's where we put + * it last time. (huber) + */ + my_remap_gt_regs (CFG_DFL_GT_REGS, CFG_GT_REGS); + +#ifdef CONFIG_PCI + gt_pci_config (); +#endif + /* mask all external interrupt sources */ + GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_HIGH, 0); + /* new in >MV6436x */ + GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_HIGH, 0); + /* --------------------- */ + GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); + GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); + GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); + + /* Device and Boot bus settings + */ + memoryMapDeviceSpace(DEVICE0, 0, 0); + GT_REG_WRITE(DEVICE_BANK0PARAMETERS, 0); + memoryMapDeviceSpace(DEVICE1, 0, 0); + GT_REG_WRITE(DEVICE_BANK1PARAMETERS, 0); + memoryMapDeviceSpace(DEVICE2, 0, 0); + GT_REG_WRITE(DEVICE_BANK2PARAMETERS, 0); + memoryMapDeviceSpace(DEVICE3, 0, 0); + GT_REG_WRITE(DEVICE_BANK3PARAMETERS, 0); + + GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CFG_BOOT_PAR); + + gt_cpu_config(); + + /* MPP setup */ + GT_REG_WRITE (MPP_CONTROL0, CFG_MPP_CONTROL_0); + GT_REG_WRITE (MPP_CONTROL1, CFG_MPP_CONTROL_1); + GT_REG_WRITE (MPP_CONTROL2, CFG_MPP_CONTROL_2); + GT_REG_WRITE (MPP_CONTROL3, CFG_MPP_CONTROL_3); + + GT_REG_WRITE (GPP_LEVEL_CONTROL, CFG_GPP_LEVEL_CONTROL); + + set_led(LED_RED); + + return 0; +} + +/* various things to do after relocation */ + +int misc_init_r () +{ + u8 val; + + icache_enable (); +#ifdef CFG_L2 + l2cache_enable (); +#endif +#ifdef CONFIG_MPSC + mpsc_sdma_init (); + mpsc_init2 (); +#endif + + /* + * Enable trickle changing in RTC upon powerup + * No diode, 250 ohm series resistor + */ + val = 0xa5; + i2c_write(CFG_I2C_RTC_ADDR, 8, 1, &val, 1); + + return 0; +} + +int board_early_init_r(void) +{ + /* now relocate the debug serial driver */ + mpsc_putchar += gd->reloc_off; + mpsc_getchar += gd->reloc_off; + mpsc_test_char += gd->reloc_off; + + return 0; +} + +void after_reloc (ulong dest_addr, gd_t * gd) +{ + memoryMapDeviceSpace (BOOT_DEVICE, CFG_BOOT_SPACE, CFG_BOOT_SIZE); + +/* display_mem_map(); */ + + /* now, jump to the main U-Boot board init code */ + set_led(LED_GREEN); + board_init_r (gd, dest_addr); + /* NOTREACHED */ +} + +/* + * Check Board Identity: + * right now, assume borad type. (there is just one...after all) + */ + +int checkboard (void) +{ + char *s = getenv("serial#"); + + printf("Board: %s", CFG_BOARD_NAME); + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} + +void set_led(int col) +{ + int tmp; + int on_pin; + int off_pin; + + /* Program Mpp[22] as Gpp[22] + * Program Mpp[23] as Gpp[23] + */ + tmp = GTREGREAD(MPP_CONTROL2); + tmp &= 0x00ffffff; + GT_REG_WRITE(MPP_CONTROL2,tmp); + + /* Program Gpp[22] and Gpp[23] as output + */ + tmp = GTREGREAD(GPP_IO_CONTROL); + tmp |= 0x00C00000; + GT_REG_WRITE(GPP_IO_CONTROL, tmp); + + /* Program Gpp[22] and Gpp[23] as active high + */ + tmp = GTREGREAD(GPP_LEVEL_CONTROL); + tmp &= 0xff3fffff; + GT_REG_WRITE(GPP_LEVEL_CONTROL, tmp); + + switch(col) { + default: + case LED_OFF : + on_pin = 0; + off_pin = ((1 << 23) | (1 << 22)); + break; + case LED_RED : + on_pin = (1 << 23); + off_pin = (1 << 22); + break; + case LED_GREEN : + on_pin = (1 << 22); + off_pin = (1 << 23); + break; + case LED_ORANGE : + on_pin = ((1 << 23) | (1 << 22)); + off_pin = 0; + break; + } + + /* Set output Gpp[22] and Gpp[23] + */ + tmp = GTREGREAD(GPP_VALUE); + tmp |= on_pin; + tmp &= ~off_pin; + GT_REG_WRITE(GPP_VALUE, tmp); +} + +int display_mem_map (void) +{ + int i; + unsigned int base, size, width; +#ifdef CONFIG_PCI + int j; +#endif + + /* SDRAM */ + printf ("SD (DDR) RAM\n"); + for (i = 0; i <= BANK3; i++) { + base = memoryGetBankBaseAddress (i); + size = memoryGetBankSize (i); + if (size != 0) + printf ("BANK%d: base - 0x%08x\tsize - %dM bytes\n", + i, base, size >> 20); + } +#ifdef CONFIG_PCI + /* CPU's PCI windows */ + for (i = 0; i <= PCI_HOST1; i++) { + printf ("\nCPU's PCI %d windows\n", i); + base = pciGetSpaceBase (i, PCI_IO); + size = pciGetSpaceSize (i, PCI_IO); + printf (" IO: base - 0x%08x\tsize - %dM bytes\n", base, + size >> 20); + /* ronen currently only first PCI MEM is used 3 */ + for (j = 0; j <= PCI_REGION0; j++) { + base = pciGetSpaceBase (i, j); + size = pciGetSpaceSize (i, j); + printf ("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n", + j, base, size >> 20); + } + } +#endif /* of CONFIG_PCI */ + + /* Bootrom */ + base = memoryGetDeviceBaseAddress (BOOT_DEVICE); /* Boot */ + size = memoryGetDeviceSize (BOOT_DEVICE); + width = memoryGetDeviceWidth (BOOT_DEVICE) * 8; + printf (" BOOT: base - 0x%08x size - %dM bytes\twidth - %d bits\t- FLASH\n", + base, size >> 20, width); + + return (0); +} + +/* DRAM check routines copied from gw8260 */ + +#if defined (CFG_DRAM_TEST) + +/*********************************************************************/ +/* NAME: move64() - moves a double word (64-bit) */ +/* */ +/* DESCRIPTION: */ +/* this function performs a double word move from the data at */ +/* the source pointer to the location at the destination pointer. */ +/* */ +/* INPUTS: */ +/* unsigned long long *src - pointer to data to move */ +/* */ +/* OUTPUTS: */ +/* unsigned long long *dest - pointer to locate to move data */ +/* */ +/* RETURNS: */ +/* None */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* May cloober fr0. */ +/* */ +/*********************************************************************/ +static void move64 (unsigned long long *src, unsigned long long *dest) +{ + asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ + "stfd 0, 0(4)" /* *dest = fpr0 */ + : : : "fr0"); /* Clobbers fr0 */ + return; +} + + +#if defined (CFG_DRAM_TEST_DATA) + +unsigned long long pattern[] = { + 0xaaaaaaaaaaaaaaaaULL, + 0xccccccccccccccccULL, + 0xf0f0f0f0f0f0f0f0ULL, + 0xff00ff00ff00ff00ULL, + 0xffff0000ffff0000ULL, + 0xffffffff00000000ULL, + 0x00000000ffffffffULL, + 0x0000ffff0000ffffULL, + 0x00ff00ff00ff00ffULL, + 0x0f0f0f0f0f0f0f0fULL, + 0x3333333333333333ULL, + 0x5555555555555555ULL +}; + +/*********************************************************************/ +/* NAME: mem_test_data() - test data lines for shorts and opens */ +/* */ +/* DESCRIPTION: */ +/* Tests data lines for shorts and opens by forcing adjacent data */ +/* to opposite states. Because the data lines could be routed in */ +/* an arbitrary manner the must ensure test patterns ensure that */ +/* every case is tested. By using the following series of binary */ +/* patterns every combination of adjacent bits is test regardless */ +/* of routing. */ +/* */ +/* ...101010101010101010101010 */ +/* ...110011001100110011001100 */ +/* ...111100001111000011110000 */ +/* ...111111110000000011111111 */ +/* */ +/* Carrying this out, gives us six hex patterns as follows: */ +/* */ +/* 0xaaaaaaaaaaaaaaaa */ +/* 0xcccccccccccccccc */ +/* 0xf0f0f0f0f0f0f0f0 */ +/* 0xff00ff00ff00ff00 */ +/* 0xffff0000ffff0000 */ +/* 0xffffffff00000000 */ +/* */ +/* The number test patterns will always be given by: */ +/* */ +/* log(base 2)(number data bits) = log2 (64) = 6 */ +/* */ +/* To test for short and opens to other signals on our boards. we */ +/* simply */ +/* test with the 1's complemnt of the paterns as well. */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* Assumes only one one SDRAM bank */ +/* */ +/*********************************************************************/ +int mem_test_data (void) +{ + unsigned long long *pmem = (unsigned long long *) CFG_MEMTEST_START; + unsigned long long temp64 = 0; + int num_patterns = sizeof (pattern) / sizeof (pattern[0]); + int i; + unsigned int hi, lo; + + for (i = 0; i < num_patterns; i++) { + move64 (&(pattern[i]), pmem); + move64 (pmem, &temp64); + + /* hi = (temp64>>32) & 0xffffffff; */ + /* lo = temp64 & 0xffffffff; */ + /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ + + hi = (pattern[i] >> 32) & 0xffffffff; + lo = pattern[i] & 0xffffffff; + /* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */ + + if (temp64 != pattern[i]) { + printf ("\n Data Test Failed, pattern 0x%08x%08x", + hi, lo); + return 1; + } + } + + return 0; +} +#endif /* CFG_DRAM_TEST_DATA */ + +#if defined (CFG_DRAM_TEST_ADDRESS) +/*********************************************************************/ +/* NAME: mem_test_address() - test address lines */ +/* */ +/* DESCRIPTION: */ +/* This function performs a test to verify that each word im */ +/* memory is uniquly addressable. The test sequence is as follows: */ +/* */ +/* 1) write the address of each word to each word. */ +/* 2) verify that each location equals its address */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern and address */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_test_address (void) +{ + volatile unsigned int *pmem = + (volatile unsigned int *) CFG_MEMTEST_START; + const unsigned int size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 4; + unsigned int i; + + /* write address to each location */ + for (i = 0; i < size; i++) + pmem[i] = i; + + /* verify each loaction */ + for (i = 0; i < size; i++) { + if (pmem[i] != i) { + printf ("\n Address Test Failed at 0x%x", i); + return 1; + } + } + return 0; +} +#endif /* CFG_DRAM_TEST_ADDRESS */ + +#if defined (CFG_DRAM_TEST_WALK) +/*********************************************************************/ +/* NAME: mem_march() - memory march */ +/* */ +/* DESCRIPTION: */ +/* Marches up through memory. At each location verifies rmask if */ +/* read = 1. At each location write wmask if write = 1. Displays */ +/* failing address and pattern. */ +/* */ +/* INPUTS: */ +/* volatile unsigned long long * base - start address of test */ +/* unsigned int size - number of dwords(64-bit) to test */ +/* unsigned long long rmask - read verify mask */ +/* unsigned long long wmask - wrtie verify mask */ +/* short read - verifies rmask if read = 1 */ +/* short write - writes wmask if write = 1 */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern and address */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_march (volatile unsigned long long *base, + unsigned int size, + unsigned long long rmask, + unsigned long long wmask, short read, short write) +{ + unsigned int i; + unsigned long long temp = 0; + unsigned int hitemp, lotemp, himask, lomask; + + for (i = 0; i < size; i++) { + if (read != 0) { + /* temp = base[i]; */ + move64 ((unsigned long long *) &(base[i]), &temp); + if (rmask != temp) { + hitemp = (temp >> 32) & 0xffffffff; + lotemp = temp & 0xffffffff; + himask = (rmask >> 32) & 0xffffffff; + lomask = rmask & 0xffffffff; + + printf ("\n Walking one's test failed: address = 0x%08x," "\n\texpected 0x%08x%08x, found 0x%08x%08x", i << 3, himask, lomask, hitemp, lotemp); + return 1; + } + } + if (write != 0) { + /* base[i] = wmask; */ + move64 (&wmask, (unsigned long long *) &(base[i])); + } + } + return 0; +} +#endif /* CFG_DRAM_TEST_WALK */ + +/*********************************************************************/ +/* NAME: mem_test_walk() - a simple walking ones test */ +/* */ +/* DESCRIPTION: */ +/* Performs a walking ones through entire physical memory. The */ +/* test uses as series of memory marches, mem_march(), to verify */ +/* and write the test patterns to memory. The test sequence is as */ +/* follows: */ +/* 1) march writing 0000...0001 */ +/* 2) march verifying 0000...0001 , writing 0000...0010 */ +/* 3) repeat step 2 shifting masks left 1 bit each time unitl */ +/* the write mask equals 1000...0000 */ +/* 4) march verifying 1000...0000 */ +/* The test fails if any of the memory marches return a failure. */ +/* */ +/* OUTPUTS: */ +/* Displays which pass on the memory test is executing */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_test_walk (void) +{ + unsigned long long mask; + volatile unsigned long long *pmem = + (volatile unsigned long long *) CFG_MEMTEST_START; + const unsigned long size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 8; + + unsigned int i; + + mask = 0x01; + + printf ("Initial Pass"); + mem_march (pmem, size, 0x0, 0x1, 0, 1); + + printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); + printf (" "); + printf (" "); + printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); + + for (i = 0; i < 63; i++) { + printf ("Pass %2d", i + 2); + if (mem_march (pmem, size, mask, mask << 1, 1, 1) != 0) { + /*printf("mask: 0x%x, pass: %d, ", mask, i); */ + return 1; + } + mask = mask << 1; + printf ("\b\b\b\b\b\b\b"); + } + + printf ("Last Pass"); + if (mem_march (pmem, size, 0, mask, 0, 1) != 0) { + /* printf("mask: 0x%x", mask); */ + return 1; + } + printf ("\b\b\b\b\b\b\b\b\b"); + printf (" "); + printf ("\b\b\b\b\b\b\b\b\b"); + + return 0; +} + +/*********************************************************************/ +/* NAME: testdram() - calls any enabled memory tests */ +/* */ +/* DESCRIPTION: */ +/* Runs memory tests if the environment test variables are set to */ +/* 'y'. */ +/* */ +/* INPUTS: */ +/* testdramdata - If set to 'y', data test is run. */ +/* testdramaddress - If set to 'y', address test is run. */ +/* testdramwalk - If set to 'y', walking ones test is run */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int testdram (void) +{ + char *s; + int rundata = 0; + int runaddress = 0; + int runwalk = 0; + +#ifdef CFG_DRAM_TEST_DATA + s = getenv ("testdramdata"); + rundata = (s && (*s == 'y')) ? 1 : 0; +#endif +#ifdef CFG_DRAM_TEST_ADDRESS + s = getenv ("testdramaddress"); + runaddress = (s && (*s == 'y')) ? 1 : 0; +#endif +#ifdef CFG_DRAM_TEST_WALK + s = getenv ("testdramwalk"); + runwalk = (s && (*s == 'y')) ? 1 : 0; +#endif + + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) + printf ("Testing RAM from 0x%08x to 0x%08x ... " + "(don't panic... that will take a moment !!!!)\n", + CFG_MEMTEST_START, CFG_MEMTEST_END); +#ifdef CFG_DRAM_TEST_DATA + if (rundata == 1) { + printf ("Test DATA ... "); + if (mem_test_data () == 1) { + printf ("failed \n"); + return 1; + } else + printf ("ok \n"); + } +#endif +#ifdef CFG_DRAM_TEST_ADDRESS + if (runaddress == 1) { + printf ("Test ADDRESS ... "); + if (mem_test_address () == 1) { + printf ("failed \n"); + return 1; + } else + printf ("ok \n"); + } +#endif +#ifdef CFG_DRAM_TEST_WALK + if (runwalk == 1) { + printf ("Test WALKING ONEs ... "); + if (mem_test_walk () == 1) { + printf ("failed \n"); + return 1; + } else + printf ("ok \n"); + } +#endif + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) + printf ("passed\n"); + return 0; + +} +#endif /* CFG_DRAM_TEST */ + +/* ronen - the below functions are used by the bootm function */ +/* - we map the base register to fbe00000 (same mapping as in the LSP) */ +/* - we turn off the RX gig dmas - to prevent the dma from overunning */ +/* the kernel data areas. */ +/* - we diable and invalidate the icache and dcache. */ +void my_remap_gt_regs_bootm (u32 cur_loc, u32 new_loc) +{ + u32 temp; + + temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); + if ((temp & 0xffff) == new_loc >> 16) + return; + + temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & + 0xffff0000) | (new_loc >> 16); + + out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); + + while ((WORD_SWAP (*((volatile unsigned int *) (NONE_CACHEABLE | + new_loc | + (INTERNAL_SPACE_DECODE))))) + != temp); + +} diff --git a/board/prodrive/p3mx/p3mx.h b/board/prodrive/p3mx/p3mx.h new file mode 100644 index 0000000..1caae6b --- /dev/null +++ b/board/prodrive/p3mx/p3mx.h @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2005 + * + * Roel Loeffen, (C) Copyright 2006 Prodrive B.V. roel.loeffen@prodrive.nl + * + * 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 + */ + +#ifndef __P3MX_H__ +#define __P3MX_H__ + +#define LED_OFF 1 +#define LED_GREEN 2 +#define LED_RED 3 +#define LED_ORANGE 4 + +#endif /* __P3MX_H__ */ diff --git a/board/prodrive/p3mx/pci.c b/board/prodrive/p3mx/pci.c new file mode 100644 index 0000000..137739b --- /dev/null +++ b/board/prodrive/p3mx/pci.c @@ -0,0 +1,1025 @@ +/* + * (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 + * + */ +/* PCI.c - PCI functions */ + + +#include <common.h> +#ifdef CONFIG_PCI +#include <pci.h> + +#ifdef CONFIG_PCI_PNP +void pciauto_config_init(struct pci_controller *hose); +int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar); +#endif + +#include "../../Marvell/include/pci.h" + +#undef DEBUG +#undef IDE_SET_NATIVE_MODE +static unsigned int local_buses[] = { 0, 0 }; + +static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = { + {0, 0, 0, 0, 0, 0, 0, 27, 27, [9 ... PCI_MAX_DEVICES - 1] = 0 }, + {0, 0, 0, 0, 0, 0, 0, 29, 29, [9 ... PCI_MAX_DEVICES - 1] = 0 }, +}; + +#ifdef CONFIG_USE_CPCIDVI +typedef struct { + unsigned int base; + unsigned int init; +} GT_CPCIDVI_ROM_T; + +static GT_CPCIDVI_ROM_T gt_cpcidvi_rom = {0, 0}; +#endif + +#ifdef DEBUG +static const unsigned int pci_bus_list[] = { PCI_0_MODE, PCI_1_MODE }; +static void gt_pci_bus_mode_display (PCI_HOST host) +{ + unsigned int mode; + + + mode = (GTREGREAD (pci_bus_list[host]) & (BIT4 | BIT5)) >> 4; + switch (mode) { + case 0: + printf ("PCI %d bus mode: Conventional PCI\n", host); + break; + case 1: + printf ("PCI %d bus mode: 66 Mhz PCIX\n", host); + break; + case 2: + printf ("PCI %d bus mode: 100 Mhz PCIX\n", host); + break; + case 3: + printf ("PCI %d bus mode: 133 Mhz PCIX\n", host); + break; + default: + printf ("Unknown BUS %d\n", mode); + } +} +#endif + +static const unsigned int pci_p2p_configuration_reg[] = { + PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION +}; + +static const unsigned int pci_configuration_address[] = { + PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS +}; + +static const unsigned int pci_configuration_data[] = { + PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER +}; + +static const unsigned int pci_error_cause_reg[] = { + PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE +}; + +static const unsigned int pci_arbiter_control[] = { + PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL +}; + +static const unsigned int pci_address_space_en[] = { + PCI_0_BASE_ADDR_REG_ENABLE, PCI_1_BASE_ADDR_REG_ENABLE +}; + +static const unsigned int pci_snoop_control_base_0_low[] = { + PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW +}; +static const unsigned int pci_snoop_control_top_0[] = { + PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0 +}; + +static const unsigned int pci_access_control_base_0_low[] = { + PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW +}; +static const unsigned int pci_access_control_top_0[] = { + PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0 +}; + +static const unsigned int pci_scs_bank_size[2][4] = { + {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE, + PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE}, + {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE, + PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE} +}; + +static const unsigned int pci_p2p_configuration[] = { + PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION +}; + + +/******************************************************************** +* pciWriteConfigReg - Write to a PCI configuration register +* - Make sure the GT is configured as a master before writing +* to another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* +* +* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec +* (or any other PCI device spec) +* pciDevNum: The device number needs to be addressed. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +void pciWriteConfigReg (PCI_HOST host, unsigned int regOffset, + unsigned int pciDevNum, unsigned int data) +{ + volatile unsigned int DataForAddrReg; + unsigned int functionNum; + unsigned int busNum = 0; + unsigned int addr; + + if (pciDevNum > 32) /* illegal device Number */ + return; + if (pciDevNum == SELF) { /* configure our configuration space. */ + pciDevNum = + (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & + 0x1f; + busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & + 0xff0000; + } + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xfc; + DataForAddrReg = + (regOffset | pciDevNum | functionNum | busNum) | BIT31; + GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); + GT_REG_READ (pci_configuration_address[host], &addr); + if (addr != DataForAddrReg) + return; + GT_REG_WRITE (pci_configuration_data[host], data); +} + +/******************************************************************** +* pciReadConfigReg - Read from a PCI0 configuration register +* - Make sure the GT is configured as a master before reading +* from another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec) +* pciDevNum: The device number needs to be addressed. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset, + unsigned int pciDevNum) +{ + volatile unsigned int DataForAddrReg; + unsigned int data; + unsigned int functionNum; + unsigned int busNum = 0; + + if (pciDevNum > 32) /* illegal device Number */ + return 0xffffffff; + if (pciDevNum == SELF) { /* configure our configuration space. */ + pciDevNum = + (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & + 0x1f; + busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & + 0xff0000; + } + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xfc; + DataForAddrReg = + (regOffset | pciDevNum | functionNum | busNum) | BIT31; + GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); + GT_REG_READ (pci_configuration_address[host], &data); + if (data != DataForAddrReg) + return 0xffffffff; + GT_REG_READ (pci_configuration_data[host], &data); + return data; +} + +/******************************************************************** +* pciOverBridgeWriteConfigReg - Write to a PCI configuration register where +* the agent is placed on another Bus. For more +* information read P2P in the PCI spec. +* +* Inputs: unsigned int regOffset - The register offset as it apears in the +* GT spec (or any other PCI device spec). +* unsigned int pciDevNum - The device number needs to be addressed. +* unsigned int busNum - On which bus does the Target agent connect +* to. +* unsigned int data - data to be written. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|01| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +* The configuration Address is configure as type-I (bits[1:0] = '01') due to +* PCI spec referring to P2P. +* +*********************************************************************/ +void pciOverBridgeWriteConfigReg (PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum, unsigned int data) +{ + unsigned int DataForReg; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xff; + busNum = busNum << 16; + if (pciDevNum == SELF) { /* This board */ + DataForReg = (regOffset | pciDevNum | functionNum) | BIT0; + } else { + DataForReg = (regOffset | pciDevNum | functionNum | busNum) | + BIT31 | BIT0; + } + GT_REG_WRITE (pci_configuration_address[host], DataForReg); + GT_REG_WRITE (pci_configuration_data[host], data); +} + + +/******************************************************************** +* pciOverBridgeReadConfigReg - Read from a PCIn configuration register where +* the agent target locate on another PCI bus. +* - Make sure the GT is configured as a master +* before reading from another device on the PCI. +* - The function takes care of Big/Little endian +* conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec). (configuration register offset.) +* pciDevNum: The device number needs to be addressed. +* busNum: the Bus number where the agent is place. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|01| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +unsigned int pciOverBridgeReadConfigReg (PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum) +{ + unsigned int DataForReg; + unsigned int data; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xff; + busNum = busNum << 16; + if (pciDevNum == SELF) { /* This board */ + DataForReg = (regOffset | pciDevNum | functionNum) | BIT31; + } else { /* agent on another bus */ + + DataForReg = (regOffset | pciDevNum | functionNum | busNum) | + BIT0 | BIT31; + } + GT_REG_WRITE (pci_configuration_address[host], DataForReg); + GT_REG_READ (pci_configuration_data[host], &data); + return data; +} + + +/******************************************************************** +* pciGetRegOffset - Gets the register offset for this region config. +* +* INPUT: Bus, Region - The bus and region we ask for its base address. +* OUTPUT: N/A +* RETURNS: PCI register base address +*********************************************************************/ +static unsigned int pciGetRegOffset (PCI_HOST host, PCI_REGION region) +{ + switch (host) { + case PCI_HOST0: + switch (region) { + case PCI_IO: + return PCI_0I_O_LOW_DECODE_ADDRESS; + case PCI_REGION0: + return PCI_0MEMORY0_LOW_DECODE_ADDRESS; + case PCI_REGION1: + return PCI_0MEMORY1_LOW_DECODE_ADDRESS; + case PCI_REGION2: + return PCI_0MEMORY2_LOW_DECODE_ADDRESS; + case PCI_REGION3: + return PCI_0MEMORY3_LOW_DECODE_ADDRESS; + } + case PCI_HOST1: + switch (region) { + case PCI_IO: + return PCI_1I_O_LOW_DECODE_ADDRESS; + case PCI_REGION0: + return PCI_1MEMORY0_LOW_DECODE_ADDRESS; + case PCI_REGION1: + return PCI_1MEMORY1_LOW_DECODE_ADDRESS; + case PCI_REGION2: + return PCI_1MEMORY2_LOW_DECODE_ADDRESS; + case PCI_REGION3: + return PCI_1MEMORY3_LOW_DECODE_ADDRESS; + } + } + return PCI_0MEMORY0_LOW_DECODE_ADDRESS; +} + +static unsigned int pciGetRemapOffset (PCI_HOST host, PCI_REGION region) +{ + switch (host) { + case PCI_HOST0: + switch (region) { + case PCI_IO: + return PCI_0I_O_ADDRESS_REMAP; + case PCI_REGION0: + return PCI_0MEMORY0_ADDRESS_REMAP; + case PCI_REGION1: + return PCI_0MEMORY1_ADDRESS_REMAP; + case PCI_REGION2: + return PCI_0MEMORY2_ADDRESS_REMAP; + case PCI_REGION3: + return PCI_0MEMORY3_ADDRESS_REMAP; + } + case PCI_HOST1: + switch (region) { + case PCI_IO: + return PCI_1I_O_ADDRESS_REMAP; + case PCI_REGION0: + return PCI_1MEMORY0_ADDRESS_REMAP; + case PCI_REGION1: + return PCI_1MEMORY1_ADDRESS_REMAP; + case PCI_REGION2: + return PCI_1MEMORY2_ADDRESS_REMAP; + case PCI_REGION3: + return PCI_1MEMORY3_ADDRESS_REMAP; + } + } + return PCI_0MEMORY0_ADDRESS_REMAP; +} + +/******************************************************************** +* pciGetBaseAddress - Gets the base address of a PCI. +* - If the PCI size is 0 then this base address has no meaning!!! +* +* +* INPUT: Bus, Region - The bus and region we ask for its base address. +* OUTPUT: N/A +* RETURNS: PCI base address. +*********************************************************************/ +unsigned int pciGetBaseAddress (PCI_HOST host, PCI_REGION region) +{ + unsigned int regBase; + unsigned int regEnd; + unsigned int regOffset = pciGetRegOffset (host, region); + + GT_REG_READ (regOffset, ®Base); + GT_REG_READ (regOffset + 8, ®End); + + if (regEnd <= regBase) + return 0xffffffff; /* ERROR !!! */ + + regBase = regBase << 16; + return regBase; +} + +bool pciMapSpace (PCI_HOST host, PCI_REGION region, unsigned int remapBase, + unsigned int bankBase, unsigned int bankLength) +{ + unsigned int low = 0xfff; + unsigned int high = 0x0; + unsigned int regOffset = pciGetRegOffset (host, region); + unsigned int remapOffset = pciGetRemapOffset (host, region); + + if (bankLength != 0) { + low = (bankBase >> 16) & 0xffff; + high = ((bankBase + bankLength) >> 16) - 1; + } + + GT_REG_WRITE (regOffset, low | (1 << 24)); /* no swapping */ + GT_REG_WRITE (regOffset + 8, high); + + if (bankLength != 0) { /* must do AFTER writing maps */ + GT_REG_WRITE (remapOffset, remapBase >> 16); /* sorry, 32 bits only. + dont support upper 32 + in this driver */ + } + return true; +} + +unsigned int pciGetSpaceBase (PCI_HOST host, PCI_REGION region) +{ + unsigned int low; + unsigned int regOffset = pciGetRegOffset (host, region); + + GT_REG_READ (regOffset, &low); + return (low & 0xffff) << 16; +} + +unsigned int pciGetSpaceSize (PCI_HOST host, PCI_REGION region) +{ + unsigned int low, high; + unsigned int regOffset = pciGetRegOffset (host, region); + + GT_REG_READ (regOffset, &low); + GT_REG_READ (regOffset + 8, &high); + return ((high & 0xffff) + 1) << 16; +} + + +/* ronen - 7/Dec/03*/ +/******************************************************************** +* gtPciDisable/EnableInternalBAR - This function enable/disable PCI BARS. +* Inputs: one of the PCI BAR +*********************************************************************/ +void gtPciEnableInternalBAR (PCI_HOST host, PCI_INTERNAL_BAR pciBAR) +{ + RESET_REG_BITS (pci_address_space_en[host], BIT0 << pciBAR); +} + +void gtPciDisableInternalBAR (PCI_HOST host, PCI_INTERNAL_BAR pciBAR) +{ + SET_REG_BITS (pci_address_space_en[host], BIT0 << pciBAR); +} + +/******************************************************************** +* pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave. +* +* Inputs: base and size of PCI SCS +*********************************************************************/ +void pciMapMemoryBank (PCI_HOST host, MEMORY_BANK bank, + unsigned int pciDramBase, unsigned int pciDramSize) +{ + /*ronen different function for 3rd bank. */ + unsigned int offset = (bank < 2) ? bank * 8 : 0x100 + (bank - 2) * 8; + + pciDramBase = pciDramBase & 0xfffff000; + pciDramBase = pciDramBase | (pciReadConfigReg (host, + PCI_SCS_0_BASE_ADDRESS + + offset, + SELF) & 0x00000fff); + pciWriteConfigReg (host, PCI_SCS_0_BASE_ADDRESS + offset, SELF, + pciDramBase); + if (pciDramSize == 0) + pciDramSize++; + GT_REG_WRITE (pci_scs_bank_size[host][bank], pciDramSize - 1); + gtPciEnableInternalBAR (host, bank); +} + +/******************************************************************** +* pciSetRegionFeatures - This function modifys one of the 8 regions with +* feature bits given as an input. +* - Be advised to check the spec before modifying them. +* Inputs: PCI_PROTECT_REGION region - one of the eight regions. +* unsigned int features - See file: pci.h there are defintion for those +* region features. +* unsigned int baseAddress - The region base Address. +* unsigned int topAddress - The region top Address. +* Returns: false if one of the parameters is erroneous true otherwise. +*********************************************************************/ +bool pciSetRegionFeatures (PCI_HOST host, PCI_ACCESS_REGIONS region, + unsigned int features, unsigned int baseAddress, + unsigned int regionLength) +{ + unsigned int accessLow; + unsigned int accessHigh; + unsigned int accessTop = baseAddress + regionLength; + + if (regionLength == 0) { /* close the region. */ + pciDisableAccessRegion (host, region); + return true; + } + /* base Address is store is bits [11:0] */ + accessLow = (baseAddress & 0xfff00000) >> 20; + /* All the features are update according to the defines in pci.h (to be on + the safe side we disable bits: [11:0] */ + accessLow = accessLow | (features & 0xfffff000); + /* write to the Low Access Region register */ + GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, + accessLow); + + accessHigh = (accessTop & 0xfff00000) >> 20; + + /* write to the High Access Region register */ + GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, + accessHigh - 1); + return true; +} + +/******************************************************************** +* pciDisableAccessRegion - Disable The given Region by writing MAX size +* to its low Address and MIN size to its high Address. +* +* Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled. +* Returns: N/A. +*********************************************************************/ +void pciDisableAccessRegion (PCI_HOST host, PCI_ACCESS_REGIONS region) +{ + /* writing back the registers default values. */ + GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, + 0x01001fff); + GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, 0); +} + +/******************************************************************** +* pciArbiterEnable - Enables PCI-0`s Arbitration mechanism. +* +* Inputs: N/A +* Returns: true. +*********************************************************************/ +bool pciArbiterEnable (PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + GT_REG_WRITE (pci_arbiter_control[host], regData | BIT31); + return true; +} + +/******************************************************************** +* pciArbiterDisable - Disable PCI-0`s Arbitration mechanism. +* +* Inputs: N/A +* Returns: true +*********************************************************************/ +bool pciArbiterDisable (PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + GT_REG_WRITE (pci_arbiter_control[host], regData & 0x7fffffff); + return true; +} + +/******************************************************************** +* pciSetArbiterAgentsPriority - Priority setup for the PCI agents (Hi or Low) +* +* Inputs: PCI_AGENT_PRIO internalAgent - priotity for internal agent. +* PCI_AGENT_PRIO externalAgent0 - priotity for external#0 agent. +* PCI_AGENT_PRIO externalAgent1 - priotity for external#1 agent. +* PCI_AGENT_PRIO externalAgent2 - priotity for external#2 agent. +* PCI_AGENT_PRIO externalAgent3 - priotity for external#3 agent. +* PCI_AGENT_PRIO externalAgent4 - priotity for external#4 agent. +* PCI_AGENT_PRIO externalAgent5 - priotity for external#5 agent. +* Returns: true +*********************************************************************/ +bool pciSetArbiterAgentsPriority (PCI_HOST host, PCI_AGENT_PRIO internalAgent, + PCI_AGENT_PRIO externalAgent0, + PCI_AGENT_PRIO externalAgent1, + PCI_AGENT_PRIO externalAgent2, + PCI_AGENT_PRIO externalAgent3, + PCI_AGENT_PRIO externalAgent4, + PCI_AGENT_PRIO externalAgent5) +{ + unsigned int regData; + unsigned int writeData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + writeData = (internalAgent << 7) + (externalAgent0 << 8) + + (externalAgent1 << 9) + (externalAgent2 << 10) + + (externalAgent3 << 11) + (externalAgent4 << 12) + + (externalAgent5 << 13); + regData = (regData & 0xffffc07f) | writeData; + GT_REG_WRITE (pci_arbiter_control[host], regData & regData); + return true; +} + +/******************************************************************** +* pciParkingDisable - Park on last option disable, with this function you can +* disable the park on last mechanism for each agent. +* disabling this option for all agents results parking +* on the internal master. +* +* Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent. +* PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent. +* PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent. +* PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent. +* PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent. +* PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent. +* PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent. +* Returns: true +*********************************************************************/ +bool pciParkingDisable (PCI_HOST host, PCI_AGENT_PARK internalAgent, + PCI_AGENT_PARK externalAgent0, + PCI_AGENT_PARK externalAgent1, + PCI_AGENT_PARK externalAgent2, + PCI_AGENT_PARK externalAgent3, + PCI_AGENT_PARK externalAgent4, + PCI_AGENT_PARK externalAgent5) +{ + unsigned int regData; + unsigned int writeData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + writeData = (internalAgent << 14) + (externalAgent0 << 15) + + (externalAgent1 << 16) + (externalAgent2 << 17) + + (externalAgent3 << 18) + (externalAgent4 << 19) + + (externalAgent5 << 20); + regData = (regData & ~(0x7f << 14)) | writeData; + GT_REG_WRITE (pci_arbiter_control[host], regData); + return true; +} + +/******************************************************************** +* pciEnableBrokenAgentDetection - A master is said to be broken if it fails to +* respond to grant assertion within a window specified in +* the input value: 'brokenValue'. +* +* Inputs: unsigned char brokenValue - A value which limits the Master to hold the +* grant without asserting frame. +* Returns: Error for illegal broken value otherwise true. +*********************************************************************/ +bool pciEnableBrokenAgentDetection (PCI_HOST host, unsigned char brokenValue) +{ + unsigned int data; + unsigned int regData; + + if (brokenValue > 0xf) + return false; /* brokenValue must be 4 bit */ + data = brokenValue << 3; + GT_REG_READ (pci_arbiter_control[host], ®Data); + regData = (regData & 0xffffff87) | data; + GT_REG_WRITE (pci_arbiter_control[host], regData | BIT1); + return true; +} + +/******************************************************************** +* pciDisableBrokenAgentDetection - This function disable the Broken agent +* Detection mechanism. +* NOTE: This operation may cause a dead lock on the +* pci0 arbitration. +* +* Inputs: N/A +* Returns: true. +*********************************************************************/ +bool pciDisableBrokenAgentDetection (PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ (pci_arbiter_control[host], ®Data); + regData = regData & 0xfffffffd; + GT_REG_WRITE (pci_arbiter_control[host], regData); + return true; +} + +/******************************************************************** +* pciP2PConfig - This function set the PCI_n P2P configurate. +* For more information on the P2P read PCI spec. +* +* Inputs: unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower +* Boundry. +* unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper +* Boundry. +* unsigned int busNum - The CPI bus number to which the PCI interface +* is connected. +* unsigned int devNum - The PCI interface's device number. +* +* Returns: true. +*********************************************************************/ +bool pciP2PConfig (PCI_HOST host, unsigned int SecondBusLow, + unsigned int SecondBusHigh, + unsigned int busNum, unsigned int devNum) +{ + unsigned int regData; + + regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) | + ((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24); + GT_REG_WRITE (pci_p2p_configuration[host], regData); + return true; +} + +/******************************************************************** +* pciSetRegionSnoopMode - This function modifys one of the 4 regions which +* supports Cache Coherency in the PCI_n interface. +* Inputs: region - One of the four regions. +* snoopType - There is four optional Types: +* 1. No Snoop. +* 2. Snoop to WT region. +* 3. Snoop to WB region. +* 4. Snoop & Invalidate to WB region. +* baseAddress - Base Address of this region. +* regionLength - Region length. +* Returns: false if one of the parameters is wrong otherwise return true. +*********************************************************************/ +bool pciSetRegionSnoopMode (PCI_HOST host, PCI_SNOOP_REGION region, + PCI_SNOOP_TYPE snoopType, + unsigned int baseAddress, + unsigned int regionLength) +{ + unsigned int snoopXbaseAddress; + unsigned int snoopXtopAddress; + unsigned int data; + unsigned int snoopHigh = baseAddress + regionLength; + + if ((region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB)) + return false; + snoopXbaseAddress = + pci_snoop_control_base_0_low[host] + 0x10 * region; + snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region; + if (regionLength == 0) { /* closing the region */ + GT_REG_WRITE (snoopXbaseAddress, 0x0000ffff); + GT_REG_WRITE (snoopXtopAddress, 0); + return true; + } + baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */ + data = (baseAddress >> 20) | snoopType << 12; + GT_REG_WRITE (snoopXbaseAddress, data); + snoopHigh = (snoopHigh & 0xfff00000) >> 20; + GT_REG_WRITE (snoopXtopAddress, snoopHigh - 1); + return true; +} + +static int gt_read_config_dword (struct pci_controller *hose, + pci_dev_t dev, int offset, u32 * value) +{ + int bus = PCI_BUS (dev); + + if ((bus == local_buses[0]) || (bus == local_buses[1])) { + *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset, + PCI_DEV (dev)); + } else { + *value = pciOverBridgeReadConfigReg ((PCI_HOST) hose-> + cfg_addr, offset, + PCI_DEV (dev), bus); + } + + return 0; +} + +static int gt_write_config_dword (struct pci_controller *hose, + pci_dev_t dev, int offset, u32 value) +{ + int bus = PCI_BUS (dev); + + if ((bus == local_buses[0]) || (bus == local_buses[1])) { + pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset, + PCI_DEV (dev), value); + } else { + pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr, + offset, PCI_DEV (dev), bus, + value); + } + return 0; +} + + +static void gt_setup_ide (struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + static const int ide_bar[] = { 8, 4, 8, 4, 0, 0 }; + u32 bar_response, bar_value; + int bar; + + for (bar = 0; bar < 6; bar++) { + /*ronen different function for 3rd bank. */ + unsigned int offset = + (bar < 2) ? bar * 8 : 0x100 + (bar - 2) * 8; + + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0 + offset, + 0x0); + pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0 + offset, + &bar_response); + + pciauto_region_allocate (bar_response & + PCI_BASE_ADDRESS_SPACE_IO ? hose-> + pci_io : hose->pci_mem, ide_bar[bar], + &bar_value); + + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0 + bar * 4, + bar_value); + } +} + +#ifdef CONFIG_USE_CPCIDVI +static void gt_setup_cpcidvi (struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + u32 bar_value, pci_response; + + pci_hose_read_config_dword (hose, dev, PCI_COMMAND, &pci_response); + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff); + pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pci_response); + pciauto_region_allocate (hose->pci_mem, 0x01000000, &bar_value); + pci_hose_write_config_dword (hose, dev, PCI_BASE_ADDRESS_0, (bar_value & 0xffffff00)); + pci_hose_write_config_dword (hose, dev, PCI_ROM_ADDRESS, 0x0); + pciauto_region_allocate (hose->pci_mem, 0x40000, &bar_value); + pci_hose_write_config_dword (hose, dev, PCI_ROM_ADDRESS, (bar_value & 0xffffff00) | 0x01); + gt_cpcidvi_rom.base = bar_value & 0xffffff00; + gt_cpcidvi_rom.init = 1; +} + +unsigned char gt_cpcidvi_in8(unsigned int offset) +{ + unsigned char data; + + if (gt_cpcidvi_rom.init == 0) { + return(0); + } + data = in8((offset & 0x04) + 0x3f000 + gt_cpcidvi_rom.base); + return(data); +} + +void gt_cpcidvi_out8(unsigned int offset, unsigned char data) +{ + unsigned int off; + + if (gt_cpcidvi_rom.init == 0) { + return; + } + off = data; + off = ((off << 3) & 0x7f8) + (offset & 0x4) + 0x3e000 + gt_cpcidvi_rom.base; + in8(off); + return; +} +#endif + +/* TODO BJW: Change this for DB64360. This was pulled from the EV64260 */ +/* and is curently not called *. */ +#if 0 +static void gt_fixup_irq (struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char pin, irq; + + pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &pin); + + if (pin == 1) { /* only allow INT A */ + irq = pci_irq_swizzle[(PCI_HOST) hose-> + cfg_addr][PCI_DEV (dev)]; + if (irq) + pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); + } +} +#endif + +struct pci_config_table gt_config_table[] = { +#ifdef CONFIG_USE_CPCIDVI + {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69030, PCI_CLASS_DISPLAY_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_cpcidvi}, +#endif + {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide}, + {} +}; + +struct pci_controller pci0_hose = { +/* fixup_irq: gt_fixup_irq, */ + config_table:gt_config_table, +}; + +struct pci_controller pci1_hose = { +/* fixup_irq: gt_fixup_irq, */ + config_table:gt_config_table, +}; + +void pci_init_board (void) +{ + unsigned int command; +#ifdef CONFIG_PCI_PNP + unsigned int bar; +#endif +#ifdef DEBUG + gt_pci_bus_mode_display (PCI_HOST0); +#endif +#ifdef CONFIG_USE_CPCIDVI + gt_cpcidvi_rom.init = 0; + gt_cpcidvi_rom.base = 0; +#endif + + pci0_hose.config_table = gt_config_table; + pci1_hose.config_table = gt_config_table; + +#ifdef CONFIG_USE_CPCIDVI + gt_config_table[0].config_device = gt_setup_cpcidvi; +#endif + gt_config_table[1].config_device = gt_setup_ide; + + pci0_hose.first_busno = 0; + pci0_hose.last_busno = 0xff; + local_buses[0] = pci0_hose.first_busno; + + /* PCI memory space */ + pci_set_region (pci0_hose.regions + 0, + CFG_PCI0_0_MEM_SPACE, + CFG_PCI0_0_MEM_SPACE, + CFG_PCI0_MEM_SIZE, PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region (pci0_hose.regions + 1, + CFG_PCI0_IO_SPACE_PCI, + CFG_PCI0_IO_SPACE, CFG_PCI0_IO_SIZE, PCI_REGION_IO); + + pci_set_ops (&pci0_hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + pci0_hose.region_count = 2; + + pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0; + + pci_register_hose (&pci0_hose); + pciArbiterDisable(PCI_HOST0); /* on PMC modules no arbiter is used */ + pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1); + command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MASTER; + pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); + command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); + +#ifdef CONFIG_PCI_PNP + pciauto_config_init(&pci0_hose); + pciauto_region_allocate(pci0_hose.pci_io, 0x400, &bar); +#endif +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + pci0_hose.last_busno = pci_hose_scan_bus (&pci0_hose, pci0_hose.first_busno); + +#ifdef DEBUG + gt_pci_bus_mode_display (PCI_HOST1); +#endif + pci1_hose.first_busno = pci0_hose.last_busno + 1; + pci1_hose.last_busno = 0xff; + pci1_hose.current_busno = pci1_hose.first_busno; + local_buses[1] = pci1_hose.first_busno; + + /* PCI memory space */ + pci_set_region (pci1_hose.regions + 0, + CFG_PCI1_0_MEM_SPACE, + CFG_PCI1_0_MEM_SPACE, + CFG_PCI1_MEM_SIZE, PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region (pci1_hose.regions + 1, + CFG_PCI1_IO_SPACE_PCI, + CFG_PCI1_IO_SPACE, CFG_PCI1_IO_SIZE, PCI_REGION_IO); + + pci_set_ops (&pci1_hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + + pci1_hose.region_count = 2; + + pci1_hose.cfg_addr = (unsigned int *) PCI_HOST1; + + pci_register_hose (&pci1_hose); + + pciArbiterEnable (PCI_HOST1); + pciParkingDisable (PCI_HOST1, 1, 1, 1, 1, 1, 1, 1); + + command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MASTER; + pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); + +#ifdef CONFIG_PCI_PNP + pciauto_config_init(&pci1_hose); + pciauto_region_allocate(pci1_hose.pci_io, 0x400, &bar); +#endif + pci1_hose.last_busno = pci_hose_scan_bus (&pci1_hose, pci1_hose.first_busno); + + command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); + +} +#endif /* of CONFIG_PCI */ diff --git a/board/prodrive/p3mx/ppc_error_no.h b/board/prodrive/p3mx/ppc_error_no.h new file mode 100644 index 0000000..53687c8 --- /dev/null +++ b/board/prodrive/p3mx/ppc_error_no.h @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.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 + */ + +/* + * BK Id: SCCS/s.errno.h 1.9 06/05/01 21:45:21 paulus + */ +#ifndef _MV_PPC_ERRNO_H +#define _MV_PPC_ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ +#define EDEADLOCK 58 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ + +#define _LAST_ERRNO 515 + +#endif diff --git a/board/prodrive/p3mx/sdram_init.c b/board/prodrive/p3mx/sdram_init.c new file mode 100644 index 0000000..0464860 --- /dev/null +++ b/board/prodrive/p3mx/sdram_init.c @@ -0,0 +1,434 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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 + */ + +/************************************************************************* + * adaption for the Marvell DB64460 Board + * Ingo Assmus (ingo.assmus@keymile.com) + *************************************************************************/ + +/* sdram_init.c - automatic memory sizing */ + +#include <common.h> +#include <74xx_7xx.h> +#include "../../Marvell/include/memory.h" +#include "../../Marvell/include/pci.h" +#include "../../Marvell/include/mv_gen_reg.h" +#include <net.h> + +#include "eth.h" +#include "mpsc.h" +#include "../../Marvell/common/i2c.h" +#include "64460.h" +#include "mv_regs.h" + +DECLARE_GLOBAL_DATA_PTR; + +#undef DEBUG +#define MAP_PCI + +#ifdef DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +int set_dfcdlInit (void); /* setup delay line of Mv64460 */ +int mvDmaIsChannelActive (int); +int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong); +int mvDmaTransfer (int, ulong, ulong, ulong, ulong); + +#define D_CACHE_FLUSH_LINE(addr, offset) \ + { \ + __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ + } + +int memory_map_bank (unsigned int bankNo, + unsigned int bankBase, unsigned int bankLength) +{ +#if defined (MAP_PCI) && defined (CONFIG_PCI) + PCI_HOST host; +#endif + +#ifdef DEBUG + if (bankLength > 0) { + printf ("mapping bank %d at %08x - %08x\n", + bankNo, bankBase, bankBase + bankLength - 1); + } else { + printf ("unmapping bank %d\n", bankNo); + } +#endif + + memoryMapBank (bankNo, bankBase, bankLength); + +#if defined (MAP_PCI) && defined (CONFIG_PCI) + for (host = PCI_HOST0; host <= PCI_HOST1; host++) { + const int features = + PREFETCH_ENABLE | + DELAYED_READ_ENABLE | + AGGRESSIVE_PREFETCH | + READ_LINE_AGGRESSIVE_PREFETCH | + READ_MULTI_AGGRESSIVE_PREFETCH | + MAX_BURST_4 | PCI_NO_SWAP; + + pciMapMemoryBank (host, bankNo, bankBase, bankLength); + + pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase, + bankLength); + + pciSetRegionFeatures (host, bankNo, features, bankBase, + bankLength); + } +#endif + + return 0; +} + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ +long int dram_size (long int *base, long int maxsize) +{ + volatile long int *addr, *b = base; + long int cnt, val, save1, save2; + +#define STARTVAL (1<<20) /* start test at 1M */ + for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long); + cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + save1 = *addr; /* save contents of addr */ + save2 = *b; /* save contents of base */ + + *addr = cnt; /* write cnt to addr */ + *b = 0; /* put null at base */ + + /* check at base address */ + if ((*b) != 0) { + *addr = save1; /* restore *addr */ + *b = save2; /* restore *b */ + return (0); + } + val = *addr; /* read *addr */ + val = *addr; /* read *addr */ + + *addr = save1; + *b = save2; + + if (val != cnt) { + DP (printf + ("Found %08x at Address %08x (failure)\n", + (unsigned int) val, (unsigned int) addr)); + /* fix boundary condition.. STARTVAL means zero */ + if (cnt == STARTVAL / sizeof (long)) + cnt = 0; + return (cnt * sizeof (long)); + } + } + + return maxsize; +} + +#define SDRAM_NORMAL 0x0 +#define SDRAM_PRECHARGE_ALL 0x1 +#define SDRAM_REFRESH_ALL 0x2 +#define SDRAM_MODE_REG_SETUP 0x3 +#define SDRAM_XTEN_MODE_REG_SETUP 0x4 +#define SDRAM_NOP 0x5 +#define SDRAM_SELF_REFRESH 0x7 + +long int initdram (int board_type) +{ + int tmp; + int start; + ulong size; + ulong memSpaceAttr; + ulong dest; + + /* first disable all banks */ + memory_map_bank(0, 0, 0); + memory_map_bank(1, 0, 0); + memory_map_bank(2, 0, 0); + memory_map_bank(3, 0, 0); + + /* calibrate delay lines */ + set_dfcdlInit(); + + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* SDRAM controller configuration */ +#ifdef CONFIG_MV64460_ECC + GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58201400); /* 0x1400 */ +#else + GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58200400); /* 0x1400 */ +#endif + GT_REG_WRITE(MV64460_D_UNIT_CONTROL_LOW, 0xC3000540); /* 0x1404 */ + GT_REG_WRITE(MV64460_D_UNIT_CONTROL_HIGH, 0x0300F777); /* 0x1424 */ + GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_LOW, 0x01712220); /* 0x1408 */ + GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_HIGH, 0x0000005D); /* 0x140C */ + GT_REG_WRITE(MV64460_SDRAM_ADDR_CONTROL, 0x00000012); /* 0x1410 */ + GT_REG_WRITE(MV64460_SDRAM_OPEN_PAGES_CONTROL, 0x00000001); /* 0x1414 */ + + /* SDRAM drive strength */ + GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000000); /* 0x14C0 */ + GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000008); /* 0x14C0 */ + GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */ + GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */ + + /* setup SDRAM device registers */ + + /* precharge all */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* enable DLL */ + GT_REG_WRITE(MV64460_EXTENDED_DRAM_MODE, 0x00000000); /* 0x1420 */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_XTEN_MODE_REG_SETUP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* reset DLL */ + GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000132); /* 0x141C */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* precharge all */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* wait for 2 auto refresh commands */ + udelay(20); + + /* un-reset DLL */ + GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000032); /* 0x141C */ + GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */ + do { + tmp = GTREGREAD(MV64460_SDRAM_OPERATION); + } while(tmp != 0x0); + + /* wait 200 cycles */ + udelay(2); /* FIXME make this dynamic for the system clock */ + + /* SDRAM init done */ + memory_map_bank(0, CFG_SDRAM_BASE, (256 << 20)); +#ifdef CFG_SDRAM1_BASE + memory_map_bank(1, CFG_SDRAM1_BASE, (256 << 20)); +#endif + + /* DUNIT_MMASK: enable SnoopHitEn bit to avoid errata CPU-#4 + */ + tmp = GTREGREAD(MV64460_D_UNIT_MMASK); /* 0x14B0 */ + GT_REG_WRITE(MV64460_D_UNIT_MMASK, tmp | 0x2); + + start = (0 << 20); +#ifdef CONFIG_P3M750 + size = (512 << 20); +#elif defined (CONFIG_P3M7448) + size = (128 << 20); +#endif + +#ifdef CONFIG_MV64460_ECC + memSpaceAttr = ((~(BIT0 << 0)) & 0xf) << 8; + mvDmaSetMemorySpace (0, 0, memSpaceAttr, start, size); + for (dest = start; dest < start + size; dest += _8M) { + mvDmaTransfer (0, start, dest, _8M, + BIT8 /*DMA_DTL_128BYTES */ | + BIT3 /*DMA_HOLD_SOURCE_ADDR */ | + BIT11 /*DMA_BLOCK_TRANSFER_MODE */ ); + while (mvDmaIsChannelActive (0)); + } +#endif + + return (size); +} + +void board_add_ram_info(int use_default) +{ + u32 val; + + puts(" (CL="); + switch ((GTREGREAD(MV64460_SDRAM_MODE) >> 4) & 0x7) { + case 0x2: + puts("2"); + break; + case 0x3: + puts("3"); + break; + case 0x5: + puts("1.5"); + break; + case 0x6: + puts("2.5"); + break; + } + + val = GTREGREAD(MV64460_SDRAM_CONFIG); + + puts(", ECC "); + if (val & 0x00001000) + puts("enabled)"); + else + puts("not enabled)"); +} + +/* + * mvDmaIsChannelActive - Check if IDMA channel is active + * + * channel = IDMA channel number from 0 to 7 + */ +int mvDmaIsChannelActive (int channel) +{ + ulong data; + + data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel); + if (data & BIT14) /* activity status */ + return 1; + + return 0; +} + +/* + * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding + * map. + * + * memSpace = IDMA memory window number from 0 to 7 + * trg_if = Target interface: + * 0x0 DRAM + * 0x1 Device Bus + * 0x2 Integrated SDRAM (or CPU bus 60x only) + * 0x3 PCI0 + * 0x4 PCI1 + * attr = IDMA attributes (see MV datasheet) + * base_addr = Sets up memory window for transfers + * + */ +int mvDmaSetMemorySpace (ulong memSpace, + ulong trg_if, + ulong attr, ulong base_addr, ulong size) +{ + ulong temp; + + /* The base address must be aligned to the size. */ + if (base_addr % size != 0) + return 0; + + if (size >= 0x10000) { /* 64K */ + size &= 0xffff0000; + base_addr = (base_addr & 0xffff0000); + /* Set the new attributes */ + GT_REG_WRITE (MV64460_DMA_BASE_ADDR_REG0 + memSpace * 8, + (base_addr | trg_if | attr)); + GT_REG_WRITE ((MV64460_DMA_SIZE_REG0 + memSpace * 8), + (size - 1) & 0xffff0000); + temp = GTREGREAD (MV64460_DMA_BASE_ADDR_ENABLE_REG); + GT_REG_WRITE (DMA_BASE_ADDR_ENABLE_REG, + (temp & ~(BIT0 << memSpace))); + return 1; + } + + return 0; +} + +/* + * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4 + * DMA channels. + * + * channel = IDMA channel number from 0 to 3 + * destAddr = Destination address + * sourceAddr = Source address + * size = Size in bytes + * command = See MV datasheet + * + */ +int mvDmaTransfer (int channel, ulong sourceAddr, + ulong destAddr, ulong size, ulong command) +{ + ulong engOffReg = 0; /* Engine Offset Register */ + + if (size > 0xffff) + command = command | BIT31; /* DMA_16M_DESCRIPTOR_MODE */ + command = command | ((command >> 6) & 0x7); + engOffReg = channel * 4; + GT_REG_WRITE (MV64460_DMA_CHANNEL0_BYTE_COUNT + engOffReg, size); + GT_REG_WRITE (MV64460_DMA_CHANNEL0_SOURCE_ADDR + engOffReg, sourceAddr); + GT_REG_WRITE (MV64460_DMA_CHANNEL0_DESTINATION_ADDR + engOffReg, destAddr); + command = command | + BIT12 | /* DMA_CHANNEL_ENABLE */ + BIT9; /* DMA_NON_CHAIN_MODE */ + /* Activate DMA channel By writting to mvDmaControlRegister */ + GT_REG_WRITE (MV64460_DMA_CHANNEL0_CONTROL + engOffReg, command); + return 1; +} + +/**************************************************************************************** + * SDRAM INIT * + * This procedure detect all Sdram types: 64, 128, 256, 512 Mbit, 1Gbit and 2Gb * + * This procedure fits only the Atlantis * + * * + ***************************************************************************************/ + +/**************************************************************************************** + * DFCDL initialize MV643xx Design Considerations * + * * + ***************************************************************************************/ +int set_dfcdlInit (void) +{ + int i; + + /* Values from MV64460 User Manual */ + unsigned int dfcdl_tbl[] = { 0x00000000, 0x00000001, 0x00000042, 0x00000083, + 0x000000c4, 0x00000105, 0x00000146, 0x00000187, + 0x000001c8, 0x00000209, 0x0000024a, 0x0000028b, + 0x000002cc, 0x0000030d, 0x0000034e, 0x0000038f, + 0x000003d0, 0x00000411, 0x00000452, 0x00000493, + 0x000004d4, 0x00000515, 0x00000556, 0x00000597, + 0x000005d8, 0x00000619, 0x0000065a, 0x0000069b, + 0x000006dc, 0x0000071d, 0x0000075e, 0x0000079f, + 0x000007e0, 0x00000821, 0x00000862, 0x000008a3, + 0x000008e4, 0x00000925, 0x00000966, 0x000009a7, + 0x000009e8, 0x00000a29, 0x00000a6a, 0x00000aab, + 0x00000aec, 0x00000b2d, 0x00000b6e, 0x00000baf, + 0x00000bf0, 0x00000c31, 0x00000c72, 0x00000cb3, + 0x00000cf4, 0x00000d35, 0x00000d76, 0x00000db7, + 0x00000df8, 0x00000e39, 0x00000e7a, 0x00000ebb, + 0x00000efc, 0x00000f3d, 0x00000f7e, 0x00000fbf }; + + for (i = 0; i < 64; i++) + GT_REG_WRITE (SRAM_DATA0, dfcdl_tbl[i]); + GT_REG_WRITE (DFCDL_CONFIG0, 0x00300000); /* enable dynamic delay line updating */ + + return (0); +} diff --git a/board/prodrive/p3mx/serial.c b/board/prodrive/p3mx/serial.c new file mode 100644 index 0000000..ba32ac1 --- /dev/null +++ b/board/prodrive/p3mx/serial.c @@ -0,0 +1,107 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + * + * modified for cpci750 board by + * Reinhard Arlt <reinhard.arlt@esd-electronics.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 + */ + +/* + * serial.c - serial support for esd cpci750 board + */ + +/* supports the MPSC */ + +#include <common.h> +#include <command.h> +#include "../../Marvell/include/memory.h" +#include "serial.h" + +#include "mpsc.h" + +DECLARE_GLOBAL_DATA_PTR; + +int serial_init (void) +{ + mpsc_init (gd->baudrate); + + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + mpsc_putchar ('\r'); + + mpsc_putchar (c); +} + +int serial_getc (void) +{ + return mpsc_getchar (); +} + +int serial_tstc (void) +{ + return mpsc_test_char (); +} + +void serial_setbrg (void) +{ + galbrg_set_baudrate (CONFIG_MPSC_PORT, gd->baudrate); +} + + +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/prodrive/p3mx/serial.h b/board/prodrive/p3mx/serial.h new file mode 100644 index 0000000..c7fc8c1 --- /dev/null +++ b/board/prodrive/p3mx/serial.h @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.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 + */ + +/* serial.h - mostly useful for DUART serial_init in serial.c */ + +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +#if 0 + +#define B230400 1 +#define B115200 2 +#define B57600 4 +#define B38400 82 +#define B19200 163 +#define B9600 24 +#define B4800 651 +#define B2400 1302 +#define B1200 2604 +#define B600 5208 +#define B300 10417 +#define B150 20833 +#define B110 28409 +#define BDEFAULT B115200 + + /* this stuff is important to initialize + the DUART channels */ + +#define Scale 0x01L /* distance between port addresses */ +#define COM1 0x000003f8 /* Keyboard */ +#define COM2 0x000002f8 /* Host */ + + +/* Port Definitions relative to base COM port addresses */ +#define DataIn (0x00*Scale) /* data input port */ +#define DataOut (0x00*Scale) /* data output port */ +#define BaudLsb (0x00*Scale) /* baud rate divisor least significant byte */ +#define BaudMsb (0x01*Scale) /* baud rate divisor most significant byte */ +#define Ier (0x01*Scale) /* interrupt enable register */ +#define Iir (0x02*Scale) /* interrupt identification register */ +#define Lcr (0x03*Scale) /* line control register */ +#define Mcr (0x04*Scale) /* modem control register */ +#define Lsr (0x05*Scale) /* line status register */ +#define Msr (0x06*Scale) /* modem status register */ + +/* Bit Definitions for above ports */ +#define LcrDlab 0x80 /* b7: enable baud rate divisor registers */ +#define LcrDflt 0x03 /* b6-0: no parity, 1 stop, 8 data */ + +#define McrRts 0x02 /* b1: request to send (I am ready to xmit) */ +#define McrDtr 0x01 /* b0: data terminal ready (I am alive ready to rcv) */ +#define McrDflt (McrRts|McrDtr) + +#define LsrTxD 0x6000 /* b5: transmit holding register empty (i.e. xmit OK!)*/ + /* b6: transmitter empty */ +#define LsrRxD 0x0100 /* b0: received data ready (i.e. got a byte!) */ + +#define MsrRi 0x0040 /* b6: ring indicator (other guy is ready to rcv) */ +#define MsrDsr 0x0020 /* b5: data set ready (other guy is alive ready to rcv */ +#define MsrCts 0x0010 /* b4: clear to send (other guy is ready to rcv) */ + +#define IerRda 0xf /* b0: Enable received data available interrupt */ + +#endif + +#endif /* __SERIAL_H__ */ diff --git a/board/prodrive/p3mx/u-boot.lds b/board/prodrive/p3mx/u-boot.lds new file mode 100644 index 0000000..d89eb6c --- /dev/null +++ b/board/prodrive/p3mx/u-boot.lds @@ -0,0 +1,138 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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 + */ + +/* + * u-boot.lds - linker script for U-Boot on the Galileo Eval Board. + */ + +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 : + { + cpu/74xx_7xx/start.o (.text) + +/* store the environment in a seperate sector in the boot flash */ +/* . = env_offset; */ +/* common/environment.o(.text) */ + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .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/board/prodrive/pdnb3/flash.c b/board/prodrive/pdnb3/flash.c index d0e5fe7..518ea9c 100644 --- a/board/prodrive/pdnb3/flash.c +++ b/board/prodrive/pdnb3/flash.c @@ -24,6 +24,8 @@ #include <common.h> #include <asm/arch/ixp425.h> +#if !defined(CFG_FLASH_CFI_DRIVER) + /* * include common flash code (for esd boards) */ @@ -83,3 +85,5 @@ unsigned long flash_init(void) return size; } + +#endif /* CFG_FLASH_CFI_DRIVER */ diff --git a/board/prodrive/pdnb3/nand.c b/board/prodrive/pdnb3/nand.c index 1931d64..92f9c01 100644 --- a/board/prodrive/pdnb3/nand.c +++ b/board/prodrive/pdnb3/nand.c @@ -148,7 +148,7 @@ static int pdnb3_nand_dev_ready(struct mtd_info *mtd) return 1; } -void board_nand_init(struct nand_chip *nand) +int board_nand_init(struct nand_chip *nand) { pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CFG_NAND_BASE; @@ -167,5 +167,6 @@ void board_nand_init(struct nand_chip *nand) nand->read_buf = pdnb3_nand_read_buf; nand->verify_buf = pdnb3_nand_verify_buf; nand->dev_ready = pdnb3_nand_dev_ready; + return 0; } #endif diff --git a/board/sandburst/common/ppc440gx_i2c.c b/board/sandburst/common/ppc440gx_i2c.c index 859dd7a..1e3dffb 100644 --- a/board/sandburst/common/ppc440gx_i2c.c +++ b/board/sandburst/common/ppc440gx_i2c.c @@ -27,13 +27,8 @@ */ #include <common.h> #include <ppc4xx.h> -#if defined(CONFIG_440) -# include <440_i2c.h> -#else -# include <405gp_i2c.h> -#endif +#include <4xx_i2c.h> #include <i2c.h> -#include <440_i2c.h> #include <command.h> #include "ppc440gx_i2c.h" diff --git a/board/sandburst/common/ppc440gx_i2c.h b/board/sandburst/common/ppc440gx_i2c.h index cd4fc86..10000f5 100644 --- a/board/sandburst/common/ppc440gx_i2c.h +++ b/board/sandburst/common/ppc440gx_i2c.h @@ -27,11 +27,7 @@ */ #include <common.h> #include <ppc4xx.h> -#if defined(CONFIG_440) -# include <440_i2c.h> -#else -# include <405gp_i2c.h> -#endif +#include <4xx_i2c.h> #include <i2c.h> #ifdef CONFIG_HARD_I2C diff --git a/board/sbc8349/Makefile b/board/sbc8349/Makefile new file mode 100644 index 0000000..02cf569 --- /dev/null +++ b/board/sbc8349/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (c) 2006 Wind River 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o pci.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/sbc8349/config.mk b/board/sbc8349/config.mk new file mode 100644 index 0000000..05fa5a0 --- /dev/null +++ b/board/sbc8349/config.mk @@ -0,0 +1,27 @@ +# +# Copyright (c) 2006 Wind River 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 +# + +# +# SBC8349E +# + +TEXT_BASE = 0xFFF00000 diff --git a/board/sbc8349/pci.c b/board/sbc8349/pci.c new file mode 100644 index 0000000..eadf230 --- /dev/null +++ b/board/sbc8349/pci.c @@ -0,0 +1,348 @@ +/* + * pci.c -- WindRiver SBC8349 PCI board support. + * Copyright (c) 2006 Wind River Systems, Inc. + * + * Based on MPC8349 PCI support but w/o PIB related code. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <asm/mmu.h> +#include <common.h> +#include <asm/global_data.h> +#include <pci.h> +#include <asm/mpc8349_pci.h> +#include <i2c.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_PCI + +/* System RAM mapped to PCI space */ +#define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE + +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc8349emds_config_table[] = { + {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_IDSEL_NUMBER, PCI_ANY_ID, + pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER + } + }, + {} +}; +#endif + +static struct pci_controller pci_hose[] = { + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc8349emds_config_table, +#endif + }, + { +#ifndef CONFIG_PCI_PNP + config_table:pci_mpc8349emds_config_table, +#endif + } +}; + +/************************************************************************** + * pci_init_board() + * + * NOTICE: PCI2 is not supported. There is only one + * physical PCI slot on the board. + * + */ +void +pci_init_board(void) +{ + volatile immap_t * immr; + volatile clk83xx_t * clk; + volatile law83xx_t * pci_law; + volatile pot83xx_t * pci_pot; + volatile pcictrl83xx_t * pci_ctrl; + volatile pciconf83xx_t * pci_conf; + u16 reg16; + u32 reg32; + u32 dev; + struct pci_controller * hose; + + immr = (immap_t *)CFG_IMMR; + clk = (clk83xx_t *)&immr->clk; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + + hose = &pci_hose[0]; + + /* + * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode + */ + + reg32 = clk->occr; + udelay(2000); + clk->occr = 0xff000000; + udelay(2000); + + /* + * Release PCI RST Output signal + */ + pci_ctrl[0].gcr = 0; + udelay(2000); + pci_ctrl[0].gcr = 1; + +#ifdef CONFIG_MPC83XX_PCI2 + pci_ctrl[1].gcr = 0; + udelay(2000); + pci_ctrl[1].gcr = 1; +#endif + + /* We need to wait at least a 1sec based on PCI specs */ + { + int i; + + for (i = 0; i < 1000; ++i) + udelay (1000); + } + + /* + * Configure PCI Local Access Windows + */ + pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR; + pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_1G; + + pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_4M; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI1 mem space - prefetch */ + pci_pot[0].potar = (CFG_PCI1_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[0].pobar = (CFG_PCI1_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[0].pocmr = POCMR_EN | POCMR_PREFETCH_EN | (POCMR_CM_256M & POCMR_CM_MASK); + + /* PCI1 IO space */ + pci_pot[1].potar = (CFG_PCI1_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[1].pobar = (CFG_PCI1_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[1].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_1M & POCMR_CM_MASK); + + /* PCI1 mmio - non-prefetch mem space */ + pci_pot[2].potar = (CFG_PCI1_MMIO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[2].pobar = (CFG_PCI1_MMIO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[2].pocmr = POCMR_EN | (POCMR_CM_256M & POCMR_CM_MASK); + + /* + * Configure PCI Inbound Translation Windows + */ + + /* we need RAM mapped to PCI space for the devices to + * access main memory */ + pci_ctrl[0].pitar1 = 0x0; + pci_ctrl[0].pibar1 = 0x0; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1); + + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* PCI memory prefetch space */ + pci_set_region(hose->regions + 0, + CFG_PCI1_MEM_BASE, + CFG_PCI1_MEM_PHYS, + CFG_PCI1_MEM_SIZE, + PCI_REGION_MEM|PCI_REGION_PREFETCH); + + /* PCI memory space */ + pci_set_region(hose->regions + 1, + CFG_PCI1_MMIO_BASE, + CFG_PCI1_MMIO_PHYS, + CFG_PCI1_MMIO_SIZE, + PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 2, + CFG_PCI1_IO_BASE, + CFG_PCI1_IO_PHYS, + CFG_PCI1_IO_SIZE, + PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose->regions + 3, + CONFIG_PCI_SYS_MEM_BUS, + CONFIG_PCI_SYS_MEM_PHYS, + gd->ram_size, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose->region_count = 4; + + pci_setup_indirect(hose, + (CFG_IMMR+0x8300), + (CFG_IMMR+0x8304)); + + pci_register_hose(hose); + + /* + * Write to Command register + */ + reg16 = 0xff; + dev = PCI_BDF(hose->first_busno, 0, 0); + pci_hose_read_config_word (hose, dev, PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); + +#ifdef CONFIG_MPC83XX_PCI2 + hose = &pci_hose[1]; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI2 mem space - prefetch */ + pci_pot[3].potar = (CFG_PCI2_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[3].pobar = (CFG_PCI2_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[3].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_PREFETCH_EN | (POCMR_CM_256M & POCMR_CM_MASK); + + /* PCI2 IO space */ + pci_pot[4].potar = (CFG_PCI2_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[4].pobar = (CFG_PCI2_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[4].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_IO | (POCMR_CM_1M & POCMR_CM_MASK); + + /* PCI2 mmio - non-prefetch mem space */ + pci_pot[5].potar = (CFG_PCI2_MMIO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[5].pobar = (CFG_PCI2_MMIO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[5].pocmr = POCMR_EN | POCMR_PCI2 | (POCMR_CM_256M & POCMR_CM_MASK); + + /* + * Configure PCI Inbound Translation Windows + */ + + /* we need RAM mapped to PCI space for the devices to + * access main memory */ + pci_ctrl[1].pitar1 = 0x0; + pci_ctrl[1].pibar1 = 0x0; + pci_ctrl[1].piebar1 = 0x0; + pci_ctrl[1].piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1); + + hose->first_busno = pci_hose[0].last_busno + 1; + hose->last_busno = 0xff; + + /* PCI memory prefetch space */ + pci_set_region(hose->regions + 0, + CFG_PCI2_MEM_BASE, + CFG_PCI2_MEM_PHYS, + CFG_PCI2_MEM_SIZE, + PCI_REGION_MEM|PCI_REGION_PREFETCH); + + /* PCI memory space */ + pci_set_region(hose->regions + 1, + CFG_PCI2_MMIO_BASE, + CFG_PCI2_MMIO_PHYS, + CFG_PCI2_MMIO_SIZE, + PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 2, + CFG_PCI2_IO_BASE, + CFG_PCI2_IO_PHYS, + CFG_PCI2_IO_SIZE, + PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose->regions + 3, + CONFIG_PCI_SYS_MEM_BUS, + CONFIG_PCI_SYS_MEM_PHYS, + gd->ram_size, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose->region_count = 4; + + pci_setup_indirect(hose, + (CFG_IMMR+0x8380), + (CFG_IMMR+0x8384)); + + pci_register_hose(hose); + + /* + * Write to Command register + */ + reg16 = 0xff; + dev = PCI_BDF(hose->first_busno, 0, 0); + pci_hose_read_config_word (hose, dev, PCI_COMMAND, ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); +#endif + +} + +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); + if (p != NULL) { + p[0] = pci_hose[0].first_busno; + p[1] = pci_hose[0].last_busno; + } + +#ifdef CONFIG_MPC83XX_PCI2 + p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8600/bus-range", &len); + if (p != NULL) { + p[0] = pci_hose[1].first_busno; + p[1] = pci_hose[1].last_busno; + } +#endif +} +#endif /* CONFIG_OF_FLAT_TREE */ +#endif /* CONFIG_PCI */ diff --git a/board/sbc8349/sbc8349.c b/board/sbc8349/sbc8349.c new file mode 100644 index 0000000..4cd447e --- /dev/null +++ b/board/sbc8349/sbc8349.c @@ -0,0 +1,585 @@ +/* + * sbc8349.c -- WindRiver SBC8349 board support. + * Copyright (c) 2006-2007 Wind River Systems, Inc. + * + * Paul Gortmaker <paul.gortmaker@windriver.com> + * Based on board/mpc8349emds/mpc8349emds.c (and previous 834x releases.) + * + * 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 <common.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <asm/mpc8349_pci.h> +#include <i2c.h> +#include <spd.h> +#include <miiphy.h> +#include <command.h> +#if defined(CONFIG_SPD_EEPROM) +#include <spd_sdram.h> +#endif +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +int fixed_sdram(void); +void sdram_init(void); + +#if defined(CONFIG_DDR_ECC) && defined(CONFIG_MPC83XX) +void ddr_enable_ecc(unsigned int dram_size); +#endif + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f (void) +{ + return 0; +} +#endif + +#define ns2clk(ns) (ns / (1000000000 / CONFIG_8349_CLKIN) + 1) + +long int initdram (int board_type) +{ + volatile immap_t *im = (immap_t *)CFG_IMMR; + u32 msize = 0; + + if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) + return -1; + + puts("Initializing\n"); + + /* DDR SDRAM - Main SODIMM */ + im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; +#if defined(CONFIG_SPD_EEPROM) + msize = spd_sdram(); +#else + msize = fixed_sdram(); +#endif + /* + * Initialize SDRAM if it is on local bus. + */ + sdram_init(); + +#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) + /* + * Initialize and enable DDR ECC. + */ + ddr_enable_ecc(msize * 1024 * 1024); +#endif + puts(" DDR RAM: "); + /* return total bus SDRAM size(bytes) -- DDR */ + return (msize * 1024 * 1024); +} + +#if !defined(CONFIG_SPD_EEPROM) +/************************************************************************* + * fixed sdram init -- doesn't use serial presence detect. + ************************************************************************/ +int fixed_sdram(void) +{ + volatile immap_t *im = (immap_t *)CFG_IMMR; + u32 msize = 0; + u32 ddr_size; + u32 ddr_size_log2; + + msize = CFG_DDR_SIZE; + for (ddr_size = msize << 20, ddr_size_log2 = 0; + (ddr_size > 1); + ddr_size = ddr_size>>1, ddr_size_log2++) { + if (ddr_size & 1) { + return -1; + } + } + im->sysconf.ddrlaw[0].bar = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff); + im->sysconf.ddrlaw[0].ar = LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); + +#if (CFG_DDR_SIZE != 256) +#warning Currently any ddr size other than 256 is not supported +#endif + im->ddr.csbnds[2].csbnds = 0x0000000f; + im->ddr.cs_config[2] = CFG_DDR_CONFIG; + + /* currently we use only one CS, so disable the other banks */ + im->ddr.cs_config[0] = 0; + im->ddr.cs_config[1] = 0; + im->ddr.cs_config[3] = 0; + + im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; + im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; + + im->ddr.sdram_cfg = + SDRAM_CFG_SREN +#if defined(CONFIG_DDR_2T_TIMING) + | SDRAM_CFG_2T_EN +#endif + | 2 << SDRAM_CFG_SDRAM_TYPE_SHIFT; +#if defined (CONFIG_DDR_32BIT) + /* for 32-bit mode burst length is 8 */ + im->ddr.sdram_cfg |= (SDRAM_CFG_32_BE | SDRAM_CFG_8_BE); +#endif + im->ddr.sdram_mode = CFG_DDR_MODE; + + im->ddr.sdram_interval = CFG_DDR_INTERVAL; + udelay(200); + + /* enable DDR controller */ + im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; + return msize; +} +#endif/*!CFG_SPD_EEPROM*/ + + +int checkboard (void) +{ + puts("Board: Wind River SBC834x\n"); + return 0; +} + +/* + * if board is fitted with SDRAM + */ +#if defined(CFG_BR2_PRELIM) \ + && defined(CFG_OR2_PRELIM) \ + && defined(CFG_LBLAWBAR2_PRELIM) \ + && defined(CFG_LBLAWAR2_PRELIM) +/* + * Initialize SDRAM memory on the Local Bus. + */ + +void sdram_init(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile lbus83xx_t *lbc= &immap->lbus; + uint *sdram_addr = (uint *)CFG_LBC_SDRAM_BASE; + + puts("\n SDRAM on Local Bus: "); + print_size (CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); + + /* + * Setup SDRAM Base and Option Registers, already done in cpu_init.c + */ + + /* setup mtrpt, lsrt and lbcr for LB bus */ + lbc->lbcr = CFG_LBC_LBCR; + lbc->mrtpr = CFG_LBC_MRTPR; + lbc->lsrt = CFG_LBC_LSRT; + asm("sync"); + + /* + * Configure the SDRAM controller Machine Mode Register. + */ + lbc->lsdmr = CFG_LBC_LSDMR_5; /* 0x40636733; normal operation */ + + lbc->lsdmr = CFG_LBC_LSDMR_1; /* 0x68636733; precharge all the banks */ + asm("sync"); + *sdram_addr = 0xff; + udelay(100); + + lbc->lsdmr = CFG_LBC_LSDMR_2; /* 0x48636733; auto refresh */ + asm("sync"); + /*1 times*/ + *sdram_addr = 0xff; + udelay(100); + /*2 times*/ + *sdram_addr = 0xff; + udelay(100); + /*3 times*/ + *sdram_addr = 0xff; + udelay(100); + /*4 times*/ + *sdram_addr = 0xff; + udelay(100); + /*5 times*/ + *sdram_addr = 0xff; + udelay(100); + /*6 times*/ + *sdram_addr = 0xff; + udelay(100); + /*7 times*/ + *sdram_addr = 0xff; + udelay(100); + /*8 times*/ + *sdram_addr = 0xff; + udelay(100); + + /* 0x58636733; mode register write operation */ + lbc->lsdmr = CFG_LBC_LSDMR_4; + asm("sync"); + *sdram_addr = 0xff; + udelay(100); + + lbc->lsdmr = CFG_LBC_LSDMR_5; /* 0x40636733; normal operation */ + asm("sync"); + *sdram_addr = 0xff; + udelay(100); +} +#else +void sdram_init(void) +{ + puts(" SDRAM on Local Bus: Disabled in config\n"); +} +#endif + +#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) +/* + * ECC user commands + */ +void ecc_print_status(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; + + printf("\nECC mode: %s\n\n", (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); + + /* Interrupts */ + printf("Memory Error Interrupt Enable:\n"); + printf(" Multiple-Bit Error Interrupt Enable: %d\n", + (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); + printf(" Single-Bit Error Interrupt Enable: %d\n", + (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); + printf(" Memory Select Error Interrupt Enable: %d\n\n", + (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); + + /* Error disable */ + printf("Memory Error Disable:\n"); + printf(" Multiple-Bit Error Disable: %d\n", + (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); + printf(" Sinle-Bit Error Disable: %d\n", + (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); + printf(" Memory Select Error Disable: %d\n\n", + (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); + + /* Error injection */ + printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", + ddr->data_err_inject_hi, ddr->data_err_inject_lo); + + printf("Memory Data Path Error Injection Mask ECC:\n"); + printf(" ECC Mirror Byte: %d\n", + (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); + printf(" ECC Injection Enable: %d\n", + (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); + printf(" ECC Error Injection Mask: 0x%02x\n\n", + ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); + + /* SBE counter/threshold */ + printf("Memory Single-Bit Error Management (0..255):\n"); + printf(" Single-Bit Error Threshold: %d\n", + (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); + printf(" Single-Bit Error Counter: %d\n\n", + (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); + + /* Error detect */ + printf("Memory Error Detect:\n"); + printf(" Multiple Memory Errors: %d\n", + (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); + printf(" Multiple-Bit Error: %d\n", + (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); + printf(" Single-Bit Error: %d\n", + (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); + printf(" Memory Select Error: %d\n\n", + (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); + + /* Capture data */ + printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); + printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", + ddr->capture_data_hi, ddr->capture_data_lo); + printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", + ddr->capture_ecc & CAPTURE_ECC_ECE); + + printf("Memory Error Attributes Capture:\n"); + printf(" Data Beat Number: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> ECC_CAPT_ATTR_BNUM_SHIFT); + printf(" Transaction Size: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> ECC_CAPT_ATTR_TSIZ_SHIFT); + printf(" Transaction Source: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> ECC_CAPT_ATTR_TSRC_SHIFT); + printf(" Transaction Type: %d\n", + (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> ECC_CAPT_ATTR_TTYP_SHIFT); + printf(" Error Information Valid: %d\n\n", + ddr->capture_attributes & ECC_CAPT_ATTR_VLD); +} + +int do_ecc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; + volatile u32 val; + u64 *addr, count, val64; + register u64 *i; + + if (argc > 4) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (argc == 2) { + if (strcmp(argv[1], "status") == 0) { + ecc_print_status(); + return 0; + } else if (strcmp(argv[1], "captureclear") == 0) { + ddr->capture_address = 0; + ddr->capture_data_hi = 0; + ddr->capture_data_lo = 0; + ddr->capture_ecc = 0; + ddr->capture_attributes = 0; + return 0; + } + } + + if (argc == 3) { + if (strcmp(argv[1], "sbecnt") == 0) { + val = simple_strtoul(argv[2], NULL, 10); + if (val > 255) { + printf("Incorrect Counter value, should be 0..255\n"); + return 1; + } + + val = (val << ECC_ERROR_MAN_SBEC_SHIFT); + val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); + + ddr->err_sbe = val; + return 0; + } else if (strcmp(argv[1], "sbethr") == 0) { + val = simple_strtoul(argv[2], NULL, 10); + if (val > 255) { + printf("Incorrect Counter value, should be 0..255\n"); + return 1; + } + + val = (val << ECC_ERROR_MAN_SBET_SHIFT); + val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); + + ddr->err_sbe = val; + return 0; + } else if (strcmp(argv[1], "errdisable") == 0) { + val = ddr->err_disable; + + if (strcmp(argv[2], "+sbe") == 0) { + val |= ECC_ERROR_DISABLE_SBED; + } else if (strcmp(argv[2], "+mbe") == 0) { + val |= ECC_ERROR_DISABLE_MBED; + } else if (strcmp(argv[2], "+mse") == 0) { + val |= ECC_ERROR_DISABLE_MSED; + } else if (strcmp(argv[2], "+all") == 0) { + val |= (ECC_ERROR_DISABLE_SBED | + ECC_ERROR_DISABLE_MBED | + ECC_ERROR_DISABLE_MSED); + } else if (strcmp(argv[2], "-sbe") == 0) { + val &= ~ECC_ERROR_DISABLE_SBED; + } else if (strcmp(argv[2], "-mbe") == 0) { + val &= ~ECC_ERROR_DISABLE_MBED; + } else if (strcmp(argv[2], "-mse") == 0) { + val &= ~ECC_ERROR_DISABLE_MSED; + } else if (strcmp(argv[2], "-all") == 0) { + val &= ~(ECC_ERROR_DISABLE_SBED | + ECC_ERROR_DISABLE_MBED | + ECC_ERROR_DISABLE_MSED); + } else { + printf("Incorrect err_disable field\n"); + return 1; + } + + ddr->err_disable = val; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + return 0; + } else if (strcmp(argv[1], "errdetectclr") == 0) { + val = ddr->err_detect; + + if (strcmp(argv[2], "mme") == 0) { + val |= ECC_ERROR_DETECT_MME; + } else if (strcmp(argv[2], "sbe") == 0) { + val |= ECC_ERROR_DETECT_SBE; + } else if (strcmp(argv[2], "mbe") == 0) { + val |= ECC_ERROR_DETECT_MBE; + } else if (strcmp(argv[2], "mse") == 0) { + val |= ECC_ERROR_DETECT_MSE; + } else if (strcmp(argv[2], "all") == 0) { + val |= (ECC_ERROR_DETECT_MME | + ECC_ERROR_DETECT_MBE | + ECC_ERROR_DETECT_SBE | + ECC_ERROR_DETECT_MSE); + } else { + printf("Incorrect err_detect field\n"); + return 1; + } + + ddr->err_detect = val; + return 0; + } else if (strcmp(argv[1], "injectdatahi") == 0) { + val = simple_strtoul(argv[2], NULL, 16); + + ddr->data_err_inject_hi = val; + return 0; + } else if (strcmp(argv[1], "injectdatalo") == 0) { + val = simple_strtoul(argv[2], NULL, 16); + + ddr->data_err_inject_lo = val; + return 0; + } else if (strcmp(argv[1], "injectecc") == 0) { + val = simple_strtoul(argv[2], NULL, 16); + if (val > 0xff) { + printf("Incorrect ECC inject mask, should be 0x00..0xff\n"); + return 1; + } + val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); + + ddr->ecc_err_inject = val; + return 0; + } else if (strcmp(argv[1], "inject") == 0) { + val = ddr->ecc_err_inject; + + if (strcmp(argv[2], "en") == 0) + val |= ECC_ERR_INJECT_EIEN; + else if (strcmp(argv[2], "dis") == 0) + val &= ~ECC_ERR_INJECT_EIEN; + else + printf("Incorrect command\n"); + + ddr->ecc_err_inject = val; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + return 0; + } else if (strcmp(argv[1], "mirror") == 0) { + val = ddr->ecc_err_inject; + + if (strcmp(argv[2], "en") == 0) + val |= ECC_ERR_INJECT_EMB; + else if (strcmp(argv[2], "dis") == 0) + val &= ~ECC_ERR_INJECT_EMB; + else + printf("Incorrect command\n"); + + ddr->ecc_err_inject = val; + return 0; + } + } + + if (argc == 4) { + if (strcmp(argv[1], "test") == 0) { + addr = (u64 *)simple_strtoul(argv[2], NULL, 16); + count = simple_strtoul(argv[3], NULL, 16); + + if ((u32)addr % 8) { + printf("Address not alligned on double word boundary\n"); + return 1; + } + + disable_interrupts(); + icache_disable(); + + for (i = addr; i < addr + count; i++) { + /* enable injects */ + ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* write memory location injecting errors */ + *i = 0x1122334455667788ULL; + __asm__ __volatile__ ("sync"); + + /* disable injects */ + ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* read data, this generates ECC error */ + val64 = *i; + __asm__ __volatile__ ("sync"); + + /* disable errors for ECC */ + ddr->err_disable |= ~ECC_ERROR_ENABLE; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* re-initialize memory, write the location again + * NOT injecting errors this time */ + *i = 0xcafecafecafecafeULL; + __asm__ __volatile__ ("sync"); + + /* enable errors for ECC */ + ddr->err_disable &= ECC_ERROR_ENABLE; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + } + + icache_enable(); + enable_interrupts(); + + return 0; + } + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + ecc, 4, 0, do_ecc, + "ecc - support for DDR ECC features\n", + "status - print out status info\n" + "ecc captureclear - clear capture regs data\n" + "ecc sbecnt <val> - set Single-Bit Error counter\n" + "ecc sbethr <val> - set Single-Bit Threshold\n" + "ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n" + " [-|+]sbe - Single-Bit Error\n" + " [-|+]mbe - Multiple-Bit Error\n" + " [-|+]mse - Memory Select Error\n" + " [-|+]all - all errors\n" + "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" + " mme - Multiple Memory Errors\n" + " sbe - Single-Bit Error\n" + " mbe - Multiple-Bit Error\n" + " mse - Memory Select Error\n" + " all - all errors\n" + "ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n" + "ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n" + "ecc injectecc <ecc> - set ECC Error Injection Mask\n" + "ecc inject <en|dis> - enable/disable error injection\n" + "ecc mirror <en|dis> - enable/disable mirror byte\n" + "ecc test <addr> <cnt> - test mem region:\n" + " - enables injects\n" + " - writes pattern injecting errors\n" + " - disables injects\n" + " - reads pattern back, generates error\n" + " - re-inits memory" +); +#endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + ft_cpu_setup(blob, bd); + + p = ft_get_prop(blob, "/memory/reg", &len); + if (p != NULL) { + *p++ = cpu_to_be32(bd->bi_memstart); + *p = cpu_to_be32(bd->bi_memsize); + } +} +#endif diff --git a/board/sbc8349/u-boot.lds b/board/sbc8349/u-boot.lds new file mode 100644 index 0000000..e32c075 --- /dev/null +++ b/board/sbc8349/u-boot.lds @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2006 Wind River Systems, Inc. + * u-boot.lds for WindRiver SBC8349. + * + * Based on the MPC8349 u-boot.lds + * + * 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) +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 : + { + cpu/mpc83xx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} +ENTRY(_start) diff --git a/board/sc3/Makefile b/board/sc3/Makefile new file mode 100644 index 0000000..4cc2b41 --- /dev/null +++ b/board/sc3/Makefile @@ -0,0 +1,51 @@ +# +# (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 = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o sc3nand.o +SOBJS = init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/sc3/config.mk b/board/sc3/config.mk new file mode 100644 index 0000000..1bdf5e4 --- /dev/null +++ b/board/sc3/config.mk @@ -0,0 +1,24 @@ +# +# (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 +# + +TEXT_BASE = 0xFFFC0000 diff --git a/board/sc3/init.S b/board/sc3/init.S new file mode 100644 index 0000000..e7b3c83 --- /dev/null +++ b/board/sc3/init.S @@ -0,0 +1,382 @@ +/*------------------------------------------------------------------------------+ + * + * This souce code has been made available to you by EuroDesign + * (www.eurodsn.de). It's based on the original IBM source code, so + * this follows: + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *------------------------------------------------------------------------------- */ + +#include <config.h> +#include <ppc4xx.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +/** + * ext_bus_cntlr_init - Initializes the External Bus Controller for the external peripherals + * + * IMPORTANT: For pass1 this code must run from cache since you can not + * reliably change a peripheral banks timing register (pbxap) while running + * code from that bank. For ex., since we are running from ROM on bank 0, we + * can NOT execute the code that modifies bank 0 timings from ROM, so + * we run it from cache. + * + * Bank 0 - Boot-Flash + * Bank 1 - NAND-Flash + * Bank 2 - ISA bus + * Bank 3 - Second Flash + * Bank 4 - USB controller + */ + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: +/* + * We need the current boot up configuration to set correct + * timings into internal flash and external flash + */ + mfdcr r24,strap /* xxxx xxxx xxxx xxx? ?xxx xxxx xxxx xxxx + 0 0 -> 8 bit external ROM + 0 1 -> 16 bit internal ROM */ + addi r4,0,2 + srw r24,r24,r4 /* shift right r24 two positions */ + andi. r24,r24,0x06000 +/* + * All calculations are based on 33MHz EBC clock. + * + * First, create a "very slow" timing (~250ns) with burst mode enabled + * This is need for the external flash access + */ + lis r25,0x0800 + ori r25,r25,0x0280 /* 0000 1000 0xxx 0000 0000 0010 100x xxxx = 0x03800280 +/* + * Second, create a fast timing: + * 90ns first cycle - 3 clock access + * and 90ns burst cycle, plus 1 clock after the last access + * This is used for the internal access + */ + lis r26,0x8900 + ori r26,r26,0x0280 /* 1000 1001 0xxx 0000 0000 0010 100x xxxx +/* + * We can't change settings on CS# if we currently use them. + * -> load a few instructions into cache and run this code from cache + */ + mflr r4 /* save link register */ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 10; used to prefetch */ + mtctr r4 /* 10 cache lines to fit this function + in cache (gives us 8x10=80 instructions) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 10 cache lines */ +/* + * Delay to ensure all accesses to ROM are complete before changing + * bank 0 timings. 200usec should be enough. + * 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles + */ + lis r3,0x0 + ori r3,r3,0xA000 /* ensure 200usec have passed since reset */ + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + +/*----------------------------------------------------------------------- + * Memory Bank 0 (BOOT-ROM) initialization + * 0xFFEF00000....0xFFFFFFF + * We only have to change the timing. Mapping is ok by boot-strapping + *----------------------------------------------------------------------- */ + + li r4,pb0ap /* PB0AP=Peripheral Bank 0 Access Parameters */ + mtdcr ebccfga,r4 + + mr r4,r26 /* assume internal fast flash is boot flash */ + cmpwi r24,0x2000 /* assumption true? ... */ + beq 1f /* ...yes! */ + mr r4,r25 /* ...no, use the slow variant */ + mr r25,r26 /* use this for the other flash */ +1: + mtdcr ebccfgd,r4 /* change timing now */ + + li r4,pb0cr /* PB0CR=Peripheral Bank 0 Control Register */ + mtdcr ebccfga,r4 + mfdcr r4,ebccfgd + lis r3,0x0001 + ori r3,r3,0x8000 /* allow reads and writes */ + or r4,r4,r3 + mtdcr ebccfgd,r4 + +/*----------------------------------------------------------------------- + * Memory Bank 3 (Second-Flash) initialization + * 0xF0000000...0xF01FFFFF -> 2MB + *----------------------------------------------------------------------- */ + + li r4,pb3ap /* Peripheral Bank 1 Access Parameter */ + mtdcr ebccfga,r4 + mtdcr ebccfgd,r2 /* change timing */ + + li r4,pb3cr /* Peripheral Bank 1 Configuration Registers */ + mtdcr ebccfga,r4 + + lis r4,0xF003 + ori r4,r4,0x8000 +/* + * Consider boot configuration + */ + xori r24,r24,0x2000 /* invert current bus width */ + or r4,r4,r24 + mtdcr ebccfgd,r4 + +/*----------------------------------------------------------------------- + * Memory Bank 1 (NAND-Flash) initialization + * 0x77D00000...0x77DFFFFF -> 1MB + * - the write/read pulse to the NAND can be as short as 25ns, bus the cycle time is always 50ns + * - the setup time is 0ns + * - the hold time is 15ns + * -> + * - TWT = 0 + * - CSN = 0 + * - OEN = 0 + * - WBN = 0 + * - WBF = 0 + * - TH = 1 + * ----> 2 clocks per cycle = 60ns cycle (30ns active, 30ns hold) + *----------------------------------------------------------------------- */ + + li r4,pb1ap /* Peripheral Bank 1 Access Parameter */ + mtdcr ebccfga,r4 + + lis r4,0x0000 + ori r4,r4,0x0200 + mtdcr ebccfgd,r4 + + li r4,pb1cr /* Peripheral Bank 1 Configuration Registers */ + mtdcr ebccfga,r4 + + lis r4,0x77D1 + ori r4,r4,0x8000 + mtdcr ebccfgd,r4 + + +/* USB init (without acceleration) */ +#ifndef CONFIG_ISP1161_PRESENT + li r4,pb4ap /* PB4AP=Peripheral Bank 4 Access Parameters */ + mtdcr ebccfga,r4 + lis r4,0x0180 + ori r4,r4,0x5940 + mtdcr ebccfgd,r4 +#endif + +/*----------------------------------------------------------------------- + * Memory Bank 2 (ISA Access) initialization (plus memory bank 6 and 7) + * 0x78000000...0x7BFFFFFF -> 64 MB + * Wir arbeiten bei 33 MHz -> 30ns + *----------------------------------------------------------------------- + + A7 (ppc notation) or A24 (standard notation) decides about + the type of access: + A7/A24=0 -> memory cycle + A7/ /A24=1 -> I/O cycle +*/ + li r4,pb2ap /* PB2AP=Peripheral Bank 2 Access Parameters */ + mtdcr ebccfga,r4 +/* + We emulate an ISA access + + 1. Address active + 2. wait 0 EBC clocks -> CSN=0 + 3. set CS# + 4. wait 0 EBC clock -> OEN/WBN=0 + 5. set OE#/WE# + 6. wait 4 clocks (ca. 90ns) and for Ready signal + 7. hold for 4 clocks -> TH=4 +*/ + +#if 1 +/* faster access to isa-bus */ + lis r4,0x0180 + ori r4,r4,0x5940 +#else + lis r4,0x0100 + ori r4,r4,0x0340 +#endif + mtdcr ebccfgd,r4 + +#ifdef IDE_USES_ISA_EMULATION + li r25,pb5ap /* PB5AP=Peripheral Bank 5 Access Parameters */ + mtdcr ebccfga,r25 + mtdcr ebccfgd,r4 +#endif + + li r25,pb6ap /* PB6AP=Peripheral Bank 6 Access Parameters */ + mtdcr ebccfga,r25 + mtdcr ebccfgd,r4 + li r25,pb7ap /* PB7AP=Peripheral Bank 7 Access Parameters */ + mtdcr ebccfga,r25 + mtdcr ebccfgd,r4 + + li r25,pb2cr /* PB2CR=Peripheral Bank 2 Configuration Register */ + mtdcr ebccfga,r25 + + lis r4,0x780B + ori r4,r4,0xA000 + mtdcr ebccfgd,r4 +/* + * the other areas are only 1MiB in size + */ + lis r4,0x7401 + ori r4,r4,0xA000 + + li r25,pb6cr /* PB6CR=Peripheral Bank 6 Configuration Register */ + mtdcr ebccfga,r25 + lis r4,0x7401 + ori r4,r4,0xA000 + mtdcr ebccfgd,r4 + + li r25,pb7cr /* PB7CR=Peripheral Bank 7 Configuration Register */ + mtdcr ebccfga,r25 + lis r4,0x7411 + ori r4,r4,0xA000 + mtdcr ebccfgd,r4 + +#ifndef CONFIG_ISP1161_PRESENT + li r25,pb4cr /* PB4CR=Peripheral Bank 4 Configuration Register */ + mtdcr ebccfga,r25 + lis r4,0x7421 + ori r4,r4,0xA000 + mtdcr ebccfgd,r4 +#endif +#ifdef IDE_USES_ISA_EMULATION + li r25,pb5cr /* PB5CR=Peripheral Bank 5 Configuration Register */ + mtdcr ebccfga,r25 + lis r4,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 +#endif + +/*----------------------------------------------------------------------- + * Memory bank 4: USB controller Philips ISP6111 + * 0x77C00000 ... 0x77CFFFFF + * + * The chip is connected to: + * - CPU CS#4 + * - CPU IRQ#2 + * - CPU DMA 3 + * + * Timing: + * - command to first data: 300ns. Software must ensure this timing! + * - Write pulse: 26ns + * - Read pulse: 33ns + * - read cycle time: 150ns + * - write cycle time: 140ns + * + * Note: All calculations are based on 33MHz EBC clock. One '#' or '_' is 30ns + * + * |- 300ns --| + * |---- 420ns ---|---- 420ns ---| cycle + * CS ############:###____#######:###____####### + * OE ############:####___#######:####___####### + * WE ############:####__########:####__######## + * + * ----> 2 clocks RD/WR pulses: 60ns + * ----> CSN: 3 clock, 90ns + * ----> OEN: 1 clocks (read cycle) + * ----> WBN: 1 clocks (write cycle) + * ----> WBE: 2 clocks + * ----> TH: 7 clock, 210ns + * ----> TWT: 7 clocks + *----------------------------------------------------------------------- */ + +#ifdef CONFIG_ISP1161_PRESENT + + li r4,pb4ap /* PB4AP=Peripheral Bank 4 Access Parameters */ + mtdcr ebccfga,r4 + + lis r4,0x030D + ori r4,r4,0x5E80 + mtdcr ebccfgd,r4 + + li r4,pb4cr /* PB2CR=Peripheral Bank 4 Configuration Register */ + mtdcr ebccfga,r4 + + lis r4,0x77C1 + ori r4,r4,0xA000 + mtdcr ebccfgd,r4 + +#endif + +#ifndef IDE_USES_ISA_EMULATION + +/*----------------------------------------------------------------------- + * Memory Bank 5 used for IDE access + * + * Timings for IDE Interface + * + * SETUP / LENGTH / HOLD - cycles valid for 33.3 MHz clk -> 30ns cycle time + * 70 165 30 PIO-Mode 0, [ns] + * 3 6 1 [Cycles] ----> AP=0x040C0200 + * 50 125 20 PIO-Mode 1, [ns] + * 2 5 1 [Cycles] ----> AP=0x03080200 + * 30 100 15 PIO-Mode 2, [ns] + * 1 4 1 [Cycles] ----> AP=0x02040200 + * 30 80 10 PIO-Mode 3, [ns] + * 1 3 1 [Cycles] ----> AP=0x01840200 + * 25 70 10 PIO-Mode 4, [ns] + * 1 3 1 [Cycles] ----> AP=0x01840200 + * + *----------------------------------------------------------------------- */ + + li r4,pb5ap + mtdcr ebccfga,r4 + lis r4,0x040C + ori r4,r4,0x0200 + mtdcr ebccfgd,r4 + + li r4,pb5cr /* PB2CR=Peripheral Bank 2 Configuration Register */ + mtdcr ebccfga,r4 + + lis r4,0x7A01 + ori r4,r4,0xA000 + mtdcr ebccfgd,r4 +#endif +/* + * External Peripheral Control Register + */ + li r4,epcr + mtdcr ebccfga,r4 + + lis r4,0xB84E + ori r4,r4,0xF000 + mtdcr ebccfgd,r4 +/* + * drive POST code + */ + lis r4,0x7900 + ori r4,r4,0x0080 + li r3,0x0001 + stb r3,0(r4) /* 01 -> external bus controller is initialized */ + nop /* pass2 DCR errata #8 */ + blr diff --git a/board/sc3/sc3.c b/board/sc3/sc3.c new file mode 100644 index 0000000..363a77d --- /dev/null +++ b/board/sc3/sc3.c @@ -0,0 +1,781 @@ +/* + * (C) Copyright 2007 + * Heiko Schocher, DENX Software Engineering, <hs@denx.de>. + * + * (C) Copyright 2003 + * Juergen Beisert, EuroDesign embedded technologies, info@eurodsn.de + * Derived from walnut.c + * + * (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 + * + * $Log:$ + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/io.h> +#include "sc3.h" +#include <pci.h> +#include <i2c.h> +#include <malloc.h> + +#undef writel +#undef writeb +#define writeb(b,addr) ((*(volatile u8 *) (addr)) = (b)) +#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b)) + +/* write only register to configure things in our CPLD */ +#define CPLD_CONTROL_1 0x79000102 +#define CPLD_VERSION 0x79000103 + +#define IS_CAMERON ((*(unsigned char *)(CPLD_VERSION)== 0x32) ? 1 : 0) + +static struct pci_controller hose={0,}; + +/************************************************************ + * Standard definition + ************************************************************/ + +/* CPC0_CR0 Function ISA bus + - GPIO0 + - GPIO1 -> Output: NAND-Command Latch Enable + - GPIO2 -> Output: NAND Address Latch Enable + - GPIO3 -> IRQ input ISA-IRQ #5 (through CPLD) + - GPIO4 -> Output: NAND-Chip Enable + - GPIO5 -> IRQ input ISA-IRQ#7 (through CPLD) + - GPIO6 -> IRQ input ISA-IRQ#9 (through CPLD) + - GPIO7 -> IRQ input ISA-IRQ#10 (through CPLD) + - GPIO8 -> IRQ input ISA-IRQ#11 (through CPLD) + - GPIO9 -> IRQ input ISA-IRQ#12 (through CPLD) + - GPIO10/CS1# -> CS1# NAND ISA-CS#0 + - GPIO11/CS2# -> CS2# ISA emulation ISA-CS#1 + - GPIO12/CS3# -> CS3# 2nd Flash-Bank ISA-CS#2 or ISA-CS#7 + - GPIO13/CS4# -> CS4# USB HC or ISA emulation ISA-CS#3 + - GPIO14/CS5# -> CS5# Boosted IDE access ISA-CS#4 + - GPIO15/CS6# -> CS6# ISA emulation ISA-CS#5 + - GPIO16/CS7# -> CS7# ISA emulation ISA-CS#6 + - GPIO17/IRQ0 -> GPIO, in, NAND-Ready/Busy# line ISA-IRQ#3 + - GPIO18/IRQ1 -> IRQ input ISA-IRQ#14 + - GPIO19/IRQ2 -> IRQ input or USB ISA-IRQ#4 + - GPIO20/IRQ3 -> IRQ input PCI-IRQ#D + - GPIO21/IRQ4 -> IRQ input PCI-IRQ#C + - GPIO22/IRQ5 -> IRQ input PCI-IRQ#B + - GPIO23/IRQ6 -> IRQ input PCI-IRQ#A + - GPIO24 -> if GPIO output: 0=JTAG CPLD activ, 1=JTAG CPLD inactiv +*/ +/* +| CPLD register: io-space at offset 0x102 (write only) +| 0 +| 1 +| 2 0=CS#4 USB CS#, 1=ISA or GP bus +| 3 +| 4 +| 5 +| 6 1=enable faster IDE access +| 7 +*/ +#define USB_CHIP_ENABLE 0x04 +#define IDE_BOOSTING 0x40 + +/* --------------- USB stuff ------------------------------------- */ +#ifdef CONFIG_ISP1161_PRESENT +/** + * initUsbHost- Initialize the Philips isp1161 HC part if present + * @cpldConfig: Pointer to value in write only CPLD register + * + * Initialize the USB host controller if present and fills the + * scratch register to inform the driver about used resources + */ + +static void initUsbHost (unsigned char *cpldConfig) +{ + int i; + unsigned long usbBase; + /* + * Read back where init.S has located the USB chip + */ + mtdcr (0x012, 0x04); + usbBase = mfdcr (0x013); + if (!(usbBase & 0x18000)) /* enabled? */ + return; + usbBase &= 0xFFF00000; + + /* + * to test for the USB controller enable using of CS#4 and DMA 3 for USB access + */ + writeb (*cpldConfig | USB_CHIP_ENABLE,CPLD_CONTROL_1); + + /* + * first check: is the controller assembled? + */ + hcWriteWord (usbBase, 0x5555, HcScratch); + if (hcReadWord (usbBase, HcScratch) == 0x5555) { + hcWriteWord (usbBase, 0xAAAA, HcScratch); + if (hcReadWord (usbBase, HcScratch) == 0xAAAA) { + if ((hcReadWord (usbBase, HcChipID) & 0xFF00) != 0x6100) + return; /* this is not our controller */ + /* + * try a software reset. This needs up to 10 seconds (see datasheet) + */ + hcWriteDWord (usbBase, 0x00000001, HcCommandStatus); + for (i = 1000; i > 0; i--) { /* loop up to 10 seconds */ + udelay (10); + if (!(hcReadDWord (usbBase, HcCommandStatus) & 0x01)) + break; + } + + if (!i) + return; /* the controller doesn't responding. Broken? */ + /* + * OK. USB controller is ready. Initialize it in such way the later driver + * can us it (without any knowing about specific implementation) + */ + hcWriteDWord (usbBase, 0x00000000, HcControl); + /* + * disable all interrupt sources. Because we + * don't know where we come from (hard reset, cold start, soft reset...) + */ + hcWriteDWord (usbBase, 0x8000007D, HcInterruptDisable); + /* + * our current setup hardware configuration + * - every port power supply can switched indepently + * - every port can signal overcurrent + * - every port is "outside" and the devices are removeable + */ + hcWriteDWord (usbBase, 0x32000902, HcRhDescriptorA); + hcWriteDWord (usbBase, 0x00060000, HcRhDescriptorB); + /* + * don't forget to switch off power supply of each port + * The later running driver can reenable them to find and use + * the (maybe) connected devices. + * + */ + hcWriteDWord (usbBase, 0x00000200, HcRhPortStatus1); + hcWriteDWord (usbBase, 0x00000200, HcRhPortStatus2); + hcWriteWord (usbBase, 0x0428, HcHardwareConfiguration); + hcWriteWord (usbBase, 0x0040, HcDMAConfiguration); + hcWriteWord (usbBase, 0x0000, HcuPInterruptEnable); + hcWriteWord (usbBase, 0xA000 | (0x03 << 8) | 27, HcScratch); + /* + * controller is present and usable + */ + *cpldConfig |= USB_CHIP_ENABLE; + } + } +} +#endif + +#if defined(CONFIG_START_IDE) +int board_start_ide(void) +{ + if (IS_CAMERON) { + puts ("no IDE on cameron board.\n"); + return 0; + } + return 1; +} +#endif + +static int sc3_cameron_init (void) +{ + /* Set up the Memory Controller for the CAMERON version */ + mtebc (pb4ap, 0x01805940); + mtebc (pb4cr, 0x7401a000); + mtebc (pb5ap, 0x01805940); + mtebc (pb5cr, 0x7401a000); + mtebc (pb6ap, 0x0); + mtebc (pb6cr, 0x0); + mtebc (pb7ap, 0x0); + mtebc (pb7cr, 0x0); + return 0; +} + +void sc3_read_eeprom (void) +{ + uchar i2c_buffer[18]; + + i2c_read (0x50, 0x03, 1, i2c_buffer, 9); + i2c_buffer[9] = 0; + setenv ("serial#", (char *)i2c_buffer); + + /* read mac-address from eeprom */ + i2c_read (0x50, 0x11, 1, i2c_buffer, 15); + i2c_buffer[17] = 0; + i2c_buffer[16] = i2c_buffer[14]; + i2c_buffer[15] = i2c_buffer[13]; + i2c_buffer[14] = ':'; + i2c_buffer[13] = i2c_buffer[12]; + i2c_buffer[12] = i2c_buffer[11]; + i2c_buffer[11] = ':'; + i2c_buffer[8] = ':'; + i2c_buffer[5] = ':'; + i2c_buffer[2] = ':'; + setenv ("ethaddr", (char *)i2c_buffer); +} + +int board_early_init_f (void) +{ + /* write only register to configure things in our CPLD */ + unsigned char cpldConfig_1=0x00; + +/*-------------------------------------------------------------------------+ +| Interrupt controller setup for the SolidCard III CPU card (plus Evaluation board). +| +| Note: IRQ 0 UART 0, active high; level sensitive +| IRQ 1 UART 1, active high; level sensitive +| IRQ 2 IIC, active high; level sensitive +| IRQ 3 Ext. master, rising edge, edge sensitive +| IRQ 4 PCI, active high; level sensitive +| IRQ 5 DMA Channel 0, active high; level sensitive +| IRQ 6 DMA Channel 1, active high; level sensitive +| IRQ 7 DMA Channel 2, active high; level sensitive +| IRQ 8 DMA Channel 3, active high; level sensitive +| IRQ 9 Ethernet Wakeup, active high; level sensitive +| IRQ 10 MAL System Error (SERR), active high; level sensitive +| IRQ 11 MAL Tx End of Buffer, active high; level sensitive +| IRQ 12 MAL Rx End of Buffer, active high; level sensitive +| IRQ 13 MAL Tx Descriptor Error, active high; level sensitive +| IRQ 14 MAL Rx Descriptor Error, active high; level sensitive +| IRQ 15 Ethernet, active high; level sensitive +| IRQ 16 External PCI SERR, active high; level sensitive +| IRQ 17 ECC Correctable Error, active high; level sensitive +| IRQ 18 PCI Power Management, active high; level sensitive +| +| IRQ 19 (EXT IRQ7 405GPr only) +| IRQ 20 (EXT IRQ8 405GPr only) +| IRQ 21 (EXT IRQ9 405GPr only) +| IRQ 22 (EXT IRQ10 405GPr only) +| IRQ 23 (EXT IRQ11 405GPr only) +| IRQ 24 (EXT IRQ12 405GPr only) +| +| IRQ 25 (EXT IRQ 0) NAND-Flash R/B# (raising edge means flash is ready) +| IRQ 26 (EXT IRQ 1) IDE0 interrupt (x86 = IRQ14). Active high (edge sensitive) +| IRQ 27 (EXT IRQ 2) USB controller +| IRQ 28 (EXT IRQ 3) INT D, VGA; active low; level sensitive +| IRQ 29 (EXT IRQ 4) INT C, Ethernet; active low; level sensitive +| IRQ 30 (EXT IRQ 5) INT B, PC104+ SLOT; active low; level sensitive +| IRQ 31 (EXT IRQ 6) INT A, PC104+ SLOT; active low; level sensitive +| +| Direct Memory Access Controller Signal Polarities +| DRQ0 active high (like ISA) +| ACK0 active low (like ISA) +| EOT0 active high (like ISA) +| DRQ1 active high (like ISA) +| ACK1 active low (like ISA) +| EOT1 active high (like ISA) +| DRQ2 active high (like ISA) +| ACK2 active low (like ISA) +| EOT2 active high (like ISA) +| DRQ3 active high (like ISA) +| ACK3 active low (like ISA) +| EOT3 active high (like ISA) +| ++-------------------------------------------------------------------------*/ + + writeb (cpldConfig_1, CPLD_CONTROL_1); /* disable everything in CPLD */ + + mtdcr (uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr (uicer, 0x00000000); /* disable all ints */ + mtdcr (uiccr, 0x00000000); /* set all to be non-critical */ + + if (IS_CAMERON) { + sc3_cameron_init(); + mtdcr (0x0B6, 0x18000000); + mtdcr (uicpr, 0xFFFFFFF0); + mtdcr (uictr, 0x10001030); + } else { + mtdcr (0x0B6, 0x0000000); + mtdcr (uicpr, 0xFFFFFFE0); + mtdcr (uictr, 0x10000020); + } + mtdcr (uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority */ + mtdcr (uicsr, 0xFFFFFFFF); /* clear all ints */ + + /* setup other implementation specific details */ + mtdcr (ecr, 0x60606000); + + mtdcr (cntrl1, 0x000042C0); + + if (IS_CAMERON) { + mtdcr (cntrl0, 0x01380000); + /* Setup the GPIOs */ + writel (0x08008000, 0xEF600700); /* Output states */ + writel (0x00000000, 0xEF600718); /* Open Drain control */ + writel (0x68098000, 0xEF600704); /* Output control */ + } else { + mtdcr (cntrl0,0x00080000); + /* Setup the GPIOs */ + writel (0x08000000, 0xEF600700); /* Output states */ + writel (0x14000000, 0xEF600718); /* Open Drain control */ + writel (0x7C000000, 0xEF600704); /* Output control */ + } + + /* Code decompression disabled */ + mtdcr (kiar, kconf); + mtdcr (kidr, 0x2B); + + /* CPC0_ER: enable sleep mode of (currently) unused components */ + /* CPC0_FR: force unused components into sleep mode */ + mtdcr (cpmer, 0x3F800000); + mtdcr (cpmfr, 0x14000000); + + /* set PLB priority */ + mtdcr (0x87, 0x08000000); + + /* --------------- DMA stuff ------------------------------------- */ + mtdcr (0x126, 0x49200000); + +#ifndef IDE_USES_ISA_EMULATION + cpldConfig_1 |= IDE_BOOSTING; /* enable faster IDE */ + /* cpldConfig |= 0x01; */ /* enable 8.33MHz output, if *not* present on your baseboard */ + writeb (cpldConfig_1, CPLD_CONTROL_1); +#endif + +#ifdef CONFIG_ISP1161_PRESENT + initUsbHost (&cpldConfig_1); + writeb (cpldConfig_1, CPLD_CONTROL_1); +#endif + /* FIXME: for what must we do this */ + *(unsigned long *)0x79000080 = 0x0001; + return(0); +} + +int misc_init_r (void) +{ + char *s1; + int i, xilinx_val; + volatile char *xilinx_adr; + xilinx_adr = (char *)0x79000102; + + *xilinx_adr = 0x00; + +/* customer settings ***************************************** */ +/* + s1 = getenv ("function"); + if (s1) { + if (!strcmp (s1, "Rosho")) { + printf ("function 'Rosho' activated\n"); + *xilinx_adr = 0x40; + } + else { + printf (">>>>>>>>>> function %s not recognized\n",s1); + } + } +*/ + +/* individual settings ***************************************** */ + if ((s1 = getenv ("xilinx"))) { + i=0; + xilinx_val = 0; + while (i < 3 && s1[i]) { + if (s1[i] >= '0' && s1[i] <= '9') + xilinx_val = (xilinx_val << 4) + s1[i] - '0'; + else + if (s1[i] >= 'A' && s1[i] <= 'F') + xilinx_val = (xilinx_val << 4) + s1[i] - 'A' + 10; + else + if (s1[i] >= 'a' && s1[i] <= 'f') + xilinx_val = (xilinx_val << 4) + s1[i] - 'a' + 10; + else { + xilinx_val = -1; + break; + } + i++; + } + if (xilinx_val >= 0 && xilinx_val <=255 && i < 3) { + printf ("Xilinx: set to %s\n", s1); + *xilinx_adr = (unsigned char) xilinx_val; + } else + printf ("Xilinx: rejected value %s\n", s1); + } + return 0; +} + +/* ------------------------------------------------------------------------- + * printCSConfig + * + * Print some informations about chips select configurations + * Only used while debugging. + * + * Params: + * - No. of CS pin + * - AP of this CS + * - CR of this CS + * + * Returns + * nothing + ------------------------------------------------------------------------- */ + +#ifdef SC3_DEBUGOUT +static void printCSConfig(int reg,unsigned long ap,unsigned long cr) +{ + const char *bsize[4] = {"8","16","32","?"}; + const unsigned char banks[8] = {1, 2, 4, 8, 16, 32, 64, 128}; + const char *bankaccess[4] = {"disabled", "RO", "WO", "RW"}; + +#define CYCLE 30 /* time of one clock (based on 33MHz) */ + + printf("\nCS#%d",reg); + if (!(cr & 0x00018000)) + puts(" unused"); + else { + if (((cr&0xFFF00000U) & ((banks[(cr & 0x000E0000) >> 17]-1) << 20))) + puts(" Address is not multiple of bank size!"); + + printf("\n -%s bit device", + bsize[(cr & 0x00006000) >> 13]); + printf(" at 0x%08lX", cr & 0xFFF00000U); + printf(" size: %u MB", banks[(cr & 0x000E0000) >> 17]); + printf(" rights: %s", bankaccess[(cr & 0x00018000) >> 15]); + if (ap & 0x80000000) { + printf("\n -Burst device (%luns/%luns)", + (((ap & 0x7C000000) >> 26) + 1) * CYCLE, + (((ap & 0x03800000) >> 23) + 1) * CYCLE); + } else { + printf("\n -Non burst device, active cycle %luns", + (((ap & 0x7F800000) >> 23) + 1) * CYCLE); + printf("\n -Address setup %luns", + ((ap & 0xC0000) >> 18) * CYCLE); + printf("\n -CS active to RD %luns/WR %luns", + ((ap & 0x30000) >> 16) * CYCLE, + ((ap & 0xC000) >> 14) * CYCLE); + printf("\n -WR to CS inactive %luns", + ((ap & 0x3000) >> 12) * CYCLE); + printf("\n -Hold after access %luns", + ((ap & 0xE00) >> 9) * CYCLE); + printf("\n -Ready is %sabled", + ap & 0x100 ? "en" : "dis"); + } + } +} +#endif + +#ifdef SC3_DEBUGOUT + +static unsigned int ap[] = {pb0ap, pb1ap, pb2ap, pb3ap, pb4ap, + pb5ap, pb6ap, pb7ap}; +static unsigned int cr[] = {pb0cr, pb1cr, pb2cr, pb3cr, pb4cr, + pb5cr, pb6cr, pb7cr}; + +static int show_reg (int nr) +{ + unsigned long ul1, ul2; + + mtdcr (ebccfga, ap[nr]); + ul1 = mfdcr (ebccfgd); + mtdcr (ebccfga, cr[nr]); + ul2 = mfdcr(ebccfgd); + printCSConfig(nr, ul1, ul2); + return 0; +} +#endif + +int checkboard (void) +{ +#ifdef SC3_DEBUGOUT + unsigned long ul1; + int i; + + for (i = 0; i < 8; i++) { + show_reg (i); + } + + mtdcr (ebccfga, epcr); + ul1 = mfdcr (ebccfgd); + + puts ("\nGeneral configuration:\n"); + + if (ul1 & 0x80000000) + printf(" -External Bus is always driven\n"); + + if (ul1 & 0x400000) + printf(" -CS signals are always driven\n"); + + if (ul1 & 0x20000) + printf(" -PowerDown after %lu clocks\n", + (ul1 & 0x1F000) >> 7); + + switch (ul1 & 0xC0000) + { + case 0xC0000: + printf(" -No external master present\n"); + break; + case 0x00000: + printf(" -8 bit external master present\n"); + break; + case 0x40000: + printf(" -16 bit external master present\n"); + break; + case 0x80000: + printf(" -32 bit external master present\n"); + break; + } + + switch (ul1 & 0x300000) + { + case 0x300000: + printf(" -Prefetch: Illegal setting!\n"); + break; + case 0x000000: + printf(" -1 doubleword prefetch\n"); + break; + case 0x100000: + printf(" -2 doublewords prefetch\n"); + break; + case 0x200000: + printf(" -4 doublewords prefetch\n"); + break; + } + putc ('\n'); +#endif + printf("Board: SolidCard III %s %s version.\n", + (IS_CAMERON ? "Cameron" : "Eurodesign"), CONFIG_SC3_VERSION); + return 0; +} + +static int printSDRAMConfig(char reg, unsigned long cr) +{ + const int bisize[8]={4, 8, 16, 32, 64, 128, 256, 0}; +#ifdef SC3_DEBUGOUT + const char *basize[8]= + {"4", "8", "16", "32", "64", "128", "256", "Reserved"}; + + printf("SDRAM bank %d",reg); + + if (!(cr & 0x01)) + puts(" disabled\n"); + else { + printf(" at 0x%08lX, size %s MB",cr & 0xFFC00000,basize[(cr&0xE0000)>>17]); + printf(" mode %lu\n",((cr & 0xE000)>>13)+1); + } +#endif + + if (cr & 0x01) + return(bisize[(cr & 0xE0000) >> 17]); + + return 0; +} + +#ifdef SC3_DEBUGOUT +static unsigned int mbcf[] = {mem_mb0cf, mem_mb1cf, mem_mb2cf, mem_mb3cf}; +#endif + +long int initdram (int board_type) +{ + unsigned int mems=0; + unsigned long ul1; + +#ifdef SC3_DEBUGOUT + unsigned long ul2; + int i; + + puts("\nSDRAM configuration:\n"); + + mtdcr (memcfga, mem_mcopt1); + ul1 = mfdcr(memcfgd); + + if (!(ul1 & 0x80000000)) { + puts(" Controller disabled\n"); + return 0; + } + for (i = 0; i < 4; i++) { + mtdcr (memcfga, mbcf[i]); + ul1 = mfdcr (memcfgd); + mems += printSDRAMConfig (i, ul1); + } + + mtdcr (memcfga, mem_sdtr1); + ul1 = mfdcr(memcfgd); + + printf ("Timing:\n -CAS latency %lu\n", ((ul1 & 0x1800000) >> 23)+1); + printf (" -Precharge %lu (PTA) \n", ((ul1 & 0xC0000) >> 18) + 1); + printf (" -R/W to Precharge %lu (CTP)\n", ((ul1 & 0x30000) >> 16) + 1); + printf (" -Leadoff %lu\n", ((ul1 & 0xC000) >> 14) + 1); + printf (" -CAS to RAS %lu\n", ((ul1 & 0x1C) >> 2) + 4); + printf (" -RAS to CAS %lu\n", ((ul1 & 0x3) + 1)); + puts ("Misc:\n"); + mtdcr (memcfga, mem_rtr); + ul1 = mfdcr(memcfgd); + printf (" -Refresh rate: %luns\n", (ul1 >> 16) * 7); + + mtdcr(memcfga,mem_pmit); + ul2=mfdcr(memcfgd); + + mtdcr(memcfga,mem_mcopt1); + ul1=mfdcr(memcfgd); + + if (ul1 & 0x20000000) + printf(" -Power Down after: %luns\n", + ((ul2 & 0xFFC00000) >> 22) * 7); + else + puts(" -Power Down disabled\n"); + + if (ul1 & 0x40000000) + printf(" -Self refresh feature active\n"); + else + puts(" -Self refresh disabled\n"); + + if (ul1 & 0x10000000) + puts(" -ECC enabled\n"); + else + puts(" -ECC disabled\n"); + + if (ul1 & 0x8000000) + puts(" -Using registered SDRAM\n"); + + if (!(ul1 & 0x6000000)) + puts(" -Using 32 bit data width\n"); + else + puts(" -Illegal data width!\n"); + + if (ul1 & 0x400000) + puts(" -ECC drivers inactive\n"); + else + puts(" -ECC drivers active\n"); + + if (ul1 & 0x200000) + puts(" -Memory lines always active outputs\n"); + else + puts(" -Memory lines only at write cycles active outputs\n"); + + mtdcr (memcfga, mem_status); + ul1 = mfdcr (memcfgd); + if (ul1 & 0x80000000) + puts(" -SDRAM Controller ready\n"); + else + puts(" -SDRAM Controller not ready\n"); + + if (ul1 & 0x4000000) + puts(" -SDRAM in self refresh mode!\n"); + + return (mems * 1024 * 1024); +#else + mtdcr (memcfga, mem_mb0cf); + ul1 = mfdcr (memcfgd); + mems = printSDRAMConfig (0, ul1); + + mtdcr (memcfga, mem_mb1cf); + ul1 = mfdcr (memcfgd); + mems += printSDRAMConfig (1, ul1); + + mtdcr (memcfga, mem_mb2cf); + ul1 = mfdcr(memcfgd); + mems += printSDRAMConfig (2, ul1); + + mtdcr (memcfga, mem_mb3cf); + ul1 = mfdcr(memcfgd); + mems += printSDRAMConfig (3, ul1); + + return (mems * 1024 * 1024); +#endif +} + +static void pci_solidcard3_fixup_irq (struct pci_controller *hose, pci_dev_t dev) +{ +/*-------------------------------------------------------------------------+ + | ,-. ,-. ,-. ,-. ,-. + | INTD# ----|B|-----|P|-. ,-|P|-. ,-| |-. ,-|G| + | |R| |C| \ / |C| \ / |E| \ / |r| + | INTC# ----|I|-----|1|-. `/---|1|-. `/---|t|-. `/---|a| + | |D| |0| \/ |0| \/ |h| \/ |f| + | INTB# ----|G|-----|4|-./`----|4|-./`----|e|-./`----|i| + | |E| |+| /\ |+| /\ |r| /\ |k| + | INTA# ----| |-----| |- `----| |- `----| |- `----| | + | `-' `-' `-' `-' `-' + | Slot 0 10 11 12 13 + | REQ# 0 1 2 * + | GNT# 0 1 2 * + +-------------------------------------------------------------------------*/ + unsigned char int_line = 0xff; + + switch (PCI_DEV(dev)) { + case 10: + int_line = 31; /* INT A */ + POST_OUT(0x42); + break; + + case 11: + int_line = 30; /* INT B */ + POST_OUT(0x43); + break; + + case 12: + int_line = 29; /* INT C */ + POST_OUT(0x44); + break; + + case 13: + int_line = 28; /* INT D */ + POST_OUT(0x45); + break; + } + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line); +} + +extern void pci_405gp_init(struct pci_controller *hose); +extern void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev); +extern void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev,struct pci_config_table *entry); +/* + * The following table is used when there is a special need to setup a PCI device. + * For every PCI device found in this table is called the given init function with given + * parameters. So never let all IDs at PCI_ANY_ID. In this case any found device gets the same + * parameters! + * +*/ +static struct pci_config_table pci_solidcard3_config_table[] = +{ +/* Host to PCI Bridge device (405GP) */ + { + vendor: 0x1014, + device: 0x0156, + class: PCI_CLASS_BRIDGE_HOST, + bus: 0, + dev: 0, + func: 0, + config_device: pci_405gp_setup_bridge + }, + { } +}; + +/*-------------------------------------------------------------------------+ + | pci_init_board (Called from pci_init() in drivers/pci.c) + | + | Init the PCI part of the SolidCard III + | + | Params: + * - Pointer to current PCI hose + * - Current Device + * + * Returns + * nothing + +-------------------------------------------------------------------------*/ + +void pci_init_board(void) +{ + POST_OUT(0x41); +/* + * we want the ptrs to RAM not flash (ie don't use init list) + */ + hose.fixup_irq = pci_solidcard3_fixup_irq; + hose.config_table = pci_solidcard3_config_table; + pci_405gp_init(&hose); +} diff --git a/board/sc3/sc3.h b/board/sc3/sc3.h new file mode 100644 index 0000000..cf920f9 --- /dev/null +++ b/board/sc3/sc3.h @@ -0,0 +1,117 @@ +/* + * (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 + */ + +/** + * hcWriteWord - write a 16 bit value into the USB controller + * @base: base address to access the chip registers + * @value: 16 bit value to write into register @offset + * @offset: register to write the @value into + * + */ +static void inline hcWriteWord (unsigned long base, unsigned int value, + unsigned int offset) +{ + out_le16 ((volatile u16*)(base + 2), offset | 0x80); + out_le16 ((volatile u16*)base, value); +} + +/** + * hcWriteDWord - write a 32 bit value into the USB controller + * @base: base address to access the chip registers + * @value: 32 bit value to write into register @offset + * @offset: register to write the @value into + * + */ + +static void inline hcWriteDWord (unsigned long base, unsigned long value, + unsigned int offset) +{ + out_le16 ((volatile u16*)(base + 2), offset | 0x80); + out_le16 ((volatile u16*)base, value); + out_le16 ((volatile u16*)base, value >> 16); +} + +/** + * hcReadWord - read a 16 bit value from the USB controller + * @base: base address to access the chip registers + * @offset: register to read from + * + * Returns the readed register value + */ + +static unsigned int inline hcReadWord (unsigned long base, unsigned int offset) +{ + out_le16 ((volatile u16*)(base + 2), offset); + return (in_le16 ((volatile u16*)base)); +} + +/** + * hcReadDWord - read a 32 bit value from the USB controller + * @base: base address to access the chip registers + * @offset: register to read from + * + * Returns the readed register value + */ + +static unsigned long inline hcReadDWord (unsigned long base, unsigned int offset) +{ + unsigned long val, val16; + + out_le16 ((volatile u16*)(base + 2), offset); + val = in_le16((volatile u16*)base); + val16 = in_le16((volatile u16*)base); + return (val | (val16 << 16)); +} + +/* control and status registers isp1161 */ +#define HcRevision 0x00 +#define HcControl 0x01 +#define HcCommandStatus 0x02 +#define HcInterruptStatus 0x03 +#define HcInterruptEnable 0x04 +#define HcInterruptDisable 0x05 +#define HcFmInterval 0x0D +#define HcFmRemaining 0x0E +#define HcFmNumber 0x0F +#define HcLSThreshold 0x11 +#define HcRhDescriptorA 0x12 +#define HcRhDescriptorB 0x13 +#define HcRhStatus 0x14 +#define HcRhPortStatus1 0x15 +#define HcRhPortStatus2 0x16 + +#define HcHardwareConfiguration 0x20 +#define HcDMAConfiguration 0x21 +#define HcTransferCounter 0x22 +#define HcuPInterrupt 0x24 +#define HcuPInterruptEnable 0x25 +#define HcChipID 0x27 +#define HcScratch 0x28 +#define HcSoftwareReset 0x29 +#define HcITLBufferLength 0x2A +#define HcATLBufferLength 0x2B +#define HcBufferStatus 0x2C +#define HcReadBackITL0Length 0x2D +#define HcReadBackITL1Length 0x2E +#define HcITLBufferPort 0x40 +#define HcATLBufferPort 0x41 diff --git a/board/sc3/sc3nand.c b/board/sc3/sc3nand.c new file mode 100644 index 0000000..7daa877 --- /dev/null +++ b/board/sc3/sc3nand.c @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2007 + * Heiko Schocher, DENX Software Engineering, hs@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 <common.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <nand.h> +#include <asm/processor.h> + +#define readb(addr) *(volatile u_char *)(addr) +#define readl(addr) *(volatile u_long *)(addr) +#define writeb(d,addr) *(volatile u_char *)(addr) = (d) + +#define SC3_NAND_ALE 29 /* GPIO PIN 3 */ +#define SC3_NAND_CLE 30 /* GPIO PIN 2 */ +#define SC3_NAND_CE 27 /* GPIO PIN 5 */ + +static void *sc3_io_base; +static void *sc3_control_base = (void *)0xEF600700; + +static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd) +{ + switch (cmd) { + case NAND_CTL_SETCLE: + set_bit (SC3_NAND_CLE, sc3_control_base); + break; + case NAND_CTL_CLRCLE: + clear_bit (SC3_NAND_CLE, sc3_control_base); + break; + + case NAND_CTL_SETALE: + set_bit (SC3_NAND_ALE, sc3_control_base); + break; + case NAND_CTL_CLRALE: + clear_bit (SC3_NAND_ALE, sc3_control_base); + break; + + case NAND_CTL_SETNCE: + set_bit (SC3_NAND_CE, sc3_control_base); + break; + case NAND_CTL_CLRNCE: + clear_bit (SC3_NAND_CE, sc3_control_base); + break; + } +} + +static int sc3_nand_dev_ready(struct mtd_info *mtd) +{ + if (!(readl(sc3_control_base + 0x1C) & 0x4000)) + return 0; + return 1; +} + +static void sc3_select_chip(struct mtd_info *mtd, int chip) +{ + clear_bit (SC3_NAND_CE, sc3_control_base); +} + +int board_nand_init(struct nand_chip *nand) +{ + nand->eccmode = NAND_ECC_SOFT; + + sc3_io_base = (void *) CFG_NAND_BASE; + /* Set address of NAND IO lines (Using Linear Data Access Region) */ + nand->IO_ADDR_R = (void __iomem *) sc3_io_base; + nand->IO_ADDR_W = (void __iomem *) sc3_io_base; + /* Reference hardware control function */ + nand->hwcontrol = sc3_nand_hwcontrol; + nand->dev_ready = sc3_nand_dev_ready; + nand->select_chip = sc3_select_chip; + return 0; +} +#endif diff --git a/board/sc3/u-boot.lds b/board/sc3/u-boot.lds new file mode 100644 index 0000000..dc255d2 --- /dev/null +++ b/board/sc3/u-boot.lds @@ -0,0 +1,150 @@ +/* + * (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 +{ + .resetvec 0xFFFFFFFC : + { + *(.resetvec) + } = 0xffff + + /* 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/sc3/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) + *(.eh_frame) + } + .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/board/spc1920/Makefile b/board/spc1920/Makefile index 424ab1c..0c48c3a 100644 --- a/board/spc1920/Makefile +++ b/board/spc1920/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o +COBJS = $(BOARD).o hpi.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/spc1920/hpi.c b/board/spc1920/hpi.c new file mode 100644 index 0000000..3c36f79 --- /dev/null +++ b/board/spc1920/hpi.c @@ -0,0 +1,603 @@ +/* + * (C) Copyright 2006 + * Markus Klotzbuecher, DENX Software Engineering, mk@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 + */ + +/* + * Host Port Interface (HPI) + */ + +/* debug levels: + * 0 : errors + * 1 : usefull info + * 2 : lots of info + * 3 : noisy + */ + +#define DEBUG 0 + +#include <config.h> +#include <common.h> +#include <mpc8xx.h> + +#include "pld.h" +#include "hpi.h" + +#define _NOT_USED_ 0xFFFFFFFF + +/* original table: + * - inserted loops to achieve long CS low and high Periods (~217ns) + * - move cs high 2/4 to the right + */ +const uint dsp_table_slow[] = +{ + /* single read (offset 0x00 in upm ram) */ + 0x8fffdc04, 0x0fffdc84, 0x0fffdc84, 0x0fffdc00, + 0x3fffdc04, 0xffffdc84, 0xffffdc84, 0xffffdc05, + + /* burst read (offset 0x08 in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* single write (offset 0x18 in upm ram) */ + 0x8fffd004, 0x0fffd084, 0x0fffd084, 0x3fffd000, + 0xffffd084, 0xffffd084, 0xffffd005, _NOT_USED_, + + /* burst write (offset 0x20 in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* refresh (offset 0x30 in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* exception (offset 0x3C in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, +}; + +/* dsp hpi upm ram table + * works fine for noninc access, failes on incremental. + * - removed first word + */ +const uint dsp_table_fast[] = +{ + /* single read (offset 0x00 in upm ram) */ + 0x8fffdc04, 0x0fffdc04, 0x0fffdc00, 0x3fffdc04, + 0xffffdc05, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* burst read (offset 0x08 in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* single write (offset 0x18 in upm ram) */ + 0x8fffd004, 0x0fffd004, 0x3fffd000, 0xffffd005, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* burst write (offset 0x20 in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* refresh (offset 0x30 in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* exception (offset 0x3C in upm ram) */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, +}; + + +#ifdef CONFIG_SPC1920_HPI_TEST +#undef HPI_TEST_OSZI + +#define HPI_TEST_CHUNKSIZE 0x1000 +#define HPI_TEST_PATTERN 0x00000000 +#define HPI_TEST_START 0x0 +#define HPI_TEST_END 0x30000 + +#define TINY_AUTOINC_DATA_SIZE 16 /* 32bit words */ +#define TINY_AUTOINC_BASE_ADDR 0x0 + +static int hpi_activate(void); +static void hpi_inactivate(void); +static void dsp_reset(void); + +static int hpi_write_inc(u32 addr, u32 *data, u32 count); +static int hpi_read_inc(u32 addr, u32 *buf, u32 count); +static int hpi_write_noinc(u32 addr, u32 data); +static u32 hpi_read_noinc(u32 addr); + +int hpi_test(void); +static int hpi_write_addr_test(u32 addr); +static int hpi_read_write_test(u32 addr, u32 data); +static int hpi_tiny_autoinc_test(void); +#endif /* CONFIG_SPC1920_HPI_TEST */ + + +/* init the host port interface on UPMA */ +int hpi_init(void) +{ + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE; + + upmconfig(UPMA, (uint *)dsp_table_slow, sizeof(dsp_table_slow)/sizeof(uint)); + udelay(100); + + memctl->memc_mamr = CFG_MAMR; + memctl->memc_or3 = CFG_OR3; + memctl->memc_br3 = CFG_BR3; + + /* reset dsp */ + dsp_reset(); + + /* activate hpi switch*/ + pld->dsp_hpi_on = 0x1; + + udelay(100); + + return 0; +} + +#ifdef CONFIG_SPC1920_HPI_TEST +/* activate the Host Port interface */ +static int hpi_activate(void) +{ + volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE; + + /* turn on hpi */ + pld->dsp_hpi_on = 0x1; + + udelay(5); + + /* turn on the power EN_DSP_POWER high*/ + /* currently always on TBD */ + + /* setup hpi control register */ + HPI_HPIC_1 = (u16) 0x0008; + HPI_HPIC_2 = (u16) 0x0008; + + udelay(100); + + return 0; +} + +/* turn off the host port interface */ +static void hpi_inactivate(void) +{ + volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE; + + /* deactivate hpi */ + pld->dsp_hpi_on = 0x0; + + /* reset the dsp */ + /* pld->dsp_reset = 0x0; */ + + /* turn off the power EN_DSP_POWER# high*/ + /* currently always on TBD */ + +} + +/* reset the DSP */ +static void dsp_reset(void) +{ + volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE; + pld->dsp_reset = 0x1; + pld->dsp_hpi_on = 0x0; + + udelay(300000); + + pld->dsp_reset = 0x0; + pld->dsp_hpi_on = 0x1; +} + + +/* write using autoinc (count is number of 32bit words) */ +static int hpi_write_inc(u32 addr, u32 *data, u32 count) +{ + int i; + u16 addr1, addr2; + + addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */ + addr2 = (u16) (addr & 0xffff); + + /* write address */ + HPI_HPIA_1 = addr1; + HPI_HPIA_2 = addr2; + + debugX(4, "writing from data=0x%x to 0x%x\n", data, (data+count)); + + for(i=0; i<count; i++) { + HPI_HPID_INC_1 = (u16) ((data[i] >> 16) & 0xffff); + HPI_HPID_INC_2 = (u16) (data[i] & 0xffff); + debugX(4, "hpi_write_inc: data1=0x%x, data2=0x%x\n", + (u16) ((data[i] >> 16) & 0xffff), + (u16) (data[i] & 0xffff)); + } +#if 0 + while(data_ptr < (u16*) (data + count)) { + HPI_HPID_INC_1 = *(data_ptr++); + HPI_HPID_INC_2 = *(data_ptr++); + } +#endif + + /* return number of bytes written */ + return count; +} + +/* + * read using autoinc (count is number of 32bit words) + */ +static int hpi_read_inc(u32 addr, u32 *buf, u32 count) +{ + int i; + u16 addr1, addr2, data1, data2; + + addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */ + addr2 = (u16) (addr & 0xffff); + + /* write address */ + HPI_HPIA_1 = addr1; + HPI_HPIA_2 = addr2; + + for(i=0; i<count; i++) { + data1 = HPI_HPID_INC_1; + data2 = HPI_HPID_INC_2; + debugX(4, "hpi_read_inc: data1=0x%x, data2=0x%x\n", data1, data2); + buf[i] = (((u32) data1) << 16) | (data2 & 0xffff); + } + +#if 0 + while(buf_ptr < (u16*) (buf + count)) { + *(buf_ptr++) = HPI_HPID_INC_1; + *(buf_ptr++) = HPI_HPID_INC_2; + } +#endif + + /* return number of bytes read */ + return count; +} + + +/* write to non- auto inc regs */ +static int hpi_write_noinc(u32 addr, u32 data) +{ + + u16 addr1, addr2, data1, data2; + + addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */ + addr2 = (u16) (addr & 0xffff); + + /* printf("hpi_write_noinc: addr1=0x%x, addr2=0x%x\n", addr1, addr2); */ + + HPI_HPIA_1 = addr1; + HPI_HPIA_2 = addr2; + + data1 = (u16) ((data >> 16) & 0xffff); + data2 = (u16) (data & 0xffff); + + /* printf("hpi_write_noinc: data1=0x%x, data2=0x%x\n", data1, data2); */ + + HPI_HPID_NOINC_1 = data1; + HPI_HPID_NOINC_2 = data2; + + return 0; +} + +/* read from non- auto inc regs */ +static u32 hpi_read_noinc(u32 addr) +{ + u16 addr1, addr2, data1, data2; + u32 ret; + + addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */ + addr2 = (u16) (addr & 0xffff); + + HPI_HPIA_1 = addr1; + HPI_HPIA_2 = addr2; + + /* printf("hpi_read_noinc: addr1=0x%x, addr2=0x%x\n", addr1, addr2); */ + + data1 = HPI_HPID_NOINC_1; + data2 = HPI_HPID_NOINC_2; + + /* printf("hpi_read_noinc: data1=0x%x, data2=0x%x\n", data1, data2); */ + + ret = (((u32) data1) << 16) | (data2 & 0xffff); + return ret; + +} + +/* + * Host Port Interface Tests + */ + +#ifndef HPI_TEST_OSZI +/* main test function */ +int hpi_test(void) +{ + int err = 0; + u32 i, ii, pattern, tmp; + + pattern = HPI_TEST_PATTERN; + + u32 test_data[HPI_TEST_CHUNKSIZE]; + u32 read_data[HPI_TEST_CHUNKSIZE]; + + debugX(2, "hpi_test: activating hpi..."); + hpi_activate(); + debugX(2, "OK.\n"); + +#if 0 + /* Dump the first 1024 bytes + * + */ + for(i=0; i<1024; i+=4) { + if(i%16==0) + printf("\n0x%08x: ", i); + printf("0x%08x ", hpi_read_noinc(i)); + } +#endif + + /* HPIA read-write test + * + */ + debugX(1, "hpi_test: starting HPIA read-write tests...\n"); + err |= hpi_write_addr_test(0xdeadc0de); + err |= hpi_write_addr_test(0xbeefd00d); + err |= hpi_write_addr_test(0xabcd1234); + err |= hpi_write_addr_test(0xaaaaaaaa); + if(err) { + debugX(1, "hpi_test: HPIA read-write tests: *** FAILED ***\n"); + return -1; + } + debugX(1, "hpi_test: HPIA read-write tests: OK\n"); + + + /* read write test using nonincremental data regs + * + */ + debugX(1, "hpi_test: starting nonincremental tests...\n"); + for(i=HPI_TEST_START; i<HPI_TEST_END; i+=4) { + err |= hpi_read_write_test(i, pattern); + + /* stolen from cmd_mem.c */ + if(pattern & 0x80000000) { + pattern = -pattern; /* complement & increment */ + } else { + pattern = ~pattern; + } + err |= hpi_read_write_test(i, pattern); + + if(err) { + debugX(1, "hpi_test: nonincremental tests *** FAILED ***\n"); + return -1; + } + } + debugX(1, "hpi_test: nonincremental test OK\n"); + + /* read write a chunk of data using nonincremental data regs + * + */ + debugX(1, "hpi_test: starting nonincremental chunk tests...\n"); + pattern = HPI_TEST_PATTERN; + for(i=HPI_TEST_START; i<HPI_TEST_END; i+=4) { + hpi_write_noinc(i, pattern); + + /* stolen from cmd_mem.c */ + if(pattern & 0x80000000) { + pattern = -pattern; /* complement & increment */ + } else { + pattern = ~pattern; + } + } + pattern = HPI_TEST_PATTERN; + for(i=HPI_TEST_START; i<HPI_TEST_END; i+=4) { + tmp = hpi_read_noinc(i); + + if(tmp != pattern) { + debugX(1, "hpi_test: noninc chunk test *** FAILED *** @ 0x%x, written=0x%x, read=0x%x\n", i, pattern, tmp); + err = -1; + } + /* stolen from cmd_mem.c */ + if(pattern & 0x80000000) { + pattern = -pattern; /* complement & increment */ + } else { + pattern = ~pattern; + } + } + if(err) + return -1; + debugX(1, "hpi_test: nonincremental chunk test OK\n"); + + +#ifdef DO_TINY_TEST + /* small verbose test using autoinc and nonautoinc to compare + * + */ + debugX(1, "hpi_test: tiny_autoinc_test...\n"); + hpi_tiny_autoinc_test(); + debugX(1, "hpi_test: tiny_autoinc_test done\n"); +#endif /* DO_TINY_TEST */ + + + /* $%& write a chunk of data using the autoincremental regs + * + */ + debugX(1, "hpi_test: starting autoinc test %d chunks with 0x%x bytes...\n", + ((HPI_TEST_END - HPI_TEST_START) / HPI_TEST_CHUNKSIZE), + HPI_TEST_CHUNKSIZE); + + for(i=HPI_TEST_START; + i < ((HPI_TEST_END - HPI_TEST_START) / HPI_TEST_CHUNKSIZE); + i++) { + /* generate the pattern data */ + debugX(3, "generating pattern data: "); + for(ii = 0; ii < HPI_TEST_CHUNKSIZE; ii++) { + debugX(3, "0x%x ", pattern); + + test_data[ii] = pattern; + read_data[ii] = 0x0; /* zero to be sure */ + + /* stolen from cmd_mem.c */ + if(pattern & 0x80000000) { + pattern = -pattern; /* complement & increment */ + } else { + pattern = ~pattern; + } + } + debugX(3, "done\n"); + + debugX(2, "Writing autoinc data @ 0x%x\n", i); + hpi_write_inc(i, test_data, HPI_TEST_CHUNKSIZE); + + debugX(2, "Reading autoinc data @ 0x%x\n", i); + hpi_read_inc(i, read_data, HPI_TEST_CHUNKSIZE); + + /* compare */ + for(ii = 0; ii < HPI_TEST_CHUNKSIZE; ii++) { + debugX(3, "hpi_test_autoinc: @ 0x%x, written=0x%x, read=0x%x", i+ii, test_data[ii], read_data[ii]); + if(read_data[ii] != test_data[ii]) { + debugX(0, "hpi_test: autoinc test @ 0x%x, written=0x%x, read=0x%x *** FAILED ***\n", i+ii, test_data[ii], read_data[ii]); + return -1; + } + } + } + debugX(1, "hpi_test: autoinc test OK\n"); + + return 0; +} +#else /* HPI_TEST_OSZI */ +int hpi_test(void) +{ + int i; + u32 read_data[TINY_AUTOINC_DATA_SIZE]; + + unsigned int dummy_data[TINY_AUTOINC_DATA_SIZE] = { + 0x11112222, 0x33334444, 0x55556666, 0x77778888, + 0x9999aaaa, 0xbbbbcccc, 0xddddeeee, 0xffff1111, + 0x00010002, 0x00030004, 0x00050006, 0x00070008, + 0x0009000a, 0x000b000c, 0x000d000e, 0x000f0001 + }; + + debugX(0, "hpi_test: activating hpi..."); + hpi_activate(); + debugX(0, "OK.\n"); + + while(1) { + led9(1); + debugX(0, " writing to autoinc...\n"); + hpi_write_inc(TINY_AUTOINC_BASE_ADDR, + dummy_data, TINY_AUTOINC_DATA_SIZE); + + debugX(0, " reading from autoinc...\n"); + hpi_read_inc(TINY_AUTOINC_BASE_ADDR, + read_data, TINY_AUTOINC_DATA_SIZE); + + for(i=0; i < (TINY_AUTOINC_DATA_SIZE); i++) { + debugX(0, " written=0x%x, read(inc)=0x%x\n", + dummy_data[i], read_data[i]); + } + led9(0); + udelay(2000000); + } + return 0; +} +#endif + +/* test if Host Port Address Register can be written correctly */ +static int hpi_write_addr_test(u32 addr) +{ + u32 read_back; + /* write address */ + HPI_HPIA_1 = ((u16) (addr >> 16)); /* First HW is most significant */ + HPI_HPIA_2 = ((u16) addr); + + read_back = (((u32) HPI_HPIA_1)<<16) | ((u32) HPI_HPIA_2); + + if(read_back == addr) { + debugX(2, " hpi_write_addr_test OK: written=0x%x, read=0x%x\n", + addr, read_back); + return 0; + } else { + debugX(0, " hpi_write_addr_test *** FAILED ***: written=0x%x, read=0x%x\n", + addr, read_back); + return -1; + } + + return 0; +} + +/* test if a simple read/write sequence succeeds */ +static int hpi_read_write_test(u32 addr, u32 data) +{ + u32 read_back; + + hpi_write_noinc(addr, data); + read_back = hpi_read_noinc(addr); + + if(read_back == data) { + debugX(2, " hpi_read_write_test: OK, addr=0x%x written=0x%x, read=0x%x\n", addr, data, read_back); + return 0; + } else { + debugX(0, " hpi_read_write_test: *** FAILED ***, addr=0x%x written=0x%x, read=0x%x\n", addr, data, read_back); + return -1; + } + + return 0; +} + +static int hpi_tiny_autoinc_test(void) +{ + int i; + u32 read_data[TINY_AUTOINC_DATA_SIZE]; + u32 read_data_noinc[TINY_AUTOINC_DATA_SIZE]; + + unsigned int dummy_data[TINY_AUTOINC_DATA_SIZE] = { + 0x11112222, 0x33334444, 0x55556666, 0x77778888, + 0x9999aaaa, 0xbbbbcccc, 0xddddeeee, 0xffff1111, + 0x00010002, 0x00030004, 0x00050006, 0x00070008, + 0x0009000a, 0x000b000c, 0x000d000e, 0x000f0001 + }; + + printf(" writing to autoinc...\n"); + hpi_write_inc(TINY_AUTOINC_BASE_ADDR, dummy_data, TINY_AUTOINC_DATA_SIZE); + + printf(" reading from autoinc...\n"); + hpi_read_inc(TINY_AUTOINC_BASE_ADDR, read_data, TINY_AUTOINC_DATA_SIZE); + + printf(" reading from noinc for comparison...\n"); + for(i=0; i < (TINY_AUTOINC_DATA_SIZE); i++) + read_data_noinc[i] = hpi_read_noinc(TINY_AUTOINC_BASE_ADDR+i*4); + + for(i=0; i < (TINY_AUTOINC_DATA_SIZE); i++) { + printf(" written=0x%x, read(inc)=0x%x, read(noinc)=0x%x\n", + dummy_data[i], read_data[i], read_data_noinc[i]); + } + return 0; +} + +#endif /* CONFIG_SPC1920_HPI_TEST */ diff --git a/board/spc1920/hpi.h b/board/spc1920/hpi.h new file mode 100644 index 0000000..4503873 --- /dev/null +++ b/board/spc1920/hpi.h @@ -0,0 +1,28 @@ +/* + * (C) Copyright 2006 + * Markus Klotzbuecher, DENX Software Engineering, mk@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 + */ + +int hpi_init(void); + +#ifdef CONFIG_SPC1920_HPI_TEST +int hpi_test(void); +#endif diff --git a/board/spc1920/pld.h b/board/spc1920/pld.h index 3254f82..5beb71b 100644 --- a/board/spc1920/pld.h +++ b/board/spc1920/pld.h @@ -5,8 +5,8 @@ typedef struct spc1920_pld { uchar com1_en; uchar dsp_reset; uchar dsp_hpi_on; + uchar superv_mode; uchar codec_dsp_power_en; - uchar clk2_en; uchar clk3_select; uchar clk4_select; } spc1920_pld_t; diff --git a/board/spc1920/spc1920.c b/board/spc1920/spc1920.c index 028f4c6..1f5dcb5 100644 --- a/board/spc1920/spc1920.c +++ b/board/spc1920/spc1920.c @@ -27,9 +27,9 @@ #include <common.h> #include <mpc8xx.h> #include "pld.h" +#include "hpi.h" #define _NOT_USED_ 0xFFFFFFFF -/* #define debug(fmt,args...) printf (fmt ,##args) */ static long int dram_size (long int, long int *, long int); @@ -172,10 +172,12 @@ long int initdram (int board_type) memctl->memc_br1 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMB | BR_V; udelay (1000); + /* initalize the DSP Host Port Interface */ + hpi_init(); - /* PLD Setup */ - memctl->memc_or5 = CFG_OR5_PRELIM; - memctl->memc_br5 = CFG_BR5_PRELIM; + /* FRAM Setup */ + memctl->memc_or4 = CFG_OR4; + memctl->memc_br4 = CFG_BR4; udelay(1000); return (size_b0); @@ -207,13 +209,31 @@ int board_early_init_f(void) { volatile immap_t *immap = (immap_t *) CFG_IMMR; + /* Set Go/NoGo led (PA15) to color red */ + immap->im_ioport.iop_papar &= ~0x1; + immap->im_ioport.iop_paodr &= ~0x1; + immap->im_ioport.iop_padir |= 0x1; + immap->im_ioport.iop_padat |= 0x1; +#if 0 /* Turn on LED PD9 */ immap->im_ioport.iop_pdpar &= ~(0x0040); immap->im_ioport.iop_pddir |= 0x0040; immap->im_ioport.iop_pddat |= 0x0040; +#endif + + /* + * Enable console on SMC1. This requires turning on + * the com2_en signal and SMC1_DISABLE + */ + + /* SMC1_DISABLE: PB17 */ + immap->im_cpm.cp_pbodr &= ~0x4000; + immap->im_cpm.cp_pbpar &= ~0x4000; + immap->im_cpm.cp_pbdir |= 0x4000; + immap->im_cpm.cp_pbdat &= ~0x4000; - /* Enable PD10 (COM2_EN) */ + /* COM2_EN: PD10 */ immap->im_ioport.iop_pdpar &= ~0x0020; immap->im_ioport.iop_pddir &= ~0x4000; immap->im_ioport.iop_pddir |= 0x0020; @@ -228,6 +248,14 @@ int board_early_init_f(void) return 0; } +int last_stage_init(void) +{ +#ifdef CONFIG_SPC1920_HPI_TEST + printf("CMB1920 Host Port Interface Test: %s\n", + hpi_test() ? "Failed!" : "OK"); +#endif + return 0; +} int checkboard (void) { diff --git a/board/tqm5200/cam5200_flash.c b/board/tqm5200/cam5200_flash.c index 8c3f62e..b3f095d 100644 --- a/board/tqm5200/cam5200_flash.c +++ b/board/tqm5200/cam5200_flash.c @@ -25,7 +25,7 @@ #include <mpc5xxx.h> #include <asm/processor.h> -#ifdef CONFIG_CAM5200 +#if defined(CONFIG_CAM5200) && defined(CONFIG_CAM5200_NIOSFLASH) #if 0 #define DEBUGF(x...) printf(x) @@ -783,4 +783,4 @@ unsigned long flash_init(void) return total_b; } -#endif /* ifdef CONFIG_CAM5200 */ +#endif /* if defined(CONFIG_CAM5200) && defined(CONFIG_CAM5200_NIOSFLASH) */ diff --git a/board/tqm8272/Makefile b/board/tqm8272/Makefile new file mode 100644 index 0000000..3dbf913 --- /dev/null +++ b/board/tqm8272/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2001 +# 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 ../tqm8xx/load_sernum_ethaddr.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/tqm8272/config.mk b/board/tqm8272/config.mk new file mode 100644 index 0000000..af7a81e --- /dev/null +++ b/board/tqm8272/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2006 +# 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 +# + +# +# TQM8272 boards +# + +# This should be equal to the CFG_FLASH_BASE define in config_TQM8260.h +# for the "final" configuration, with U-Boot in flash, or the address +# in RAM where U-Boot is loaded at for debugging. +# +TEXT_BASE = 0x40000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR) diff --git a/board/tqm8272/tqm8272.c b/board/tqm8272/tqm8272.c new file mode 100644 index 0000000..70d1bb8 --- /dev/null +++ b/board/tqm8272/tqm8272.c @@ -0,0 +1,1234 @@ +/* + * (C) Copyright 2006 + * Heiko Schocher, DENX Software Engineering, hs@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 <common.h> +#include <ioports.h> +#include <mpc8260.h> + +#include <command.h> +#ifdef CONFIG_PCI +#include <pci.h> +#include <asm/m8260_pci.h> +#endif +#if CONFIG_OF_FLAT_TREE +#include <ft_build.h> +#include <image.h> +#endif + +#if 0 +#define deb_printf(fmt,arg...) \ + printf ("TQM8272 %s %s: " fmt,__FILE__, __FUNCTION__, ##arg) +#else +#define deb_printf(fmt,arg...) \ + do { } while (0) +#endif + +#if defined(CONFIG_BOARD_GET_CPU_CLK_F) +unsigned long board_get_cpu_clk_f (void); +#endif + +/* + * I/O Port configuration table + * + * if conf is 1, then that port pin will be configured at boot time + * according to the five values podr/pdir/ppar/psor/pdat for that entry + */ + +const iop_conf_t iop_conf_tab[4][32] = { + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMTXEN */ + /* PA30 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTCA */ + /* PA29 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTSOC */ + /* PA28 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMRXEN */ + /* PA27 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRSOC */ + /* PA26 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRCA */ + /* PA25 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[0] */ + /* PA24 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[1] */ + /* PA23 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[2] */ + /* PA22 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[3] */ + /* PA21 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[4] */ + /* PA20 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[5] */ + /* PA19 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[6] */ + /* PA18 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[7] */ + /* PA17 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[7] */ + /* PA16 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[6] */ + /* PA15 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[5] */ + /* PA14 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[4] */ + /* PA13 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[3] */ + /* PA12 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[2] */ + /* PA11 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[1] */ + /* PA10 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[0] */ + /* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */ + /* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */ + /* PA7 */ { 0, 0, 0, 1, 0, 0 }, /* PA7 */ + /* PA6 */ { 0, 0, 0, 1, 0, 0 }, /* PA6 */ + /* PA5 */ { 0, 0, 0, 1, 0, 0 }, /* PA5 */ + /* PA4 */ { 0, 0, 0, 1, 0, 0 }, /* PA4 */ + /* PA3 */ { 0, 0, 0, 1, 0, 0 }, /* PA3 */ + /* PA2 */ { 0, 0, 0, 1, 0, 0 }, /* PA2 */ + /* PA1 */ { 0, 0, 0, 1, 0, 0 }, /* PA1 */ + /* PA0 */ { 0, 0, 0, 1, 0, 0 } /* PA0 */ + }, + + /* Port B configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */ + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */ + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */ + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */ + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */ + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */ + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */ + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */ + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */ + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */ + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */ + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */ + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */ + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */ + /* PB17 */ { 0, 0, 0, 0, 0, 0 }, /* PB17 */ + /* PB16 */ { 0, 0, 0, 0, 0, 0 }, /* PB16 */ + /* PB15 */ { 0, 0, 0, 0, 0, 0 }, /* PB15 */ + /* PB14 */ { 0, 0, 0, 0, 0, 0 }, /* PB14 */ + /* PB13 */ { 0, 0, 0, 0, 0, 0 }, /* PB13 */ + /* PB12 */ { 0, 0, 0, 0, 0, 0 }, /* PB12 */ + /* PB11 */ { 0, 0, 0, 0, 0, 0 }, /* PB11 */ + /* PB10 */ { 0, 0, 0, 0, 0, 0 }, /* PB10 */ + /* PB9 */ { 0, 0, 0, 0, 0, 0 }, /* PB9 */ + /* PB8 */ { 0, 0, 0, 0, 0, 0 }, /* PB8 */ + /* PB7 */ { 0, 0, 0, 0, 0, 0 }, /* PB7 */ + /* PB6 */ { 0, 0, 0, 0, 0, 0 }, /* PB6 */ + /* PB5 */ { 0, 0, 0, 0, 0, 0 }, /* PB5 */ + /* PB4 */ { 0, 0, 0, 0, 0, 0 }, /* PB4 */ + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + }, + + /* Port C */ + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { 0, 0, 0, 1, 0, 0 }, /* PC31 */ + /* PC30 */ { 0, 0, 0, 0, 0, 0 }, /* PC30 */ + /* PC29 */ { 1, 1, 1, 0, 0, 0 }, /* SCC1 EN *CLSN */ + /* PC28 */ { 0, 0, 0, 1, 0, 0 }, /* PC28 */ + /* PC27 */ { 0, 0, 0, 1, 0, 0 }, /* PC27 */ + /* PC26 */ { 0, 0, 0, 1, 0, 0 }, /* PC26 */ + /* PC25 */ { 0, 0, 0, 1, 0, 0 }, /* PC25 */ + /* PC24 */ { 0, 0, 0, 1, 0, 0 }, /* PC24 */ + /* PC23 */ { 0, 1, 0, 1, 0, 0 }, /* ATMTFCLK */ + /* PC22 */ { 0, 1, 0, 0, 0, 0 }, /* ATMRFCLK */ + /* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RXCLK */ + /* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN TXCLK */ + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */ + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */ + /* PC17 */ { 1, 0, 0, 1, 0, 0 }, /* PC17 MDC */ + /* PC16 */ { 1, 0, 0, 0, 0, 0 }, /* PC16 MDIO*/ + /* PC15 */ { 0, 0, 0, 1, 0, 0 }, /* PC15 */ + /* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN *CD */ + /* PC13 */ { 0, 0, 0, 1, 0, 0 }, /* PC13 */ + /* PC12 */ { 0, 0, 0, 1, 0, 0 }, /* PC12 */ + /* PC11 */ { 0, 0, 0, 1, 0, 0 }, /* PC11 */ + /* PC10 */ { 0, 0, 0, 1, 0, 0 }, /* PC10 */ + /* PC9 */ { 0, 0, 0, 1, 0, 0 }, /* PC9 */ + /* PC8 */ { 0, 0, 0, 1, 0, 0 }, /* PC8 */ + /* PC7 */ { 0, 0, 0, 1, 0, 0 }, /* PC7 */ + /* PC6 */ { 0, 0, 0, 1, 0, 0 }, /* PC6 */ + /* PC5 */ { 1, 1, 0, 1, 0, 0 }, /* PC5 SMC1 TXD */ + /* PC4 */ { 1, 1, 0, 0, 0, 0 }, /* PC4 SMC1 RXD */ + /* PC3 */ { 0, 0, 0, 1, 0, 0 }, /* PC3 */ + /* PC2 */ { 0, 0, 0, 1, 0, 1 }, /* ENET FDE */ + /* PC1 */ { 0, 0, 0, 1, 0, 0 }, /* ENET DSQE */ + /* PC0 */ { 0, 0, 0, 1, 0, 0 }, /* ENET LBK */ + }, + + /* Port D */ + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RxD */ + /* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 EN TxD */ + /* PD29 */ { 1, 1, 0, 1, 0, 0 }, /* SCC1 EN TENA */ + /* PD28 */ { 0, 0, 0, 1, 0, 0 }, /* PD28 */ + /* PD27 */ { 0, 0, 0, 1, 0, 0 }, /* PD27 */ + /* PD26 */ { 0, 0, 0, 1, 0, 0 }, /* PD26 */ + /* PD25 */ { 0, 0, 0, 1, 0, 0 }, /* PD25 */ + /* PD24 */ { 0, 0, 0, 1, 0, 0 }, /* PD24 */ + /* PD23 */ { 0, 0, 0, 1, 0, 0 }, /* PD23 */ + /* PD22 */ { 0, 0, 0, 1, 0, 0 }, /* PD22 */ + /* PD21 */ { 0, 0, 0, 1, 0, 0 }, /* PD21 */ + /* PD20 */ { 0, 0, 0, 1, 0, 0 }, /* PD20 */ + /* PD19 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */ + /* PD18 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */ + /* PD17 */ { 0, 1, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */ + /* PD16 */ { 0, 1, 0, 1, 0, 0 }, /* FCC1 ATMTXPRTY */ +#if defined(CONFIG_SOFT_I2C) + /* PD15 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SDA */ + /* PD14 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SCL */ +#else +#if defined(CONFIG_HARD_I2C) + /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */ + /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */ +#else /* normal I/O port pins */ + /* PD15 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SDA */ + /* PD14 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SCL */ +#endif +#endif + /* PD13 */ { 0, 0, 0, 0, 0, 0 }, /* PD13 */ + /* PD12 */ { 0, 0, 0, 0, 0, 0 }, /* PD12 */ + /* PD11 */ { 0, 0, 0, 0, 0, 0 }, /* PD11 */ + /* PD10 */ { 0, 0, 0, 0, 0, 0 }, /* PD10 */ + /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */ + /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */ + /* PD7 */ { 0, 0, 0, 1, 0, 1 }, /* PD7 */ + /* PD6 */ { 0, 0, 0, 1, 0, 1 }, /* PD6 */ + /* PD5 */ { 0, 0, 0, 1, 0, 0 }, /* PD5 */ + /* PD4 */ { 0, 0, 0, 1, 0, 1 }, /* PD4 */ + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + } +}; + +#define _NOT_USED_ 0xFFFFFFFF + +/* UPM pattern for bus clock = 66.7 MHz */ +static const uint upmTable67[] = +{ + /* Offset UPM Read Single RAM array entry -> NAND Read Data */ + /* 0x00 */ 0x0fa3f100, 0x0fa3b000, 0x0fa33100, 0x0fa33000, + /* 0x04 */ 0x0fa33000, 0x0fa33004, 0xfffffc01, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */ + /* 0x18 */ 0x00a3fc00, 0x00a3fc00, 0x00a3fc00, 0x00a3fc00, + /* 0x1C */ 0x0fa3fc00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00, + + /* UPM Write Burst RAM array entry -> unused */ + /* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Refresh Timer RAM array entry -> unused */ + /* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Exception RAM array entry -> unsused */ + /* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +}; + +/* UPM pattern for bus clock = 100 MHz */ +static const uint upmTable100[] = +{ + /* Offset UPM Read Single RAM array entry -> NAND Read Data */ + /* 0x00 */ 0x0fa3f200, 0x0fa3b000, 0x0fa33300, 0x0fa33000, + /* 0x04 */ 0x0fa33000, 0x0fa33004, 0xfffffc01, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */ + /* 0x18 */ 0x00a3ff00, 0x00a3fc00, 0x00a3fc00, 0x0fa3fc00, + /* 0x1C */ 0x0fa3fc00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00, + + /* UPM Write Burst RAM array entry -> unused */ + /* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Refresh Timer RAM array entry -> unused */ + /* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Exception RAM array entry -> unsused */ + /* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +}; + +/* UPM pattern for bus clock = 133.3 MHz */ +static const uint upmTable133[] = +{ + /* Offset UPM Read Single RAM array entry -> NAND Read Data */ + /* 0x00 */ 0x0fa3f300, 0x0fa3b000, 0x0fa33300, 0x0fa33000, + /* 0x04 */ 0x0fa33200, 0x0fa33004, 0xfffffc01, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */ + /* 0x18 */ 0x00a3ff00, 0x00a3fc00, 0x00a3fd00, 0x0fa3fc00, + /* 0x1C */ 0x0fa3fd00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00, + + /* UPM Write Burst RAM array entry -> unused */ + /* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Refresh Timer RAM array entry -> unused */ + /* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Exception RAM array entry -> unsused */ + /* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +}; + +static int chipsel = 0; + +/* UPM pattern for slow init */ +static const uint upmTableSlow[] = +{ + /* Offset UPM Read Single RAM array entry */ + /* 0x00 */ 0xffffee00, 0x00ffcc80, 0x00ffcf00, 0x00ffdc00, + /* 0x04 */ 0x00ffce80, 0x00ffcc00, 0x00ffee00, 0x3fffcc07, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Write Single RAM array entry */ + /* 0x18 */ 0xffffee00, 0x00ffec80, 0x00ffef00, 0x00fffc80, + /* 0x1C */ 0x00fffe00, 0x00ffec00, 0x0fffef00, 0x3fffec05, + + /* UPM Write Burst RAM array entry -> unused */ + /* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Refresh Timer RAM array entry -> unused */ + /* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Exception RAM array entry -> unused */ + /* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +}; + +/* UPM pattern for fast init */ +static const uint upmTableFast[] = +{ + /* Offset UPM Read Single RAM array entry */ + /* 0x00 */ 0xffffee00, 0x00ffcc80, 0x00ffcd80, 0x00ffdc00, + /* 0x04 */ 0x00ffdc00, 0x00ffcf00, 0x00ffec00, 0x3fffcc07, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Read Burst RAM array entry -> unused */ + /* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + + /* UPM Write Single RAM array entry */ + /* 0x18 */ 0xffffee00, 0x00ffec80, 0x00ffee80, 0x00fffc00, + /* 0x1C */ 0x00fffc00, 0x00ffec00, 0x0fffef00, 0x3fffec05, + + /* UPM Write Burst RAM array entry -> unused */ + /* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Refresh Timer RAM array entry -> unused */ + /* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, + /* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, + + /* UPM Exception RAM array entry -> unused */ + /* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +}; + + +/* ------------------------------------------------------------------------- */ + +/* Check Board Identity: + */ +int checkboard (void) +{ + char *p = (char *) HWIB_INFO_START_ADDR; + + puts ("Board: "); + if (*((unsigned long *)p) == (unsigned long)CFG_HWINFO_MAGIC) { + puts (p); + } else { + puts ("No HWIB assuming TQM8272"); + } + putc ('\n'); + + return 0; +} + +/* ------------------------------------------------------------------------- */ +#if defined(CONFIG_BOARD_GET_CPU_CLK_F) +static int get_cas_latency (void) +{ + /* get it from the option -ts in CIB */ + /* default is 3 */ + int ret = 3; + int pos = 0; + char *p = (char *) CIB_INFO_START_ADDR; + + while ((*p != '\0') && (pos < CIB_INFO_LEN)) { + if (*p < ' ' || *p > '~') { /* ASCII strings! */ + return ret; + } + if (*p == '-') { + if ((p[1] == 't') && (p[2] == 's')) { + return (p[4] - '0'); + } + } + p++; + pos++; + } + return ret; +} +#endif + +static ulong set_sdram_timing (volatile uint *sdmr_ptr, ulong sdmr, int col) +{ +#if defined(CONFIG_BOARD_GET_CPU_CLK_F) + int clk = board_get_cpu_clk_f (); + volatile immap_t *immr = (immap_t *)CFG_IMMR; + int busmode = (immr->im_siu_conf.sc_bcr & BCR_EBM ? 1 : 0); + int cas; + + sdmr = sdmr & ~(PSDMR_RFRC_MSK | PSDMR_PRETOACT_MSK | PSDMR_WRC_MSK | \ + PSDMR_BUFCMD); + if (busmode) { + switch (clk) { + case 66666666: + sdmr |= (PSDMR_RFRC_66MHZ_60X | \ + PSDMR_PRETOACT_66MHZ_60X | \ + PSDMR_WRC_66MHZ_60X | \ + PSDMR_BUFCMD_66MHZ_60X); + break; + case 100000000: + sdmr |= (PSDMR_RFRC_100MHZ_60X | \ + PSDMR_PRETOACT_100MHZ_60X | \ + PSDMR_WRC_100MHZ_60X | \ + PSDMR_BUFCMD_100MHZ_60X); + break; + + } + } else { + switch (clk) { + case 66666666: + sdmr |= (PSDMR_RFRC_66MHZ_SINGLE | \ + PSDMR_PRETOACT_66MHZ_SINGLE | \ + PSDMR_WRC_66MHZ_SINGLE | \ + PSDMR_BUFCMD_66MHZ_SINGLE); + break; + case 100000000: + sdmr |= (PSDMR_RFRC_100MHZ_SINGLE | \ + PSDMR_PRETOACT_100MHZ_SINGLE | \ + PSDMR_WRC_100MHZ_SINGLE | \ + PSDMR_BUFCMD_100MHZ_SINGLE); + break; + case 133333333: + sdmr |= (PSDMR_RFRC_133MHZ_SINGLE | \ + PSDMR_PRETOACT_133MHZ_SINGLE | \ + PSDMR_WRC_133MHZ_SINGLE | \ + PSDMR_BUFCMD_133MHZ_SINGLE); + break; + } + } + cas = get_cas_latency(); + sdmr &=~ (PSDMR_CL_MSK | PSDMR_LDOTOPRE_MSK); + sdmr |= cas; + sdmr |= ((cas - 1) << 6); + return sdmr; +#else + return sdmr; +#endif +} + +/* Try SDRAM initialization with P/LSDMR=sdmr and ORx=orx + * + * This routine performs standard 8260 initialization sequence + * and calculates the available memory size. It may be called + * several times to try different SDRAM configurations on both + * 60x and local buses. + */ +static long int try_init (volatile memctl8260_t * memctl, ulong sdmr, + ulong orx, volatile uchar * base, int col) +{ + volatile uchar c = 0xff; + volatile uint *sdmr_ptr; + volatile uint *orx_ptr; + ulong maxsize, size; + int i; + + /* We must be able to test a location outsize the maximum legal size + * to find out THAT we are outside; but this address still has to be + * mapped by the controller. That means, that the initial mapping has + * to be (at least) twice as large as the maximum expected size. + */ + maxsize = (1 + (~orx | 0x7fff)) / 2; + + /* Since CFG_SDRAM_BASE is always 0 (??), we assume that + * we are configuring CS1 if base != 0 + */ + sdmr_ptr = base ? &memctl->memc_lsdmr : &memctl->memc_psdmr; + orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1; + + *orx_ptr = orx; + sdmr = set_sdram_timing (sdmr_ptr, sdmr, col); + /* + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): + * + * "At system reset, initialization software must set up the + * programmable parameters in the memory controller banks registers + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, + * system software should execute the following initialization sequence + * for each SDRAM device. + * + * 1. Issue a PRECHARGE-ALL-BANKS command + * 2. Issue eight CBR REFRESH commands + * 3. Issue a MODE-SET command to initialize the mode register + * + * The initial commands are executed by setting P/LSDMR[OP] and + * accessing the SDRAM with a single-byte transaction." + * + * The appropriate BRx/ORx registers have already been set when we + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + + *sdmr_ptr = sdmr | PSDMR_OP_PREA; + *base = c; + + *sdmr_ptr = sdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) + *base = c; + + *sdmr_ptr = sdmr | PSDMR_OP_MRW; + *(base + CFG_MRS_OFFS) = c; /* setting MR on address lines */ + + *sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *base = c; + + size = get_ram_size((long *)base, maxsize); + *orx_ptr = orx | ~(size - 1); + + return (size); +} + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + +#ifndef CFG_RAMBOOT + long size8, size9; +#endif + long psize, lsize; + + psize = 16 * 1024 * 1024; + lsize = 0; + + memctl->memc_psrt = CFG_PSRT; + memctl->memc_mptpr = CFG_MPTPR; + +#ifndef CFG_RAMBOOT + /* 60x SDRAM setup: + */ + size8 = try_init (memctl, CFG_PSDMR_8COL, CFG_OR1_8COL, + (uchar *) CFG_SDRAM_BASE, 8); + size9 = try_init (memctl, CFG_PSDMR_9COL, CFG_OR1_9COL, + (uchar *) CFG_SDRAM_BASE, 9); + + if (size8 < size9) { + psize = size9; + printf ("(60x:9COL - %ld MB, ", psize >> 20); + } else { + psize = try_init (memctl, CFG_PSDMR_8COL, CFG_OR1_8COL, + (uchar *) CFG_SDRAM_BASE, 8); + printf ("(60x:8COL - %ld MB, ", psize >> 20); + } + +#endif /* CFG_RAMBOOT */ + + icache_enable (); + + return (psize); +} + + +static inline int scanChar (char *p, int len, unsigned long *number) +{ + int akt = 0; + + *number = 0; + while (akt < len) { + if ((*p >= '0') && (*p <= '9')) { + *number *= 10; + *number += *p - '0'; + p += 1; + } else { + if (*p == '-') return akt; + return -1; + } + akt ++; + } + return akt; +} + +typedef struct{ + int Bus; + int flash; + int flash_nr; + int ram; + int ram_cs; + int nand; + int nand_cs; + int eeprom; + int can; + unsigned long cpunr; + unsigned long option; + int SecEng; + int cpucl; + int cpmcl; + int buscl; + int busclk_real_ok; + int busclk_real; + unsigned char OK; + unsigned char ethaddr[20]; +} HWIB_INFO; + +HWIB_INFO hwinf = {0, 0, 1, 0, 1, 0, 0, 0, 0, 8272, 0 ,0, + 0, 0, 0, 0, 0, 0}; + +static int dump_hwib(void) +{ + HWIB_INFO *hw = &hwinf; + volatile immap_t *immr = (immap_t *)CFG_IMMR; + char *s = getenv("serial#"); + + if (hw->OK) { + printf ("HWIB on %x\n", HWIB_INFO_START_ADDR); + printf ("serial : %s\n", s); + printf ("ethaddr: %s\n", hw->ethaddr); + printf ("FLASH : %x nr:%d\n", hw->flash, hw->flash_nr); + printf ("RAM : %x cs:%d\n", hw->ram, hw->ram_cs); + printf ("CPU : %d\n", hw->cpunr); + printf ("CAN : %d\n", hw->can); + if (hw->eeprom) printf ("EEprom : %x\n", hw->eeprom); + else printf ("No EEprom\n"); + if (hw->nand) { + printf ("NAND : %x\n", hw->nand); + printf ("NAND CS: %d\n", hw->nand_cs); + } else { printf ("No NAND\n");} + printf ("Bus %s mode.\n", (hw->Bus ? "60x" : "Single PQII")); + printf (" real : %s\n", (immr->im_siu_conf.sc_bcr & BCR_EBM ? \ + "60x" : "Single PQII")); + printf ("Option : %x\n", hw->option); + printf ("%s Security Engine\n", (hw->SecEng ? "with" : "no")); + printf ("CPM Clk: %d\n", hw->cpmcl); + printf ("CPU Clk: %d\n", hw->cpucl); + printf ("Bus Clk: %d\n", hw->buscl); + if (hw->busclk_real_ok) { + printf (" real Clk: %d\n", hw->busclk_real); + } + printf ("CAS : %d\n", get_cas_latency()); + } else { + printf("HWIB @%x not OK\n", HWIB_INFO_START_ADDR); + } + return 0; +} + +static inline int search_real_busclk (int *clk) +{ + int part = 0, pos = 0; + char *p = (char *) CIB_INFO_START_ADDR; + int ok = 0; + + while ((*p != '\0') && (pos < CIB_INFO_LEN)) { + if (*p < ' ' || *p > '~') { /* ASCII strings! */ + return 0; + } + switch (part) { + default: + if (*p == '-') { + ++part; + } + break; + case 3: + if (*p == '-') { + ++part; + break; + } + if (*p == 'b') { + ok = 1; + p++; + break; + } + if (ok) { + switch (*p) { + case '6': + *clk = 66666666; + return 1; + break; + case '1': + if (p[1] == '3') { + *clk = 133333333; + } else { + *clk = 100000000; + } + return 1; + break; + } + } + break; + } + p++; + } + return 0; +} + +int analyse_hwib (void) +{ + char *p = (char *) HWIB_INFO_START_ADDR; + int anz; + int part = 1, i = 0, pos = 0; + HWIB_INFO *hw = &hwinf; + + deb_printf(" %s pointer: %p\n", __FUNCTION__, p); + /* Head = TQM */ + if (*((unsigned long *)p) != (unsigned long)CFG_HWINFO_MAGIC) { + deb_printf("No HWIB\n"); + return -1; + } + p += 3; + if (scanChar (p, 4, &hw->cpunr) < 0) { + deb_printf("No CPU\n"); + return -2; + } + p +=4; + + hw->flash = 0x200000 << (*p - 'A'); + p++; + hw->flash_nr = *p - '0'; + p++; + + hw->ram = 0x2000000 << (*p - 'A'); + p++; + if (*p == '2') { + hw->ram_cs = 2; + p++; + } + + if (*p == 'A') hw->can = 1; + if (*p == 'B') hw->can = 2; + p +=1; + p +=1; /* connector */ + if (*p != '0') { + hw->eeprom = 0x1000 << (*p - 'A'); + } + p++; + + if ((*p < '0') || (*p > '9')) { + /* NAND before z-option */ + hw->nand = 0x8000000 << (*p - 'A'); + p++; + hw->nand_cs = *p - '0'; + p += 2; + } + /* z-option */ + anz = scanChar (p, 4, &hw->option); + if (anz < 0) { + deb_printf("No option\n"); + return -3; + } + if (hw->option & 0x8) hw->Bus = 1; + p += anz; + if (*p != '-') { + deb_printf("No -\n"); + return -4; + } + p++; + /* C option */ + if (*p == 'E') { + hw->SecEng = 1; + p++; + } + switch (*p) { + case 'M': hw->cpucl = 266666666; + break; + case 'P': hw->cpucl = 300000000; + break; + case 'T': hw->cpucl = 400000000; + break; + default: + deb_printf("No CPU Clk: %c\n", *p); + return -5; + break; + } + p++; + switch (*p) { + case 'I': hw->cpmcl = 200000000; + break; + case 'M': hw->cpmcl = 300000000; + break; + default: + deb_printf("No CPM Clk\n"); + return -6; + break; + } + p++; + switch (*p) { + case 'B': hw->buscl = 66666666; + break; + case 'E': hw->buscl = 100000000; + break; + case 'F': hw->buscl = 133333333; + break; + default: + deb_printf("No BUS Clk\n"); + return -7; + break; + } + p++; + + hw->OK = 1; + /* search MAC Address */ + while ((*p != '\0') && (pos < CFG_HWINFO_SIZE)) { + if (*p < ' ' || *p > '~') { /* ASCII strings! */ + return 0; + } + switch (part) { + default: + if (*p == ' ') { + ++part; + i = 0; + } + break; + case 3: /* Copy MAC address */ + if (*p == ' ') { + ++part; + i = 0; + break; + } + hw->ethaddr[i++] = *p; + if ((i % 3) == 2) + hw->ethaddr[i++] = ':'; + break; + + } + p++; + } + + hw->busclk_real_ok = search_real_busclk (&hw->busclk_real); + return 0; +} + +#if defined(CONFIG_GET_CPU_STR_F) +/* !! This routine runs from Flash */ +char get_cpu_str_f (char *buf) +{ + char *p = (char *) HWIB_INFO_START_ADDR; + int i = 0; + + buf[i++] = 'M'; + buf[i++] = 'P'; + buf[i++] = 'C'; + if (*((unsigned long *)p) == (unsigned long)CFG_HWINFO_MAGIC) { + buf[i++] = *&p[3]; + buf[i++] = *&p[4]; + buf[i++] = *&p[5]; + buf[i++] = *&p[6]; + } else { + buf[i++] = '8'; + buf[i++] = '2'; + buf[i++] = '7'; + buf[i++] = 'x'; + } + buf[i++] = 0; + return 0; +} +#endif + +#if defined(CONFIG_BOARD_GET_CPU_CLK_F) +/* !! This routine runs from Flash */ +unsigned long board_get_cpu_clk_f (void) +{ + char *p = (char *) HWIB_INFO_START_ADDR; + int i = 0; + + if (*((unsigned long *)p) == (unsigned long)CFG_HWINFO_MAGIC) { + if (search_real_busclk (&i)) + return i; + } + return CONFIG_8260_CLKIN; +} +#endif + +#if CONFIG_BOARD_EARLY_INIT_R + +static int can_test (unsigned long off) +{ + volatile unsigned char *base = (unsigned char *) (CFG_CAN_BASE + off); + + *(base + 0x17) = 'T'; + *(base + 0x18) = 'Q'; + *(base + 0x19) = 'M'; + if ((*(base + 0x17) != 'T') || + (*(base + 0x18) != 'Q') || + (*(base + 0x19) != 'M')) { + return 0; + } + return 1; +} + +static int can_config_one (unsigned long off) +{ + volatile unsigned char *ctrl = (unsigned char *) (CFG_CAN_BASE + off); + volatile unsigned char *cpu_if = (unsigned char *) (CFG_CAN_BASE + off + 0x02); + volatile unsigned char *clkout = (unsigned char *) (CFG_CAN_BASE + off + 0x1f); + unsigned char temp; + + *cpu_if = 0x45; + temp = *ctrl; + temp |= 0x40; + *ctrl = temp; + *clkout = 0x20; + temp = *ctrl; + temp &= ~0x40; + *ctrl = temp; + return 0; +} + +static int can_config (void) +{ + int ret = 0; + can_config_one (0); + if (hwinf.can == 2) { + can_config_one (0x100); + } + /* make Test if they really there */ + ret += can_test (0); + ret += can_test (0x100); + return ret; +} + +static int init_can (void) +{ + volatile immap_t * immr = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immr->im_memctl; + int count = 0; + + if ((hwinf.OK) && (hwinf.can)) { + memctl->memc_or4 = CFG_CAN_OR; + memctl->memc_br4 = CFG_CAN_BR; + /* upm Init */ + upmconfig (UPMC, (uint *) upmTableFast, + sizeof (upmTableFast) / sizeof (uint)); + memctl->memc_mcmr = (MxMR_DSx_3_CYCL | + MxMR_GPL_x4DIS | + MxMR_RLFx_2X | + MxMR_WLFx_2X | + MxMR_OP_NORM); + /* can configure */ + count = can_config (); + printf ("CAN: %d @ %x\n", count, CFG_CAN_BASE); + if (hwinf.can != count) printf("!!! difference to HWIB\n"); + } else { + printf ("CAN: No\n"); + } + return 0; +} + +int board_early_init_r(void) +{ + analyse_hwib (); + init_can (); + return 0; +} +#endif + +int do_hwib_dump (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + dump_hwib (); + return 0; +} + +U_BOOT_CMD( + hwib, 1, 1, do_hwib_dump, + "hwib - dump HWIB'\n", + "\n" +); + +#ifdef CFG_UPDATE_FLASH_SIZE +static int get_flash_timing (void) +{ + /* get it from the option -tf in CIB */ + /* default is 0x00000c84 */ + int ret = 0x00000c84; + int pos = 0; + int nr = 0; + char *p = (char *) CIB_INFO_START_ADDR; + + while ((*p != '\0') && (pos < CIB_INFO_LEN)) { + if (*p < ' ' || *p > '~') { /* ASCII strings! */ + return ret; + } + if (*p == '-') { + if ((p[1] == 't') && (p[2] == 'f')) { + p += 6; + ret = 0; + while (nr < 8) { + if ((*p >= '0') && (*p <= '9')) { + ret *= 0x10; + ret += *p - '0'; + p += 1; + nr ++; + } else if ((*p >= 'A') && (*p <= 'F')) { + ret *= 10; + ret += *p - '7'; + p += 1; + nr ++; + } else { + if (nr < 8) return 0x00000c84; + return ret; + } + } + } + } + p++; + pos++; + } + return ret; +} + +/* Update the Flash_Size and the Flash Timing */ +int update_flash_size (int flash_size) +{ + volatile immap_t * immr = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immr->im_memctl; + unsigned long reg; + unsigned long tim; + + /* I must use reg, otherwise the board hang */ + reg = memctl->memc_or0; + reg &= ~ORxU_AM_MSK; + reg |= MEG_TO_AM(flash_size >> 20); + tim = get_flash_timing (); + reg &= ~0xfff; + reg |= (tim & 0xfff); + memctl->memc_or0 = reg; + return 0; +} +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <nand.h> +#include <linux/mtd/mtd.h> + +static u8 hwctl = 0; + +static void upmnand_hwcontrol(struct mtd_info *mtdinfo, int cmd) +{ + switch (cmd) { + case NAND_CTL_SETCLE: + hwctl |= 0x1; + break; + case NAND_CTL_CLRCLE: + hwctl &= ~0x1; + break; + + case NAND_CTL_SETALE: + hwctl |= 0x2; + break; + + case NAND_CTL_CLRALE: + hwctl &= ~0x2; + break; + } +} + +static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) (this->IO_ADDR_W + chipsel * CFG_NAND_CS_DIST); + + if (hwctl & 0x1) { + WRITE_NAND_UPM(byte, base, CFG_NAND_UPM_WRITE_CMD_OFS); + } else if (hwctl & 0x2) { + WRITE_NAND_UPM(byte, base, CFG_NAND_UPM_WRITE_ADDR_OFS); + } else { + WRITE_NAND(byte, base); + } +} + +static u_char upmnand_read_byte(struct mtd_info *mtdinfo) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) (this->IO_ADDR_W + chipsel * CFG_NAND_CS_DIST); + + return READ_NAND(base); +} + +static int tqm8272_dev_ready(struct mtd_info *mtdinfo) +{ + /* constant delay (see also tR in the datasheet) */ + udelay(12); \ + return 1; +} + +#ifndef CONFIG_NAND_SPL +static void tqm8272_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len) +{ + struct nand_chip *this = mtdinfo->priv; + unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CFG_NAND_CS_DIST); + int i; + + for (i = 0; i< len; i++) + buf[i] = *base; +} + +static void tqm8272_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) +{ + struct nand_chip *this = mtdinfo->priv; + unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CFG_NAND_CS_DIST); + int i; + + for (i = 0; i< len; i++) + *base = buf[i]; +} + +static int tqm8272_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) +{ + struct nand_chip *this = mtdinfo->priv; + unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CFG_NAND_CS_DIST); + int i; + + for (i = 0; i < len; i++) + if (buf[i] != *base) + return -1; + return 0; +} +#endif /* #ifndef CONFIG_NAND_SPL */ + +void board_nand_select_device(struct nand_chip *nand, int chip) +{ + chipsel = chip; +} + +int board_nand_init(struct nand_chip *nand) +{ + static int UpmInit = 0; + volatile immap_t * immr = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immr->im_memctl; + + if (hwinf.nand == 0) return -1; + + /* Setup the UPM */ + if (UpmInit == 0) { + switch (hwinf.busclk_real) { + case 100000000: + upmconfig (UPMB, (uint *) upmTable100, + sizeof (upmTable100) / sizeof (uint)); + break; + case 133333333: + upmconfig (UPMB, (uint *) upmTable133, + sizeof (upmTable133) / sizeof (uint)); + break; + default: + upmconfig (UPMB, (uint *) upmTable67, + sizeof (upmTable67) / sizeof (uint)); + break; + } + UpmInit = 1; + } + + /* Setup the memctrl */ + memctl->memc_or3 = CFG_NAND_OR; + memctl->memc_br3 = CFG_NAND_BR; + memctl->memc_mbmr = (MxMR_OP_NORM); + + nand->eccmode = NAND_ECC_SOFT; + + nand->hwcontrol = upmnand_hwcontrol; + nand->read_byte = upmnand_read_byte; + nand->write_byte = upmnand_write_byte; + nand->dev_ready = tqm8272_dev_ready; + +#ifndef CONFIG_NAND_SPL + nand->write_buf = tqm8272_write_buf; + nand->read_buf = tqm8272_read_buf; + nand->verify_buf = tqm8272_verify_buf; +#endif + + /* + * Select required NAND chip + */ + board_nand_select_device(nand, 0); + return 0; +} + +#endif /* CFG_CMD_NAND */ + +#ifdef CONFIG_PCI +struct pci_controller hose; + +int board_early_init_f (void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + + immap->im_clkrst.car_sccr |= M826X_SCCR_PCI_MODE_EN; + return 0; +} + +extern void pci_mpc8250_init(struct pci_controller *); + +void pci_init_board(void) +{ + pci_mpc8250_init(&hose); +} +#endif diff --git a/board/tqm8272/u-boot.lds b/board/tqm8272/u-boot.lds new file mode 100644 index 0000000..05f29c6 --- /dev/null +++ b/board/tqm8272/u-boot.lds @@ -0,0 +1,126 @@ +/* + * (C) Copyright 2001 + * 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 : + { + cpu/mpc8260/start.o (.text) + *(.text) + common/environment.o(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/tqm834x/pci.c b/board/tqm834x/pci.c index 5a23e6c..d896f17 100644 --- a/board/tqm834x/pci.c +++ b/board/tqm834x/pci.c @@ -69,17 +69,17 @@ void pci_init_board(void) { volatile immap_t * immr; - volatile clk8349_t * clk; - volatile law8349_t * pci_law; - volatile pot8349_t * pci_pot; - volatile pcictrl8349_t * pci_ctrl; - volatile pciconf8349_t * pci_conf; + volatile clk83xx_t * clk; + volatile law83xx_t * pci_law; + volatile pot83xx_t * pci_pot; + volatile pcictrl83xx_t * pci_ctrl; + volatile pciconf83xx_t * pci_conf; u16 reg16; u32 reg32; struct pci_controller * hose; - immr = (immap_t *)CFG_IMMRBAR; - clk = (clk8349_t *)&immr->clk; + immr = (immap_t *)CFG_IMMR; + clk = (clk83xx_t *)&immr->clk; pci_law = immr->sysconf.pcilaw; pci_pot = immr->ios.pot; pci_ctrl = immr->pci_ctrl; @@ -186,8 +186,8 @@ pci_init_board(void) hose->region_count = 3; pci_setup_indirect(hose, - (CFG_IMMRBAR+0x8300), - (CFG_IMMRBAR+0x8304)); + (CFG_IMMR+0x8300), + (CFG_IMMR+0x8304)); pci_register_hose(hose); diff --git a/board/tqm834x/tqm834x.c b/board/tqm834x/tqm834x.c index 41b34cc..9c35e22 100644 --- a/board/tqm834x/tqm834x.c +++ b/board/tqm834x/tqm834x.c @@ -69,7 +69,7 @@ static void set_cs_config(short cs, long config); static void set_ddr_config(void); /* Local variable */ -static volatile immap_t *im = (immap_t *)CFG_IMMRBAR; +static volatile immap_t *im = (immap_t *)CFG_IMMR; /************************************************************************** * Board initialzation after relocation to RAM. Used to detect the number @@ -147,15 +147,15 @@ int checkboard (void) volatile immap_t * immr; u32 w, f; - immr = (immap_t *)CFG_IMMRBAR; - if (!(immr->reset.rcwh & RCWH_PCIHOST)) { + immr = (immap_t *)CFG_IMMR; + if (!(immr->reset.rcwh & HRCWH_PCI_HOST)) { printf("PCI: NOT in host mode..?!\n"); return 0; } /* get bus width */ w = 32; - if (immr->reset.rcwh & RCWH_PCI64) + if (immr->reset.rcwh & HRCWH_64_BIT_PCI) w = 64; /* get clock */ diff --git a/board/trab/auto_update.c b/board/trab/auto_update.c index 7684499..6f903d2 100644 --- a/board/trab/auto_update.c +++ b/board/trab/auto_update.c @@ -203,7 +203,6 @@ extern int flash_write (char *, ulong, ulong); /* change char* to void* to shutup the compiler */ extern int i2c_write_multiple (uchar, uint, int, void *, int); extern int i2c_read_multiple (uchar, uint, int, void *, int); -extern block_dev_desc_t *get_dev (char*, int); extern int u_boot_hush_start(void); int diff --git a/board/uc101/Makefile b/board/uc101/Makefile new file mode 100644 index 0000000..ddfd2ef --- /dev/null +++ b/board/uc101/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2003-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/uc101/config.mk b/board/uc101/config.mk new file mode 100644 index 0000000..51e8e84c --- /dev/null +++ b/board/uc101/config.mk @@ -0,0 +1,41 @@ +# +# (C) Copyright 2004 +# 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 +# + +# +# INKA 4X0 board: +# +# Valid values for TEXT_BASE are: +# +# 0xFFE00000 boot high +# +# 0x00100000 boot from RAM (for testing only) +# + +ifndef TEXT_BASE +## Standard: boot high +TEXT_BASE = 0xFFF00000 +## For testing: boot from RAM +#TEXT_BASE = 0x00100000 +endif + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/uc101/u-boot.lds b/board/uc101/u-boot.lds new file mode 100644 index 0000000..123a14c --- /dev/null +++ b/board/uc101/u-boot.lds @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2003-2004 + * 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/mpc5xxx/start.o (.text) + cpu/mpc5xxx/traps.o (.text) + lib_generic/crc32.o (.text) + lib_ppc/cache.o (.text) + lib_ppc/time.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.ppcenv) + + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/uc101/uc101.c b/board/uc101/uc101.c new file mode 100644 index 0000000..7a6b3be --- /dev/null +++ b/board/uc101/uc101.c @@ -0,0 +1,371 @@ +/* + * (C) Copyright 2006 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * (C) Copyright 2003-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2004 + * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com. + * + * (C) Copyright 2004 + * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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 <common.h> +#include <mpc5xxx.h> +#include <pci.h> +#include <malloc.h> + +/* some SIMPLE GPIO Pins */ +#define GPIO_USB_8 (31-12) +#define GPIO_USB_7 (31-13) +#define GPIO_USB_6 (31-14) +#define GPIO_USB_0 (31-15) +#define GPIO_PSC3_7 (31-18) +#define GPIO_PSC3_6 (31-19) +#define GPIO_PSC3_1 (31-22) +#define GPIO_PSC3_0 (31-23) + +/* some simple Interrupt GPIO Pins */ +#define GPIO_PSC3_8 2 +#define GPIO_USB1_9 3 + +#define GPT_OUT_0 0x00000027 +#define GPT_OUT_1 0x00000037 +#define GPT_DISABLE 0x00000000 /* GPT pin disabled */ + +#define GP_SIMP_ENABLE_O(n, v) {pgpio->simple_dvo |= (v << n); \ + pgpio->simple_ddr |= (1 << n); \ + pgpio->simple_gpioe |= (1 << n); \ + } + +#define GP_SIMP_ENABLE_I(n) { pgpio->simple_ddr |= ~(1 << n); \ + pgpio->simple_gpioe |= (1 << n); \ + } + +#define GP_SIMP_SET_O(n, v) (pgpio->simple_dvo = v ? \ + (pgpio->simple_dvo | (1 << n)) : \ + (pgpio->simple_dvo & ~(1 << n)) ) + +#define GP_SIMP_GET_O(n) ((pgpio->simple_dvo >> n) & 1) +#define GP_SIMP_GET_I(n) ((pgpio->simple_ival >> n) & 1) + +#define GP_SINT_SET_O(n, v) (pgpio->sint_dvo = v ? \ + (pgpio->sint_dvo | (1 << n)) : \ + (pgpio->sint_dvo & ~(1 << n)) ) + +#define GP_SINT_ENABLE_O(n, v) {pgpio->sint_ode &= ~(1 << n); \ + pgpio->sint_ddr |= (1 << n); \ + GP_SINT_SET_O(n, v); \ + pgpio->sint_gpioe |= (1 << n); \ + } + +#define GP_SINT_ENABLE_I(n) { pgpio->sint_ddr |= ~(1 << n); \ + pgpio->sint_gpioe |= (1 << n); \ + } + +#define GP_SINT_GET_O(n) ((pgpio->sint_ival >> n) & 1) +#define GP_SINT_GET_I(n) ((pgpio-ntt_ival >> n) & 1) + +#define GP_TIMER_ENABLE_O(n, v) ( \ + ((volatile struct mpc5xxx_gpt *)(MPC5XXX_GPT + n))->emsr = v ? \ + GPT_OUT_1 : \ + GPT_OUT_0 ) + +#define GP_TIMER_SET_O(n, v) GP_TIMER_ENABLE_O(n, v) + +#define GP_TIMER_GET_O(n, v) ( \ + (((volatile struct mpc5xxx_gpt *)(MPC5XXX_GPT + n))->emsr & 0x10) >> 4) + +#define GP_TIMER_GET_I(n, v) ( \ + (((volatile struct mpc5xxx_gpt *)(MPC5XXX_GPT + n))->sr & 0x100) >> 8) + +#ifndef CFG_RAMBOOT +static void sdram_start (int hi_addr) +{ + long hi_addr_bit = hi_addr ? 0x01000000 : 0; + + /* unlock mode register */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit; + __asm__ volatile ("sync"); + +#if SDRAM_DDR + /* set mode register: extended mode */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_EMODE; + __asm__ volatile ("sync"); + + /* set mode register: reset DLL */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000; + __asm__ volatile ("sync"); +#endif + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* auto refresh */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | hi_addr_bit; + __asm__ volatile ("sync"); + + /* set mode register */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE; + __asm__ volatile ("sync"); + + /* normal operation */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit; + __asm__ volatile ("sync"); +} +#endif + +/* + * ATTENTION: Although partially referenced initdram does NOT make real use + * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE + * is something else than 0x00000000. + */ + +long int initdram (int board_type) +{ + ulong dramsize = 0; +#ifndef CFG_RAMBOOT + ulong test1, test2; + + /* setup SDRAM chip selects */ + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001c; /* 512MB at 0x0 */ + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x40000000; /* disabled */ + __asm__ volatile ("sync"); + + /* setup config registers */ + *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1; + *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2; + __asm__ volatile ("sync"); + +#if SDRAM_DDR + /* set tap delay */ + *(vu_long *)MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY; + __asm__ volatile ("sync"); +#endif + + /* find RAM size using SDRAM CS0 only */ + sdram_start(0); + test1 = get_ram_size((long *)CFG_SDRAM_BASE, 0x20000000); + sdram_start(1); + test2 = get_ram_size((long *)CFG_SDRAM_BASE, 0x20000000); + if (test1 > test2) { + sdram_start(0); + dramsize = test1; + } else { + dramsize = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize < (1 << 20)) { + dramsize = 0; + } + + /* set SDRAM CS0 size according to the amount of RAM found */ + if (dramsize > 0) { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + + __builtin_ffs(dramsize >> 20) - 1; + } else { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */ + } + + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */ +#else /* CFG_RAMBOOT */ + + /* retrieve size of memory connected to SDRAM CS0 */ + dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF; + if (dramsize >= 0x13) { + dramsize = (1 << (dramsize - 0x13)) << 20; + } else { + dramsize = 0; + } + + /* retrieve size of memory connected to SDRAM CS1 */ + dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF; + if (dramsize2 >= 0x13) { + dramsize2 = (1 << (dramsize2 - 0x13)) << 20; + } else { + dramsize2 = 0; + } + +#endif /* CFG_RAMBOOT */ + +/* return dramsize + dramsize2; */ + return dramsize; +} + +int checkboard (void) +{ + puts ("Board: MAN UC101\n"); + return 0; +} + +static void init_ports (void) +{ + volatile struct mpc5xxx_gpio *pgpio = + (struct mpc5xxx_gpio *)MPC5XXX_GPIO; + + GP_SIMP_ENABLE_I(GPIO_USB_8); /* HEX Bit 3 */ + GP_SIMP_ENABLE_I(GPIO_USB_7); /* HEX Bit 2 */ + GP_SIMP_ENABLE_I(GPIO_USB_6); /* HEX Bit 1 */ + GP_SIMP_ENABLE_I(GPIO_USB_0); /* HEX Bit 0 */ + GP_SIMP_ENABLE_I(GPIO_PSC3_0); /* Switch Menue A */ + GP_SIMP_ENABLE_I(GPIO_PSC3_1); /* Switch Menue B */ + GP_SIMP_ENABLE_I(GPIO_PSC3_6); /* Switch Cold_Warm */ + GP_SIMP_ENABLE_I(GPIO_PSC3_7); /* Switch Restart */ + GP_SINT_ENABLE_O(GPIO_PSC3_8, 0); /* LED H2 */ + GP_SINT_ENABLE_O(GPIO_USB1_9, 0); /* LED H3 */ + GP_TIMER_ENABLE_O(4, 0); /* LED H4 */ + GP_TIMER_ENABLE_O(5, 0); /* LED H5 */ + GP_TIMER_ENABLE_O(3, 0); /* LED HB */ + GP_TIMER_ENABLE_O(1, 0); /* RES_COLDSTART */ +} + +#ifdef CONFIG_PREBOOT + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +struct kbd_data_t { + char s1; +}; + +struct kbd_data_t* get_keys (struct kbd_data_t *kbd_data) +{ + volatile struct mpc5xxx_gpio *pgpio = + (struct mpc5xxx_gpio *)MPC5XXX_GPIO; + + kbd_data->s1 = GP_SIMP_GET_I(GPIO_USB_8) << 3 | \ + GP_SIMP_GET_I(GPIO_USB_7) << 2 | \ + GP_SIMP_GET_I(GPIO_USB_6) << 1 | \ + GP_SIMP_GET_I(GPIO_USB_0) << 0; + return kbd_data; +} + +static int compare_magic (const struct kbd_data_t *kbd_data, char *str) +{ + char s1 = str[0]; + + if (s1 >= '0' && s1 <= '9') + s1 -= '0'; + else if (s1 >= 'a' && s1 <= 'f') + s1 = s1 - 'a' + 10; + else if (s1 >= 'A' && s1 <= 'F') + s1 = s1 - 'A' + 10; + else + return -1; + + if (s1 != kbd_data->s1) return -1; + return 0; +} + +static char *key_match (const struct kbd_data_t *kbd_data) +{ + char magic[sizeof (kbd_magic_prefix) + 1]; + char *suffix; + char *kbd_magic_keys; + + /* + * The following string defines the characters that can be appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix = kbd_magic_keys; *suffix || + suffix == kbd_magic_keys; ++suffix) { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); + + if (compare_magic(kbd_data, getenv(magic)) == 0) { + char cmd_name[sizeof (kbd_command_prefix) + 1]; + char *cmd; + + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + cmd = getenv (cmd_name); + + return (cmd); + } + } + + return (NULL); +} + +#endif /* CONFIG_PREBOOT */ + +int misc_init_r (void) +{ + /* Init the I/O ports */ + init_ports (); + +#ifdef CONFIG_PREBOOT + struct kbd_data_t kbd_data; + /* Decode keys */ + char *str = strdup (key_match (get_keys (&kbd_data))); + /* Set or delete definition */ + setenv ("preboot", str); + free (str); +#endif /* CONFIG_PREBOOT */ + return 0; +} + +int board_early_init_r (void) +{ + *(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ + *(vu_long *)MPC5XXX_BOOTCS_START = + *(vu_long *)MPC5XXX_CS0_START = START_REG(CFG_FLASH_BASE); + *(vu_long *)MPC5XXX_BOOTCS_STOP = + *(vu_long *)MPC5XXX_CS0_STOP = STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE); + /* Interbus enable it here ?? */ + *(vu_long *)MPC5XXX_GPT6_ENABLE = GPT_OUT_1; + return 0; +} +#ifdef CONFIG_PCI +static struct pci_controller hose; + +extern void pci_mpc5xxx_init(struct pci_controller *); + +void pci_init_board(void) +{ + pci_mpc5xxx_init(&hose); +} +#endif + +#if defined(CONFIG_HW_WATCHDOG) +void hw_watchdog_reset(void) +{ + /* Trigger HW Watchdog with TIMER_0 */ + *(vu_long *)MPC5XXX_GPT0_ENABLE = GPT_OUT_1; + *(vu_long *)MPC5XXX_GPT0_ENABLE = GPT_OUT_0; +} +#endif diff --git a/board/v38b/v38b.c b/board/v38b/v38b.c index dede996..ace4aa2 100644 --- a/board/v38b/v38b.c +++ b/board/v38b/v38b.c @@ -191,16 +191,8 @@ int checkboard (void) return 0; } - -int board_early_init_r(void) +int board_early_init_f(void) { - /* - * Now, when we are in RAM, enable flash write access for the - * detection process. Note that CS_BOOT cannot be cleared when - * executing in flash. - */ - *(vu_long *) MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ - #ifdef CONFIG_HW_WATCHDOG /* * Enable and configure the direction (output) of PSC3_9 - watchdog @@ -210,6 +202,17 @@ int board_early_init_r(void) *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC3_9; *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC3_9; #endif /* CONFIG_HW_WATCHDOG */ + return 0; +} + +int board_early_init_r(void) +{ + /* + * Now, when we are in RAM, enable flash write access for the + * detection process. Note that CS_BOOT cannot be cleared when + * executing in flash. + */ + *(vu_long *) MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ /* * Enable GPIO_WKUP_7 to "read the status of the actual power diff --git a/board/xilinx/ml300/Makefile b/board/xilinx/ml300/Makefile index 02c22fb..05ad235 100644 --- a/board/xilinx/ml300/Makefile +++ b/board/xilinx/ml300/Makefile @@ -28,7 +28,7 @@ $(shell mkdir -p $(obj)../xilinx_enet) $(shell mkdir -p $(obj)../xilinx_iic) endif -INCS := -I../ml300 -I../common -I../xilinx_enet -I../xilinx_iic +INCS := -I../common -I../xilinx_enet -I../xilinx_iic CFLAGS += $(INCS) HOST_CFLAGS += $(INCS) diff --git a/board/xilinx/ml300/ml300.c b/board/xilinx/ml300/ml300.c index dad562f..60f0bc2 100644 --- a/board/xilinx/ml300/ml300.c +++ b/board/xilinx/ml300/ml300.c @@ -38,9 +38,9 @@ * */ +#include <config.h> #include <common.h> #include <asm/processor.h> -#include "xparameters.h" #ifdef CFG_ENV_IS_IN_EEPROM extern void convert_env(void); diff --git a/board/xilinx/ml300/serial.c b/board/xilinx/ml300/serial.c index c204b88..9b03f89 100644 --- a/board/xilinx/ml300/serial.c +++ b/board/xilinx/ml300/serial.c @@ -40,8 +40,7 @@ #include <asm/processor.h> #include <common.h> #include <command.h> -#include <configs/ml300.h> -#include "xparameters.h" +#include <config.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/board/xilinx/xilinx_enet/emac_adapter.c b/board/xilinx/xilinx_enet/emac_adapter.c index b30e897..f159cb6 100644 --- a/board/xilinx/xilinx_enet/emac_adapter.c +++ b/board/xilinx/xilinx_enet/emac_adapter.c @@ -37,9 +37,9 @@ * ******************************************************************************/ +#include <config.h> #include <common.h> #include <net.h> -#include "xparameters.h" #include "xemac.h" #if defined(XPAR_EMAC_0_DEVICE_ID) diff --git a/board/xilinx/xilinx_enet/xemac.h b/board/xilinx/xilinx_enet/xemac.h index ed704bf..584cb7a 100644 --- a/board/xilinx/xilinx_enet/xemac.h +++ b/board/xilinx/xilinx_enet/xemac.h @@ -257,9 +257,9 @@ /***************************** Include Files *********************************/ +#include <config.h> #include "xbasic_types.h" #include "xstatus.h" -#include "xparameters.h" #include "xpacket_fifo_v1_00_b.h" /* Uses v1.00b of Packet Fifo */ #include "xdma_channel.h" diff --git a/board/xilinx/xilinx_enet/xemac_g.c b/board/xilinx/xilinx_enet/xemac_g.c index 9340f91..d985157 100644 --- a/board/xilinx/xilinx_enet/xemac_g.c +++ b/board/xilinx/xilinx_enet/xemac_g.c @@ -43,7 +43,7 @@ * *******************************************************************/ -#include "xparameters.h" +#include <config.h> #include "xemac.h" /* diff --git a/board/xilinx/xilinx_iic/iic_adapter.c b/board/xilinx/xilinx_iic/iic_adapter.c index 163fe15..37dce03 100644 --- a/board/xilinx/xilinx_iic/iic_adapter.c +++ b/board/xilinx/xilinx_iic/iic_adapter.c @@ -37,10 +37,10 @@ * ******************************************************************************/ +#include <config.h> #include <common.h> #include <environment.h> #include <net.h> -#include "xparameters.h" #ifdef CFG_ENV_IS_IN_EEPROM #include <i2c.h> diff --git a/board/zylonite/nand.c b/board/zylonite/nand.c index 5d2cd65..a417143 100644 --- a/board/zylonite/nand.c +++ b/board/zylonite/nand.c @@ -448,7 +448,7 @@ static void dfc_gpio_init(void) * Members with a "?" were not set in the merged testing-NAND branch, * so they are not set here either. */ -void board_nand_init(struct nand_chip *nand) +int board_nand_init(struct nand_chip *nand) { unsigned long tCH, tCS, tWH, tWP, tRH, tRP, tRP_high, tR, tWHR, tAR; @@ -576,6 +576,7 @@ void board_nand_init(struct nand_chip *nand) nand->cmdfunc = dfc_cmdfunc; nand->autooob = &delta_oob; nand->badblock_pattern = &delta_bbt_descr; + return 0; } #else |